FreeBSD Manual Pages
MAME(1) MAME Documentation MAME(1) NAME MAME - MAME Documentation [image: MAME] [image] NOTE: This documentation is a work in progress. You can track the status of these topics through MAME's issue tracker. Learn how you can contribute. WHAT IS MAME MAME is a multi-purpose emulation framework. MAMEs purpose is to preserve decades of software history. As elec- tronic technology continues to rush forward, MAME prevents this impor- tant vintage software from being lost and forgotten. This is achieved by documenting the hardware and how it functions. The source code to MAME serves as this documentation. The fact that the software is us- able serves primarily to validate the accuracy of the documentation (how else can you prove that you have recreated the hardware faith- fully?). MAME, originally the Multiple Arcade Machine Emulator, ab- sorbed sister-projects, including MESS (Multi-Emulator Super System) and AGEMAME (Arcade Gambling Extensions for MAME), so MAME now docu- ments a wide variety of (mostly vintage) computers, video game con- soles, calculators and gambling machines, in addition to the arcade video games that were its initial focus. MAME Copyright 1997-2025 MAMEdev and contributors MAME is a registered trademark of Gregory Ember I. Purpose MAMEs main purpose is to be a reference to the inner workings of the emulated machines. This is done both for educational purposes and for preservation purposes, in order to prevent historical software from disappearing forever once the hardware it runs on stops working. Of course, in order to preserve the software and demonstrate that the emu- lated behavior matches the original, one must also be able to actually use the software. This is considered a nice side effect, and is not MAMEs primary focus. It is not our intention to infringe on any copyrights or patents on the original software and systems. All of MAMEs source code is either our own or freely available. To operate, the emulator requires images of the original ROMs, CDs, hard disks or other media from the machines, which must be provided by the user. No portions of the original soft- ware are included in the MAME executable. II. Cost MAME is made available at no cost. Its source code is freely avail- able. The project as whole is distributed under the terms of the GNU General Public License, version 2 or later (GPL-2.0+), but most of code, including core functionality, is also available under the terms of the more permissive 3-clause BSD license (BSD-3-clause). III. Software Image Files ROM, CD, hard disk and other media images are all copyrighted material. They may not be lawfully distributed without the explicit permission of the copyright holder(s). They are not abandonware, nor has copyright expired on any of the software supported by MAME. MAME is not intended to be used as a tool for mass copyright infringe- ment. Therefore, it is strongly against the authors wishes to sell, advertise, or link to resources that provide illegal copies of ROM, CD, hard disk or other media images. IV. Derivative Works Because the name MAME is trademarked, you must abide by the rules set out for trademark usage if you wish to use MAME as part of the name your derivative work. In general, this means you must request permis- sion, which requires that you follow the guidelines above. The version number of any derivative work should reflect the version number of the MAME release from which it was derived. V. Official Contact Information For questions regarding the MAME license, trademark, or other usage, see https://www.mamedev.org/legal.html HEALTH WARNINGS Epilepsy Warning A very small percentage of individuals may experience epileptic seizures when exposed to certain light patterns or flashing lights. Ex- posure to certain patterns or backgrounds on a television screen or computer monitor, or while playing video games may induce an epileptic seizure in these individuals. Certain conditions may induce previously undetected epileptic symptoms even in persons who have no history of prior seizures or epilepsy. These conditions can include emulation accuracy or inaccuracy, computer performance at the time of running MAME, video card drivers, your moni- tor, and a lot of other factors. If you, or anyone in your family, has an epileptic condition, consult your physician prior to using MAME. If you experience any of the following while using MAME, IMMEDIATELY discontinue use and consult your physician before resuming use of MAME. • Dizziness • Altered vision • Eye or muscle twitches • Loss of awareness • Disorientation • Any involuntary movement • Convulsions GETTING MAME PREPARED This section covers initial preparation work needed to use MAME, in- cluding downloading MAME, compiling MAME from source, and configuring MAME. An Introduction to MAME MAME, formerly an acronym which stood for Multi Arcade Machine Emula- tor, documents and reproduces through emulation the inner components of arcade machines, computers, consoles, chess computers, calculators, and many other types of electronic amusement machines. As a nice side-ef- fect, MAME allows to use on a modern PC those programs and games which were originally developed for the emulated machines. At one point there were actually two separate projects, MAME and MESS. MAME covered arcade video games, while MESS covered home and business systems. They are now merged into the one MAME. MAME is written in C++ and can currently emulate over 32,000 individual systems from the last five decades. Purpose of MAME The primary purpose of MAME is to preserve decades of arcade, computer, and console history. As technology continues to rush forward, MAME pre- vents these important vintage systems from being lost and forgotten. Systems Emulated by MAME The Arcade Database contains a complete list of the systems currently emulated. As you will notice, being supported does not always mean that the status of the emulation is perfect. You may want 1. to check the status of the emulation in the wiki pages of each sys- tem, accessible from the drivers page (e.g. for Apple Macintosh, from the page for the mac128.cpp driver you can reach the pages for both macplus and macse), 2. to read the corresponding sysinfo.dat entry in order to better un- derstand which issues you may encounter while running a system in MAME (again, for Apple Macintosh Plus you have to check this entry). Alternatively, you can simply see the status by yourself, launching the system emulation and taking a look at the red or yellow warning screen which appears before the emulation starts, if any. Notice that if you have information which can help to improve the emulation of a supported system, or if you can directly contribute fixes and/or addition to the current source, you can do any of the following: • Send in a pull request (for code) or open an issue (information) on our GitHub page • Post the information or code on the MAME Forums • Follow the instructions on our contact page Supported OS The current source code can be directly compiled under all the main op- erating systems: Microsoft Windows (both with DirectX/BGFX native sup- port or with SDL support), Linux, FreeBSD, and macOS. System Requirements MAME is written in C++, and has been ported to numerous platforms. Over time, as computer hardware has evolved, the MAME code has evolved as well to take advantage of the greater processing power and hardware ca- pabilities offered. The official MAME binaries are compiled and designed to run on a stan- dard Windows-based system. The minimum requirements are: • Intel Core 2-series CPU or equivalent, at least 2.0 GHz • 64-bit OS (Windows 7 or later on Windows, macOS 10.9 or later on Mac) • 4 GB RAM • DirectX 9.0c for Windows • A Direct3D, or OpenGL capable graphics card Of course, the minimum requirements are just that: minimal. You may not get optimal performance from such a system, but MAME should run. Modern versions of MAME require more power than older versions, so if you have a less-capable PC, you may find that using an older version of MAME may get you better performance, at the cost of greatly lowered accuracy and fewer supported systems. MAME will take advantage of 3D hardware for compositing artwork and scaling displayed software to full screen. To make use of this, you should have at least a semi-modern computer with semi-modern 3D hard- ware made within the last five to ten years. HLSL or GLSL special effects such as CRT simulation will put a very heavy load on your video card, especially at higher resolutions. You will need a fairly powerful modern video card, and the load on your video card goes up exponentially as your resolution increases. If HLSL or GLSL are too intensive, try reducing your output resolution. Keep in mind that even on the fastest computers available, MAME is still incapable of playing some systems at full speed. The goal of the project isnt to make all system run speedy on your system; the goal is to document the hardware and reproduce the behavior of the hardware as faithfully as possible. BIOS Dumps and Software Most of the systems emulated by MAME requires a dump of the internal chips of the original system. These can be obtained by extracting the data from an original unit, or finding them (at your own risk) on vari- ous place on the Internet. Being copyrighted material, MAME does not come with any of these. Also, you may want to find some software to be run on the emulated ma- chine where it does not have internal software (e.g. some computers will need a disk to boot to an operating system). Again, Google and other search engines are your best friends. MAME does not provide any software in the MAME package to be run on the emulated machines because it is very often (almost always, in the case of con- sole software) protected by copyright. The MAME team has been permitted to redistribute some old software, which can be found in the ROMS section of the MAME site. Installing MAME Microsoft Windows You simply have to download the latest binary archive available from http://www.mamedev.org and to extract its content to a folder. You will end up with many files (below you will find explanations about some of these), and in particular mame.exe. This is a command line program. The installation procedure ends here. Easy, isnt it? Other Operating Systems In this case, you can either look for pre-compiled (SDL)MAME binaries (e.g. in the repositories of your favorite Linux distro) which should simply extract all the needed files in a folder you choose, or compile the source code by yourself. In the latter case, see our section on compiling MAME. Compiling MAME • All Platforms • Microsoft Windows • Using a standard MSYS2 installation • Building with Microsoft Visual Studio • Some notes about the MSYS2 environment • Fedora Linux • Debian and Ubuntu (including Raspberry Pi and ODROID devices) • Arch Linux • Apple macOS • Emscripten Javascript and HTML • Compiling the Documentation • Compiling the Documentation on Microsoft Windows • Compiling the Documentation on Debian and Ubuntu • Useful Options • Overall build options • Tool locations • Including subsets of supported systems • Optional features • Compilation options • Library/framework locations • Known Issues • Issues with specific compiler versions • GNU C Library fortify source feature • Issues affecting Microsoft Visual Studio • Unusual Build Configurations • Linking using the LLVM linker • Cross-compiling MAME • Using libc++ on Linux • Using a GCC/GNU libstdc++ installation in a non-standard location on Linux All Platforms • To compile MAME, you need a C++17 compiler and runtime library. We support building with GCC version 10.3 or later and clang version 11 or later. MAME should run with GNU libstdc++ version 10.3 or later or libc++ version 11 or later. The initial release of any major ver- sion of GCC should be avoided. For example, if you want to compile MAME with GCC 12, you should use version 12.1 or later. • Whenever you are changing build parameters, (for example changing op- timisation settings, or adding tools to the compile list), or system drivers sources are added, removed, or renamed, the project files need to be regenerated. You can do this by adding REGENIE=1 to the make arguments, or updating the modification time of the makefile (for example using the touch command). Failure to do this may cause difficult to troubleshoot problems. • If you want to add various additional tools to the compile, such as chdman, add a TOOLS=1 to your make command, like make REGENIE=1 TOOLS=1 • You can build an emulator for a subset of the systems supported by MAME by using SOURCES=<driver>,... in your make command. For example make SUBTARGET=pacem SOURCES=src/mame/pacman/pacman.cpp REGENIE=1 would build an emulator called pacem including the system drivers from the source file pacman.cpp (REGENIE=1 is specified to ensure project files are regenerated). You can specify folders to include their entire contents, and you can separate multiple files/folders with commas. You can also omit the src/mame/ prefix in many cases. If you encounter linking errors after changing the included sources, delete the static libraries for the subtarget from the build folder. For the previous example on Windows using GCC, these would be in build/mingw-gcc/bin/x64/Release/mame_pacem by default. • On a system with multiple CPU cores, compilation can be sped up by compiling multiple source files in parallel. This is done with the -j parameter. For instance, make -j5 is a good starting point on a system with a quad-core CPU. Note: a good number to start with is the total number of CPU cores in your system plus one. An excessive number of concurrent jobs will increase compilation time, particularly if the compiler jobs exhaust available memory. The optimal number depends on many factors, in- cluding number of CPU cores, available RAM, disk and filesystem per- formance, and memory bandwidth. • Debugging information can be added to a compile using SYMBOLS=1 though most users will not want or need to use this. This increases compile time and disk space used. Note that a full build of MAME in- cluding internal debugging symbols will exceed the maximum size for an executable on Windows, and will not be possible to run without first stripping the symbols. Putting all of these together, we get a couple of examples: Rebuilding MAME on a dual-core (e.g. i3 or laptop i5) machine: make -j3 Rebuilding MAME for just the Pac-Man and Galaxian families of systems, with tools, on a quad-core (e.g. i5 or i7) machine: make SUBTARGET=pacem SOURCES=src/mame/pacman,src/mame/galaxian TOOLS=1 REGENIE=1 -j5 Rebuilding MAME for just the Apple II systems, compiling up to six sources in parallel: make SUBTARGET=appulator SOURCES=apple/apple2.cpp,apple/apple2e.cpp,apple/apple2gs.cpp REGENIE=1 -j6 Microsoft Windows MAME for Windows is built using the MSYS2 environment. You will need Windows 7 or later and a reasonably up-to-date MSYS2 installation. We strongly recommend building MAME on a 64-bit system. Instructions may need to be adjusted for 32-bit systems. • A pre-packaged MSYS2 installation including the prerequisites for building MAME can be downloaded from the MAME Build Tools page. • After initial installation, you can update the MSYS2 environment us- ing the pacman (Arch package manage) command. • By default, MAME will be built using native Windows OS interfaces for window management, audio/video output, font rendering, etc. If you want to use the portable SDL (Simple DirectMedia Layer) interfaces instead, you can add OSD=sdl to the make options. The main emulator binary will have an sdl prefix prepended (e.g. sdlmame.exe). You will need to install the MSYS2 packages for SDL 2 version 2.0.14 or later. • By default, MAME will include the native Windows debugger. To also include the portable Qt debugger, add USE_QTDEBUG=1 to the make op- tions. You will need to install the MSYS2 packages for Qt 5. Using a standard MSYS2 installation You may also build MAME using a standard MSYS2 installation and adding the tools needed for building MAME. These instructions assume you have some familiarity with MSYS2 and the pacman package manager. • Install the MSYS2 environment from the MSYS2 homepage. • Download the latest version of the mame-essentials package from the MAME package repository and install it using the pacman command. • Add the mame package repository to /etc/pacman.conf using /etc/pac- man.d/mirrorlist.mame for locations, and disable signature verifica- tion for this repository (SigLevel = Never). • Install packages necessary to build MAME. At the very least, youll need bash, git, make. • For 64-bit builds youll need mingw-w64-x86_64-gcc and mingw-w64-x86_64-python. • For 32-bit builds youll need mingw-w64-i686-gcc and mingw-w64-i686-python. • For debugging you may want to install gdb. • To link using the LLVM linker (generally much faster than the GNU linker), youll need mingw-w64-x86_64-lld and mingw-w64-x86_64-libc++ for 64-bit builds, or mingw-w64-i686-lld and mingw-w64-i686-libc++ for 32-bit builds. • To build against the portable SDL interfaces, youll need mingw-w64-x86_64-SDL2 and mingw-w64-x86_64-SDL2_ttf for 64-bit builds, or mingw-w64-i686-SDL2 and mingw-w64-i686-SDL2_ttf for 32-bit builds. • To build the Qt debugger, youll need mingw-w64-x86_64-qt5 for 64-bit builds, or mingw-w64-i686-qt5 for 32-bit builds. • To build the HTML user/developer documentation, youll need mingw-w64-x86_64-librsvg, mingw-w64-x86_64-python-sphinx, mingw-w64-x86_64-python-sphinx_rtd_theme and mingw-w64-x86_64-python-sphinxcontrib-svg2pdfconverter for a 64-bit MinGW environment (or alternatively mingw-w64-i686-librsvg, mingw-w64-i686-python-sphinx, mingw-w64-i686-python-sphinx_rtd_theme and mingw-w64-x86_64-python-sphinxcontrib-svg2pdfconverter a 32-bit MinGW environment). • To build the PDF documentation, youll additionally need mingw-w64-x86_64-texlive-latex-extra and mingw-w64-x86_64-texlive-fonts-recommended (or mingw-w64-i686-texlive-latex-extra and mingw-w64-i686-texlive-fonts-recommended for a 32-but MinGW environ- ment). • To generate API documentation from source, youll need doxygen. • If you plan to rebuild bgfx shaders and you want to rebuild the GLSL parser, youll need bison. • For 64-bit builds, open MSYS2 MinGW 64-bit from the start menu, and set up the environment variables MINGW64 to /mingw64 and MINGW32 to an empty string (e.g. using the command export MINGW64=/mingw64 MINGW32= in the Bash shell). • For 32-bit builds, open MSYS2 MinGW 32-bit from the start menu, and set up the environment variables MINGW32 to /mingw32 and MINGW64 to an empty string (e.g. using the command export MINGW32=/mingw32 MINGW64= in the Bash shell). For example you could use these commands to ensure you have the pack- ages you need to compile MAME, omitting the ones for configurations you dont plan to build for or combining multiple pacman commands to install more packages at once: pacman -Syu pacman -S curl git make pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-libc++ mingw-w64-x86_64-lld mingw-w64-x86_64-python pacman -S mingw-w64-x86_64-SDL2 mingw-w64-x86_64-SDL2_ttf pacman -S mingw-w64-x86_64-qt5 pacman -S mingw-w64-i686-gcc mingw-w64-i686-libc++ mingw-w64-i686-lld mingw-w64-i686-python pacman -S mingw-w64-i686-SDL2 mingw-w64-i686-SDL2_ttf pacman -S mingw-w64-i686-qt5 You could use these commands to install the current version of the mame-essentials package and add the MAME package repository to your pacman configuration: curl -O "https://repo.mamedev.org/x86_64/mame-essentials-1.0.6-1-x86_64.pkg.tar.xz" pacman -U mame-essentials-1.0.6-1-x86_64.pkg.tar.xz echo -e '\n[mame]\nInclude = /etc/pacman.d/mirrorlist.mame\nSigLevel = Never' >> /etc/pacman.conf Building with Microsoft Visual Studio • You can generate Visual Studio 2022 projects using make vs2022. The solution and project files will be created in build/projects/win- dows/mame/vs2022 by default (the name of the build folder can be changed using the BUILDDIR option). This will always regenerate the settings, so REGENIE=1 is not needed. • Adding MSBUILD=1 to the make options will build the solution using the Microsoft Build Engine after generating the project files. Note that this requires paths and environment variables to be configured so the correct Visual Studio tools can be located; please refer to the Microsoft-provided instructions on using the Microsoft C++ toolset from the command line. You may find it easier to not use MS- BUILD=1 and load the project file into Visual Studios GUI for compi- lation. • The MSYS2 environment is still required to generate the project files, convert built-in layouts, compile UI translations, etc. Some notes about the MSYS2 environment MSYS2 uses the pacman tool from Arch Linux for package management. There is a page on the Arch Linux wiki with helpful information on us- ing the pacman package management tool. The MSYS2 environment includes two kinds of tools: MSYS2 tools designed to work in a UNIX-like environment on top of Windows, and MinGW tools designed to work in a more Windows-like environment. The MSYS2 tools are installed in /usr/bin while the MinGW tools are installed in /ming64/bin and/or /mingw32/bin (relative to the MSYS2 installation di- rectory). MSYS2 tools work best in an MSYS2 terminal, while MinGW tools work best in a Microsoft command prompt. The most obvious symptom of this is that arrow keys dont work in inter- active programs if you run them in the wrong kind of terminal. If you run MinGW gdb or python from an MSYS2 terminal window, command history wont work and it may not be possible to interrupt an attached program with gdb. Similarly it may be very difficult to edit using MSYS2 vim in a Microsoft command prompt window. MAME is built using the MinGW compilers, so the MinGW directories are included earlier in the PATH for the build environments. If you want to use an interactive MSYS2 program from an MSYS2 shell, you may need to type the absolute path to avoid using the MinGW equivalent instead. MSYS2 gdb may have issues debugging MinGW programs like MAME. You may get better results by installing the MinGW version of gdb and running it from a Microsoft command prompt window to debug MAME. GNU make supports both POSIX-style shells (e.g. bash) and the Microsoft cmd.exe shell. One issue to be aware of when using the cmd.exe shell is that the copy command doesnt provide a useful exit status, so file copy tasks can fail silently. It is not possible to cross-compile a 32-bit version of MAME using 64-bit MinGW tools on Windows, the 32-bit MinGW tools must be used. This causes issues due to the size of MAME. It is not possible to link a full 32-bit MAME build including the SDL OS-dependent layer and the Qt debugger. GNU ld and lld will both run out of memory, leaving an output file that doesnt work. Its also impossible to make a 32-bit build with full local variable symbols. GCC may run out of memory, and certain source files may exceed the limit of 32,768 sections imposed by the PE/COFF object file format. Fedora Linux Youll need a few prerequisites from your Linux distribution. Make sure you get SDL 2 version 2.0.14 or later as earlier versions lack required functionality: sudo dnf install gcc gcc-c++ SDL2-devel SDL2_ttf-devel libXi-devel libXinerama-devel qt5-qtbase-devel qt5-qttools expat-devel fontconfig-devel alsa-lib-devel pulseaudio-libs-devel If you want to use the more efficient LLVM tools for archiving static libraries and linking, youll need to install the corresponding pack- ages: sudo dnf install lld llvm Compilation is exactly as described above in All Platforms. To build the HTML user/developer documentation, youll need Sphinx, as well as the theme and the SVG converter: sudo dnf install python3-sphinx python3-sphinx_rtd_theme python3-sphinxcontrib-rsvgconverter The HTML documentation can be built with this command: make -C docs SPHINXBUILD=sphinx-build-3 html Debian and Ubuntu (including Raspberry Pi and ODROID devices) Youll need a few prerequisites from your Linux distribution. Make sure you get SDL 2 version 2.0.14 or later as earlier versions lack required functionality: sudo apt-get install git build-essential python3 libsdl2-dev libsdl2-ttf-dev libfontconfig-dev libpulse-dev qtbase5-dev qtbase5-dev-tools qtchooser qt5-qmake Compilation is exactly as described above in All Platforms. Note the Ubuntu Linux modifies GCC to enable the GNU C Library fortify source feature by default, which may cause issues compiling MAME (see Known Issues). Arch Linux Youll need a few prerequisites from your distro: sudo pacman -S base-devel git sdl2_ttf python libxinerama libpulse alsa-lib qt5-base Compilation is exactly as described above in All Platforms. Apple macOS Youll need a few prerequisites to get started. Make sure youre on ma- cOS 11.0 Big Sur or later. You will need SDL 2 version 2.0.14 or later. Youll also need to install Python 3 its currently included with the Xcode command line tools, but you can also install a stand-alone version or get it via the Homebrew package manager. • Install Xcode from the Mac App Store or ADC (AppleID required). • To find the corresponding Xcode for your MacOS release please visit xcodereleases.com to find the latest version of Xcode available to you. • Launch Xcode. It will download a few additional prerequisites. Let this run through before proceeding. • Once thats done, quit Xcode and open a Terminal window. • Type xcode-select --install to install additional tools necessary for MAME (also available as a package on ADC). Next youll need to get SDL 2 installed. • Go to this site and download the macOS .dmg file • If the .dmg doesnt open automatically, open it • Click Macintosh HD (or whatever your Macs hard disk is named) in the left pane of a Finder window, then open the Library folder and drag the SDL2.framework folder from the SDL disk image into the Frameworks folder. You will have to authenticate with your user password. If you dont already have it, get Python 3 set up: • Go to the official Python site, navigate to the releases for macOS, and click the link to download the installer for the latest stable release (this was Python 3.10.4 at the time of writing). • Scroll down to the Files section, and download the macOS version (called macOS 64-bit universal2 installer or similar). • Once the package downloads, open it and follow the standard installa- tion process. Finally to begin compiling, use Terminal to navigate to where you have the MAME source tree (cd command) and follow the normal compilation in- structions from above in All Platforms. Emscripten Javascript and HTML First, download and install Emscripten 2.0.25 or later by following the instructions at the official site. Once Emscripten has been installed, it should be possible to compile MAME out-of-the-box using Emscriptens emmake tool. Because a full MAME compile is too large to load into a web browser at once, you will want to use the SOURCES parameter to compile only a subset of the project, e.g. (in the MAME directory): emmake make SUBTARGET=pacmantest SOURCES=src/mame/pacman/pacman.cpp The SOURCES parameter should have the path to at least one driver .cpp file. The make process will attempt to locate and include all depen- dencies necessary to produce a complete build including the specified driver(s). However, sometimes it is necessary to manually specify ad- ditional files (using commas) if this process misses something. e.g. emmake make SUBTARGET=apple2e SOURCES=src/mame/apple/apple2e.cpp,src/devices/machine/applefdc.cpp The value of the SUBTARGET parameter serves only to differentiate mul- tiple builds and need not be set to any specific value. Emscripten supports compiling to WebAssembly with a JavaScript loader instead of all-JavaScript, and in later versions this is actually the default. To force WebAssembly on or off, add WEBASSEMBLY=1 or WEBASSEM- BLY=0 to the make command line, respectively. Other make parameters can also be used, e.g. -j for multithreaded com- pilation as described earlier. When the compilation reaches the emcc phase, you may see a number of "unresolved symbol" warnings. At the moment, this is expected for OpenGL-related functions such as glPointSize. Any others may indicate that an additional dependency file needs to be specified in the SOURCES list. Unfortunately this process is not automated and you will need to search the source tree to locate the files supplying the missing sym- bols. You may also be able to get away with ignoring the warnings if the code path referencing them is not used at run-time. If all goes well, a .js file will be output to the current directory. This file cannot be run by itself, but requires an HTML loader to pro- vide it with a canvas to draw to and to pass in command-line parame- ters. The Emularity project provides such a loader. There are example .html files in that repository which can be edited to point to your newly compiled MAME .js file and pass in whatever parame- ters you desire. You will then need to place all of the following on a web server: • The compiled MAME .js file • The compiled MAME .wasm file if using WebAssembly • The .js files from the Emularity package (loader.js, browserfs.js, etc.) • A .zip file with the ROMs for the MAME driver you would like to run (if any) • Any software files you would like to run with the MAME driver • An Emularity loader .html modified to point to all of the above You need to use a web server instead of opening the local files di- rectly due to security restrictions in modern web browsers. If the result fails to run, you can open the Web Console in your browser to see any error output which may have been produced (e.g. missing or incorrect ROM files). A ReferenceError: foo is not defined error most likely indicates that a needed source file was omitted from the SOURCES list. Compiling the Documentation Compiling the documentation will require you to install several pack- ages depending on your operating system. Compiling the Documentation on Microsoft Windows On Windows, youll need a couple of packages from the MSYS2 environment. You can install these packages with pacman -S mingw-w64-x86_64-librsvg mingw-w64-x86_64-python-sphinx mingw-w64-x86_64-python-sphinxcontrib-svg2pdfconverter If you intend to make a PDF via LaTeX, youll need to install a LaTeX distribution such as TeX Live: pacman -S mingw-w64-x86_64-texlive-fonts-recommended mingw-w64-x86_64-texlive-latex-extra Compiling the Documentation on Debian and Ubuntu On Debian/Ubuntu flavors of Linux, youll need python3-sphinx/python-sphinx and the python3-pip/python-pip packages: sudo apt-get install python3-sphinx python3-pip pip3 install sphinxcontrib-svg2pdfconverter On Debian, youll need to install the librsvg2-bin package: sudo apt-get install librsvg2-bin If you intend to make a PDF via LaTeX, youll need to install a LaTeX distribution such as TeX Live: sudo apt-get install librsvg2-bin latexmk texlive texlive-science texlive-formats-extra From this point you can do make html or make latexpdf from the docs folder to generate the output of your choice. Typing make by itself will tell you all available formats. The output will be in the docs/build folder in a subfolder based on the type chosen (e.g. make html will create docs/build/html with the output.) Useful Options This section summarises some of the more useful options recognised by the main makefile. You use these options by appending them to the make command, setting them as environment variables, or adding them to your prefix makefile. Note that in order to apply many of these settings when rebuilding, you need to set REGENIE=1 the first time you build af- ter changing the option(s). Also note that GENie does not automati- cally rebuild affected files when you change an option that affects compiler settings. Overall build options PREFIX_MAKEFILE Name of a makefile to include for additional options if found (defaults to useroptions.mak). May be useful if you want to quickly switch between different build configurations. BUILDDIR Set to change the name of the subfolder used for project files, generated sources, object files, and intermediate libraries (de- faults to build). REGENIE Set to 1 to force project files to be regenerated. VERBOSE Set to 1 to show full commands when using GNU make as the build tool. This option applies immediately without needing regener- ate project files. IGNORE_GIT Set to 1 to skip the working tree scan and not attempt to embed a git revision description in the version string. Tool locations OVERRIDE_CC Set the C/Objective-C compiler command. (This sets the target C compiler command when cross-compiling.) OVERRIDE_CXX Set the C++/Objective-C++ compiler command. (This sets the tar- get C++ compiler command when cross-compiling.) OVERRIDE_LD Set the linker command. This is often not necessary or useful because the C or C++ compiler command is used to invoke the linker. (This sets the target linker command when cross-compil- ing.) PYTHON_EXECUTABLE Set the Python interpreter command. You need Python 3.2 or later to build MAME. CROSS_BUILD Set to 1 to use separate host and target compilers and linkers, as required for cross-compilation. In this case, OVERRIDE_CC, OVERRIDE_CXX and OVERRIDE_LD set the target C compiler, C++ com- piler and linker commands, while CC, CXX and LD set the host C compiler, C++ compiler and linker commands. Including subsets of supported systems SUBTARGET Set emulator subtarget to build. Some pre-defined subtargets are provided, using Lua scripts in scripts/target/mame and sys- tem driver filter files in src/mame. User-defined substargets can be created using the SOURCES or SOURCEFILTER option. SOURCES Specify system driver source files and/or folders to include. Usually used in conjunction with the SUBTARGET option. Separate multiple files/folders with commas. SOURCEFILTER Specify a system driver filter file. Usually used in conjunc- tion with the SUBTARGET option. The filter file can specify source files to include system drivers from, and individual sys- tem drivers to include or exclude. There are some example sys- tem driver filter files in the src/mame folder. Optional features TOOLS Set to 1 to build additional tools along with the emulator, in- cluding unidasm, chdman, romcmp, and srcclean. EMULATOR When set to 0, the main emulator target will not be created. This is intended to be used in conjunction with setting TOOLS to 1 to build the additional tools without building the emulator. NO_OPENGL Set to 1 to disable building the OpenGL video output module. NO_USE_PORTAUDIO Set to 1 to disable building the PortAudio sound output module and the PortAudio library. NO_USE_PULSEAUDIO Set to 1 to disable building the PulseAudio sound output module on Linux. USE_WAYLAND Set to 1 to include support for bgfx video output with the Way- land display server. USE_TAPTUN Set to 1 to include the tap/tun network module, or set to 0 to disable building the tap/tun network module. The tap/tun net- work module is included by default on Windows and Linux. USE_PCAP Set to 1 to include the pcap network module, or set to 0 to dis- able building the pcap network module. The pcap network module is included by default on macOS and NetBSD. USE_QTDEBUG Set to 1 to include the Qt debugger on platforms where its not built by default (e.g. Windows or macOS), or to 0 to disable it. Youll need to install Qt development libraries and tools to build the Qt debugger. The process depends on the platform. Compilation options NOWERROR Set to 1 to disable treating compiler warnings as errors. This may be needed in marginally supported configurations. DEPRECATED Set to 0 to disable deprecation warnings (note that deprecation warnings are not treated as errors). DEBUG Set to 1 to enable runtime assertion checks and additional diag- nostics. Note that this has a performance cost, and is most useful for developers. OPTIMIZE Set optimisation level. The default is 3 to favour performance at the expense of larger executable size. Set to 0 to disable optimisation (can make debugging easier), 1 for basic optimisa- tion that doesnt have a space/speed trade-off and doesnt have a large impact on compile time, 2 to enable most optimisation that improves performance and reduces size, or s to enable only opti- misations that generally dont increase executable size. The ex- act set of supported values depends on your compiler. SYMBOLS Set to 1 to include additional debugging symbols over the de- fault for the target platform (many target platforms include function name symbols by default). SYMLEVEL Numeric value that controls the level of detail in debugging symbols. Higher numbers make debugging easier at the cost of increased build time and executable size. The supported values depend on your compiler. For GCC and similar compilers, 1 in- cludes line number tables and external variables, 2 also in- cludes local variables, and 3 also includes macro definitions. ARCHOPTS Additional command-line options to pass to the compiler and linker. This is useful for supplying code generation or ABI op- tions, for example to enable support for optional CPU features. ARCHOPTS_C Additional command-line options to pass to the compiler when compiling C source files. ARCHOPTS_CXX Additional command-line options to pass to the compiler when compiling C++ source files. ARCHOPTS_OBJC Additional command-line options to pass to the compiler when compiling Objective-C source files. ARCHOPTS_OBJCXX Additional command-line options to pass to the compiler when compiling Objective-C++ source files. Library/framework locations SDL_INSTALL_ROOT SDL installation root directory for shared library style SDL. SDL_FRAMEWORK_PATH Search path for SDL framework. USE_LIBSDL Set to 1 to use shared library style SDL on targets where frame- work is default. USE_SYSTEM_LIB_ASIO Set to 1 to prefer the system installation of the Asio C++ asyn- chronous I/O library over the version provided with the MAME source. USE_SYSTEM_LIB_EXPAT Set to 1 to prefer the system installation of the Expat XML parser library over the version provided with the MAME source. USE_SYSTEM_LIB_ZLIB Set to 1 to prefer the system installation of the zlib data com- pression library over the version provided with the MAME source. USE_SYSTEM_LIB_ZSTD Set to 1 to prefer the system installation of the Zstandard data compression library over the version provided with the MAME source. USE_SYSTEM_LIB_JPEG Set to 1 to prefer the system installation of the libjpeg image compression library over the version provided with the MAME source. USE_SYSTEM_LIB_FLAC Set to 1 to prefer the system installation of the libFLAC audio compression library over the version provided with the MAME source. USE_SYSTEM_LIB_LUA Set to 1 to prefer the system installation of the embedded Lua interpreter over the version provided with the MAME source. USE_SYSTEM_LIB_SQLITE3 Set to 1 to prefer the system installation of the SQLITE embed- ded database engine over the version provided with the MAME source. USE_SYSTEM_LIB_PORTMIDI Set to 1 to prefer the system installation of the PortMidi li- brary over the version provided with the MAME source. USE_SYSTEM_LIB_PORTAUDIO Set to 1 to prefer the system installation of the PortAudio li- brary over the version provided with the MAME source. USE_SYSTEM_LIB_UTF8PROC Set to 1 to prefer the system installation of the Julia utf8proc library over the version provided with the MAME source. USE_SYSTEM_LIB_GLM Set to 1 to prefer the system installation of the GLM OpenGL Mathematics library over the version provided with the MAME source. USE_SYSTEM_LIB_RAPIDJSON Set to 1 to prefer the system installation of the Tencent Rapid- JSON library over the version provided with the MAME source. USE_SYSTEM_LIB_PUGIXML Set to 1 to prefer the system installation of the pugixml li- brary over the version provided with the MAME source. Known Issues Issues with specific compiler versions • GCC 7 for 32-bit x86 targets produces spurious out-of-bounds access warnings. Adding NOWERROR=1 to your build options works around this by not treating warnings as errors. GNU C Library fortify source feature The GNU C Library has options to perform additional compile- and run-time checks on string operations, enabled by defining the _FOR- TIFY_SOURCE preprocessor macro. This is intended to improve security at the cost of a small amount of overhead. MAME is not secure soft- ware, and we do not support building with _FORTIFY_SOURCE defined. Some Linux distributions (including Gentoo and Ubuntu) have patched GCC to define _FORTIFY_SOURCE to 1 as a built-in macro. This is problem- atic for more projects than just MAME, as it makes it hard to disable the additional checks (e.g. if you dont want the performance impact of the run-time checks), and it also makes it hard to define _FOR- TIFY_SOURCE to 2 if you want to enable stricter checks. You should re- ally take it up with the distribution maintainers, and make it clear you dont want non-standard GCC behaviour. It would be better if these distributions defined this macro by default in their packaging environ- ments if they think its important, rather than trying to force it on everything compiled on their distributions. (This is what Red Hat does: the _FORTIFY_SOURCE macro is set in the RPM build environment, and not by distributing a modified version of GCC.) If you get compilation errors in bits/string_fortified.h you should first ensure that the _FORTIY_SOURCE macro is defined via the environ- ment (e.g. a CFLAGS or CXXFLAGS environment variable). You can check to see whether the _FORTIFY_SOURCE macro is a built-in macro with your version of GCC with a command like this: gcc -dM -E - < /dev/null | grep _FORTIFY_SOURCE If _FORTIFY_SOURCE is defined to a non-zero value by default, you can work around it by adding -U_FORTIFY_SOURCE to the compiler flags (e.g. by using the ARCHOPTS setting, or setting the CFLAGS and CXXFLAGS envi- ronment variables. Issues affecting Microsoft Visual Studio Microsoft introduced a new version of XAudio2 with Windows 8 thats in- compatible with the version included with DirectX for prior Windows versions at the API level. Newer versions of the Microsoft Windows SDK include headers and libraries for the new version of XAudio2. By de- fault, the target Windows version is set to Windows Vista (6.0) when compiling MAME, which prevents the use of this version of the XAudio2 headers and libraries. To build MAME with XAudio2 support using the Microsoft Windows SDK, you must do one of the following: • Add MODERN_WIN_API=1 to the options passed to make when generating the Visual Studio project files. This will set the target Windows version to Windows 8 (6.2). The resulting binaries may not run on earlier versions of Windows. • Install the DirectX SDK (already included since Windows 8.0 SDK and automatically installed with Visual Studio 2013 and later). Config- ure the osd_windows project to search the DirectX header/library paths before searching the Microsoft Windows SDK paths. The MSVC compiler produces spurious warnings about potentially unini- tialised local variables. You currently need to add NOWERROR=1 to the options passed to make when generating the Visual Studio project files. This stops warnings from being treated as errors. (MSVC seems to lack options to control which specific warnings are treated as errors, which other compilers support.) Unusual Build Configurations Linking using the LLVM linker The LLVM linker is generally faster than the GNU linker that GCC uses by default. This is more pronounced on systems with a high overhead for file system operations (e.g. Microsoft Windows, or when compiling on a disk mounted over a network). To use the LLVM linker with GCC, ensure the LLVM linker is installed and add -fuse-ld=lld to the linker options (e.g. in the LDFLAGS environment variable or in the ARCHOPTS setting). Cross-compiling MAME MAMEs build system has basic support for cross-compilation. Set CROSS_BUILD=1 to enable separate host and target compilers, set OVER- RIDE_CC and OVERRIDE_CXX to the target C/C++ compiler commands, and if necessary set CC and CXX to the host C/C++ compiler commands. If the target OS is different to the host OS, set it with TARGETOS. For exam- ple it may be possible to build a MinGW32 x64 build on a Linux host us- ing a command like this: make TARGETOS=windows PTR64=1 OVERRIDE_CC=x86_64-w64-mingw32-gcc OVERRIDE_CXX=x86_64-w64-mingw32-g++ OVERRIDE_LD=x86_64-w64-mingw32-ld MINGW64=/usr** (The additional packages required for producing a standard MinGW32 x64 build on a Fedora Linux host are mingw64-gcc-c++, mingw64-winpthreads-static and their dependencies. Non-standard builds may require additional packages.) Using libc++ on Linux MAME may be built using the LLVM projects libc++ C++ Standard Library. The prerequisites are a working clang/LLVM installation, and the libc++ development libraries. On Fedora Linux, the necessary packages are libcxx, libcxx-devel, libcxxabi and libcxxabi-devel. Set the C and C++ compiler commands to use clang, and add -stdlib=libc++ to the C++ com- piler and linker options. You could use a command like this: env LDFLAGS=-stdlib=libc++ make OVERRIDE_CC=clang OVERRIDE_CXX=clang++ ARCHOPTS_CXX=-stdlib=libc++ ARCHOPTS_OBJCXX=-stdlib=libc++ The options following the make command may be placed in a prefix make- file if you want to use this configuration regularly, but LDFLAGS needs to be be set in the environment. Using a GCC/GNU libstdc++ installation in a non-standard location on Linux GCC may be built and installed to a custom location, typically by sup- plying the --prefix= option to the configure command. This may be use- ful if you want to build MAME on a Linux distribution that still uses a version of GNU libstdC++ that predates C++17 support. To use an alter- nate GCC installation to, build MAME, set the C and C++ compilers to the full paths to the gcc and g++ commands, and add the library path to the run-time search path. If you installed GCC in /opt/local/gcc72, you might use a command like this: make OVERRIDE_CC=/opt/local/gcc72/bin/gcc OVERRIDE_CXX=/opt/local/gcc72/bin/g++ ARCHOPTS=-Wl,-R,/opt/local/gcc72/lib64 You can add these options to a prefix makefile if you plan to use this configuration regularly. Configuring MAME • Getting Started: A Quick Preface • Initial Setup: Creating mame.ini From Command Line on Windows • Initial Setup: Creating mame.ini From Command Line on Linux or MacOS • Initial Setup: Graphical Setup Getting Started: A Quick Preface Once you have MAME installed, the next step is to configure it. There are several ways to do this, and each will be covered in turn. If you are on Windows, the MAME executable will be called mame.exe. If you are on Linux or MacOS, the MAME executable will be called mame. Initial Setup: Creating mame.ini From Command Line on Windows First, you will need to cd to the directory where you installed MAME into. If, for instance, you have MAME installed in C:\Users\Pub- lic\MAME you will need to type cd C:\Users\Public\MAME into the command prompt. Then you have MAME create the config file by typing mame -createconfig. MAME will then create the mame.ini file in the MAME installation folder. This file contains the default configuration settings for a new MAME installation. Initial Setup: Creating mame.ini From Command Line on Linux or MacOS The steps for Linux and MacOS are similar to those of Windows. If you installed MAME using the package manager that came from a Linux distro, you will type mame -createconfig into your terminal of choice. If you have compiled from source or downloaded a binary package of MAME, you will cd into the directory you put the MAME files into. For instance, cd /home/myusername/mame Then you will type ./mame -createconfig into your terminal of choice. You can then need to edit the mame.ini file in your favorite text edi- tor, e.g. Notepad on Windows or vi on Linux/MacOS, or you can change settings from inside of MAME. Initial Setup: Graphical Setup This is the easiest way to get started. Start MAME by opening the MAME icon in the location where you installed it. This will be mame.exe on Windows, mame on Linux and macOS. Once MAME has started, you can either use your mouse to click on the Configure Options menu selection at the bottom center of your screen, or you can switch panes to the bottom one (default key is Tab), then press the menu accept button (default key is Return/Enter) to go into the Configuration menu. Choose Save Configuration to create the mame.ini file with default set- tings. From here, you can either continue to configure things from the graphical user interface or edit the mame.ini file in your favorite text editor. BASIC MAME USAGE AND CONFIGURATION This section describes general usage information about MAME. It is in- tended to cover aspects of using and configuring MAME that are common across all operating systems. For additional OS-specific options, please see the separate documentation for your platform of choice. Using MAME If you want to dive right in and skip the command line, there's a nice graphical way to use MAME without the need to download and set up a front end. Simply start MAME with no parameters, by double-clicking the mame.exe file or running it directly from the command line. If you're looking to harness the full power of MAME, keep reading further. On macOS and *nix-based platforms, please be sure to set your font up to match your locale before starting, otherwise you may not be able to read the text due to missing glyphs. If you are a new MAME user, you could find this emulator a bit complex at first. Let's take a moment to talk about software lists, as they can simplify matters quite a bit. If the content you are trying to play is a documented entry on one of the MAME software lists, starting the con- tent is as easy as mame.exe <system> <software> For instance: mame.exe nes metroidu will load the USA version of Metroid for the Nintendo Entertainment System. Alternatively, you could start MAME with mame.exe nes and choose the software list from the cartridge slot. From there, you could pick any software list-compatible software you have in your roms folders. Please note that many older dumps of cartridges and discs may either be bad or require renaming to match up to the software list in order to work in this way. If you are loading an arcade board or other non-software list content, things are only a little more complicated: The basic usage, from command line, is mame.exe <system> <media> <software> <options> where • <system> is the short name of the system you want to emulate (e.g. nes, c64, etc.) • <media> is the switch for the media you want to load (if it's a car- tridge, try -cart or -cart1; if it's a floppy disk, try -flop or -flop1; if it's a CD-ROM, try -cdrom) • <software> is the program / game you want to load (and it can be given either as the fullpath to the file to load, or as the shortname of the file in our software lists) • <options> is any additional command line option for controllers, video, sound, etc. Remember that if you type a <system> name which does not correspond to any emulated system, MAME will suggest some possible choices which are close to what you typed; and if you don't know which <media> switch are available, you can always launch mame.exe <system> -listmedia If you don't know what <options> are available, there are a few things you can do. First of all, you can check the command line options sec- tion of this manual. You can also try one of the many Front-ends avail- able for MAME. Alternatively, you should keep in mind the following command line op- tions, which might be very useful on occasion: mame.exe -help gives a basic summary of command line options for MAME, as explained above. mame.exe -showusage gives you the (quite long) list of available command line options for MAME. The main options are described, in the Universal Command-line Options section of this manual. mame.exe -showconfig gives you a (quite long) list of available configuration options for MAME. These options can always be modified at command line, or by editing them in mame.ini which is the main configuration file for MAME. You can find a description of some configuration options in the Universal Command-line Options section of the manual (in most cases, each configuration option has a corresponding command line option to configure and modify it). mame.exe -createconfig creates a brand new mame.ini file, with default configuration settings. Notice that mame.ini is basically a plain text file, so you can open it with any text editor (e.g. Notepad, Emacs or TextEdit) and configure every option you need. However, no particular tweaks are needed to start, so you can leave most of the options unaltered. If you execute mame -createconfig when you already have an existing mame.ini from a previous MAME version, MAME automatically updates the pre-existing mame.ini by copying changed options into it. Once you are more confident with MAME options, you may want to adjust the configuration of your setup a bit more. In this case, keep in mind the order in which options are read; see Order of Config Loading for details. MAMEs User Interface • Introduction • Navigating menus • Using a game controller • Using a mouse or trackball • Using a touch screen • Configuring inputs • Digital input settings • Analog input settings • The system and software selection menus • Navigation controls • The simple system selection menu Introduction MAME provides a simple user interface for selecting the system and software to run and changing settings while running an emulated system. MAMEs user interface is designed to be usable with a keyboard, game controller, or pointing device, but will require a keyboard for initial configuration. The default settings for the most important controls to know when run- ning an emulated system, and the settings they correspond to in case you want to change them, are as follows: Scroll Lock, or Forward Delete on macOS (Toggle UI Controls) For emulated systems with keyboard inputs, enable or disable UI controls. (MAME starts with UI controls disabled for systems with keyboard inputs unless the ui_active option is on.) Tab (Show/Hide Menu) Show or hide the menu during emulation. Escape (UI Back and UI Cancel) Return to the system selection menu, or exit if MAME was started with a system specified (from the command line or using an external front-end). Navigating menus By default, MAME menus can be navigated using the keyboard cursor keys. All the UI controls can be changed by going to the General Inputs menu and then selecting User Interface. The default keyboard controls on a US ANSI QWERTY layout keyboard, and the settings they correspond to, are as follows: Up Arrow (UI Up) Highlight the previous menu item, or the last item if the first item is highlighted. Down Arrow (UI Down) Highlight the next menu item, or the first item if the last item is highlighted. Left Arrow (UI Left) For menu items that are adjustable settings, reduce the value or select the previous setting (these menu items show left- and right-facing triangles beside the value). Right Arrow (UI Left) For menu items that are adjustable settings, increase the value or select the next setting (these menu items show left- and right-facing triangles beside the value). Return/Enter keypad Enter (UI Select) Select the highlighted menu item. Forward Delete, or Fn+Delete on some compact keyboards (UI Clear) Clear setting or reset to default value. Escape (UI Back and UI Cancel) Clear the search if searching the menu, otherwise close the menu, returning to the previous menu, or returning to the emu- lated system in the case of the main menu (theres usually an item at the bottom of the menu for the same purpose). Home (UI Home) Highlight the first menu item and scroll to the top of the menu. End (UI End) Highlight the last menu item and scroll to the bottom of the menu. Page Up (UI Page Up) Scroll the menu up by one screen. Page Down (UI Page Down) Scroll the menu down by one screen. [ (UI Previous Group) Move to the previous group of items (not used by all menus). ] (UI Next Group) Move to the next group of items (not used by all menus). Using a game controller MAME supports navigating menus with a game controller or joystick, but only the most important UI controls have joystick assignments by de- fault: • Move the first joystick up or down in the Y axis to highlight the previous or next menu item. • Move the first joystick left or right in the X axis to adjust set- tings. • Press the first button on the first joystick to select the high- lighted menu item. • If the first joystick has at least three buttons, press the second button on the first joystick to close the menu, returning to the pre- vious menu, or returning to the emulated system in the case of the main menu (theres usually an item at the bottom of the menu for the same purpose). For gamepad-style controllers, the left analog thumb stick and direc- tional pad usually control UI navigation. Depending on the controller, the right analog thumb stick, triggers and additional buttons may auto- matically be assigned to UI inputs. Check the User Interface input as- signments menu to see how controls are assigned. If you want to be able to use MAME with a game controller without need- ing a keyboard, youll need to assign joystick buttons (or combinations of buttons) to these controls as well: • Show/Hide Menu to show or hide the menu during emulation • UI Back to close menus • UI Cancel to return to the system selection menu or exit MAME • UI Clear isnt essential for basic emulation, but its used to clear or reset some settings to defaults • UI Home, UI End, UI Page Up, UI Page Down, UI Previous Group and UI Next Group are not essential, but make navigating some menus easier If youre not using an external front-end to launch systems in MAME, you should assign joystick buttons (or combinations of buttons) to these controls to make full use of the system and software selection menus: • UI Focus Next/UI Focus Previous to navigate between panes • UI Add/Remove favorite, UI Export List and UI Audit Media if you want access to these features without using a keyboard or pointing device Using a mouse or trackball MAME supports navigating menus using a mouse or trackball that works as a system pointing device: • Click menu items to highlight them. • Double-click menu items to select them. • Click the left- or right-pointing triangle to adjust settings. • For menus or text boxes with too many items or lines to fit on the screen, press on the upward- or downward-pointing triangle at the top or bottom to scroll up or down. • Use vertical scrolling gestures to scroll menus or text boxes with too many items or lines to fit on the screen. • Click toolbar items to select them, or hover over them to see a de- scription. If you have enough additional mouse buttons, you may want to assign button combinations to the Show/Hide Menu, Pause, UI Back and/or UI Cancel inputs to make it possible to use MAME without a keyboard. Using a touch screen MAME has basic support for navigating menus using a touch screen: • Tap menu items to highlight them. • Double-tap menu items to select them. • Swipe left or right (horizontally) on the highlighted menu item to adjust the setting if applicable. • Swipe up or down (vertically) to scroll menus or text boxes with too many items to fit on the screen. • For menus or text boxes with too many items or lines to fit on the screen, press on the upward- or downward-pointing triangle at the top or bottom to scroll up or down. Note that for SDL-based MAME, the enable_touch option must be switched on to use touch screen support. Configuring inputs MAME needs a flexible input system to support the control schemes of the vast array of systems it emulates. In MAME, inputs that only have two distinct states, on and off or active and inactive, are called dig- ital inputs, and all other inputs are called analog inputs, even if this is not strictly true (for example multi-position switches are called analog inputs in MAME). To assign MAMEs user interface controls or the default inputs for all systems, select Input Settings from the main menu during emulation and then select Input Assignments (general) from the Input Settings menu, or select General Settings from the system selection menu and then se- lect Input Assignments from the General Settings menu. From there, se- lect a category. To assign inputs for the currently running system, select Input Set- tings from the main menu during emulation and then select Input Assign- ments (this system) from the Input Settings menu. Inputs are grouped by device and sorted by type. You can move between devices with the next group and previous group keys/buttons (opening/closing brackets [ and ] on the keyboard by default). The input assignment menus show the name of the emulated input or user interface control on the left, and the controls (or combination of con- trols) assigned to it on the right. To adjust the sensitivity, auto-centre speed and inversion settings, or to see how emulated analog controls react to your inputs, select Input Settings from the main menu during emulation, and then select Analog Input Adjustments from the Input Settings Menu (this item only appears on the Input Settings menu for systems with analog controls). Digital input settings Each emulated digital input has a single assignment setting. For flex- ibility, MAME can combine controls (keys, buttons and joystick axes) using logical and, not and or operations. This is best illustrated with some examples: Kbd 1 In this simple case, pressing the 1 key on the keyboard acti- vates the emulated input or user interface control. Kbd Down or Joy 1 Down Pressing the down arrow on the keyboard or moving the first joy- stick down activates the emulated input or user interface con- trol. Kbd P not Kbd Shift not Kbd Right Shift Pressing the P key on the keyboard while not pressing either Shift key activates the emulated input or user interface con- trol. MAME does not show the implicit and operations. Kbd P Kbd Shift or Kbd P Kbd Right Shift Pressing the P key while also pressing either of the Shift keys activates the emulated input or user interface control. Once again, the implicit and operations are not shown. (In technical terms, MAME uses Boolean sum of products logic to combine inputs.) When a digital input setting is highlighted, the prompt below the menu shows whether selecting it will replace the current assignment or ap- pend an or operation to it. Press UI Left/Right before selecting the setting to switch between replacing the assignment or appending an or operation to it. Press UI Clear (Delete or Forward Delete by default) to clear the highlighted setting, or restore the default assignment if it is currently cleared. When you select a digital input setting, MAME will wait for you to en- ter an input or a combination of inputs for a logical and operation: • Press a key or button or move an analog control once to add it to the and operation. • Press a key or button or move an analog control twice to add a not item to the and operation. Pressing the same key or button or moving the same analog control additional times toggles the not on and off. • Press UI Cancel (Escape by default) to leave the setting unchanged. • The new setting is shown below the menu. Wait one second after acti- vating an input to accept the new setting. Heres how to produce some example settings: Kbd 1 Press the 1 key on the keyboard once, then wait one second to accept the setting. Kbd F12 Kbd Shift Keyboard Alt Press the F12 key on the keyboard once, press the left Shift key once, press the left Alt key once, then wait one second to ac- cept the setting. Kbd P not Kbd Shift not Kbd Right Shift Press the P key on the keyboard once, press the left Shift key twice, press the right Shift key twice, then wait one second to accept the setting. Analog input settings Each emulated analog input has three assignment settings: • Use the axis setting to assign an analog axis to control the emulated analog input. The axis setting uses the name of the input with the suffix Analog. For example the axis setting for the steering wheel in Ridge Racer is called Steering Wheel Analog. • Use the increment setting assign a control (or combination of con- trols) to increase the value of the emulated analog input. The in- crement setting uses the name of the input with the suffix Analog Inc. For example the increment setting for the steering wheel in Ridge Racer is called Steering Wheel Analog Inc. This is a digital input setting if an analog axis is assigned to it, MAME will not in- crease the emulated input value at a proportional speed. • Use the decrement setting assign a control (or combination of con- trols) to decrease the value of the emulated analog input. The decrement setting uses the name of the input with the suffix Analog Dec. For example the decrement setting for the steering wheel in Ridge Racer is called Steering Wheel Analog Dec. This is a digital input setting if an analog axis is assigned to it, MAME will not de- crease the emulated input value at a proportional speed. The increment and decrement settings are most useful for controlling an emulated analog input using digital controls (for example keyboard keys, joystick buttons, or a directional pad). They are configured in the same way as emulated digital inputs (see above). Its important that you dont assign the same control to the axis setting as well as the increment and/or decrement settings for the same emulated input at the same time. For example if you assign Ridge Racers Steering Wheel Analog setting to the X axis of the left analog stick on your con- troller, you should not assign either the Steering Wheel Analog Inc or Steering Wheel Analog Dec setting to the X axis of the same analog stick. You can assign one or more analog axes to the axis setting for an emu- lated analog input. When multiple axes are assigned to an axis set- ting, they will be added together, but absolute position controls will override relative position controls. For example suppose for Arkanoid you assign the Dial Analog axis setting to Mouse X or Joy 1 LSX or Joy 1 RSX on a mouse and Xbox-style controller. You will be able to control the paddle with the mouse or either analog stick, but the mouse will only take effect if both analog sticks are in the neutral position (centred) on the X axis. If either analog stick is not centred on the X axis, the mouse will have no effect, because a mouse is a relative position control while joysticks are absolute position controls. For absolute position controls like joysticks and pedals, MAME allows you to assign either the full range of an axis or the range on one side of the neutral position (a half axis) to an axis setting. Assigning a half axis is usually used for pedals or other absolute inputs where the neutral position is at one end of the input range. For example suppose for Ridge Racer you assign the Brake Pedal Analog setting to the por- tion of a vertical joystick axis below the neutral position. If the joystick is at or above the neutral position vertically, the brake pedal will be released; if the joystick is below the neutral position vertically, the brake pedal will be applied proportionally. Half axes are displayed as the name of the axis followed by a plus or minus sign (+ or -). Plus refers to the portion of the axis below or to the right of the neutral position; minus refers to the portion of the axis above or to the left of the neutral position. For pedal or analog trigger controls, the active range is treated as being above the neutral posi- tion (the half axis indicated by a minus sign). When keys or buttons are assigned to an axis setting, they condition- ally enable analog controls assigned to the setting. This can be used in conjunction with an absolute position control to create a sticky control. Here are some examples of some possible axis setting assignments, as- suming an Xbox-style controller and a mouse are used: Joy 1 RSY Use vertical movement of the right analog stick to control the emulated input. Mouse X or Joy 1 LT or Joy 1 RT Reverse Use horizontal mouse movement, or the left and right triggers to control the emulated input. The right trigger is reversed so it acts in the opposite direction to the left trigger. Joy 1 LB Joy 1 LSX Use horizontal movement of the left analog stick to control the emulated input, but only while holding the left shoulder button. If the left shoulder button is released while the left analog stick is not centred horizontally, the emulated input will hold its value until the left shoulder button is pressed again (a sticky control). not Joy 1 RB Joy 1 RSX or Joy 1 RB Joy 1 RSX Reverse Use horizontal movement of the right analog stick to control the emulated input, but invert the control if the right shoulder button is held. When you select an axis setting, MAME will wait for you to enter an in- put: • Move an analog control to assign it to the axis setting. • Press a key or button (or a combination of keys or buttons) before moving an analog control to conditionally enable the analog control. • When appending to a setting, if the last assigned control is an ab- solute position control, move the same control again to cycle between the full range of the axis, the portion of the axis on either side of the neutral position, and the full range of the axis reversed. • When appending to a setting, if the last assigned control is a rela- tive position control, move the same control again to toggle revers- ing the direction of the control on or off. • When appending to a setting, move an analog control other than the last assigned control or press a key or button to add an or opera- tion. • Pressing UI Cancel (Escape by default) leaves the setting unchanged. • The new setting is shown below the menu. Wait one second after mov- ing an analog control to accept the new setting. To adjust sensitivity, auto-centring speed and inversion settings for emulated analog inputs, or to see how they respond to controls with your settings, select Input Settings from the main menu during emula- tion, and then select Analog Input Adjustments from the Input Settings Menu. Settings for emulated analog inputs are grouped by device and sorted by type. You can move between devices with the next group and previous group keys/buttons (opening/closing brackets [ and ] on the keyboard by default). The state of the emulated analog inputs is shown below the menu, and reacts in real time. Press the On Screen Display key or button (the backtick/tilde key by default on a US ANSI QWERTY keyboard) to hide the menu to make it easier to test without changing settings. Press the same key or button to show the menu again. Each emulated input has four settings on the Analog Controls menu: • The increment/decrement speed setting controls how fast the input value increases or decreases in response to the controls assigned to the increment/decrement settings. • The auto-centering speed setting controls how fast the input value returns to the neutral state when the controls assigned to the incre- ment/decrement settings are released. Setting it to zero (0) will result in the value not automatically returning to the neutral posi- tion. • The reverse setting allows the direction of the emulated inputs re- sponse to controls to be inverted. This applies to controls assigned to the axis setting and the increment/decrement settings. • The sensitivity setting adjusts the input values response to the con- trol assigned to the axis setting. Use the UI left/right keys or buttons to adjust the highlighted set- ting. Selecting a setting or pressing the UI clear key/button (Forward Delete by default) restores its default value. The units for the increment/decrement speed, auto-centering speed and sensitivity settings are tied to the driver/device implementation. The increment/decrement speed and auto-centering speed settings are also tied to the frame rate of the first emulated screen in the system. The response to controls assigned to the increment/decrement settings will change if the system changes the frame rate of this screen. The system and software selection menus If you start MAME without specifying a system on the command line, the system selection menu will be shown (assuming the ui option is set to cabinet). The system selection menu is also shown if you select Select New System from the main menu during emulation. Selecting a system that uses software lists shows the similar software selection menu. The system and software selection menus have the following parts: • The heading area at the top, showing the emulator name and version, the number of systems or software items in the menu, and the current search text. The software selection menu also shows the name of the selected system. • The toolbar immediately below the heading area. The exact toolbar buttons shown depend on the menu. Hover the mouse pointer over a button to see a description. Click a button to select it. Toolbar buttons are add/remove highlighted system/software from favourites (star), export displayed list to file (diskette), audit media (magnifying glass), show info viewer (i emblazoned on blue cir- cle), return to previous menu (bent arrow on blue), and exit (cross on red). • The list of systems or software in the centre. For the system selec- tion menu, there are configuration options below the list of systems. Clones are shown with a different text colour (grey by default). You can right-click a system name as a shortcut to show the System Set- tings menu for the system. Systems or software items are sorted by full name or description, keeping clones immediately below their parents. This may appear con- fusing if your filter settings cause a parent system or software item to be hidden while one or more of its clones are visible. • The info panel at the bottom, showing summary information about the highlighted system or software. The background colour changes de- pending on the emulation status: green for working, amber for imper- fectly emulated features or known issues, or red for more serious is- sues. A yellow star is show at the top left of the info panel if the high- lighted system or software is in your favourites list. • The collapsible list of filter options on the left. Click a filter to apply it to the list of systems/software. Some filters show a menu with additional options (e.g. specifying the manufacturer for the Manufacturer filter, or specifying a file and group for the Cate- gory filter). Click Unfiltered to display all items. Click Custom Filter to com- bine multiple filters. Click the strip between the list of filters and the list of systems/software to show or hide the list of filters. Be aware that filters still apply when the list of filters is hidden. • The collapsible info viewer on the right. This has two tabs for showing images and information. Click a tab to switch tabs; click the left- or right-facing triangles next to the image/info title to switch between images or information sources. Emulation information is automatically shown for systems, and infor- mation from the software list is shown for software items. Addi- tional information from external files can be shown using the Data plugin. You can type to search the displayed list of systems or software. Sys- tems are searched by full name, manufacturer and full name, and short name. If you are using localised system names, phonetic names will also be searched if present. Software items are searched by descrip- tion, alternate titles (alt_title info elements in the software lists), and short name. UI Cancel (Escape by default) will clear the search if currently searching. Navigation controls In addition to the usual menu navigation controls, the system and soft- ware selection menus have additional configurable controls for navigat- ing the multi-pane layout, and providing alternatives to toolbar but- tons if you dont want to use a pointing device. The default additional controls (with a US ANSI QWERTY keyboard), and the settings they corre- spond to, are: Tab (UI Focus Next) Move focus to the next area. The order is system/software list, configuration options (if visible), filter list (if visible), info/image tabs (if visible), info/image source (if visible). Shift+Tab (UI Focus Previous) Move focus to the previous area. Alt+D (UI External DAT View) Show the full-size info viewer. Alt+F (UI Add/Remove favorite) Add or remove the highlighted system or software item from the favourites list. F1 (UI Audit Media) Audit ROMs and/or disk images for systems. The results are saved for use with the Available and Unavailable filters. When focus is on the filter list, you can use the menu navigation con- trols (up, down, home and end) to highlight a filter, and UI Select (Return/Enter by default) apply it. When focus is on any area besides the info/image tabs, you can change the image or info source with left/right. When focus is on the info/image tabs, left/right switch between tabs. When focus is on the image/info tabs or source, you can scroll the info using up, down, page up, page down, home and end. You can move focus to an area by clicking on it with the middle mouse button. The simple system selection menu If you start MAME without specifying a system on the command line (or choose Select New System from the main menu during emulation) with the ui option set to simple, the simple system selection menu will be shown. The simple system selection menu shows fifteen randomly se- lected systems that have ROM sets present in your configured ROM folder(s). You can type to search for a system. Clearing the search causes fifteen systems to be randomly selected again. The info panel below the menu shows summary information about the high- lighted system. The background colour changes depending on the emula- tion status: green for working, amber for imperfectly emulated features or known issues, or red for more serious issues. Default Keyboard Controls • Controls Foreword • MAME User Interface Controls • System and software selection menus • Default Arcade Machine Controls • Default Arcade Game Controls • Player 1 Controls • Player 2 Controls • Player 3 Controls • Player 4 Controls • Default Mahjong and Hanafuda Keys • Default Gambling Keys • Default Blackjack Keys • Default Poker Keys • Default Slots Keys • Default Computer Keys • Other Machines Controls Foreword MAME supports a vast array of different types of machines, with a sig- nificantly different array of inputs across them. This means that some keyboard keys, mouse buttons, and joystick buttons will be used for multiple functions. As a result, the control charts below are separated by machine-types to make it easier to find what youre looking for. All of the controls below are fully configurable in the user interface. These charts show the default configuration. Note that the defaults shown here are arranged by US ANSI key position- ing. If you are using a different layout, the keys will vary. MAME User Interface Controls The controls here cover MAME functions such as MAMEs menus, machine pause, and saving/loading save states. Tab Toggles the configuration menu. `/~ (backtick/tilde key) Toggles the On-Screen Display. If you are running with -debug, this key sends a break in emula- tion. When a slider control is visible, you can use the following keys to control it: • Up - select previous parameter to modify. • Down - select next parameter to modify. • Left - decrease the value of the selected parameter. • Right - increase the value of the selected parameter. • Enter - reset parameter value to its default. • Control+Left - decrease the value by 10x. • Shift+Left - decrease the value by 0.1x. • Alt+Left - decrease the value by the smallest amount. • Control+Right - increase the value by 10x. • Shift+Right - increase the value by 0.1x. • Alt+Right - increase the value by the smallest amount. • End - temporarily hide the On Screen Display. • Home - bring the On Screen Display back after hiding it. Up Arrow Highlight previous UI menu option. Down Arrow Highlight next UI menu option. Left Arrow Change current UI option setting when an arrow is present on it. Right Arrow Change current UI option setting when an arrow is present on it. Home/End Highlight first or last UI menu option. [ ] Move to previous or next group in UI menus that support it (e.g. move to the inputs for the previous or next device in the Input Assignments (this System) menu). Enter/Joystick 1 Button 1 Select currently highlighted UI menu option. Space Show comment on currently highlighted UI menu option. Delete Clear/reset to default when highlighting an entry on the input configuration, cheat options, and plugin options pages. F1 Power the machine on for machines that have specific power but- ton behavior. F2 Power the machine off for machines that have specific power but- ton behavior. F3 Soft resets the machine. Left Shift+F3 Performs a hard reset, which tears everything down and re-cre- ates it from scratch. This is a more thorough and complete reset than the reset you get from hitting F3. F4 Shows the game palette, decoded graphics tiles/characters and any tilemaps. Use the Enter key to switch between the three modes (palette, graphics, and tilemaps). Press F4 again to turn off the display. The key controls in each mode vary slightly: Palette/colortable mode: • [ ] - switch between palette devices. • Up/Down - scroll up/down one line at a time. • Page Up/Page Down - scroll up/down one page at a time. • Home/End - move to top/bottom of list. • -/+ - increase/decrease the number of colors per row. • 0 - restore the default number of colors per row. • Enter - switch to graphics viewer. Graphics mode: • [ ] - switch between different graphics sets. • Up/Down - scroll up/down one line at a time. • Page Up/Page Down - scroll up/down one page at a time. • Home/End - move to top/bottom of list. • Left/Right - change color displayed. • R - rotate tiles 90 degrees clockwise. • -/+ - increase/decrease the number of tiles per row (hold Shift to restrict to integer scale factors). • 0 - restore the default number of tiles per row (hold Shift to restrict to integer scale factors). • Enter - switch to tilemap viewer. Tilemap mode: • [ ] - switch between different tilemaps. • Up/Down/Left/Right - scroll 8 pixels at a time. • Shift+Up/Down/Left/Right - scroll 1 pixel at a time. • Control+Up/Down/Left/Right - scroll 64 pixels at a time. • R - rotate tilemap view 90 degrees clockwise. • -/+ - decrease/increase the zoom factor. • 0 - expand small tilemaps to fill the display. • Enter - switch to palette/colortable mode. Note: Not all systems have decoded graphics and/or tilemaps. Left Shift+F4 While paused, loads the most recent rewind save state. F5 Pauses the emulated machine. Left Shift+F5 While paused, advances to next frame. If rewind is enabled, a new rewind save state is also captured. F6 Create a save state. Requires an additional keypress to identify the state, similar to the load option above. If an existing save state is present, it will also appear in the selection menu to allow overwriting of that save state. Left Shift+F6 Create a quick save state. F7 Load a save state. You will be prompted to press a key or select from the menu to determine which save state you wish to load. Note that the save state feature is not supported for a large number of drivers. If a given driver is not known to work per- fectly, you will receive a warning that the save state may not be valid when attempting to save or load. Left Shift+F7 Load a quick save state. F8 Decrease frame skipping on the fly. Left Shift+F8 Toggle cheat mode. (if started with -cheat) Left Alt+F8 Decrease Prescaling. (SDL MAME only) F9 Increase frame skipping on the fly. Left Alt+F9 Increase Prescaling. (SDL MAME only) F10 Toggle speed throttling. Left Alt+F10 Toggle HLSL Post-Processing. (Windows non-SDL MAME only) Left Alt+F10 Toggle Filter. (SDL MAME only) F11 Toggles speed display. Left Shift+F11 Toggles internal profiler display (if compiled in). Left Alt+F11 Record HLSL Rendered Video. F12 Saves a screen snapshot. Left Shift+F12 Begin recording MNG video. Left Control+Left Shift+F12 Begin recording AVI video. Left Alt+F12 Take HLSL Rendered Snapshot. Insert (Windows non-SDL MAME)/Page Down (SDL MAME) Fast forward. While held, runs game with throttling disabled and with the maximum frameskip. Left Alt+Enter Toggles between full-screen and windowed mode. Scroll Lock/Forward Delete (Mac Desktop)/fn-Delete (Mac Laptop) Default mapping for the uimodekey. This key toggles MAMEs response to user interface keys such as the (by default) Tab key being used for menus. All emulated ma- chines which require emulated keyboards will start with UI con- trols disabled by default and you can only access the internal UI by first hitting this uimodekey key. You can change the ini- tial status of the emulated keyboard as presented upon start by using -uimodekey Escape Exit emulator, return to the previous menu, or cancel the cur- rent UI option. System and software selection menus The system and software selection menus use additional controls Tab Moves keyboard/controller focus to the next UI panel. Shift+Tab Moves keyboard/controller focus to the previous UI panel. Left Alt+F Adds or removes the selected system or software list item from the favorites list. Left Alt+E Exports the currently displayed list of systems. Left Alt+D Shows the full-size info viewer if info is available for the se- lected system or software list item. (Shows information loaded by the data plugin from external files, including history.xml and mameinfo.dat.) F1 Audits system ROMs and disk images. Default Arcade Machine Controls This section covers controls that are applicable to most kinds of ar- cade machines. Note that not all machines will have all of these con- trols. All the controls below are fully configurable in the user in- terface. This list shows the standard keyboard configuration. 5 (not numeric keypad) Coin slot 1 6 (not numeric keypad) Coin slot 2 7 (not numeric keypad) Coin slot 3 8 (not numeric keypad) Coin slot 4 Backspace Bill 1 (For machines that have a bill receptor/note reader) T Tilt Usually a tilt switch or shock sensor that will end the current game, reset credits and/or reset the machine if the machine is knocked excessively hard or moved. Most commonly found on pin- ball machines. - (not numeric keypad) Volume Down For machines that have an electronic volume control. = (not numeric keypad) Volume Up For machines that have an electronic volume control. F1 Memory Reset This resets high scores, credits/winnings, statistics, and/or operator settings on machines that support it. F2 Service Mode This is a momentary push-button on some machines, while it is a toggle switch or DIP switch on others. 9 (not numeric keypad) Service 1 Service buttons are typically used to give free credits or to navigate the operator service menus. 0 (not numeric keypad) Service 2 - (not numeric keypad) Service 3 = (not numeric keypad) Service 4 Default Arcade Game Controls This section covers controls for arcade games using common joy- stick/button control schemes. All the controls below are fully config- urable in the user interface. This list shows the standard keyboard configuration. 5 (not numeric keypad) Coin slot 1 6 (not numeric keypad) Coin slot 2 7 (not numeric keypad) Coin slot 3 8 (not numeric keypad) Coin slot 4 1 (not numeric keypad) Player 1 start or 1 player mode 2 (not numeric keypad) Player 2 start or 2 players mode 3 (not numeric keypad) Player 3 start or 3 players mode 4 (not numeric keypad) Player 4 start or 4 players mode Player 1 Controls Up Arrow Player 1 Up Down Arrow Player 1 Down Left Arrow Player 1 Left Right Arrow Player 1 Right E Player 1 Up on Left Stick for dual-stick machines (e.g. Robot- ron) D Player 1 Down on Left Stick for dual-stick machines (e.g. Robot- ron) S Player 1 Left on Left Stick for dual-stick machines (e.g. Robot- ron) F Player 1 Right on Left Stick for dual-stick machines (e.g. Ro- botron) I Player 1 Up on Right Stick for dual-stick machines (e.g. Robot- ron) K Player 1 Down on Right Stick for dual-stick machines (e.g. Ro- botron) J Player 1 Left on Right Stick for dual-stick machines (e.g. Ro- botron) L Player 1 Right on Right Stick for dual-stick machines (e.g. Ro- botron) Left Ctrl/Mouse B0/Gun 1 Button 0 Player 1 Button 1 Left Alt/Mouse B2/Gun 1 Button 1 Player 1 Button 2 Spacebar/Mouse B1/Joystick 1 Button 1 or B Player 1 Button 3 Left Shift Player 1 Button 4 Z Player 1 Button 5 X Player 1 Button 6 C Player 1 Button 7 V Player 1 Button 8 B Player 1 Button 9 N Player 1 Button 10 M Player 1 Button 11 , Player 1 Button 12 . Player 1 Button 13 / Player 1 Button 14 Right Shift Player 1 Button 15 Player 2 Controls R Player 2 Up F Player 2 Down D Player 2 Left G Player 2 Right A Player 2 Button 1 S Player 2 Button 2 Q Player 2 Button 3 W Player 2 Button 4 E Player 2 Button 5 Player 3 Controls I Player 3 Up K Player 3 Down J Player 3 Left L Player 3 Right Right Control Player 3 Button 1 Right Shift Player 3 Button 2 Enter (not numeric keypad) Player 3 Button 3 Player 4 Controls 8 (on numeric keypad) Player 4 Up 2 (on numeric keypad) Player 4 Down 4 (on numeric keypad) Player 4 Left 6 (on numeric keypad) Player 4 Right 0 (on numeric keypad) Player 4 Button 1 . (on numeric keypad) Player 4 Button 2 Enter (on numeric keypad) Player 4 Button 3 Default Mahjong and Hanafuda Keys Most mahjong and hanafuda games use a standard control panel layout. Some keys may not be present, depending on the kind of game. For exam- ple games without a bonus game feature may lack the Take Score, Double Up, Big and Small keys, and games without gambling features may also lack the Bet key. Some games may not use all keys that are present. For example many games do not use the Flip Flop and Last Chance keys. [image: Standard mahjong control panel layout] [image] Due to the large number of keys, MAME only provides default input con- figuration for a single set of player controls. For multi-player mahjong/hanafuda games, or mahjong/hanafuda games with multiple player positions, manual configuration is required. All the keys below are fully configurable in the user interface. This list shows the standard keyboard configuration. 5 (not numeric keypad) Coin slot 1 6 (not numeric keypad) Coin slot 2 7 (not numeric keypad) Coin slot 3 8 (not numeric keypad) Coin slot 4 Y Player 1 Mahjong/Hanafuda Flip Flop 1 (not numeric keypad) Player 1 start or 1 player mode 2 (not numeric keypad) Player 2 start or 2 players mode 3 (not numeric keypad) Player 3 start or 3 players mode Mahjong Bet 4 (not numeric keypad) Player 4 start or 4 players mode Right Ctrl Player 1 Mahjong/Hanafuda Take Score Right Shift Player 1 Mahjong/Hanafuda Double Up Enter Player 1 Mahjong/Hanafuda Big Backspace Player 1 Mahjong/Hanafuda Small Right Alt Player 1 Mahjong/Hanafuda Last Chance Ctrl Mahjong Kan Alt Mahjong Pon Spacebar Mahjong Chi Shift Mahjong Reach Z Mahjong Ron A Player 1 Mahjong/Hanafuda A B Player 1 Mahjong/Hanafuda B C Player 1 Mahjong/Hanafuda C D Player 1 Mahjong/Hanafuda D E Player 1 Mahjong/Hanafuda E F Player 1 Mahjong/Hanafuda F G Player 1 Mahjong/Hanafuda G H Player 1 Mahjong/Hanafuda H I Player 1 Mahjong I J Player 1 Mahjong J K Player 1 Mahjong K L Player 1 Mahjong L M Player 1 Mahjong M Player 1 Hanafuda Yes N Player 1 Mahjong N Player 1 Hanafuda No O Player 1 Taiwanese Mahjong O Semicolon Player 1 Taiwanese Mahjong P Q Player 1 Taiwanese Mahjong Q Default Gambling Keys All the keys below are fully configurable in the user interface. This list shows the standard keyboard configuration. Note that many gambling games use buttons for multiple functions. For example a slots game may use the Start button to stop all reels, lack- ing a dedicated Stop All Reels button, or a poker game may use the hold buttons to control the double-up bonus game, lacking dedicated Take Score, Double Up, High and Low buttons. 5 Coin slot 1 6 Coin slot 2 7 Coin slot 3 8 Coin slot 4 Backspace Bill 1 (For machines that have a bill receptor/note reader) I Payout Q Key In W Key Out F1 Memory Reset 9 (not numeric keypad) Service 1 (Service buttons are typically used to give free cred- its or to navigate the internal operator service menus) 0 (not numeric keypad) Service 2 Book-Keeping (for machines that have this functional- ity) - (not numeric keypad) Service 3 = (not numeric keypad) Service 4 M Bet 1 (not numeric keypad) Player 1 start or 1 player mode 2 (not numeric keypad) Deal L Stand 4 (not numeric keypad) Take Score For games that allow gambling winnings in a double-or-nothing bonus game, this takes the winnings from the main game. 3 (not numeric keypad) Double Up For games that allow gambling winnings in a double-or-nothing bonus game, this gambles the winnings from the main game in the bonus game. D Half Gamble Used by games that allow gambling half or all of the winnings from the main game in the bonus game. A High S Low O Door Default Blackjack Keys All the keys below are fully configurable in the user interface. This list shows the standard keyboard configuration. 1 Player 1 start or 1 player mode Used to deal a new hand for games that have separate buttons to deal a new hand and draw an additional card. 2 Deal (hit) Used to draw an additional card, and to deal a new hand in games that dont use separate buttons to deal a new hand and draw an additional card. L Stand Default Poker Keys All the keys below are fully configurable in the user interface. This list shows the standard keyboard configuration. 1 Player 1 start or 1 player mode Used to deal a new hand for games that have separate buttons to deal a new hand and draw replacement cards. 2 Deal Used to draw replacement cards, and to deal a new hand in games that dont use separate buttons to deal a new hand and draw re- placement cards. Z Hold 1/discard 1 X Hold 2/discard 2 C Hold 3/discard 3 V Hold 4/discard 4 B Hold 5/discard 5 N Cancel Used by some games to cancel current selection for cards to hold/discard. Default Slots Keys All the keys below are fully configurable in the user interface. This list shows the standard keyboard configuration. 1 Player 1 start or 1 player mode X Stop Reel 1 C Stop Reel 2 V Stop Reel 3 B Stop Reel 4 Z Stop All Reels Default Computer Keys All the keys below are fully configurable in the user interface. This list shows the standard keyboard configuration. Note that controls can vary widely by computer type, so not all keys are shown here. See the Input Assignments (this system) section of MAMEs Input Settings menu for details for the machine you are currently using. Tab Toggles the configuration menu. Scroll Lock/Forward Delete (Mac Desktop)/fn-Delete (Mac Laptop) Default mapping for the uimodekey. This key toggles MAMEs response to user interface keys such as the (by default) Tab key being used for menus. All emulated ma- chines which require emulated keyboards will start with UI con- trols disabled by default and you can only access the internal UI by first hitting this uimodekey key. You can change the ini- tial status of the emulated keyboard as presented upon start by using -uimodekey F2 Start tape for machines that have cassette tape drives. Shift+F2 Stop tape for machines that have cassette tape drives. Left Shift+Scroll Lock Pastes from system clipboard into the emulated machine. Alphanumeric Keys These keys are mapped to their equivalents in the emulated ma- chine by default. Other Machines All the keys are fully configurable in the user interface. Note that controls can vary widely by machine type, so default keys are not shown here and defaults will vary considerably based on the manu- facturer and style. See the Input Assignments (this system) section of MAMEs Input Settings menu for details for the machine you are currently using. MAME Menus • Introduction • Main menu • Input Settings menu • Toggle Inputs menu • Keyboard Selection menu • Input Devices menu Introduction To show the main menu while running an emulated system in MAME, press the Show/Hide Menu key or button (Tab by default). If the emulated system has keyboard inputs, you may need to press the Toggle UI Con- trols key or button (Scroll Lock, or Forward Delete on macOS, by de- fault) to enable user interface controls first. You can dismiss a menu by pressing the UI Back key or button (Escape by default). Dismissing a menu will return to its parent menu, or to the running system in the case of the main menu. You can hide a menu and return to the running system by pressing the Show/Hide Menu key or button. Pressing the Show/Hide Menu key or but- ton again will jump back to the same menu. This is useful when testing changes to settings. Emulated system inputs are ignored while menus are displayed. You can still pause or resume the running system while most menus are displayed by pressing the Pause key or button (F5 on the keyboard by default). If you start MAME without specifying a system on the command line, the system selection menu will be shown (assuming the ui option is set to cabinet). The system selection menu is also shown if you select Select New System from the main menu during emulation. For more information on navigating menus, see the relevant section. Main menu The main menu is shown when you press the Show/Hide Menu key or button while running an emulated system or while the system information screen is displayed. It provides access to menus used to change settings, control various features, and show information about the running system and MAME itself. If you press the Show/Hide Menu key or button to show the main menu while the system information screen is displayed, the emulated system will not start until the main menu is dismissed (either by selecting Start System, pressing the UI Back key or button, or pressing the Show/Hide Menu key or button). This can be useful for mounting media images or changing DIP switches and machine configuration settings be- fore the emulated system starts. Input Settings Shows the Input Settings menu, where you can assign controls to emulated inputs, adjust analog control settings, control toggle inputs, and test input devices. DIP Switches Shows the DIP Switches menu, where configuration switches for the running system can be changed. This item is not shown if the running system has no DIP switches. Machine Configuration Shows the Machine Configuration menu, where various settings specific to the emulated system can be changed. This item is not shown if the running system has no configuration settings. Bookkeeping Shows uptime, coin counter and ticket dispenser statistics (if relevant) for the running system. System Information Shows information about the running system as emulated in MAME, including CPU, sound and video devices. Warning Information Shows information about imperfectly emulated features of the running system. This item is not shown if there are no relevant warnings. Media Image Information Shows information about mounted media images (if any). This item is only shown if the running system has one or more media devices (e.g. floppy disk drives or memory card slots). File Manager Shows the File Manager menu, where you can mount new or existing media image files, or unmount currently mounted media images. This item is only shown if the running system has one or more media devices (e.g. floppy disk drives or memory card slots). Tape Control Shows the Tape Control menu, where you can control emulated cas- sette tape mechanisms. This item is only shown for systems that use cassette tape media. Pseudo Terminals Shows the status of any pseudo terminal devices in the running system (used to connect the emulated system to host pseudo ter- minals, for example via emulated serial ports). This item is not shown if there are no pseudo terminal devices in the running system. BIOS Selection Shows the BIOS Selection menu, where you can select the BIOS/boot ROM/firmware for the system and slot cards it con- tains. This item is not shown if no BIOS options are available. Slot Devices Shows the Slot Devices menu, where you can choose between emu- lated peripherals. This item is not shown for systems that have no slot devices. Barcode Reader Shows the Barcode Reader menu, where you can simulate scanning barcodes with emulated barcode readers. This item is not shown if there are no barcode readers in the running system. Network Devices Shows the Network Devices menu, where you can set up emulated network adapters that support bridging to a host network. This item is not shown if there are no network adaptors that support bridging in the running system. Slider Controls Shows the Slider Controls menu, where you can adjust various settings, including video adjustments and individual sound chan- nel levels. Video Options Shows the Video Options menu, where you can change the view for each screen/window, as well as for screenshots. Crosshair Options Shows the Crosshair Options menu, where you can adjust the ap- pearance of crosshairs used to show the location of emulated light guns and other absolute pointer inputs. This item is not shown if the emulated system has no absolute pointer inputs. Cheat Shows the Cheat menu, for controlling the built-in cheat engine. This item is only shown if the built-in chat engine is enabled. Note that the cheat plugins menu is accessed via the Plugin Op- tions menu. Plugin Options Shows the Plugin Options menu, where you can access settings for enabled plugins. This item is not shown if no plugins are en- abled, or if the main menu is shown before the emulated system starts (by pressing the Show/Hide Menu key/button while the sys- tem information screen is displayed). External DAT View Shows the info viewer, which displays information loaded from various external support files. This item is not shown if the data plugin is not enabled, or if the main menu is shown before the emulated system starts (by pressing the Show/Hide Menu key/button while the system information screen is displayed). Add To Favorites/Remove From Favorites Adds the running system to the favourites list, or removes it if its already in the favourites list. The favourites list can be used as a filter for the system selection menu. About MAME Shows the emulator version, data model, and copyright license information. Select New System Shows the system selection menu, where you can select a system to start a new emulation session. This item is not shown if the main menu is shown before the emulated system starts (by press- ing the Show/Hide Menu key/button while the system information screen is displayed). Close Menu/Start System Closes the main menu, returning control of the running system. Shows Start System if the main menu is shown before the emulated system starts (by pressing the Show/Hide Menu key/button while the system information screen is displayed). Input Settings menu The Input Settings provides options for assigning controls to emulated inputs, adjusting analog control settings, controlling toggle inputs, and testing input devices. You can reach the Input Settings menu by selecting Input Settings from the main menu. The items shown on this menu depend on available emulated inputs for the running system. Available emulated inputs may depend on slot options, machine configu- ration settings and DIP switch settings. Input Assignments (this system) Lets you select assign controls to emulated inputs for the run- ning system. See the section on configuring inputs for more de- tails. This item is not shown if the running system has no en- abled inputs that can be assigned controls. Analog Input Adjustments Shows the Analog Input Adjustments menu, where you can adjust sensitivity, auto-centring speed and inversion settings for emu- lated analog inputs, and see how the emulated analog inputs re- spond to controls with your settings. For more details, see the analog input settings section for more details. This item is not shown if the running system has no enabled analog inputs. Keyboard Selection Shows the Keyboard Selection menu, where you can select between emulated and natural keyboard modes, and enable and disable key- board and keypad inputs for individual emulated devices. This item is not shown if the running system has no keyboard or key- pad inputs. Toggle Inputs Shows the Toggle Inputs menu, where you can view and adjust the state of multi-position or toggle inputs. This item is not shown if the running system has no enabled toggle inputs. Input Assignments (general) Lets you select assign user interface controls, or assign de- fault controls for all emulated systems. See the section on configuring inputs for more details. Input Devices Shows the Input Devices menu, which lists the input devices recognised by MAME. Toggle Inputs menu The Toggle Inputs menu shows the current state of multi-position or toggle inputs. Common examples include mechanically locking Caps Lock keys on computers, and two-position gear shit levers on driving games. You can reach the Toggle Inputs menu by selecting Toggle Inputs from the Input Settings menu. Note that available emulated inputs may de- pend on slot options, machine configuration settings and DIP switch settings. Inputs are grouped by the emulated device they belong to. You can move between devices using the Next Group and Previous Group keys or but- tons. Names of inputs are shown on the left, and the current settings are shown on the right. To change the state of an input, highlight it and use the UI Left and UI Right keys or buttons, or click the arrows beside the current set- ting. Keyboard Selection menu The Keyboard Selection menu lets your switch between emulated and nat- ural keyboard modes, and enable or disable keyboard inputs for individ- ual emulated devices. You can reach the Keyboard Selection menu by se- lecting Keyboard Selection from the Input Settings menu. In emulated keyboard mode, keyboard and keypad inputs behave like any other digital inputs, responding to their assigned controls. In nat- ural keyboard mode, MAME attempts to translate typed characters to emu- lated keystrokes. The initial keyboard mode is set using the natural option. There are a number of unavoidable limitations in natural keyboard mode: • The emulated system must to support it. • The selected keyboard must match the keyboard layout selected in the emulated software. • Keystrokes that dont produce characters cant be translated. (e.g. pressing a modifier key on its own, such as Shift or Control). • Holding a key until the character repeats will cause the emulated key to be pressed repeatedly as opposed to being held down. • Dead key sequences are cumbersome to use at best. • Complex input methods will not work at all (e.g. for Chinese/Japan- ese/Korean). Each emulated device in the system that has keyboard and/or keypad in- puts is listed on the menu, allowing keyboard/keypad inputs to be en- abled or disabled for individual devices. By default, keyboard/keypad inputs are enabled for the first device with keyboard inputs (if any), and for all other devices that have keypad inputs but no keyboard in- puts. The enabled keyboard/keypad inputs are automatically saved to the configuration file for the system when the emulation session ends. Input Devices menu The Input Devices menu lists input devices recognised by MAME and en- abled with your current settings. Recognised input devices depend on the keyboardprovider, mouseprovider, lightgunprovider and joystickprovider options. Classes of input devices can be enabled or disabled using the mouse, lightgun and joystick options. You can reach the Input Devices menu by selecting Input Devices from the Input Set- tings menu or the General Settings menu. Input devices are grouped by device class (for example keyboards or light guns). You can move between device classes using the Next Group and Previous Group keys or buttons. For each device, the device number (within its class) is shown on the left, and the name is shown on the right. Select a device to show the supported controls for the device. The name of each control is displayed on the left and its current state is shown on the right. When an analog axis control is highlighted, its state is also shown in graphical form below the menu. Digital control states are either zero (inactive) or one (active). Analog axis input states range from -65,536 to 65,536 with the neutral position at zero. You can also select Copy Device ID to copy the devices ID to the clip- board. This is useful for setting up stable controller IDs in controller configuration files. How does MAME look for files? • Introduction • Terminology • Search path options • Archive files • How does MAME search for media? • System ROMs • Device ROMs • Software Item ROMs • CHD format disk images • Loose software • Diagnosing missing media Introduction Unlike typical desktop applications where you browse your disk and se- lect a file to open or a location to save to, MAME has settings to tell it where to look for the files it needs. You can change these settings by starting MAME without specifying a system, selecting Configure Op- tions from the system selection menu, and then selecting Configure Di- rectories (remember to select Save Configuration if you want to keep your changes). You can also change settings by editing your mame.ini and ui.ini files directly, or specify settings on the command line. For information on available options for controlling where MAME searches for files, see Core Search Path Options. Terminology Its necessary to understand some MAME-specific terminology used in the explanations here: System A system is a complete machine that can be emulated by MAME. Some systems run fixed software, while others can load software from software list items and/or media files. Device An emulated component that can be used by multiple systems, or by other devices. Some devices require ROM dumps, and some de- vices allow software from additional software lists to be used with a system. Parent system MAME uses so-called parent/clone relationships to group related systems. One system in the group is chosen to be the parent and the others are called clones. (The choice of the parent system is somewhat arbitrary. It is not necessarily the original or definitive variant.) BIOS system A system configured with no software. This is mostly applicable for arcade systems that used interchangeable game cartridges or ROM boards. Note that this is not the same as the BIOS selec- tion settings that allow you to select system boot ROMs or de- vice firmware. Software item A software package described in a software list. Software items may consist of multiple parts that can be mounted independently. Due to the large variety of media supported by MAME, software parts may use different loaders. These include the ROM loader, typically used for cartridge media, and the image file loader, used for software parts consisting of a single media image (in- cluding floppy disk and cassette media). Parent software item Related software items are grouped using parent/clone relation- ships, in a similar way to related systems. This is usually used to group different versions or releases of the same piece of software. If a software item has a parent item, it will al- ways be in the same software list. Short name MAME uses short names to uniquely identify systems and devices, to uniquely identify software lists, to uniquely identify soft- ware items within a software list, and to uniquely identify software parts within a software item. You can see the short name for a system by highlighting it in the system selection menu, ensuring the info panel is visible on the right, and showing the General Info in the Infos tab. For example the short name for the Nintendo Virtual Boy is vboy. System and device short names can also be seen in the output of various command line verbs, including -listxml, -listfull, -listroms and -listcrc. You can see the short names for a software item and the software list it belongs to by highlighting it in the software selection menu, ensuring the info panel is visible on the right, and show- ing the Software List Info in the Infos tab. For example the short name for Macintosh System Software 6.0.3 is sys603 and the short name of the software list it belongs to is mac_flop. Software list short names match their file names (for example the Sega Mega Drive/Genesis cartridge software list is called megadriv.xml and its short name is megadriv). You can also see the short names software lists, software items and parts by finding the name attributes in the XML software list files. Search path options Most options for specifying locations to search allow multiple directo- ries to be specified, separated by semicolon (;) characters. Environ- ment variables are expanded, using CMD shell syntax on Windows, or Bourne shell syntax on UNIX-like systems. Relative paths are interpreted relative to the current working direc- tory at the time of use. If you start MAME by double-clicking it in Windows Explorer, the working directory is set to the folder containing the MAME executable. If you start MAME by double-clicking it in the macOS Finder or from most Linux desktop environments, the working di- rectory will be set to your home directory. Archive files MAME can load files from PKZIP and 7-Zip archives (these must have .zip and .7z file name extensions, respectively). A number of extensions to the PKZIP format are supported, including Zip64 for large archives, NTFS timestamps, and LZMA compression. Only ASCII or UTF-8 filenames are supported in PKZIP archives (7-Zip archives always use UTF-16 file- names). MAME does not load files from nested archives. MAME will not load files stored in a PKZIP or 7-Zip archive which is itself contained within a PKZIP or 7-Zip archive. Multi-segment archives and encrypted archives are not supported. The legacy implode compression method in PKZIP archives is not supported. MAME may perform poorly with archives containing large numbers of files. Files compressed using the LZMA compression algorithm are in- herently more CPU-intensive to decompress than files compressed using simpler algorithms. MAME does not take the archive layout into consid- eration when loading files from archives, so using solid compression often results in MAME decompressing the same data repeatedly when load- ing media. How does MAME search for media? Use the rompath option sets the folders where searches for ROM dumps, disk images, and other media. By default MAME looks for media in a folder called roms in the working directory. For the purpose of this discussion, floppy disk, cassette, paper tape and other media images that are not stored in CHD format are treated as ROM dumps. When searching for system, device and software ROM dumps, MAME treats folders and archives inside the folders configured in you rompath set- ting as equivalent, but remember the limitation that MAME cannot load files from an archive contained within another archive. MAME looks for a folder first, then a PKZIP archive, and finally a 7-Zip archive. When searching for a ROM dump in an archive, MAME first looks for a file with the expected name and CRC. If no matching file is found, MAME looks for a file with the expected CRC ignoring the name. If no matching file is found, MAME finally looks for a file with the expected name, ignoring the CRC. While MAME can load disk images in CHD format from inside archives, this is not recommended. CHD files contain compressed data stored in a format allowing random access. If a CHD format disk image is stored in a PKZIP or 7-Zip archive, MAME needs to load the entire file into mem- ory in order to use it. For hard disk or LaserDisc images in particu- lar, this will likely use an excessive amount of swap file space, hurt- ing performance and possibly reducing the life expectancy of your disks or SSDs. Its best to keep CHD format disk images in folders. System ROMs For each folder configured in your rompath setting, MAME looks for sys- tem ROMs in the following locations: • A folder or archive matching the short name of the system itself. • A folder or archive matching the short name of the systems parent system, if applicable. • A folder or archive matching the short name of the corresponding BIOS system, if applicable. Using Shiritsu Justice Gakuen as an example, MAME will search for sys- tem ROMs as follows: • The short name of the system is jgakuen, so MAME will look for a folder called jgakuen, a PKZIP archive called jgakuen.zip, or a 7-Zip archive called jgakuen.7z. • The parent system is the European version of Rival Schools, which has the short name rvschool, so MAME will look for a folder called rvschool, a PKZIP archive called rvschool.zip, or a 7-Zip archive called rvschool.7z. • The corresponding BIOS system is the Capcom ZN2 board, which has the short name coh3002c, so MAME will look for a folder called coh3002c, a PKZIP archive called coh3002c.zip, or a 7-Zip archive called coh3002c.7z. Device ROMs For each folder configured in your rompath setting, MAME looks for de- vice ROMs in the following locations: • A folder or archive matching the short name of the device. • A folder or archive matching the short name of the devices parent ROM device, if applicable. • A folder or archive matching the short name of the system. • A folder or archive matching the short name of the systems parent system, if applicable. • A folder or archive matching the short name of the corresponding BIOS system, if applicable. Using a Unitron 1024 Macintosh clone with a French Macintosh Plus key- board with integrated numeric keypad attached as an example, MAME will look for the keyboard microcontroller ROM as follows: • The short name of the French Macintosh Plus keyboard is mackbd_m0110a_f, so MAME will look for a folder called mackbd_m0110a_f, a PKZIP archive called mackbd_m0110a_f.zip, or a 7-Zip archive called mackbd_m0110a_f.7z. • The parent ROM device is the U.S. Macintosh Plus keyboard with inte- grated numeric keypad, which has the short name mackbd_m0110a, so MAME will look for a folder called mackbd_m0110a, a PKZIP archive called mackbd_m0110a.zip, or a 7-Zip archive called mackbd_m0110a.7z. • The short name of the Unitron 1024 system is utrn1024, so MAME will look for a folder called utrn1024, a PKZIP archive called utrn1024.zip, or a 7-Zip archive called utrn1024.7z. • The parent system of the Unitron 1024 is the Macintosh Plus, which has the short name macplus, so MAME will look for a folder called macplus, a PKZIP archive called macplus.zip, or a 7-Zip archive called macplus.7z. • There is no corresponding BIOS system, so MAME will not search in any further locations. Software Item ROMs For each folder configured in your rompath setting, MAME looks for software item ROMs in the following locations: • A folder or archive matching the short name of the software item in- side a folder matching the short name of the software list (or a folder matching the short name of the software item inside an archive matching the name of the software list). • A folder or archive matching the short name of the parent software item inside a folder matching the short name of the software list, if applicable (or a folder matching the short name of the parent soft- ware item in an archive matching the name of the software list). • A folder or archive matching the short name of the software item. (This is for convenience for software items that also run as stand-alone systems with the same short name, such as Neo Geo games.) • A folder or archive matching the short name of the parent software item, if applicable. (This is for convenience for software items that also run as stand-alone systems with the same short name, such as Neo Geo games.) If you load the German version of Dune II from the Mega Drive/Genesis cartridge software list in the PAL Mega Drive console, MAME will look for the cartridge ROM as follows: • The short name of the software item for the German version of Dune II is dune2g and the short name of the Mega Drive/Genesis cartridge software list is megadriv, so MAME will look for a folder called dune2g, a PKZIP archive called dune2g.zip or a 7-Zip archive called dune2g.7z inside a folder called megadriv (or a folder called dune2g inside a PKZIP archive called megadriv.zip or a 7-Zip archive called megadriv.7z). • The parent software item is the general European PAL version of Dune II in the same software list, which has the short name dune2, so MAME will look for a folder called dune2, a PKZIP archive called dune2.zip or a 7-Zip archive called dune2.7z inside a folder called megadriv (or a folder called dune2 inside a PKZIP archive called megadriv.zip or a 7-Zip archive called megadriv.7z). • Next MAME will ignore the short name of the software list and use the short name of the software item only, looking for a folder called dune2g, a PKZIP archive called dune2g.zip or a 7-Zip archive called dune2g.7z. • Still ignoring the short name of the software list, MAME will use the short name of the parent software item only, looking for a folder called dune2, a PKZIP archive called dune2.zip or a 7-Zip archive called dune2.7z. CHD format disk images MAME searches for system, device and software item CHD format disk im- ages in almost the same way it searches for ROMs, with just a few dif- ferences: • For systems and software items, MAME will check the parent system or software item if applicable for alternate names for a disk image with the same content digest. This allows you to keep a single copy of a CHD format disk image for a parent system or software item and any clones that expect a disk image with the same content, irrespective of the name the clones expect. • For software items, MAME will look for CHD format disk images in a folder matching the short name of the software list. This is for convenience when all items in a software list only contain a single CHD format disk image each. • We recommend that you do not store CHD format disk images inside PKZIP or 7-Zip archives. However, if you do decide to do this, MAME will only find CHD format disk images inside archives with an ex- pected name. This is because MAME uses the content digest from the CHD header, not the checksum of the CHD file itself. The checksum of the CHD file itself can vary depending on compression options. To save space, MAME allows delta CHD files to be used for clone sys- tems, devices with parent ROM devices and clone software items. The delta CHD file must use a CHD format disk image from the parent system, parent ROM device or parent software item as its parent CHD file. The space saved depends on how much content can be reused from the parent CHD file. MAME searches the same locations for parent CHD files that it would search for the disk image itself. Loose software Many systems support loading media from a file by supplying the path on the command line for one of the media options. Relative paths are in- terpreted relative to the current working directory. You can specify a path to a file inside a PKZIP or 7-Zip archive simi- larly to specifying a path to a file in a folder (keep in mind that you can have at most a single archive file in a path, as MAME does not sup- port loading files from archives contained within other archives). If you specify a path to a PKZIP or 7-Zip archive, MAME will use the first file found in the archive (this depends on the order that files are stored in the archive its most useful for archives containing a single file). Start the Nintendo Entertainment System/Famicom system with the file amazon_diet_EN.nes mounted in the cartridge slot: mame nes -cart amazon_diet_EN.nes Start the Osborne-1 system with the first file in the archive os1xutls.zip mounted in the first floppy disk drive: mame osborne1 -flop1 os1xutils.zip Start the Macintosh Plus system with the file system tools.img in the archive sys603.zip mounted in the first floppy disk drive: mame macplus -flop1 "sys603.zip/system tools.img" Diagnosing missing media When starting a system from MAMEs system selection menu or software se- lection menu, MAME will list any missing system or device ROM dumps or disk images, as long as at least one ROM dump or disk image for the system is present. For clone systems, at least one ROM dump or disk image unique to the clone must be present for MAME to list missing ROM dumps and disk images. If all system and device ROM dump and disk images are present and the system is being started with a software item, MAME will check that ROM dumps and disk images for the software item are present. If at least one ROM dump or disk image for the software item is present, MAME will list any missing ROM dumps or disk images. For example if you try to start the Macintosh Plus system and the key- board microcontroller ROM dump is missing, MAME displays the following error message: Required ROM/disk images for the selected system are missing or in- correct. Please acquire the correct files or select a different system. 341-0332-a.bin (mackbd_m0110a) - not found Press any key to continue. The name of the missing ROM dump is shown (341-0332-a.bin), as well as the short name of the device it belongs to (mackbd_m0110a). When a missing ROM dump or disk image is not specific to the selected system, the short name of the system or device it belongs to is shown. If you start a system in MAME from a command prompt, MAME will show where it searched for any ROM dumps or disk images that were not found. Using the example of a Unitron 1024 Macintosh clone with a French key- board connected, MAME will show the following error messages if no ROMs are present: mame utrn1024 -kbd frp 342-0341-a.u6d NOT FOUND (tried in utrn1024 macplus) 342-0342-a.u8d NOT FOUND (tried in utrn1024 macplus) 341-0332-a.bin NOT FOUND (tried in mackbd_m0110a_f mackbd_m0110a utrn1024 macplus) MAME used the system short name utrn1024 and the parent system short name macplus when searching for system ROMs. When searching for the keyboard microcontroller ROM, MAME used the device short name mackbd_m0110a_f, the parent ROM device short name mackbd_m0110a, the system short name utrn1024, and the parent system short name macplus. Software parts that use the ROM loader (typically cartridge media) show similar messages when ROM dumps are not found. Using the example of the German version of Dune II on a PAL Mega Drive, MAME will show the following error messages if no ROMs are present: mame megadriv dune2g mpr-16838-f.u1 NOT FOUND (tried in megadriv\dune2g megadriv\dune2 dune2g dune2 megadriv genesis) Fatal error: Required files are missing, the machine cannot be run. MAME searched for the cartridge ROM using: • The software list short name megadriv and the software item short name dune2g. • The software list short name megadriv and the parent software item short name dune2. • The software item short name dune2g only. • The parent software item short name dune2 only. • The locations that would be searched for the PAL Mega Drive system (the system short name megadriv and the parent system short name gen- esis). Software parts that use the image file loader (including floppy disk and cassette media) only check for media after ROM images are loaded, and missing media files are shown differently. Using the example of Macintosh System 6.0.3, MAME will show these error messages if the software is missing: mame macplus -flop1 sys603:flop1 :fdc:0:35dd: error opening image file system tools.img: No such file or directory (generic:2) (tried in mac_flop\sys603 sys603 macplus) Fatal error: Device Apple/Sony 3.5 DD (400/800K GCR) load (-floppydisk1 sys603:flop1) failed: No such file or directory The error messages show where MAME searched for the image file in the same format. In this case, it used the software list short name mac_flop and the software short name sys603, the software short name sys603 only, and the locations that would be searched for system ROMs. Front-ends A number of third party tools for MAME to make system and software se- lection simpler are available. These tools are called front-ends, and there are far too many to list exhaustively here. Some are free, some are commercial caveat emptor. Some older front-ends predate the merg- ing of MAME and MESS and do not support the additional console, hand-held, and computer functionality inherited from MESS. This following list is not an endorsement of any of these front-ends by the MAME team. It simply shows a number of commonly used free front-ends to provide a starting point. QMC2 (multiple platforms) Provides a graphical interface for configuring many of MAMEs settings and features. Also includes ROM management and media auditing features. Written in C++ using the Qt toolkit, the source code is on SourceForge. Negatron (multiple platforms) Negatron emphasises features for configuring emulated computers and consoles. Written in Java, the source code is on GitHub. BletchMAME (multiple platforms) BletchMAME takes advantage of MAMEs Lua scripting interface to integrate tightly and effectively replace MAMEs internal user interface. It has many useful features for home computer emula- tion. Written in C++, the source code is on GitHub. IV/Play (Microsoft Windows) A simple Windows program for launching systems in MAME. Written in C#, the source code is on GitHub. Emu Loader (Microsoft Windows) Emu Loader provides a Windows interface for launching systems in multiple emulators, including MAME, Supermodel and DEMUL. Writ- ten in Delphi Pascal, the source code is available on the down- load page. Retrofire (Japanese, Microsoft Windows) Provides a Japanese-language graphical interface for launching systems or software in MAME. The MAME team will not provide support for issues with front-ends. For support, we suggest contacting the front-end author or asking on one of the popular MAME-friendly forums on the Internet. About ROMs and Sets Handling and updating of ROMs and Sets used in MAME is probably the biggest area of confusion and frustration that MAME users will run into. This section aims to clear up a lot of the most common questions and cover simple details you'll need to know to use MAME effectively. Let's start with a simple definition of what a ROM is. What is a ROM image? For arcade games, a ROM image or file is a copy of all of the data in- side a given chip on the arcade motherboard. For most consoles and handhelds, the individual chips are frequently (but not always) merged into a single file. As arcade machines are much more complicated in their design, you'll typically need the data from a number of different chips on the board. Grouping all of the files from Puckman together will get you a ROM set of Puckman. An example ROM image would be the file pm1_prg1.6e stored in the Puck- man ROM set. Why ROM and not some other name? ROM stands for Read-Only Memory. The chips used to store the game data were not rewritable and were permanent (as long as the chip wasn't dam- aged or aged to death!) As such, a copy of the data necessary to reconstitute and replace a dead data chip on a board became known as a "ROM image" or ROMs for short. Parents, Clones, Splitting, and Merging As the MAME developers received their third or fourth revision of Pac-Man, with bugfixes and other code changes, they quickly discovered that nearly all of the board and chips were identical to the previously dumped version. In order to save space, MAME was adjusted to use a par- ent/clone set system. A given set, usually (but not necessarily) the most recent bugfixed World revision of a game, will be designated as the parent. All sets that use mostly the same chips (e.g. Japanese Puckman and USA/World Pac-Man) will be clones that contain only the changed data compared to the parent set. This typically comes up as an error message to the user when trying to run a Clone set without having the Parent set handy. Using the above example, trying to play the USA version of Pac-Man without having the PUCKMAN.ZIP parent set will result in an error message that there are missing files. Now we add the final pieces of the puzzle: non-merged, split, and merged sets. MAME is extremely versatile about where ROM data is located and is quite intelligent about looking for what it needs. This allows us to do some magic with how we store these ROM sets to save further space. A non-merged set is one that contains absolutely everything necessary for a given game to run in one ZIP file. This is ordinarily very space-inefficient, but is a good way to go if you want to have very few sets and want everything self-contained and easy to work with. We do not recommend this for most users. A split set is one where the parent set contains all of the normal data it should, and the clone sets contain only what has changed as compared to the parent set. This saves some space, but isn't quite as efficient as A merged set takes the parent set and one or more clone sets and puts them all inside the parent set's storage. For instance, if we combine the Puckman sets, Midway Pac-Man (USA) sets, and various other related official and bootleg sets all into PUCKMAN.ZIP, the result would be a merged set. A complete merged set with the parent and all clones uses less disk space than a split set. With those basic principles, there are two other kinds of set that will come up in MAME use from time to time. First, the BIOS set: Some arcade machines shared a common hardware platform, such as the Neo-Geo arcade hardware. As the main board had data necessary to start up and self-test the hardware before passing it off to the game cartridge, it's not really appropriate to store that data as part of the game ROM sets. Instead, it is stored as a BIOS im- age for the system itself (e.g. NEOGEO.ZIP for Neo-Geo games) Secondly, the device set. Frequently the arcade manufacturers would reuse pieces of their designs multiple times in order to save on costs and time. Some of these smaller circuits would reappear in later boards that had minimal common ground with the previous boards that used the circuit, so you couldn't just have them share the circuit/ROM data through a normal parent/clone relationship. Instead, these re-used de- signs and ROM data are categorized as a Device, with the data stored as a Device set. For instance, Namco used the Namco 51xx custom I/O chip to handle the joystick and DIP switches for Galaga and other games, and as such you'll also need the NAMCO51.ZIP device set as well as any needed for the game. Troubleshooting your ROM sets and the history of ROMs A lot of the frustration users feel towards MAME can be directly tied to what may feel like pointless ROM changes that seem to only serve to make life more difficult for end-users. Understanding the source of these changes and why they are necessary will help you to avoid being blindsided by change and to know what you need to do to keep your sets running. A large chunk of arcade ROMs and sets existed before emulation did. These early sets were created by arcade owners and used to repair bro- ken boards by replacing damaged chips. Unfortunately, these sets even- tually proved to be missing critical information. Many of the early dumps missed a new type of chip that contained, for instance, color palette information for the screen. The earliest emulators approximated colors until the authors discovered the existence of these missing chips. This resulted in a need to go back and get the missing data and update the sets to add the new dumps as needed. It wouldn't be much longer before it would be discovered that many of the existing sets had bad data for one or more chips. These, too, would need to be re-dumped, and many sets would need complete overhauls. Occasionally games would be discovered to be completely wrongly docu- mented. Some games thought to be legitimate ended up being bootleg copies from pirate manufacturers. Some games thought to be bootlegs ended up being legit. Some games were completely mistaken as to which region the board was actually from (e.g. World as compared to Japan) and this too would require adjustments and renaming. Even now, occasional miracle finds occur that change our understanding of these games. As accurate documentation is critical to detailing the history of the arcades, MAME will change sets as needed to keep things as accurate as possible within what the team knows at the time of each release. This results in very spotty compatibility for ROM sets designated for older versions of MAME. Some games may not have changed much within 20-30 revisions of MAME, and others may have drastically changed multi- ple times. If you hit problems with a set not working, there are several things to check-- are you trying to run a set meant for an older version of MAME? Do you have any necessary BIOS or Device ROMs? Is this a Clone set that would need to have the Parent as well? MAME will tell you what files are missing as well as where it looked for these files. Use that to de- termine which set(s) may be missing files. ROMs and CHDs ROM chip data tends to be relatively small and are loaded into system memory in their entirety. Some games also used additional storage me- dia such as hard disks, CD-ROMs, DVDs, and LaserDiscs. Those storage media are, for multiple technical reasons, not well-suited to being stored the same way as ROM data and wont fully fit in memory in some cases. Thus, a new format was created for these in the CHD file. Compressed Hunks of Data files, or CHD files for short, are designed very specifi- cally around the needs of mass storage media. Some arcade games, con- soles, and PCs will require one or more CHD files to run. As CHD files are already compressed, they should not be stored PKZIP or 7-Zip archives as ROM images would be. To save space when multiple variants of a system or software item are present, MAME supports delta CHD files. A delta CHD file only stores the parts of the data that differ from its parent CHD file. This al- lows large space savings when different variants share a lot of data. Delta CHD files can only be used for clone systems, devices with a par- ent ROM device, and clone software items. A delta CHD file must use a (non-delta) CHD file from the parent system, parent ROM device or par- ent software item as its parent CHD file. The parent CHD file must be present to use a delta CHD file, or MAME will not be able to read the shared data from it. Common Issues and Questions (FAQ) Disclaimer: The following information is not legal advice and was not written by a lawyer. 1. Why does my game show an error screen if I insert coins rapidly? 2. Why is my non-official MAME package (e.g. EmuCR build) broken? Why is my official update broken? 3. Why does MAME support console games and dumb terminals? Wouldn't it be faster if MAME had just the arcade games? Wouldn't it take less RAM? Wouldn't MAME be faster if you just X? 4. Why do my Neo Geo ROMs no longer work? How do I get the Humble Bun- dle Neo Geo sets working? 5. How can I use the Sega Genesis & Mega Drive Classics collection from Steam with MAME? 6. Why does MAME report "missing files" even if I have the ROMs? 7. How can I be sure I have the right ROMs? 8. Why is it that some games have the US version as the main set, some have Japanese, and some are the World? 9. How do I legally obtain ROMs or disk images to run on MAME? 10. Isn't copying ROMs a legal gray area? 11. Can't game ROMs be considered abandonware? 12. I had ROMs that worked with an old version of MAME and now they don't. What happened? 13. What about those arcade cabinets on eBay that come with all the ROMs? 14. What about those guys who burn DVDs of ROMs for the price of the media? 15. But isn't there a special DMCA exemption that makes ROM copying le- gal? 16. But isn't it OK to download and "try" ROMs for 24 hours? 17. If I buy a cabinet with legitimate ROMs, can I set it up in a pub- lic place to make money? 18. But I've seen Ultracade and Global VR Classics cabinets out in pub- lic places? Why can they do it? 19. HELP! I'm getting a black screen or an error message in regards to DirectX on Windows! 20. I have a controller that doesn't want to work with the standard Mi- crosoft Windows version of MAME, what can I do? 21. What happened to the MAME support for external OPL2-carrying sound- cards? 22. What happened to the MAME support for autofire? 23. Does MAME support G-Sync or FreeSync? How do I configure MAME to use them? Why does my game show an error screen if I insert coins rapidly? This is not a bug in MAME. On original arcade hardware, you simply could not insert coins as fast as you can mash the button. The only ways you could feed credits at that kind of pace was if the coin mech hardware was defective or if you were physically trying to cheat the coin mech. In either case, the game would display an error for the operator to look into the situation to prevent cheating them out of their hard-earned cash. Keep a slow, coin-insert-ish pace and you wont trig- ger this. Why is my non-official MAME package (e.g. EmuCR build) broken? Why is my official update broken? Many MAME features, such as software lists, HLSL or BGFX shaders, Lua plugins and UI translations, use external files. Updates to these fea- tures often require the external files to be updated along with MAME. Unfortunately, builds provided by third parties may only include the main MAME executable, or may include outdated external files. Using an updated MAME executable with outdated external files causes issues with features reliant on the external files. Despite repeated requests that they distribute MAME complete with matching external files, some of these third parties persist in distributing incomplete or broken MAME updates. As we have no control over how third parties distribute MAME, all we really can do is recommend against obtaining MAME from sites like EmuCR. We cannot provide any support for packages we didnt build our- selves. You can completely avoid these issues by compiling MAME your- self, or using an official package we provide. You may also encounter this problem if you do not update the contents of the hlsl, bgfx or plugins folders when updating your MAME installa- tion with a new official build. Why does MAME support console games and dumb terminals? Wouldn't it be faster if MAME had just the arcade games? Wouldn't it take less RAM? Wouldn't MAME be faster if you just X? This is a common misconception. The actual size of the MAME file doesn't affect the speed of it; only the parts that are actively being used are in memory at any given time. In truth, the additional supported devices are a good thing for MAME as they allow us to stress test sections of the various CPU cores and other parts of the emulation that don't normally see heavy utilization. While a computer and an arcade machine may use the exact same CPU, how they use that CPU can differ pretty dramatically. No part of MAME is a second-class citizen to any other part. Video poker machines are just as important to document and preserve as arcade games. There's still room for improvements in MAME's speed, but chances are that if you're not already a skilled programmer any ideas you have will have already been covered. Don't let that discourage you-- MAME is open source, and improvements are always welcome. Why do my Neo Geo ROMs no longer work? How do I get the Humble Bundle Neo Geo sets working? Recently the Neo Geo BIOS was updated to add a new version of the Uni- verse BIOS. This was done between 0.171 and 0.172, and results in an error trying to load Neo Geo games with an un-updated neogeo.zip set. This also affects the Humble Bundle set: the games themselves are cor- rect and up to date as of MAME 0.173 (and most likely will remain so) though you'll have to pull the ROM set .ZIP files out of the package somehow yourself. However, the Neo Geo BIOS set (neogeo.zip) included in the Humble Bundle set is incomplete as of the 0.172 release of MAME. We suggest you contact the provider of your sets (Humble Bundle and DotEmu) and ask them to update their content to the newest revision. If enough people ask nicely, maybe they'll update the package. How can I use the Sega Genesis & Mega Drive Classics collection from Steam with MAME? As of the April 2016 update to the program, the ROM images included in the set are now 100% compatible with MAME and other Genesis/Mega Drive emulators. The ROMs are contained in the steamapps\Sega Classics\uncom- pressed ROMs folder as a series of .68K and .SGD images that can be loaded directly into MAME. PDF manuals for the games can be found in steamapps\Sega Classics\manuals as well. Why does MAME report "missing files" even if I have the ROMs? There can be several reasons for this: • It is not unusual for the ROMs to change for a game between releases of MAME. Why would this happen? Oftentimes, better or more complete ROM dumps are made, or errors are found in the way the ROMs were pre- viously defined. Early versions of MAME were not as meticulous about this issue, but more recent MAME builds are. Additionally, there can be more features of a game emulated in a later release of MAME than an earlier release, requiring more ROM code to run. • You may find that some games require CHD files. A CHD file is a com- pressed representation of a game's hard disk, CD-ROM, or laserdisc, and is generally not included as part of a game's ROMs. However, in most cases, these files are required to run the game, and MAME will complain if they cannot be found. • Some games such as Neo-Geo, Playchoice-10, Convertible Video System, Deco Cassette, MegaTech, MegaPlay, ST-V Titan, and others need their BIOS ROMs in addition to the game ROMs. The BIOS ROMs often contain ROM code that is used for booting the machine, menu processor code on multi-game systems, and code common to all games on a system. BIOS ROMS must be named correctly and left zipped inside your ROMs folder. • Older versions of MAME needed decryption tables in order for MAME to emulate Capcom Play System 2 (a.k.a. CPS2) games. These are created by team CPS2Shock. • Some games in MAME are considered "Clones" of another game. This is often the case when the game in question is simply an alternate ver- sion of the same game. Common alternate versions of games include versions with text in other languages, versions with different copy- right dates, later versions or updates, bootlegs, etc. "Cloned" games often overlap some of the ROM code as the original or "parent" ver- sion of the game. To see if you have any "clones" type "MAME -list- clones". To run a "cloned game" you simply need to place its parent ROM file in your ROMs folder (leave it zipped). How can I be sure I have the right ROMs? MAME checks to be sure you have the right ROMs before emulation begins. If you see any error messages, your ROMs are not those tested to work properly with MAME. You will need to obtain a correct set of ROMs through legal methods. If you have several games and you wish to verify that they are compati- ble with the current version of MAME, you can use the -verifyroms para- meter. For example: mame -verifyroms robby ...checks your ROMs for the game Robby Roto and displays the results on the screen. mame -verifyroms * >verify.txt ...checks the validity of ALL the ROMs in your ROMS directory, and writes the results to a textfile called verify.txt. Why is it that some games have the US version as the main set, some have Japanese, and some are the World? Parent and clone sets are a convenience feature to help keep different versions of the same system or software together. The decision on which set to make the parent will always be somewhat arbitrary, but we do have some guidelines: • Prefer latest release version • Prefer English language • Prefer most widespread release • Prefer most complete version • Prefer versions that are uncensored, and have story/cutscenes intact • Prefer versions that keep the original gameplay balance • Prefer releases from original developers/publishers rather than li- censees • Prefer releases without region-specific notices or warnings Its not always possible to choose a set thats preferred according to all criteria. As an example, the World release of Ghoulsn Ghosts (ghouls) is the par- ent of the US release (ghoulsu) and the Japanese original Daimakaimura, as it is the most widespread English-language release, and has the story and cutscenes intact. Another example is Midway Pac-Man (pacman), which is a clone of Namco Puck Man (puckman), because Pac-Man is a licensed version for the US market, while Puck Man was released by Namco themselves. How do I legally obtain ROMs or disk images to run on MAME? You have several options: • You can obtain a license to them by purchasing one via a distributor or vendor who has proper authority to do so. • You can download one of the ROM sets that have been released for free to the public for non-commercial use. • You can purchase an actual arcade PCB, read the ROMs or disks your- self, and let MAME use that data. Beyond these options, you are on your own. Isn't copying ROMs a legal gray area? No, its not. You are not permitted to make copies of software without the copyright owners permission. This is a black and white issue. Can't game ROMs be considered abandonware? No. Even the companies that went under had their assets purchased by somebody, and that person is the copyright owner. I had ROMs that worked with an old version of MAME and now they don't. What happened? As time passes, MAME is perfecting the emulation of older games, even when the results aren't immediately obvious to the user. Often times the better emulation requires more data from the original game to oper- ate. Sometimes the data was overlooked, sometimes it simply wasn't fea- sible to get at it (for instance, chip "decapping" is a technique that only became affordable very recently for people not working in high-end laboratories). In other cases it's much simpler: more sets of a game were dumped and it was decided to change which sets were which version. What about those arcade cabinets on eBay that come with all the ROMs? If the seller does not have a proper license to include the ROMs with their system, they are not legally permitted to include any ROMs with the system. If they have purchased a license to the ROMs in your name from a distributor or vendor with legitimate licenses, then they may include the ROMs with the cabinet. After signing an agreement, cabinet owners that include legitimate licensed ROMs may be permitted to in- clude a version of MAME that runs those ROMs and nothing more. What about those guys who burn DVDs of ROMs for the price of the media? What they are doing is just as unlawful as selling the ROMs outright. As long as somebody holds the copyright, making unauthorised copies is unlawful. If someone went on the internet and started a business of selling cheap copies of U2 albums for the price of media, do you think they would get away with it? Even worse, a lot of these people like to claim that they are helping the project. In reality, they only create more problems for the MAME team. We are not associated with these people in any way, regardless of how official they may attempt to appear. By buying from them, you only help criminals profit from selling software they have no right to sell. Anyone using the MAME name and/or logo to sell such products is also in violation of the MAME trademark. But isn't there a special DMCA exemption that makes ROM copying legal? No, you have misread the exemptions. The exemption allows people to reverse-engineer the copy protection or encryption in computer programs that are obsolete. The exemption simply means that figuring out how these obsolete programs worked is not illegal according to the DMCA. It does not have any effect on the legality of making unauthorised copies of computer programs, which is what you are doing if you make copies of ROMs. But isn't it OK to download and "try" ROMs for 24 hours? This is an urban legend that was made up by people who made ROMs avail- able for download from their web sites, in order to justify the fact that they were breaking the law. There is no provision like this in any copyright law. If I buy a cabinet with legitimate ROMs, can I set it up in a public place to make money? Probably not. ROMs are typically only licensed for personal, non-com- mercial purposes. But I've seen Ultracade and Global VR Classics cabinets out in public places? Why can they do it? Ultracade had two separate products. The Ultracade product is a commer- cial machine with commercial licenses to the games. These machines were designed to be put on location and make money, like traditional arcade machines. Their other product is the Arcade Legends series. These are home machines with non- commercial licenses for the games, and can only be legally operated in a private environment. Since their buyout by Global VR they only offer the Global VR Classics cabinet, which is equivalent to the earlier Ultracade product. HELP! I'm getting a black screen or an error message in regards to DirectX on Windows! You probably have missing or damaged DirectX runtimes. You can download the latest DirectX setup tool from Microsoft at https://www.microsoft.com/en-us/download/details.aspx?displaylang=en&id=35 Additional troubleshooting information can be found on Microsoft's web- site at https://support.microsoft.com/en-us/kb/179113 I have a controller that doesn't want to work with the standard Microsoft Windows version of MAME, what can I do? By default, MAME on Microsoft Windows tries to read joystick(s), mouse/mice and keyboard(s) using the RawInput API. This works with most devices, and allows multiple keyboards and mice to be used inde- pendently. However, some device drivers are not compatible with RawIn- put, and it may be necessary to use DirectInput or window events to re- ceive input. This is also the case for most software that simulates mouse or keyboard input, like JoyToKey, VNC or Remote Desktop. You can try changing the keyboardprovider, mouseprovider, joystickprovider or lightgunprovider setting (depending on which kind of device youre having issues with) from rawinput to one of the other options such as dinput or win32. See OSD-related Options for details on input provider options What happened to the MAME support for external OPL2-carrying soundcards? MAME 0.23 added support for using a sound cards onboard OPL2 (Yamaha YM3812 chip) instead of emulating the OPL2. This feature was only sup- ported for DOS it was never supported in official Windows versions of MAME. It dropped entirely as of MAME 0.60, as the OPL2 emulation in MAME had become advanced enough to be a better solution in almost all cases. MAMEs OPL2 emulation is now superior to using a sound cards YM3812 in all cases, especially as modern sound cards lack a YM3812. What happened to the MAME support for autofire? A Lua plugin providing enhanced autofire support was added in MAME 0.210, and the built-in autofire functionality was removed in MAME 0.216. This plugin has more functionality than the built-in autofire feature it replaced; for example, you can configure alternate buttons for different autofire rates. You can enable and configure the new autofire system with the following steps: • Start MAME with no system selected. • Choose Configure Options at the bottom (use Tab to move focus, or double-click the menu item). • Choose Plugins near the bottom of the Settings menu. • Turn Autofire plugin on (use Left/Right or click the arrows to change options). • Exit MAME completely and start MAME again so the setting takes ef- fect. The setting will be automatically saved for future use. See Autofire Plugin for more information about using the autofire plu- gin, or Plugins for more information about using plugins with MAME in general. Does MAME support G-Sync or FreeSync? How do I configure MAME to use them? MAME supports both G-Sync and FreeSync right out of the box for Windows and Linux, however macOS does not support G-Sync or FreeSync. • Make sure your monitor is capable of at least 120Hz G-Sync/FreeSync. If your monitor is only capable of 60Hz in G-Sync/FreeSync modes, you will hit problems with drivers such as Pac-Man that run at 60.60606Hz and may hit problems with others that are very close to but not quite 60Hz. • If playing MAME windowed or using the BGFX video system, you'll need to make sure that you have G-Sync/FreeSync turned on for windowed ap- plications as well as full screen in your video driver. • Be sure to leave triple buffering turned off. • Turning VSync on is suggested in general with G-Sync and FreeSync. • Low Latency Mode will not affect MAME performance with G-Sync/FreeSync. The effects of G-Sync and FreeSync will be most noticeable in drivers that run at refresh rates that are very different from normal PC re- fresh rates. For instance, the first three Mortal Kombat titles run at 54.706841Hz. MAME COMMAND-LINE USAGE AND OS-SPECIFIC CONFIGURATION Universal Command-line Options This section contains configuration options that are applicable to all MAME configurations (including both SDL and Windows native). • Commands and Verbs • Patterns • File Names and Directory Paths • Core Verbs • Configuration Verbs • Frontend Verbs • OSD-related Options • OSD Command-Line Verbs • OSD Output Options • Configuration Options • Core Search Path Options • Core Output Directory Options • Core State/Playback Options • Core Performance Options • Core Rotation Options • Core Video Options • Core Full Screen Options • Core Per-Window Options • Core Artwork Options • Core Screen Options • Core Vector Options • Core Video OpenGL Feature Options • Core Video OpenGL GLSL Options • Core Sound Options • Core Input Options • Core Input Automatic Enable Options • Debugging Options • Core Communication Options • Core Misc Options • Scripting Options • HTTP Server Options • PortAudio Options Commands and Verbs Commands include mame itself as well as various tools included with the MAME distribution such as romcmp and srcclean. Verbs are actions to take upon something with the command (e.g. mame -validate pacman has mame as a command and -validate as a verb) Patterns Many verbs support the use of patterns, which are either a system or device short name (e.g. a2600, zorba_kbd) or a glob pattern that matches either (e.g. zorba_*). Depending on the command you're using the pattern with, pattern match- ing may match systems or systems and devices. It is advised to put quotes around your patterns to avoid having your shell try to expand them against filenames (e.g. mame -validate "pac*"). File Names and Directory Paths A number of options for specifying directories support multiple paths (for example to search for ROMs in multiple locations). MAME expects multiple paths to be separated with semicolons ( ; ). MAME expands environment variable expressions in paths. The syntax used depends on your operating system. On Windows, % (percent) syntax is used. For example %APPDATA%\mame\cfg will expand the application data path for the current user's roaming profile. On UNIX-like system (including macOS and Linux), Bourne shell syntax is used, and a leading ~ expands to the current user's home directory. For example, ~/.mame/${HOSTNAME}/cfg expands to a host-specific path inside the .mame directory in the current user's home directory. Note that only simple variable substitutions are supported; more complex expressions supported by Bash, ksh or zsh are not recognized by MAME. Relative paths are resolved relative to the current working directory. If you start MAME by double-clicking it in Windows Explorer, the work- ing directory is set to the folder containing the MAME executable. If you start MAME by double-clicking it in the macOS Finder, it will open a Terminal window with the working directory is set to your home direc- tory (usually /Users/<username> ) and start MAME. If you want behaviour similar to what Windows Explorer provides on ma- cOS, create a script file containing these lines in the directory con- taining the MAME executable (for example you could call it mame-here ): #!/bin/sh cd "`dirname "$0"`" exec ./mame You should be able to use any text editor. If you have a choice of file format or line ending style, choose UNIX. This assumes you're us- ing a 64-bit release build of MAME, but if you aren't you just need to change mame to the name of your MAME executable (e.g. mamed, mamep, mamedp). Once you've created the file, you need to mark it as exe- cutable. You can do this by opening a Terminal window, typing chmod a+x followed by a space, dragging the file you created onto the window (this causes Terminal to insert the full escaped path to the file), and then ensuring the Terminal window is active and hitting Return (or En- ter) on your keyboard. You can close the Terminal window after doing this. Now if you double-click the script in the Finder, it will open a Terminal window, set the working directory to the location of the script (i.e. the folder containing MAME), and then start MAME. Core Verbs TIP: Examples that have the output abbreviated for space reasons will show "..." in the output where needed. For instance: .. code-block:: bash A B C ... Z -help / -h / -? Displays current MAME version and copyright notice. Example: mame -help -validate / -valid [<pattern>] Performs internal validation on one or more drivers and devices in the system. Run this before submitting changes to ensure that you haven't violated any of the core system rules. If a pattern is specified, it will validate systems matching the pattern, otherwise it will validate all systems and devices. Note that if a pattern is specified, it will be matched against systems only (not other devices), and no device type validation will be per- formed. Example: mame -validate Driver ace100 (file apple2.cpp): 1 errors, 0 warnings Errors: Software List device 'flop525_orig': apple2_flop_orig.xml: Errors parsing software list: apple2_flop_orig.xml(126.2): Unknown tag: year apple2_flop_orig.xml(126.8): Unexpected content apple2_flop_orig.xml(127.2): Unknown tag: publisher apple2_flop_orig.xml(127.13): Unexpected content apple2_flop_orig.xml(128.2): Unknown tag: info apple2_flop_orig.xml(129.2): Unknown tag: sharedfeat apple2_flop_orig.xml(132.2): Unknown tag: part apple2_flop_orig.xml(133.3): Tag dataarea found outside of software context apple2_flop_orig.xml(134.4): Tag rom found outside of part context apple2_flop_orig.xml(137.3): mismatched tag Configuration Verbs -createconfig / -cc Creates the default mame.ini file. All the configuration options (not verbs) described below can be permanently changed by editing this configuration file. Example: mame -createconfig -showconfig / -sc Displays the current configuration settings. If you route this to a file, you can use it as an INI file. Example: mame -showconfig > mame.ini This example is equivalent to -createconfig. -showusage / -su Displays a summary of all the command line options. For options that are not mentioned here, the short summary given by "mame -showusage" is usually a sufficient description. Frontend Verbs Note: By default, all the '-list' verbs below write info to the stan- dard output (usually the terminal/command window where you typed the command). If you wish to write the info to a text file instead, add this to the end of your command: > filename where filename is the name of the file to save the output in (e.g. list.txt ). Note that if this file already exists, it will be com- pletely overwritten. Example: mame -listcrc puckman > list.txt This creates (or overwrites the existing file if already there) list.txt and fills the file with the results of -listcrc puckman. In other words, the list of each ROM used in Puckman and the CRC for that ROM are written into that file. -listxml / -lx [<pattern>...] List comprehensive details for all of the supported systems and de- vices in XML format. The output is quite long, so it is usually better to redirect this into a file. By default all systems are listed; however, you can limit this list by specifying one or more patterns after the -listxml verb. This XML output is typically imported into other tools (like graphi- cal front-ends and ROM managers), or processed with scripts query detailed information. Example: mame galaxian -listxml <?xml version="1.0"?> <!DOCTYPE mame [ <!ELEMENT mame (machine+)> <!ATTLIST mame build CDATA #IMPLIED> <!ATTLIST mame debug (yes|no) "no"> <!ATTLIST mame mameconfig CDATA #REQUIRED> <!ELEMENT machine (description, year?, manufacturer?, biosset*, rom*, disk*, device_ref*, sample*, chip*, display*, sound?, input?, dipswitch*, configuration*, port*, adjuster*, driver?, feature*, device*, slot*, softwarelist*, ramoption*)> <!ATTLIST machine name CDATA #REQUIRED> <!ATTLIST machine sourcefile CDATA #IMPLIED> ... <mame build="0.216 (mame0216-154-gabddfb0404c-dirty)" debug="no" mameconfig="10"> <machine name="galaxian" sourcefile="galaxian.cpp"> <description>Galaxian (Namco set 1)</description> <year>1979</year> <manufacturer>Namco</manufacturer> ... <machine name="z80" sourcefile="src/devices/cpu/z80/z80.cpp" isdevice="yes" runnable="no"> <description>Zilog Z80</description> </machine> </mame> TIP: Output from this command is typically more useful if redirected to an output file. For instance, doing mame -listxml galaxian > galax.xml will make galax.xml or overwrite any existing data in the file with the results of -listxml; this will allow you to view it in a text editor or parse it with external tools. -listfull / -ll [<pattern>...] Example: mame -listfull galaxian* Name: Description: galaxian "Galaxian (Namco set 1)" galaxiana "Galaxian (Namco set 2)" galaxianbl "Galaxian (bootleg, set 2)" galaxianbl2 "Galaxian (bootleg, set 4)" galaxiani "Galaxian (Irem)" galaxianm "Galaxian (Midway set 1)" galaxianmo "Galaxian (Midway set 2)" galaxiant "Galaxian (Taito)" galaxian_sound "Galaxian Custom Sound" Displays a list of system driver names and descriptions. By default all systems and devices are listed; however, you can limit this list by specifying one or more patterns after the -listfull verb. -listsource / -ls [<pattern>...] Displays a list of system drivers/devices and the names of the source files where they are defined. Useful for finding which dri- ver a system runs on in order to fix bugs. By default all systems and devices are listed; however, you can limit this list by specify- ing one or more pattern after the -listsource verb. Example: mame galaga -listsource galaga galaga.cpp -listclones / -lc [<pattern>] Displays a list of clones. By default all clones are listed; how- ever, you can limit this list by specifying a pattern after the -listsource verb. If a pattern is specified, MAME will list clones of systems that match the pattern, as well as clones that match the pattern themselves. Example 1: mame pacman -listclones Name: Clone of: pacman puckman Example 2: mame puckman -listclones Name: Clone of: abscam puckman bucaner puckman crockman puckman crockmnf puckman ... puckmod puckman titanpac puckman -listbrothers / -lb [<pattern>] Displays a list of brothers, i.e. other systems that are defined in the same source file as a system that matches the specified pattern. Example: mame galaxian -listbrothers Source file: Name: Parent: galaxian.cpp amidar galaxian.cpp amidar1 amidar galaxian.cpp amidarb amidar ... galaxian.cpp zigzagb galaxian.cpp zigzagb2 zigzagb -listcrc [<pattern>...] Displays a full list of CRCs and names of all ROM images referenced by systems and devices matching the specified pattern(s). If no patterns are specified, ROMs referenced by all supported systems and devices will be included. Example: mame playch10 -listcrc d52fa07a pch1-c__8t_e-2.8t playch10 PlayChoice-10 BIOS 503ee8b1 pck1-c.8t playch10 PlayChoice-10 BIOS 123ffa37 pch1-c_8te.8t playch10 PlayChoice-10 BIOS 0be8ceb4 pck1-c_fix.8t playch10 PlayChoice-10 BIOS 9acffb30 pch1-c__8k.8k playch10 PlayChoice-10 BIOS c1232eee pch1-c__8m_e-1.8m playch10 PlayChoice-10 BIOS 30c15e23 pch1-c__8p_e-1.8p playch10 PlayChoice-10 BIOS 9acffb30 pch1-c__8k.8k playch10 PlayChoice-10 BIOS c1232eee pch1-c__8m_e-1.8m playch10 PlayChoice-10 BIOS 30c15e23 pch1-c__8p_e-1.8p playch10 PlayChoice-10 BIOS 9acffb30 pch1-c__8k.8k playch10 PlayChoice-10 BIOS 83ebc7a3 pch1-c_8m.8m playch10 PlayChoice-10 BIOS 90e1b80c pch1-c_8p-8p playch10 PlayChoice-10 BIOS 9acffb30 pch1-c__8k.8k playch10 PlayChoice-10 BIOS c1232eee pch1-c__8m_e-1.8m playch10 PlayChoice-10 BIOS 30c15e23 pch1-c__8p_e-1.8p playch10 PlayChoice-10 BIOS e5414ca3 pch1-c-6f.82s129an.6f playch10 PlayChoice-10 BIOS a2625c6e pch1-c-6e.82s129an.6e playch10 PlayChoice-10 BIOS 1213ebd4 pch1-c-6d.82s129an.6d playch10 PlayChoice-10 BIOS 48de65dc rp2c0x.pal playch10 PlayChoice-10 BIOS -listroms / -lr [<pattern>...] Displays a list of ROM images referenced by supported systems/de- vices that match the specified pattern(s). If no patterns are speci- fied, the results will include all supported systems and devices. Example: mame neogeo -listroms ROMs required for driver "neogeo". Name Size Checksum sp-s2.sp1 131072 CRC(9036d879) SHA1(4f5ed7105b7128794654ce82b51723e16e389543) sp-s.sp1 131072 CRC(c7f2fa45) SHA1(09576ff20b4d6b365e78e6a5698ea450262697cd) sp-45.sp1 524288 CRC(03cc9f6a) SHA1(cdf1f49e3ff2bac528c21ed28449cf35b7957dc1) ... sm1.sm1 131072 CRC(94416d67) SHA1(42f9d7ddd6c0931fd64226a60dc73602b2819dcf) 000-lo.lo 131072 CRC(5a86cff2) SHA1(5992277debadeb64d1c1c64b0a92d9293eaf7e4a) sfix.sfix 131072 CRC(c2ea0cfd) SHA1(fd4a618cdcdbf849374f0a50dd8efe9dbab706c3) -listsamples [<pattern>] Displays a list of samples referenced by the specified pattern of system or device names. If no pattern is specified, the results will be all systems and devices. Example: mame armorap -listsamples Samples required for driver "armorap". loexp jeepfire hiexp tankfire tankeng beep chopper -verifyroms [<pattern>] Checks for invalid or missing ROM images. By default all drivers that have valid ZIP files or directories in the rompath are veri- fied; however, you can limit this list by specifying a pattern after the -verifyroms command. Example: mame gradius -verifyroms romset gradius [nemesis] is good 1 romsets found, 1 were OK. -verifysamples [<pattern>] Checks for invalid or missing samples. By default all drivers that have valid ZIP files or directories in the samplepath are verified; however, you can limit this list by specifying a pattern after the -verifyroms command. Example: mame armorap -verifysamples sampleset armorap [armora] is good 1 samplesets found, 1 were OK. -romident [path/to/romstocheck.zip] Attempts to identify ROM files, if they are known to MAME, in the specified .zip file or directory. This command can be used to try and identify ROM sets taken from unknown boards. On exit, the error- level is returned as one of the following: • 0: means all files were identified • 7: means all files were identified except for 1 or more "non-ROM" files • 8: means some files were identified • 9: means no files were identified Example: mame unknown.rom -romident Identifying unknown.rom.... unknown.rom = 456-a07.17l gradius Gradius (Japan, ROM version) -listdevices / -ld [<pattern>] Displays a list of all devices known to be hooked up to a system. The ":" is considered the system itself with the devices list being attached to give the user a better understanding of what the emula- tion is using. If slots are populated with devices, any additional slots those de- vices provide will be visible with -listdevices as well. For in- stance, installing a floppy controller into a PC will expose the disk drive slots. Example: mame apple2e -listdevices Driver apple2e (Apple //e): <root> Apple //e a2bus Apple II Bus a2common Apple II Common Components @ 14.31 MHz a2video Apple II video @ 14.31 MHz aux Apple IIe AUX Slot ext80 Apple IIe Extended 80-Column Card auxbus Apple IIe AUX Bus ay3600 AY-5-3600 Keyboard Encoder ... speaker Filtered 1-bit DAC tape Cassette -listslots / -lslot [<pattern>] Show available slots and options for each slot (if available). Pri- marily used for MAME to allow control over internal plug-in cards, much like PCs needing video, sound and other expansion cards. If slots are populated with devices, any additional slots those de- vices provide will be visible with -listslots as well. For instance, installing a floppy controller into a PC will expose the disk drive slots. The slot name (e.g. ctrl1) can be used from the command line (-ctrl1 in this case) Example: mame apple2e -listslots SYSTEM SLOT NAME SLOT OPTIONS SLOT DEVICE NAME ---------------- ---------------- ---------------- ---------------------------- apple2e sl1 4play 4play Joystick Card (rev. B) ... aevm80 Applied Engineering Viewmaster 80 alfam2 ALF MC1 / Apple Music II ... zipdrive Zip Technologies ZipDrive ... aux ext80 Apple IIe Extended 80-Column Card rw3 Applied Engineering RamWorks III std80 Apple IIe Standard 80-Column Card gameio compeyes Digital Vision ComputerEyes joy Apple II analog joysticks paddles Apple II paddles -listbios [<pattern>] Show available BIOS options for a system (if available). BIOS op- tions may be available for the system or any devices selected as slot options. If no pattern is specified, the results will include all supported systems. Example: mamed -listbios apple2 -sl2 grapplus -sl4 videoterm BIOS options for system Apple ][ (apple2): default Original Monitor autostart Autostart Monitor BIOS options for device Orange Micro Grappler+ Printer Interface (-sl2 grapplus): v30 ROM 3.0 v32 ROM 3.2 BIOS options for device Videx Videoterm 80 Column Display (-sl4 videoterm): v24_60hz Firmware v2.4 (60 Hz) v24_50hz Firmware v2.4 (50 Hz) -listmedia / -lm [<pattern>] List available media that the chosen system allows to be used. This includes media types (cartridge, cassette, diskette and more) as well as common file extensions which are supported. Example: mame coco3 -listmedia SYSTEM MEDIA NAME (brief) IMAGE FILE EXTENSIONS SUPPORTED ---------------- --------------------------- ------------------------------- coco3 cassette (cass) .wav .cas printout (prin) .prn cartridge (cart) .ccc .rom floppydisk1 (flop1) .dmk .jvc .dsk .vdk .sdf .os9 .d77 .d88 .1dd .dfi .hfe .imd .ipf .mfi .mfm .td0 .cqm .cqi floppydisk2 (flop2) .dmk .jvc .dsk .vdk .sdf .os9 .d77 .d88 .1dd .dfi .hfe .imd .ipf .mfi .mfm .td0 .cqm .cqi harddisk1 (hard1) .vhd harddisk2 (hard2) .vhd -listsoftware / -lsoft [<pattern>] Displays the contents of all software lists that can be used by the system or systems represented by pattern. Example: mame coco3 -listsoftware <?xml version="1.0"?> <!DOCTYPE softwarelists [ <!ELEMENT softwarelists (softwarelist*)> <!ELEMENT softwarelist (software+)> <!ATTLIST softwarelist name CDATA #REQUIRED> <!ATTLIST softwarelist description CDATA #IMPLIED> <!ELEMENT software (description, year, publisher, info*, sharedfeat*, part*)> ... <softwarelists> <softwarelist name="coco_cart" description="Tandy Radio Shack Color Computer cartridges"> <software name="7cardstd"> <description>7 Card Stud</description> <year>1983</year> <publisher>Tandy</publisher> <info name="developer" value="Intelligent Software"/> <info name="serial" value="26-3074"/> <part name="cart" interface="coco_cart"> <dataarea name="rom" size="8192"> <rom name="7 card stud (1983) (26-3074) (intelligent software).rom" size="8192" crc="f38d8c97" sha1="5cfcb699ce09840dbb52714c8d91b3d86d3a86c3"/> </dataarea> </part> </software> ... -verifysoftware / -vsoft [<pattern>] Checks for invalid or missing ROM images in your software lists. By default all drivers that have valid ZIP files or directories in the rompath are verified; however, you can limit this list by specifying a specific driver name or pattern after the -verifysoftware command. Example: mame coco3 -verifysoftware romset coco_cart:7cardstd is good coco_cart:amazing: a mazing world of malcom mortar (1987)(26-3160)(zct systems).rom (16384 bytes) - NEEDS REDUMP romset coco_cart:amazing is best available coco_cart:amazing1: a mazing world of malcom mortar (1987)(26-3160)(zct systems)[a].rom (16384 bytes) - NEEDS REDUMP romset coco_cart:amazing1 is best available romset coco_cart:androne is good ... -getsoftlist / -glist [<pattern>] Displays the contents of a specific softlist with the filename rep- resented by pattern. Example: mame -getsoftlist apple2_flop_orig <?xml version="1.0"?> <!DOCTYPE softwarelists [ <!ELEMENT softwarelists (softwarelist*)> <!ELEMENT softwarelist (software+)> <!ATTLIST softwarelist name CDATA #REQUIRED> <!ATTLIST softwarelist description CDATA #IMPLIED> <!ELEMENT software (description, year, publisher, info*, sharedfeat*, part*)> <!ATTLIST software name CDATA #REQUIRED> <!ATTLIST software cloneof CDATA #IMPLIED> <!ATTLIST software supported (yes|partial|no) "yes"> <!ELEMENT description (#PCDATA)> <!ELEMENT year (#PCDATA)> <!ELEMENT publisher (#PCDATA)> <!ELEMENT info EMPTY> <!ATTLIST info name CDATA #REQUIRED> <!ATTLIST info value CDATA #IMPLIED> <!ELEMENT sharedfeat EMPTY> <!ATTLIST sharedfeat name CDATA #REQUIRED> <!ATTLIST sharedfeat value CDATA #IMPLIED> ... -verifysoftlist / -vlist [softwarelistname] Checks a specified software list for missing ROM images if files ex- ist for issued softwarelistname. By default, all drivers that have valid ZIP files or directories in the rompath are verified; however, you can limit this list by specifying a specific softwarelistname (without .XML) after the -verifysoftlist command. Example: mame -verifysoftlist apple2_flop_orig romset apple2_flop_orig:agentusa is good romset apple2_flop_orig:airheart is good romset apple2_flop_orig:aplpanic is good romset apple2_flop_orig:alambush is good romset apple2_flop_orig:ankh is good romset apple2_flop_orig:aplcdspd is good romset apple2_flop_orig:agalxian is good romset apple2_flop_orig:aquatron is good romset apple2_flop_orig:archon is good romset apple2_flop_orig:archon2 is good romset apple2_flop_orig:ardyardv is good romset apple2_flop_orig:autobahn is good ... OSD-related Options -uimodekey [keystring] Key used to enable/disable MAME keyboard controls when the emulated system has keyboard inputs. The default setting is Forward Delete on macOS or SCRLOCK on other operating systems (including Windows and Linux). Use FN-Delete on Macintosh computers with notebook/com- pact keyboards. Example: mame ibm5150 -uimodekey DEL -controller_map / -ctrlmap <filename> Path to a text file containing game controller button and axis map- pings in the format used by SDL2 and Steam, or none to use only built-in mappings. Must use an ASCII-compatible text encoding with native line endings (e.g. CRLF on Windows). Currently only sup- ported when using the sdlgame joystick provider. The default set- ting is none. A community-sourced list of game controller mappings can be found on GitHub. Besides using a text editor, several tools are available for creating game controller mappings, including SDL2 Gamepad Mapper and SDL2 ControllerMap which is supplied with SDL. You can also configure your controller in Steams Big Picture mode, then copy the mappings from SDL_GamepadBind entries in the config.vdf file found in the config folder inside your Steam installation folder. Example: mame -controller_map gamecontrollerdb.txt sf2ce -[no]background_input Sets whether input is accepted or ignored when MAME does not have UI focus. This setting is ignored when the debugger is enabled. The default is OFF (-nobackground_input). Currently supported for RawInput mouse/keyboard input, DirectInput mouse/keyboard/joystick input and XInput joystick input on Windows, and SDL game controller/joystick input. Example: mame -background_input ssf2tb -uifontprovider <module> Chooses provider for UI font rendering. The default setting is auto. Supported UI font providers per-platform +-----------+-----+--------+------+-----+---------+------+ | Microsoft | win | dwrite | auto | | sdl [1] | none | | Windows | | | | | | | +-----------+-----+--------+------+-----+---------+------+ | macOS | | | auto | osx | sdl | none | +-----------+-----+--------+------+-----+---------+------+ | Linux | | | auto | | sdl | none | +-----------+-----+--------+------+-----+---------+------+ FOOTNOTES [1] SDL support on Windows requires that you compile MAME with the support in. By default SDL is not included in Windows builds of MAME. Example: mame ajax -uifontprovider dwrite -keyboardprovider <module> Chooses how MAME will get keyboard input. The default is auto. Supported keyboard input providers per-platform +------------+----------+----------+--------+-------+---------+------+ | Microsoft | auto [2] | rawinput | dinput | win32 | sdl [3] | none | | Windows | | | | | | | +------------+----------+----------+--------+-------+---------+------+ | SDL (macOS | auto [4] | | | | sdl | none | | and Linux) | | | | | | | +------------+----------+----------+--------+-------+---------+------+ FOOTNOTES [2] auto on Windows will try rawinput with fallback to dinput. [3] SDL support on Windows requires that you compile MAME with the support in. By default SDL is not included in Windows builds of MAME. [4] auto on SDL will default to sdl. TIP: Note that user-mode keyboard emulation tools such as joy2key will almost certainly require the use of -keyboardprovider win32 on Win- dows machines. Example: mame c64 -keyboardprovider win32 -mouseprovider <module> Chooses how MAME will get mouse input. The default is auto. Supported mouse input providers per-platform +------------+----------+----------+--------+-------+---------+------+ | Microsoft | auto [5] | rawinput | dinput | win32 | sdl [6] | none | | Windows | | | | | | | +------------+----------+----------+--------+-------+---------+------+ | SDL (macOS | auto [7] | | | | sdl | none | | and Linux) | | | | | | | +------------+----------+----------+--------+-------+---------+------+ FOOTNOTES [5] On Windows, auto will try rawinput with fallback to dinput. [6] SDL support on Windows requires that you compile MAME with the support in. By default SDL is not included in Windows builds of MAME. [7] auto on SDL will default to sdl. Example: mame indy_4610 -mouseprovider win32 -lightgunprovider <module> Chooses how MAME will get light gun input. The default is auto. Supported light gun input providers per-platform +-----------+-----------+----------+-------+---------+-----+------+ | Microsoft | auto [8] | rawinput | win32 | sdl [9] | | none | | Windows | | | | | | | +-----------+-----------+----------+-------+---------+-----+------+ | macOS | auto [10] | | | sdl | | none | +-----------+-----------+----------+-------+---------+-----+------+ | Linux | auto [10] | | | sdl | x11 | none | +-----------+-----------+----------+-------+---------+-----+------+ FOOTNOTES [8] On Windows, auto will try rawinput with fallback to win32, or none if it doesn't find any. [9] SDL support on Windows requires that you compile MAME with the support in. By default SDL is not included in Windows builds of MAME. [10] On SDL, auto will default to sdl. Example: mame lethalen -lightgunprovider x11 -joystickprovider <module> Chooses how MAME will get joystick and other game controller input. The default is auto. Supported joystick input providers per-platform +-----------+-----------+-----------+--------+--------+---------+--------+------+ | Microsoft | auto [11] | winhybrid | dinput | xinput | sdlgame | sdljoy | none | | Windows | | | | | [12] | [12] | | +-----------+-----------+-----------+--------+--------+---------+--------+------+ | SDL | auto [13] | | | | sdlgame | sdljoy | none | +-----------+-----------+-----------+--------+--------+---------+--------+------+ FOOTNOTES [11] On Windows native, auto will default to winhybrid. [12] SDL support on Windows requires that you compile MAME with the support in. By default SDL is not included in Windows builds of MAME. [13] On SDL, auto will default to sdlgame. winhybrid Uses XInput for compatible game controllers, falling back to Di- rectInput for other game controllers. Typically provides the best experience on Windows. dinput Uses DirectInput for all game controllers. May be useful if you want to use more than four XInput game controllers simultane- ously. Note that LT and RT controls are combined with using XInput game controllers via DirectInput. xinput Supports up to four XInput game controllers. sdlgame Uses the SDL game controller API for game controllers with but- ton/axis mappings available, falling back to the SDL joystick API for other game controllers. Provides consistent button and axis assignment and meaningful control names for popular game controllers. Use the controller_map option to supply mappings for additional game controllers or override built-in mappings. sdljoy Uses the SDL joystick API for all game controllers. none Ignores all game controllers. Example: mame mk2 -joystickprovider winhybrid -midiprovider <module> Chooses how MAME will communicate with MIDI devices and applications (e.g. music keyboards and synthesisers). Supported options are pm to use the PortMidi library, or none to disable MIDI input and out- put (MIDI files can still be played). The default is auto, which will use PortMidi if available. Example: mame -midiprovider none dx100 -midiin canyon.mid -networkprovider <module> Chooses how MAME will provide communication for emulated packet-ori- ented network interfaces (e.g. Ethernet cards). Supported options are taptun to use the TUN/TAP, TAP-Windows or similar, pcap to use a pcap library, or none to disable communication for emulated network interfaces. Available options depend on your operating system. By default, taptun and none are available on Windows and Linux, and pcap and none are available on macOS. The default is auto which will use taptun if available, falling back to pcap. Example: mame -networkprovider pcap apple2ee -sl3 uthernet OSD Command-Line Verbs -listmidi List available MIDI I/O devices for use with emulation. Example: mame -listmidi MIDI input ports: MIDI output ports: Microsoft MIDI Mapper (default) Microsoft GS Wavetable Synth -listnetwork List available network adapters for use with emulation. Example 1: mame -listnetwork No network adapters were found Example 2: mame -listnetwork Available network adapters: Local Area Connection TIP: On Windows, you'll need the TAP driver from OpenVPN for MAME to see any network adapters. OSD Output Options -output Chooses how MAME will handle processing of output notifiers. These are used to connect external outputs such as the LED lights for the Player 1/2 start buttons on certain arcade machines. You can choose from: auto, none, console or network Note that network port is fixed at 8000. Example: mame asteroid -output console led0 = 1 led0 = 0 ... led0 = 1 led0 = 0 Configuration Options -[no]readconfig / -[no]rc Enables or disables the reading of the config files. When enabled (which is the default), MAME reads the following config files in or- der: • mame.ini • debug.ini (if the debugger is enabled) • source/<driver>.ini (based on the source filename of the driver) • vertical.ini (for systems with vertical monitor orientation) • horizont.ini (for systems with horizontal monitor orientation) • arcade.ini (for systems in source added with GAME() macro) • console.ini (for systems in source added with CONS() macro) • computer.ini (for systems in source added with COMP() macro) • othersys.ini (for systems in source added with SYST() macro) • vector.ini (for vector systems only) • <parent>.ini (for clones only, may be called recursively) • <systemname>.ini (See Order of Config Loading for further details) The settings in the later INIs override those in the earlier INIs. So, for example, if you wanted to disable overlay effects in the vector systems, you can create a vector.ini with line effect none in it, and it will override whatever effect value you have in your mame.ini. The default is ON (-readconfig). Example: mame apple2ee -noreadconfig -sl6 diskii -sl7 cffa2 -hard1 TotalReplay.2mg Core Search Path Options -homepath <path> Specifies a path for Lua plugins to store data. The default is . (that is, in the current working directory). Example: mame -homepath C:\mame\lua -rompath / -rp <path> Specifies one or more paths within which to find ROM or disk images. Multiple paths can be specified by separating them with semicolons. The default is roms (that is, a directory roms in the current work- ing directory). Example: mame -rompath C:\mame\roms;C:\roms\another -hashpath / -hash_directory / -hash <path> Specifies one or more paths within which to find software definition files. Multiple paths can be specified by separating them with semicolons. The default is hash (that is, a directory hash in the current work- ing directory). Example: mame -hashpath C:\mame\hash;C:\roms\softlists -samplepath / -sp <path> Specifies one or more paths within which to find audio sample files. Multiple paths can be specified by separating them with semicolons. The default is samples (that is, a directory samples in the current working directory). Example: mame -samplepath C:\mame\samples;C:\roms\samples -artpath <path> Specifies one or more paths within which to find external layout and artwork files. Multiple paths can be specified by separating them with semicolons. The default is artwork (that is, a directory artwork in the current working directory). Example: mame -artpath C:\mame\artwork;C:\emu\shared-artwork -ctrlrpath <path> Specifies one or more paths within which to find controller configu- ration files. Multiple paths can be specified by separating them with semicolons. Used in conjunction with the -ctrlr option. The default is ctrlr (that is, a directory ctrlr in the current working directory). Example: mame -ctrlrpath C:\mame\ctrlr;C:\emu\controllers -inipath <path> Specifies one or more paths within which to find INI files. Multi- ple paths can be specified by separating them with semicolons. On Windows, the default is .;ini;ini/presets (that is, search in the current directory first, then in the directory ini in the current working directory, and finally the directory presets inside that di- rectory). On macOS, the default is $HOME/Library/Application Sup- port/mame;$HOME/.mame;.;ini (that is, search the mame folder inside the current user's Application Support folder, followed by the .mame folder in the current user's home directory, then the current work- ing directory, and finally the directory ini in the current working directory). On other platforms (including Linux), the default is $HOME/.mame;.;ini (that is search the .mame directory in the current user's home directory, followed by the current working directory, and finally the directory ini in the current working directory). Example: mame -inipath C:\Users\thisuser\documents\mameini -fontpath <path> Specifies one or more paths within which to find BDF (Adobe Glyph Bitmap Distribution Format) font files. Multiple paths can be spec- ified by separating them with semicolons. The default is . (that is, search in the current working directory). Example: mame -fontpath C:\mame\;C:\emu\artwork\mamefonts -cheatpath <path> Specifies one or more paths within which to find XML cheat files. Multiple paths can be specified by separating them with semicolons. The default is cheat (that is, a folder called cheat located in the current working directory). Example: mame -cheatpath C:\mame\cheat;C:\emu\cheats -crosshairpath <path> Specifies one or more paths within which to find crosshair image files. Multiple paths can be specified by separating them with semicolons. The default is crsshair (that is, a directory crsshair in the cur- rent working directory). Example: mame -crosshairpath C:\mame\crsshair;C:\emu\artwork\crosshairs -pluginspath <path> Specifies one or more paths within which to find Lua plugins for MAME. The default is plugins (that is, a directory plugins in the current working directory). Example: mame -pluginspath C:\mame\plugins;C:\emu\lua -languagepath <path> Specifies one or more paths within which to find language files for localized UI text. The default is language (that is, a directory language in the cur- rent working directory). Example: mame -languagepath C:\mame\language;C:\emu\mame-languages -swpath <path> Specifies the default path from which to load loose software image files. The default is sofware (that is, a directory software in the current working directory). Example: mame -swpath C:\mame\software;C:\emu\mydisks Core Output Directory Options -cfg_directory <path> Specifies the directory where configuration files are stored. Con- figuration files are read when starting MAME or when starting an em- ulated machine, and written on exit. Configuration files preserve settings including input assignment, DIP switch settings, bookkeep- ing statistics, and debugger window arrangement. The default is cfg (that is, a directory cfg in the current working directory). If this directory does not exist, it will be created au- tomatically. Example: mame -cfg_directory C:\mame\cfg -nvram_directory <path> Specifies the directory where NVRAM files are stored. NVRAM files store the contents of EEPROM, non-volatile RAM (NVRAM), and other programmable devices for systems that used this type of hardware. This data is read when starting an emulated machine and written on exit. The default is nvram (that is, a directory nvram in the current working directory)). If this directory does not exist, it will be created automatically. Example: mame -nvram_directory C:\mame\nvram -input_directory <path> Specifies the directory where input recording files are stored. In- put recordings are created using the -record option and played back using the -playback option. The default is inp (that is, a directory inp in the current working directory). If this directory does not exist, it will be created automatically. Example: mame -input_directory C:\mame\inp -state_directory <path> Specifies the directory where save state files are stored. Save state files are read and written either upon user request, or when using the -autosave option. The default is sta (that is, a directory sta in the current working directory). If this directory does not exist, it will be created automatically. Example: mame -state_directory C:\mame\sta -snapshot_directory <path> Specifies the directory where screen snapshots and video recordings are stored when requested by the user. The default is snap (that is, a directory snap in the current work- ing directory). If this directory does not exist, it will be created automatically. Example: mame -snapshot_directory C:\mame\snap -diff_directory <path> Specifies the directory where hard drive difference files are stored. Hard drive difference files store data that is written back to an emulated hard disk, in order to preserve the original image file. The difference files are created when starting an emulated system with a compressed hard disk image. The default is diff (that is, a directory diff in the current work- ing directory). If this directory does not exist, it will be cre- ated automatically. Example: mame -diff_directory C:\mame\diff -comment_directory <path> Specifies a directory where debugger comment files are stored. De- bugger comment files are written by the debugger when comments are added to the disassembly for a system. The default is comments (that is, a directory comments in the cur- rent working directory). If this directory does not exist, it will be created automatically. Example: mame -comment_directory C:\mame\comments Core State/Playback Options -[no]rewind When enabled and emulation is paused, automatically creates a save state in memory every time a frame is advanced. Rewind save states can then be loaded consecutively by pressing the rewind single step shortcut key (Left Shift + Tilde by default). The default rewind value is OFF (-norewind). If debugger is in a 'break' state, a save state is instead created every time step in, step over, or step out occurs. In that mode, rewind save states can be loaded by executing the debugger rewind (or rw) command. Example: mame -norewind -rewind_capacity <value> Sets the rewind capacity value, in megabytes. It is the total amount of memory rewind savestates can occupy. When capacity is hit, old savestates get erased as new ones are captured. Setting capacity lower than the current savestate size disables rewind. Val- ues below 0 are automatically clamped to 0. Example: mame -rewind_capacity 30 -state <slot> Immediately after starting the specified system, will cause the save state in the specified <slot> to be loaded. Example: mame -state 1 -[no]autosave When enabled, automatically creates a save state file when exiting MAME and automatically attempts to reload it when later starting MAME with the same system. This only works for systems that have explicitly enabled save state support in their driver. The default is OFF (-noautosave). Example: mame -autosave -playback / -pb <filename> Specifies a file from which to play back a series of inputs. This feature does not work reliably for all systems, but can be used to watch a previously recorded game session from start to finish. The default is NULL (no playback). Example: mame pacman -playback worldrecord TIP: You may experience desync in playback if the configuration, NVRAM, and memory card files don't match the original; this is why it is suggested you should only record and playback with all configuration (.cfg), NVRAM (.nv), and memory card files deleted. -[no]exit_after_playback When used in conjunction with the -playback option, MAME will exit after playing back the input file. By default, MAME continues to run the emulated system after playback completes. The default is OFF (-noexit_after_playback). Example: mame pacman -playback worldrecord -exit_after_playback -record / -rec <filename> Specifies a file to record all input from a session. This can be used to record a session for later playback. This feature does not work reliably for all systems, but can be used to record a session from start to finish. The default is NULL (no recording). Example: mame pacman -record worldrecord TIP: You may experience desync in playback if the configuration, NVRAM, and memory card files don't match the original; this is why it is suggested you should only record and playback with all configuration (.cfg), NVRAM (.nv), and memory card files deleted. -mngwrite <filename> Writes each video frame to the given <filename> in MNG format, pro- ducing an animation of the session. Note that -mngwrite only writes video frames; it does not save any audio data. Either use -wavwrite to record audio and combine the audio and video tracks using video editing software, or use -aviwrite to record audio and video to a single file. The default is NULL (no recording). Example: mame pacman -mngwrite pacman-video -aviwrite <filename> Stream video and sound data to the given <filename> in uncompressed AVI format, producing an animation of the session complete with sound. Note that the AVI format does not changes to resolution or frame rate, uncompressed video consumes a lot of disk space, and recording uncompressed video in realtime requires a fast disk. It may be more practical to record an emulation session using -record then make a video of it with -aviwrite in combination with -playback and -exit_after_playback options. The default is NULL (no recording). Example: mame pacman -playback worldrecord -exit_after_playback -aviwrite worldrecord -wavwrite <filename> Writes the final mixer output to the given <filename> in WAV format, producing an audio recording of the session. The default is NULL (no recording). Example: mame pacman -wavwrite pacsounds -snapname <name> Describes how MAME should name files for snapshots. <name> is a string that provides a template that is used to generate a filename. Three simple substitutions are provided: the / character represents the path separator on any target platform (even Windows); the string %g represents the driver name of the current system; and the string %i represents an incrementing index. If %i is omitted, then each snapshot taken will overwrite the previous one; otherwise, MAME will find the next empty value for %i and use that for a filename. The default is %g/%i, which creates a separate folder for each sys- tem, and names the snapshots under it starting with 0000 and in- creasing from there. In addition to the above, for drivers using different media, like carts or floppy disks, you can also use the %d_[media] indicator. Replace [media] with the media switch you want to use. Example 1: mame robby -snapname foo\%g%i Snapshots will be saved as snaps\foo\robby0000.png, snaps\foo\robby0001.png and so on. Example 2: mame nes -cart robby -snapname %g\%d_cart Snapshots will be saved as snaps\nes\robby.png. Example 3: mame c64 -flop1 robby -snapname %g\%d_flop1/%i Snapshots will be saved as snaps\c64\robby\0000.png. -snapsize <width>x<height> Hard-codes the size for snapshots and movie recording. By default, MAME will create snapshots at the system's current resolution in raw pixels, and will create movies at the system's starting resolution in raw pixels. If you specify this option, then MAME will create both snapshots and movies at the size specified, and will bilinear filter the result. The default is auto. Example: mame pacman -snapsize 1920x1080 TIP: -snapsize does not automatically rotate if the system is vertically oriented, so for vertical systems you'll want to swap the width and height options. -snapview <viewname> Specifies the view to use when rendering snapshots and videos. The <viewname> does not need to be the full name of a view, MAME will choose the first view with a name that has the <viewname> as a pre- fix. For example -snapview "screen 0 pixel" will match the Screen 0 Pixel Aspect (10:7) view. If the <viewname> is auto or an empty string, MAME will select a view based on the number of emulated screens in the system, and the available external and internal artwork. MAME tries to select a view that shows all emulated screens by default. If the <viewname> is native, MAME uses special internal view to save a separate snapshot for each visible emulated screen, or to record a video for the first visible screen only. The snapshot(s) or video will have the same resolution as the emulated screen(s) with no art- work elements drawn or effects applied. The default value is auto. Example: mame wrecking -snapview cocktail -[no]snapbilinear Specify if the snapshot or movie should have bilinear filtering ap- plied. Disabling this off can improve performance while recording video to a file. The default is ON (-snapbilinear). Example: mame pacman -nosnapbilinear -statename <name> Describes how MAME should store save state files, relative to the state_directory path. <name> is a string that provides a template that is used to generate a relative path. Two simple substitutions are provided: the / character represents the path separator on any target platform (even Windows); the string %g represents the driver name of the current system. The default is %g, which creates a separate folder for each system. In addition to the above, for drivers using different media, like carts or floppy disks, you can also use the %d_[media] indicator. Replace [media] with the media switch you want to use. Example 1: mame robby -statename foo\%g All save states will be stored inside sta\foo\robby\ Example 2: mame nes -cart robby -statename %g/%d_cart All save states will be stored inside sta\nes\robby\ Example 3: mame c64 -flop1 robby -statename %g/%d_flop1 All save states will be stored inside sta\c64\robby\ TIP: Note that even on Microsoft Windows, you should use / as your path seperator for -statename -[no]burnin Tracks brightness of the screen during play and at the end of emula- tion generates a PNG that can be used to simulate burn-in effects on other systems. The resulting PNG is created such that the least used-areas of the screen are fully white (since burned-in areas are darker, all other areas of the screen must be lightened a touch). The intention is that this PNG can be loaded via an artwork file with a low alpha (e.g, 0.1-0.2 seems to work well) and blended over the entire screen. The PNG files are saved in the snap directory under the <system- name>/burnin-<screen.name>.png. The default is OFF (-noburnin). Example: mame neogeo -burnin Core Performance Options -[no]autoframeskip / -[no]afs Dynamically adjust the frameskip level while you're running the sys- tem to maintain full speed. Turning this on overrides the -frameskip setting described below. This is off by default (-noautoframeskip). Example: mame gradius4 -autoframeskip -frameskip / -fs <level> Specifies the frameskip value. This is the number of frames out of every 12 to drop when running. For example, if you specify -frameskip 2, MAME will render and display 10 out of every 12 emu- lated frames. By skipping some frames, you may be able to get full speed emulation for a system that would otherwise be too demanding for your computer. The default value is -frameskip 0, which skips no frames. Example: mame gradius4 -frameskip 2 -seconds_to_run / -str <seconds> This option tells MAME to automatically stop emulation after a fixed number of seconds of emulated time have elapsed. This may be useful for benchmarking and automated testing. By combining this with a fixed set of other command line options, you can set up a consistent environment for benchmarking MAME's emulation performance. In addi- tion, upon exit, the -str option will write a screenshot to the sys- tem's snapshot directory with the file name determined by the -snap- name option. Example: mame pacman -seconds_to_run 60 -[no]throttle Enable or disable throttling emulation speed. When throttling is enabled, MAME limits emulation speed to so the emulated system will not run faster than the original hardware. When throttling is dis- abled, MAME runs the emulation as fast as possible. Depending on your settings and the characteristics of the emulated system, per- formance may be limited by your CPU, graphics card, or even memory performance. The default is to enable throttling (-throttle). Example: mame pacman -nothrottle -[no]sleep When enabled along with -throttle, MAME will yield the CPU when lim- iting emulation speed. This allows other programs to use CPU time, assuming the main emulation thread isn't completely utilising a CPU core. This option can potentially cause hiccups in performance if other demanding programs are running. The default is on (-sleep). Example: mame gradius 4 -nosleep -speed <factor> Changes the way MAME throttles the emulation so that it runs at some multiple of the system's original speed. A <factor> of 1.0 means to run the system at its normal speed, a <factor> of 0.5 means run at half speed, and a <factor> of 2.0 means run at double speed. Note that changing this value affects sound playback as well, which will scale in pitch accordingly. The internal precision of the fraction is two decimal places, so a <factor> of 1.002 is rounded to 1.00. The default is 1.0 (normal speed). Example: mame pacman -speed 1.25 -[no]refreshspeed / -[no]rs Allows MAME to adjust the emulation speed so that the refresh rate of the first emulated screen does not exceed the slowest refresh rate for any targeted monitors in your system. Thus, if you have a 60Hz monitor and run a system that is designed to run at 60.6Hz, MAME will reduce the emulation speed to 99% in order to prevent sound hiccups or other undesirable side effects of running at a slower refresh rate. The default is off (-norefreshspeed). Example: mame pacman -refreshspeed -numprocessors / -np auto|<value> Specify the number of threads to use for work queues. Specifying auto will use the value reported by the system or environment vari- able OSDPROCESSORS. This value is internally limited to four times the number of processors reported by the system. The default is auto. Example: mame gradius4 -numprocessors 2 -bench <n> Benchmark for <n> emulated seconds. This is equivalent to the fol- lowing options: -str <n> -video none -sound none -nothrottle Example: mame gradius4 -bench 300 -[no]lowlatency This tells MAME to draw a new frame before throttling to reduce in- put latency. This is particularly effective with VRR (Variable Re- fresh Rate) displays. This may cause frame pacing issues in the form of jitter with some systems (especially newer 3D-based systems or systems that run soft- ware akin to an operating system), so the default is off (-nolowla- tency). Example: mame bgaregga -lowlatency Core Rotation Options -[no]rotate Rotate the system to match its normal state (horizontal/vertical). This ensures that both vertically and horizontally oriented systems show up correctly without the need to rotate your monitor. If you want to keep the system displaying 'raw' on the screen the way it would have in the arcade, turn this option OFF. The default is ON (-rotate). Example: mame pacman -norotate -[no]ror -[no]rol Rotate the system screen to the right (clockwise) or left (counter-clockwise) relative to either its normal state (if -rotate is specified) or its native state (if -norotate is specified). The default for both of these options is OFF (-noror -norol). Example 1: mame pacman -ror Example 2: mame pacman -rol -[no]autoror -[no]autorol These options are designed for use with pivoting screens that only pivot in a single direction. If your screen only pivots clockwise, use -autorol to ensure that the system will fill the screen either horizontally or vertically in one of the directions you can handle. If your screen only pivots counter-clockwise, use -autoror. Example 1: mame pacman -autoror Example 2: mame pacman -autorol TIP: If you have a display that can be rotated, -autorol or -autoror will allow you to get a larger display for both horizontal and vertical systems. -[no]flipx -[no]flipy Flip (mirror) the system screen either horizontally (-flipx) or ver- tically (-flipy). The flips are applied after the -rotate and -ror/-rol options are applied. The default for both of these options is OFF (-noflipx -noflipy). Example 1: mame -flipx pacman Example 2: mame -flipy suprmrio Core Video Options -video <bgfx|gdi|d3d|opengl|soft|accel|none> Specifies which video subsystem to use for drawing. Options here de- pend on the operating system and whether this is an SDL-compiled version of MAME. Generally Available: • Using bgfx specifies the new hardware accelerated renderer. • Using opengl tells MAME to render video using OpenGL acceleration. • Using none displays no windows and does no drawing. This is pri- marily intended for benchmarking emulation without the overhead of the video system. On Windows: • Using gdi tells MAME to render video using older standard Windows graphics drawing calls. This is the slowest but most compatible option on older versions of Windows or buggy graphics hardware drivers. • Using d3d tells MAME to use Direct3D 9 for rendering. This pro- duces better quality output than gdi and enables additional ren- dering options. It is recommended if you have a 3D-capable video card or onboard Intel video of the HD3000 line or better. On other platforms (including SDL on Windows): • Using accel tells MAME to render video using SDLs 2D acceleration if possible. • Using soft uses software rendering for video output. This isnt as fast or as nice as OpenGL, but it will work on any platform. Defaults: • The default on Windows is d3d. • The default for macOS is opengl because OS X is guaranteed to have a compliant OpenGL stack. • The default on all other systems is soft. Example: mame gradius3 -video bgfx -numscreens <count> Tells MAME how many output windows or screens to create. For most systems, a single output window is all you need, but some systems originally used multiple screens (e.g. Darius and PlayChoice-10 ar- cade machines). Some systems with front panel controls and/or sta- tus lights also may let you put these in different windows/screens. Each screen (up to 4) has its own independent settings for physical monitor, aspect ratio, resolution, and view, which can be set using the options below. The default is 1. Example 1: mame darius -numscreens 3 Example 2: mame pc_cntra -numscreens 2 -[no]window / -[no]w Run MAME in either a window or full screen. The default is OFF (-nowindow). Example: mame coco3 -window -[no]maximize / -[no]max Controls initial window size in windowed mode. If it is set on, the window will initially be set to the maximum supported size when you start MAME. If it is turned off, the window will start out at the closest possible size to the original size of the display; it will scale on only one axis where non-square pixels are used. This option only has an effect when the -window option is used. The default is ON (-maximize). Example: mame apple2e -window -nomaximize -[no]keepaspect / -[no]ka When enabled, MAME preserves the correct aspect ratio for the emu- lated system's screen(s). This is most often 4:3 or 3:4 for CRT monitors (depending on the orientation), though many other aspect ratios have been used, such as 3:2 (Nintendo Game Boy), 5:4 (some workstations), and various other ratios. If the emulated screen and/or artwork does not fill MAME's screen or Window, the image will be centred and black bars will be added as necessary to fill unused space (either above/below or to the left and right). When this option is disabled, the emulated screen and/or artwork will be stretched to fill MAME's screen or window. The image will be distorted by non-proportional scaling if the aspect ratio does not match. This is very pronounced when the emulated system uses a vertically-oriented screen and MAME stretches the image to fill a horizontally-oriented screen. On Windows, when this option is enabled and MAME is running in a window (not full screen), the aspect ratio will be maintained when you resize the window unless you hold the Control (or Ctrl) key on your keyboard. The window size will not be restricted when this op- tion is disabled. The default is ON (-keepaspect). The MAME team strongly recommends leaving this option enabled. Stretching systems beyond their original aspect ratio will mangle the appearance of the system in ways that no filtering or shaders can repair. Example: mame sf2ua -nokeepaspect -[no]waitvsync Waits for the refresh period on your computer's monitor to finish before starting to draw video to your screen. If this option is off, MAME will just draw to the screen as a frame is ready, even if in the middle of a refresh cycle. This can cause "tearing" arti- facts, where the top portion of the screen is out of sync with the bottom portion. The effect of turning -waitvsync on differs a bit between combina- tions of different operating systems and video drivers. On Windows, -waitvsync will block until video blanking before allow- ing MAME to draw the next frame, limiting the emulated machine's framerate to that of the host display. Note that this option does not work with -video gdi mode in Windows. On macOS, -waitvsync does not block; instead the most recent com- pletely drawn frame will be displayed at vblank. This means that if an emulated system has a higher framerate than your host display, emulated frames will be dropped periodically resulting in motion judder. On Windows, you should only need to turn this on in windowed mode. In full screen mode, it is only needed if -triplebuffer does not re- move the tearing, in which case you should use -notriplebuffer -waitvsync. Note that SDL-based MAME support for this option depends entirely on your operating system and video drivers; in general it will not work in windowed mode so -video opengl and fullscreen give the greatest chance of success with SDL builds of MAME. The default is OFF (-nowaitvsync). Example: mame gradius2 -waitvsync -[no]syncrefresh Enables speed throttling only to the refresh of your monitor. This means that the system's actual refresh rate is ignored; however, the sound code still attempts to keep up with the system's original re- fresh rate, so you may encounter sound problems. This option is intended mainly for those who have tweaked their video card's settings to provide carefully matched refresh rate op- tions. Note that this option does not work with -video gdi mode. The default is OFF (-nosyncrefresh). Example: mame mk -syncrefresh -prescale <amount> Controls the size of the screen images when they are passed off to the graphics system for scaling. At the minimum setting of 1, the screen is rendered at its original resolution before being scaled. At higher settings, the screen is expanded in both axes by a factor of <amount> using nearest-neighbor sampling before applying filters or shaders. With -video d3d, this produces a less blurry image at the expense of speed. The default is 1. This is supported with all video output types ( bgfx, d3d, etc.) on Windows and is supported with BGFX and OpenGL on other platforms. Example: mame pacman -video d3d -prescale 3 -[no]filter / -[no]d3dfilter / -[no]flt Enable bilinear filtering on the system screen graphics. When dis- abled, point filtering is applied, which is crisper but leads to scaling artifacts. If you don't like the filtered look, you are probably better off increasing the -prescale value rather than turn- ing off filtering altogether. The default is ON (-filter). This is supported with OpenGL and D3D video on Windows and is ONLY supported with OpenGL on other platforms. Use bgfx_screen_chains in your INI file(s) to adjust filtering with the BGFX video system. Example: mame pacman -nofilter -[no]unevenstretch Allow non-integer scaling factors allowing for great window sizing flexibility. The default is ON. (-unevenstretch) Example: mame dkong -nounevenstretch Core Full Screen Options -[no]switchres Enables resolution switching. This option is required for the -reso- lution* options to switch resolutions in full screen mode. On modern video cards, there is little reason to switch resolutions unless you are trying to achieve the "exact" pixel resolutions of the original systems, which requires significant tweaking. This is also true on LCD displays, since they run with a fixed resolution and switching resolutions on them is just silly. This option does not work with -video gdi and -video bgfx. The default is OFF (-noswitchres). Example: mame kof97 -video d3d -switchres -resolution 1280x1024 Core Per-Window Options -screen <display> -screen0 <display> -screen1 <display> -screen2 <display> -screen3 <display> Specifies which physical monitor on your system you wish to have each window use by default. In order to use multiple windows, you must have increased the value of the -numscreens option. The name of each display in your system can be determined by running MAME with the -verbose option. The display names are typically in the format of: \\\\.\\DISPLAYn, where 'n' is a number from 1 to the num- ber of connected monitors. The default value for these options is auto, which means that the first window is placed on the first display, the second window on the second display, etc. The -screen0, -screen1, -screen2, -screen3 parameters apply to the specific window. The -screen parameter applies to all windows. The window-specific options override values from the all window option. Example 1: mame pc_cntra -numscreens 2 -screen0 \\.\DISPLAY1 -screen1 \\.\DISPLAY2 Example 2: mame darius -numscreens 3 -screen0 \\.\DISPLAY1 -screen1 \\.\DISPLAY3 -screen2 \\.\DISPLAY2 TIP: Using -verbose will tell you which displays you have on your system, where they are connected, and what their current resolutions are. TIP: Multiple Screens may fail to work correctly on some Mac machines as of right now. -aspect <width:height> / -screen_aspect <num:den> -aspect0 <width:height> -aspect1 <width:height> -aspect2 <width:height> -aspect3 <width:height> Specifies the physical aspect ratio of the physical monitor for each window. In order to use multiple windows, you must have increased the value of the -numscreens option. The physical aspect ratio can be determined by measuring the width and height of the visible screen image and specifying them separated by a colon. The default value for these options is auto, which means that MAME assumes the aspect ratio is proportional to the number of pixels in the desktop video mode for each monitor. The -aspect0, -aspect1, -aspect2, -aspect3 parameters apply to the specific window. The -aspect parameter applies to all windows. The window-specific options override values from the all window option. Example 1: mame contra -aspect 16:9 Example 2: mame pc_cntra -numscreens 2 -aspect0 16:9 -aspect1 5:4 -resolution <widthxheight[@refresh]> / -r <widthxheight[@refresh]> -resolution0 <widthxheight[@refresh]> / -r0 <widthxheight[@refresh]> -resolution1 <widthxheight[@refresh]> / -r1 <widthxheight[@refresh]> -resolution2 <widthxheight[@refresh]> / -r2 <widthxheight[@refresh]> -resolution3 <widthxheight[@refresh]> / -r3 <widthxheight[@refresh]> Specifies an exact resolution to run in. In full screen mode, MAME will try to use the specific resolution you request. The width and height are required; the refresh rate is optional. If omitted or set to 0, MAME will determine the mode automatically. For example, -resolution 640x480 will force 640x480 resolution, but MAME is free to choose the refresh rate. Similarly, -resolution 0x0@60 will force a 60Hz refresh rate, but allows MAME to choose the resolution. The string auto is also supported, and is equivalent to 0x0@0. In window mode, this resolution is used as a maximum size for the window. This option requires the -switchres option as well in order to actually enable resolution switching with -video d3d. The default value for these options is auto. The -resolution0, -resolution1, -resolution2, -resolution3 parame- ters apply to the specific window. The -resolution parameter applies to all windows. The window-specific options override values from the all window option. Example: mame pc_cntra -numscreens 2 -resolution0 1920x1080 -resolution1 1280x1024 -view <viewname> -view0 <viewname> -view1 <viewname> -view2 <viewname> -view3 <viewname> Specifies the initial view setting for each window/screen. The <viewname> does not need to be the full name of a view, MAME will choose the first view with a name that has the <viewname> as a pre- fix. For example -view "screen 0 pixel" will match the Screen 0 Pixel Aspect (10:7) view. If the <viewname> is auto or an empty string, MAME will select views based on the number of emulated screens in the system, the number of windows/screens MAME is using, and the available external and inter- nal artwork. MAME tries to select views so that all emulated screens are visible by default. The default value for these options is auto. The -view0, -view1, -view2, -view3 parameters apply to the specific window. The -view parameter applies to all windows. The win- dow-specific options override values from the all windows option. Note that view settings saved in the configuration file for the ma- chine take precedence over the initial view settings. If you change the selected views in the Video Options menu, this will be saved in the configuration file for the machine and take precedence over any initial views specified in INI files or on the command line. Example: mame contra -view native Core Artwork Options -[no]artwork_crop / -[no]artcrop Enable cropping of artwork to the system screen area only. This means that vertically oriented systems running full screen can dis- play their artwork to the left and right sides of the screen. This option can also be controlled via the Video Options menu in the user interface. The default is OFF -noartwork_crop. Example: mame pacman -artwork_crop TIP: -artwork_crop is great for widescreen displays. You will get a full-sized system display and the artwork will fill the empty space on the sides as much as possible. -fallback_artwork Specifies fallback artwork if no external artwork or internal driver layout is defined. If external artwork for the system is present or a layout is included in the driver for the system, then that will take precedence. Example: mame coco -fallback_artwork suprmrio TIP: You can use fallback_artwork <artwork name> in horizontal.ini and vertical.ini to specify different fallback artwork choices for hori- zontal and vertical systems. -override_artwork Specifies override artwork for external artwork and internal driver layout. Example: mame galaga -override_artwork puckman Core Screen Options -brightness <value> Controls the default brightness, or black level, of the system screens. This option does not affect the artwork or other parts of the display. Using the MAME UI, you can individually set the brightness for each system screen; this option controls the initial value for all visible system screens. The standard and default value is 1.0. Selecting lower values (down to 0.1) will produce a dark- ened display, while selecting higher values (up to 2.0) will give a brighter display. Example: mame pacman -brightness 0.5 -contrast <value> Controls the contrast, or white level, of the system screens. This option does not affect the artwork or other parts of the display. Using the MAME UI, you can individually set the contrast for each system screen; this option controls the initial value for all visi- ble system screens. The standard and default value is 1.0. Select- ing lower values (down to 0.1) will produce a dimmer display, while selecting higher values (up to 2.0) will give a more saturated dis- play. Example: mame pacman -contrast 0.5 -gamma <value> Controls the gamma, which produces a potentially nonlinear black to white ramp, for the system screens. This option does not affect the artwork or other parts of the display. Using the MAME UI, you can individually set the gamma for each system screen; this option con- trols the initial value for all visible system screens. The stan- dard and default value is 1.0, which gives a linear ramp from black to white. Selecting lower values (down to 0.1) will increase the nonlinearity toward black, while selecting higher values (up to 3.0) will push the nonlinearity toward white. The default is 1.0. Example: mame pacman -gamma 0.8 -pause_brightness <value> This controls the brightness level when MAME is paused. The default value is 0.65. Example: mame pacman -pause_brightness 0.33 -effect <filename> Specifies a single PNG file that is used as an overlay over any sys- tem screens in the video display. This PNG file is assumed to live in the root of one of the artpath directories. The pattern in the PNG file is repeated both horizontally and vertically to cover the entire system screen areas (but not any external artwork), and is rendered at the target resolution of the system image. For -video gdi and -video d3d modes, this means that one pixel in the PNG will map to one pixel on your output display. The RGB val- ues of each pixel in the PNG are multiplied against the RGB values of the target screen. The default is none, meaning no effect. Example: mame pacman -effect scanlines Core Vector Options -beam_width_min <width> Sets the vector beam minimum width. The beam width varies between the minimum and maximum beam widths as the intensity of the vector drawn changes. To disable vector width changes based on intensity, set the maximum equal to the minimum. Example: mame asteroid -beam_width_min 0.1 -beam_width_max <width> Sets the vector beam maximum width. The beam width varies between the minimum and maximum beam widths as the intensity of the vector drawn changes. To disable vector width changes based on intensity, set the maximum equal to the minimum. Example: mame asteroid -beam_width_max 2 -beam_intensity_weight <weight> Sets the vector beam intensity weight. This value determines how the intensity of the vector drawn affects the width. A value of 0 cre- ates a linear mapping from intensity to width. Negative values mean that lower intensities will increase the width toward maximum faster, while positive values will increase the width toward maximum more slowly. Example: mame asteroid -beam_intensity_weight 0.5 -beam_dot_size <scale> Scale factor to apply to the size of single-point dots in vector games. Normally these are rendered according to the computed beam width; however, it is common for this to produce dots that are dif- ficult to see. The beam_dot_size option applies a scale factor on top of the beam width to help them show up better. The default is 1. Example: mame asteroid -beam_dot_size 2 -flicker <value> Simulates a vector "flicker" effect, similar to a vector monitor that needs adjustment. This option requires a float argument in the range of 0.00 - 100.00 (0=none, 100=maximum). The default is 0. Example: mame asteroid -flicker 0.15 Core Video OpenGL Feature Options These options are for compatibility in -video opengl. If you report rendering artifacts you may be asked to try messing with them by the developers, but normally they should be left at their defaults which results in the best possible video performance. TIP: Examples are not provided for these options as MAMEdev will provide suitable test options in the case of needing them for debugging. -[no]gl_forcepow2texture Always use only power-of-2 sized textures. The default is OFF. (-nogl_forcepow2texture) -[no]gl_notexturerect Don't use OpenGL GL_ARB_texture_rectangle. The default is ON. (-gl_notexturerect) -[no]gl_vbo Enable OpenGL VBO (Vertex Buffer Objects), if available. The default is ON. (-gl_vbo) -[no]gl_pbo Enable OpenGL PBO (Pixel Buffer Objects), if available (default on ) The default is ON. (-gl_pbo) Core Video OpenGL GLSL Options -[no]gl_glsl Enable OpenGL GLSL, if available. The default is OFF (-nogl_glsl). Example: mame galaxian -gl_glsl -gl_glsl_filter Use OpenGL GLSL shader-based filtering instead of fixed function pipeline-based filtering. 0-plain, 1-bilinear, 2-bicubic The default is 1. (-gl_glsl_filter 1) Example: mame galaxian -gl_glsl -gl_glsl_filter 0 -glsl_shader_mame0 -glsl_shader_mame1 ... -glsl_shader_mame9 Set a custom OpenGL GLSL shader effect to the internal system screen in the given slot. MAME does not include a vast selection of shaders by default; more can be found online. Example: mame suprmrio -gl_glsl -glsl_shader_mame0 NTSC/NTSC_chain -glsl_shader_mame1 CRT-geom/CRT-geom -glsl_shader_screen0 -glsl_shader_screen1 ... -glsl_shader_screen9 Set a custom OpenGL GLSL shader effect to the whole scaled-up output screen that will be rendered by your graphics card. MAME does not include a vast selection of shaders by default; more can be found online. Example: mame suprmrio -gl_glsl -glsl_shader_screen0 gaussx -glsl_shader_screen1 gaussy -glsl_shader_screen2 CRT-geom-halation Core Sound Options -samplerate <value> / -sr <value> Sets the audio sample rate. Smaller values (e.g. 11025) cause lower audio quality but faster emulation speed. Higher values (e.g. 48000) cause higher audio quality but slower emulation speed. The default is 48000. Example: mame galaga -samplerate 44100 -[no]samples Use samples if available. The default is ON (-samples). Example: mame qbert -nosamples -[no]compressor Enable audio compressor. It temporarily reduces the overall volume when the audio output is overdriven. The default is ON (-compressor). Example: mame popeye -nocompressor -volume / -vol <value> Sets the initial sound volume. It can be changed later with the user interface (see Keys section). The volume is an attenuation in decibels: e.g. "-volume -12" will start with -12 dB attenuation. Note that if the volume is changed in the user interface it will be saved to the configuration file for the system. The value from the configuration file for the system has priority over volume settings in general INI files. The default is 0 (no attenuation, or full volume). Example: mame pacman -volume -30 -sound <dsound | coreaudio | sdl | xaudio2 | portaudio | none> Specifies which sound subsystem to use. Selecting none disables sound output altogether (sound hardware is still emulated). On Windows and Linux, portaudio is likely to give the lowest possi- ble latency, while Mac users will find coreaudio provides the best results. When using the sdl sound subsystem, the audio API to use may be se- lected by setting the SDL_AUDIODRIVER environment variable. Avail- able audio APIs depend on the operating system. On Windows, it may be necessary to set SDL_AUDIODRIVER=directsound if no sound output is produced by default. The default is dsound on Windows. On Mac, coreaudio is the default. On all other platforms, sdl is the default. Example: mame pacman -sound portaudio Supported sound subsystems per-platform +------------+--------+---------+-----------+-----------+-----------+------+ | Microsoft | dsound | xaudio2 | portaudio | | sdl [14]. | none | | Windows | | | | | | | +------------+--------+---------+-----------+-----------+-----------+------+ | macOS | | | portaudio | coreaudio | sdl | none | +------------+--------+---------+-----------+-----------+-----------+------+ | Linux and | | | portaudio | | sdl | none | | others | | | | | | | +------------+--------+---------+-----------+-----------+-----------+------+ FOOTNOTES [14] While SDL is not a supported option on official builds for Win- dows, you can compile MAME with SDL support on Windows. -audio_latency <value> The exact behavior depends on the selected audio output module. Smaller values provide less audio delay while requiring better sys- tem performance. Higher values increase audio delay but may help avoid buffer under-runs and audio interruptions. The default is 1. • For PortAudio, see the section on -pa_latency. • XAudio2 calculates audio_latency as 10ms steps. • DSound calculates audio_latency as 10ms steps. • CoreAudio calculates audio_latency as 25ms steps. • SDL calculates audio_latency as Xms steps. Example: mame galaga -audio_latency 1 Core Input Options -[no]coin_lockout / -[no]coinlock Enables simulation of the "coin lockout" feature that is implemented on a number of arcade game PCBs. It was up to the operator whether or not the coin lockout outputs were actually connected to the coin mechanisms. If this feature is enabled, then attempts to enter a coin while the lockout is active will fail and will display a popup message in the user interface (in debug mode). If this feature is disabled, the coin lockout signal will be ignored. The default is ON (-coin_lockout). Example: mame suprmrio -coin_lockout -ctrlr <controller> Specifies a controller configuration file, typically used to set more suitable default input assignments for special controllers. Di- rectories specified using the ctrlrpath option are searched. Con- troller configuration files use a similar format to .cfg used to save system settings. See Controller Configuration Files for more details. The default is NULL (no controller configuration file). Example: mame dkong -ctrlr xarcade -[no]mouse Controls whether or not MAME makes use of mouse controllers. When this is enabled, you will likely be unable to use your mouse for other purposes until you exit or pause the system. Supported mouse controllers depend on your mouseprovider setting. Note that if this setting is off (-nomouse), mouse input may still be enabled depending on the inputs present on the emulated system and your automatic input enable settings. In particular, the de- fault is to enable mouse input when the emulated system has mouse inputs (-mouse_device mouse), so MAME will capture your mouse pointer when you run a system with mouse inputs unless you also change the mouse_device setting. The default is OFF (-nomouse). Example: mame centiped -mouse -[no]joystick / -[no]joy Controls whether or not MAME makes use of game controllers (e.g. joysticks, gamepads and simulation controls). Supported game con- trollers depend on your joystickprovider setting. When this is enabled, MAME will ask the system about which con- trollers are connected. Note that if this setting is off (-nojoystick), joystick input may still be enabled depending on the inputs present on the emulated system and your automatic input enable settings. The default is OFF (-nojoystick). Example: mame mappy -joystick -[no]lightgun / -[no]gun Controls whether or not MAME makes use of lightgun controllers. Note that most lightguns also produce mouse input, so enabling mouse and lightgun controllers simultaneously (using -lightgun and -mouse together) may produce strange behaviour. Supported lightgun con- trollers depend on your lightgunprovider setting. Note that if this setting is off (-nolightgun), lightgun input may still be enabled depending on the inputs present on the emulated system and your automatic input enable settings. The default is OFF (-nolightgun). Example: mame lethalen -lightgun -[no]multikeyboard / -[no]multikey Determines whether MAME differentiates between multiple keyboards. Some systems may report more than one keyboard; by default, the data from all of these keyboards is combined so that it looks like a sin- gle keyboard. Turning this option on will enable MAME to report keypresses on dif- ferent keyboards independently. The default is OFF (-nomultikeyboard). Example: mame sf2ceua -multikey -[no]multimouse Determines whether MAME differentiates between multiple mice. Some systems may report more than one mouse device; by default, the data from all of these mice is combined so that it looks like a single mouse. Turning this option on will enable MAME to report mouse movement and button presses on different mice independently. The default is OFF (-nomultimouse). Example: mame warlords -multimouse -[no]steadykey / -[no]steady Some systems require two or more buttons to be pressed at exactly the same time to make special moves. Due to limitations in the key- board hardware, it can be difficult or even impossible to accomplish that using the standard keyboard handling. This option selects a different handling that makes it easier to register simultaneous button presses, but has the disadvantage of making controls less re- sponsive. The default is OFF (-nosteadykey) Example: mame sf2ua -steadykey -[no]ui_active Enable user interface on top of emulated keyboard (if present). The default is OFF (-noui_active) Example: mame apple2e -ui_active -[no]offscreen_reload / -[no]reload Controls whether or not MAME treats a second button input from a lightgun as a reload signal. In this case, MAME will report the gun's position as (0,MAX) with the trigger held, which is equivalent to an offscreen reload. This is only needed for games that required you to shoot offscreen to reload, and then only if your gun does not support off screen re- loads. The default is OFF (-nooffscreen_reload). Example: mame lethalen -offscreen_reload -joystick_map <map> / -joymap <map> Controls how analog joystick values map to digital joystick con- trols. Systems such as Pac-Man use a 4-way digital joystick and will ex- hibit undesired behavior when a diagonal is triggered; in the case of Pac-Man, movement will stop completely at intersections when di- agonals are triggered and the game will be considerably harder to play correctly. Many other arcade cabinets used 4-way or 8-way joy- sticks (as opposed to full analog joysticks), so for true analog joysticks such as flight sticks and analog thumb sticks, this then needs to be mapped down to the expected 4-way or 8-way digital joy- stick values. To do this, MAME divides the analog range into a 9x9 grid that looks like this: insert 9x9 grid picture here MAME then takes the joystick axis position (for X and Y axes only), maps it to this grid, and then looks up a translation from a joy- stick map. This parameter allows you to specify the map. For instance, an 8-way joystick map traditionally looks like this: insert 8-way map picture here This mapping gives considerable leeway to the angles accepted for a given direction, so that being approximately in the area of the di- rection you want will give you the results you want. Without that, if you were slightly off center while holding the stick left, it would not recognize the action correctly. The default is auto, which means that a standard 8-way, 4-way, or 4-way diagonal map is selected automatically based on the input port configuration of the current system. Generally you will want to set up the -joystick_map setting in the per-system <system>.ini file as opposed to the main MAME.INI file so that the mapping only affects the systems you want it to. See Multiple Configuration Files for further details on per-system con- figuration. Maps are defined as a string of numbers and characters. Since the grid is 9x9, there are a total of 81 characters necessary to define a complete map. Below is an example map for an 8-way joystick that matches the picture shown above: +-----------+-------------------------------------------------------+ | 777888999 | Note that the numeric digits correspond to the keys | | 777888999 | on a numeric keypad. So '7' maps to up+left, '4' maps | | 777888999 | to left, '5' maps to neutral, etc. In addition to the | | 444555666 | numeric values, you can specify the character 's', | | 444555666 | which means "sticky". Sticky map positions will keep | | 444555666 | the output the same as the last non-sticky input sent | | 111222333 | to the system. | | 111222333 | | | 111222333 | | +-----------+-------------------------------------------------------+ To specify the map for this parameter, you can specify a string of rows separated by a '.' (which indicates the end of a row), like so: +-------------------------------------------------------------------------------------------+ | -joymap | | 777888999.777888999.777888999.444555666.444555666.444555666.111222333.111222333.111222333 | +-------------------------------------------------------------------------------------------+ However, this can be reduced using several shorthands supported by the <map> parameter. If information about a row is missing, then it is assumed that any missing data in columns 5-9 are left/right sym- metric with data in columns 0-4; and any missing data in columns 0-4 is assumed to be copies of the previous data. The same logic ap- plies to missing rows, except that up/down symmetry is assumed. By using these shorthands, the 81 character map can be simply speci- fied by this 11 character string: 7778...4445 (which means we then use -joymap 7778...4445) Looking at the first row, 7778 is only 4 characters long. The 5th entry can't use symmetry, so it is assumed to be equal to the previ- ous character '8'. The 6th character is left/right symmetric with the 4th character, giving an '8'. The 7th character is left/right symmetric with the 3rd character, giving a '9' (which is '7' with left/right flipped). Eventually this gives the full 777888999 string of the row. The second and third rows are missing, so they are assumed to be identical to the first row. The fourth row decodes similarly to the first row, producing 444555666. The fifth row is missing so it is assumed to be the same as the fourth. The remaining three rows are also missing, so they are assumed to be the up/down mirrors of the first three rows, giving three final rows of 111222333. With 4-way games, sticky becomes important to avoid problems with diagonals. Typically you would choose a map that looks something like this: insert 9x9 4-way sticky grid picture here This means that if you press left, then roll the stick towards up (without re-centering it) you'll pass through the sticky section in the corner. As you do, MAME will read that sticky corner as left as that's the last non-sticky input it received. As the roll gets into the upward space of the map, this then switches to an up motion. This map would look somewhat like: +-----------+--------------------------------------------------------+ | s8888888s | For this mapping, we have a wide range for the | | 4s88888s6 | cardinal directions on 8, 4, 6, and 2. We have sticky | | 44s888s66 | on the meeting points between those cardinal | | 444555666 | directions where the appropriate direction isn't | | 444555666 | going to be completely obvious. | | 444555666 | | | 44s222s66 | | | 4s22222s6 | | | s2222222s | | +-----------+--------------------------------------------------------+ To specify the map for this parameter, you can specify a string of rows separated by a '.' (which indicates the end of a row), like so: +-------------------------------------------------------------------------------------------+ | -joymap | | s8888888s.4s88888s6.44s888s66.444555666.444555666.444555666.44s222s66.4s22222s6.s2222222s | +-------------------------------------------------------------------------------------------+ Like before, because of the symmetry between top and bottom and left and right, we can shorten this down to: +--------------------------+ | -joymap s8.4s8.44s8.4445 | +--------------------------+ -joystick_deadzone <value> / -joy_deadzone <value> / -jdz <value> If you play with an analog joystick, the center can drift a little. joystick_deadzone tells how far along an axis you must move before the axis starts to change. This option expects a float in the range of 0.0 to 1.0. Where 0 is the center of the joystick and 1 is the outer limit. The default is 0.15. Example: mame sinistar -joystick_deadzone 0.3 -joystick_saturation <value> / joy_saturation <value> / -jsat <value> If you play with an analog joystick, the ends can drift a little, and may not match in the +/- directions. joystick_saturation tells how far along an axis movement change will be accepted before it reaches the maximum range. This option expects a float in the range of 0.0 to 1.0, where 0 is the center of the joystick and 1 is the outer limit. The default is 0.85. Example: mame sinistar -joystick_saturation 1.0 -joystick_threshold <value> / joy_threshold <value> / -jthresh <value> When a joystick axis (or other absolute analog axis) is assigned to a digital input, this controls how far it must be moved from the neutral position (or centre) to be considered active or switched on. This option expects a float in the range of 0.0 to 1.0, where 0 means any movement from the neutral position is considered active, and 1 means only the outer limits are considered active. This threshold is not adjusted to the range between the dead zone and saturation point. Note that if a joystick map is configured, that will take precedence over this setting when a joysticks main X/Y axes are assigned to digital inputs. The default is 0.3. Example: mame raiden -joystick_threshold 0.2 -[no]natural Allows user to specify whether or not to use a natural keyboard or not. This allows you to start your system in a 'native' mode, de- pending on your region, allowing compatibility for non-"QWERTY" style keyboards. The default is OFF (-nonatural) In "emulated keyboard" mode (the default mode), MAME translates pressing/releasing host keys/buttons to emulated keystrokes. When you press/release a key/button mapped to an emulated key, MAME presses/releases the emulated key. In "natural keyboard" mode, MAME attempts to translate characters to keystrokes. The OS translates keystrokes to characters (similarly to when you type into a text editor), and MAME attempts to translate these characters to emulated keystrokes. There are a number of unavoidable limitations in "natural keyboard" mode: • The emulated system driver and/or keyboard device has to support it. • The selected keyboard layout must match the keyboard layout se- lected in the emulated OS! • Keystrokes that dont produce characters cant be translated (e.g. pressing a modifier on its own such as shift, ctrl, or alt). • Holding a key until the character repeats will cause the emulated key to be pressed repeatedly as opposed to being held down. • Dead key sequences are cumbersome to use at best. • It wont work at all if IME edit is involved (e.g. for Chinese, Japanese or Korean language input). Example: mame coco2 -natural -[no]joystick_contradictory Enable contradictory direction digital joystick input at the same time such as Left and Right or Up and Down at the same time. The default is OFF (-nojoystick_contradictory) Example: mame pc_smb -joystick_contradictory -coin_impulse [n] Set coin impulse time based on n (n<0 disable impulse, n==0 obey driver, 0<n set time n). Default is 0. Example: mame contra -coin_impulse 1 Core Input Automatic Enable Options -paddle_device ( none | keyboard | mouse | lightgun | joystick ) -adstick_device ( none | keyboard | mouse | lightgun | joystick ) -pedal_device ( none | keyboard | mouse | `lightgun | joystick ) -dial_device ( none | keyboard | mouse | lightgun | joystick ) -trackball_device ( none | keyboard | mouse | lightgun | joystick ) -lightgun_device ( none | keyboard | mouse | lightgun | joystick ) -positional_device ( none | keyboard | mouse | lightgun | joystick ) -mouse_device ( none | keyboard | mouse | lightgun | joystick ) Each of these options sets whether mouse, joystick or lightgun con- trollers should be enabled when running an emulated system that uses a particular class of analog inputs. These options can effectively set -mouse, -joystick and/or -lightgun depending on the type of in- puts present on the emulated system. Note that these options will not override explicit -nomouse, -nojoystick and/or -nolightgun set- tings at a higher priority level (e.g. in a more specific INI file or on the command line). For example, if you specify the option -paddle_device mouse, then mouse controls will automatically be enabled when you run a game that has paddle controls (e.g. Super Breakout), even if you speci- fied -nomouse . The default is to automatically enable mouse controls when running emulated systems with mouse inputs (-mouse_device mouse). Example: mame sbrkout -paddle_device mouse TIP: Note that these settings can override -nomouse, -nojoystick and/or -nolightgun depending on the inputs present on the emulated system. Debugging Options -[no]verbose / -[no]v Displays internal diagnostic information. This information is very useful for debugging problems with your configuration. The default is OFF (-noverbose). Example: mame polepos -verbose TIP: IMPORTANT: When reporting bugs to MAMEdev, please run with -verbose and include the resulting information. -[no]oslog Output error.log messages to the system diagnostic output, if one is present. By default messages are sent to the standard error output (this is typically displayed in the terminal or command prompt window, or saved to a system log file). On Windows, if a debugger is attached (e.g. the Visual Studio debugger or WinDbg), messages will be sent to the debugger instead. The default is OFF (-nooslog). Example: mame mappy -oslog -[no]log Creates a file called error.log which contains all of the internal log messages generated by the MAME core and system drivers. This can be used at the same time as -oslog to output the log data to both targets as well. The default is OFF (-nolog). Example 1: mame qbert -log Example 2: mame qbert -oslog -log -[no]debug Activates the integrated debugger. By default, pressing the back- tick/tilde (~) key during emulation breaks into the debugger. MAME also breaks into the debugger after the initial soft reset on startup if the debugger is active. See MAME Debugger for informa- tion on using the debugger. The default is OFF (-nodebug). Example: mame indy_4610 -debug -debugger <module> Chooses the module to use for debugging the target system when the debug option is on. Available debugger modules depend on the host platform and build options. Supported debugger modules: windows Win32 GUI debugger (default on Windows). Only supported on Windows. qt Qt GUI debugger (default on Linux). Supported on Windows, Linux and macOS, but only included on Linux by default. Set USE_QTDEBUG=1 when compiling MAME to include the Qt debugger on Windows or macOS. osx Cocoa GUI debugger (default on macOS). Only supported on ma- cOS. imgui ImgUi GUI debugger displayed in first MAME window. Requires video option to be set to bgfx. Supported on all platforms with BGFX video output support. gdbstub Acts as a remote debugging server for the GNU debugger (GDB). Only a small subset of the CPUs emulated by MAME are sup- ported. Use the debugger_port option to set the listening port and the debugger_host option to set the address to bind to. Supported on all platforms with TCP socket support. Example: mame ambush -debug -debugger qt -debugscript <filename> Specifies a file that contains a list of debugger commands to exe- cute immediately upon startup. The default is NULL (no commands). Example: mame galaga -debug -debugscript testscript.txt -[no]update_in_pause Enables updating of the main screen bitmap while the system is paused. This means that the video update callback will be called repeatedly while the emulation is paused, which can be useful for debugging. The default is OFF (-noupdate_in_pause). Example: mame indy_4610 -update_in_pause -watchdog <duration> / -wdog <duration> Enables an internal watchdog timer that will automatically kill the MAME process if more than <duration> seconds passes without a frame update. Keep in mind that some systems sit for a while during load time without updating the screen, so <duration> should be long enough to cover that. 10-30 seconds on a modern system should be plenty in general. By default there is no watchdog. Example: mame ibm_5150 -watchdog 30 -debugger_host <address> Set the IP address to listen on to accept GDB connections when using the GDB stub debugger module (see the debugger option). The default is localhost. Example: mame rfjet -debug -debugger gdbstub -debugger_host 0.0.0.0 -debugger_port <port> Set the TCP port number to accept GDB connections on when using the GDB stub debugger module (see the debugger option). The default is 23946. Example: mame rfjet -debug -debugger gdbstub -debugger_port 2159 -debugger_font <fontname> / -dfont <fontname> Specifies the name of the font to use for debugger windows. The Windows default font is Lucida Console. The Mac (Cocoa) default font is system fixed-pitch font default (typically Monaco). The Qt default font is Courier New. Example: mame marble -debug -debugger_font "Comic Sans MS" -debugger_font_size <points> / -dfontsize <points> Specifies the size of the font to use for debugger windows, in points. The Windows default size is 9 points. The Qt default size is 11 points. The Mac (Cocoa) default size is the system default size. Example: mame marble -debug -debugger_font "Comic Sans MS" -debugger_font_size 16 Core Communication Options -comm_localhost <string> Local address to bind to. This can be a traditional xxx.xxx.xxx.xxx address or a string containing a resolvable hostname. The default is value is 0.0.0.0 (which binds to all local IPv4 ad- dresses). Example: mame arescue -comm_localhost 192.168.1.2 -comm_localport <string> Local port to bind to. This can be any traditional communications port as an unsigned 16-bit integer (0-65535). The default value is 15122. Example: mame arescue -comm_localhost 192.168.1.2 -comm_localport 30100 -comm_remotehost <string> Remote address to connect to. This can be a traditional xxx.xxx.xxx.xxx address or a string containing a resolvable host- name. The default is value is "0.0.0.0" (which binds to all local IPv4 ad- dresses). Example: mame arescue -comm_remotehost 192.168.1.2 -comm_remoteport <string> Remote port to connect to. This can be any traditional communica- tions port as an unsigned 16-bit integer (0-65535). The default value is "15122". Example: mame arescue -comm_remotehost 192.168.1.2 -comm_remoteport 30100 -[no]comm_framesync Synchronize frames between the communications network. The default is OFF (-nocomm_framesync). Example: mame arescue -comm_remotehost 192.168.1.3 -comm_remoteport 30100 -comm_framesync Core Misc Options -[no]drc Enable DRC (dynamic recompiler) CPU core if available for maximum speed. The default is ON (-drc). Example: mame ironfort -nodrc -[no]drc_use_c Force DRC to use the C code backend. The default is OFF (-nodrc_use_c). Example: mame ironfort -drc_use_c -[no]drc_log_uml Write DRC UML disassembly log. The default is OFF (-nodrc_log_uml). Example: mame ironfort -drc_log_uml -[no]drc_log_native Write DRC native disassembly log. The default is OFF (-nodrc_log_native). Example: mame ironfort -drc_log_native -bios <biosname> Specifies the specific BIOS to use with the current system, for sys- tems that make use of a BIOS. The -listbios output will list all of the possible BIOS names for a system, as does the -listxml output. The default is default. Example: mame mslug -bios unibios33 -[no]cheat / -[no]c Activates the cheat menu with autofire options and other tricks from the cheat database, if present. This also activates additional op- tions on the slider menu for overclocking/underclocking. Be advised that savestates created with cheats on may not work cor- rectly with this turned off and vice-versa. The default is OFF (-nocheat). Example: mame dkong -cheat -[no]skip_gameinfo Forces MAME to skip displaying the system info screen. The default is OFF (-noskip_gameinfo). Example: mame samsho5 -skip_gameinfo -uifont <fontname> Specifies the name of a font file to use for the UI font. If this font cannot be found or cannot be loaded, the system will fall back to its built-in UI font. On some platforms fontname can be a system font name instead of a BDF font file. The default is default (use the OSD-determined default font). Example: mame -uifont "Comic Sans MS" -ui <type> Specifies the type of UI to use, either simple or cabinet. The default is cabinet (-ui cabinet). Example: mame -ui simple -ramsize [n] Allows you to change the default RAM size (if supported by driver). Example: mame coco -ramsize 16K -[no]confirm_quit Display a Confirm Quit dialog to screen on exit, requiring one extra step to exit MAME. The default is OFF (-noconfirm_quit). Example: mame pacman -confirm_quit -[no]ui_mouse Displays a mouse cursor when using the built-in MAME user interface. The default is ON (-ui_mouse). Example: mame -ui_mouse -language <language> Specify a localization language found in the languagepath tree. Example: mame -language Japanese -[no]nvram_save Save the NVRAM contents when exiting machine emulation. By turning this off, you can retain your previous NVRAM contents as any current changes made will not be saved. Turning this option off will also unconditionally suppress the saving of .nv files associated with some types of software cartridges. The default is ON (-nvram_save). Example: mame galaga88 -nonvram_save Scripting Options -autoboot_command "<command>" Command string to execute after machine boot (in quotes " "). To is- sue a quote to the emulation, use """ in the string. Using \n will create a new line, issuing what was typed prior as a command. This works only with systems that support natural keyboard mode. Example: mame c64 -autoboot_delay 5 -autoboot_command "load """$""",8,1\n" -autoboot_delay [n] Timer delay (in seconds) to trigger command execution on autoboot. Example: mame c64 -autoboot_delay 5 -autoboot_command "load """$""",8,1\n" -autoboot_script / -script [filename.lua] File containing scripting to execute after machine boot. Example: mame ibm5150 -autoboot_script myscript.lua -[no]console Enables emulator Lua Console window. The default of OFF (-noconsole). Example: mame ibm5150 -console -plugins Enable the use of Lua Plugins. The default is ON (-plugins). Example: mame apple2e -plugins -plugin [plugin shortname] A list of Lua Plugins to enable, comma separated. Example: mame alcon -plugin cheat,discord,autofire -noplugin [plugin shortname] A list of Lua Plugins to disable, comma separated. Example: mame alcon -noplugin cheat HTTP Server Options -[no]http Enable HTTP server. The default is OFF (-nohttp). Example: mame -http -http_port <port> Choose HTTP server port. The default is 8080. Example: mame apple2 -http -http_port 6502 -http_root <rootfolder> Choose HTTP server document root. The default is web. Example: mame apple2 -http -http_port 6502 -http_root C:\Users\me\appleweb\root PortAudio Options -pa_api API Choose which API that PortAudio should use to talk to your sound hardware. You can use -verbose to see which APIs are available. The default is none. Example 1: mame -sound portaudio -verbose Attempting load of mame.ini ... PortAudio: API MME has 20 devices PortAudio: MME: " - Input" PortAudio: MME: "Microphone (3- USB Camera-B4.09" PortAudio: MME: "Line (AVerMedia Live Gamer HD 2" PortAudio: MME: "Digital Audio Interface (AVerMe" PortAudio: MME: "Headset Microphone (Razer Krake" ... PortAudio: MME: " - Output" PortAudio: MME: "Headset Earphone (Razer Kraken " PortAudio: MME: "Digital Audio (S/PDIF) (High De" PortAudio: MME: "NX-EDG27 (NVIDIA High Definitio" ... PortAudio: API Windows DirectSound has 20 devices PortAudio: Windows DirectSound: "Primary Sound Capture Driver" PortAudio: Windows DirectSound: "Headset Microphone (Razer Kraken 7.1 V2)" PortAudio: Windows DirectSound: "Primary Sound Driver" (default) PortAudio: Windows DirectSound: "Headset Earphone (Razer Kraken 7.1 V2)" PortAudio: Windows DirectSound: "Digital Audio (S/PDIF) (High Definition Audio Device)" PortAudio: Windows DirectSound: "NX-EDG27 (NVIDIA High Definition Audio)" ... PortAudio: API Windows WASAPI has 18 devices PortAudio: Windows WASAPI: "Headset Earphone (Razer Kraken 7.1 V2)" PortAudio: Windows WASAPI: "Digital Audio (S/PDIF) (High Definition Audio Device)" PortAudio: Windows WASAPI: "NX-EDG27 (NVIDIA High Definition Audio)" PortAudio: Windows WASAPI: "Headset Microphone (Razer Kraken 7.1 V2)" ... PortAudio: API Windows WDM-KS has 22 devices PortAudio: Windows WDM-KS: "Output (NVIDIA High Definition Audio)" PortAudio: Windows WDM-KS: "SPDIF Out (HD Audio SPDIF out)" PortAudio: Windows WDM-KS: "Headset Microphone (Razer Kraken 7.1 V2)" PortAudio: Windows WDM-KS: "Headset Earphone (Razer Kraken 7.1 V2)" PortAudio: Windows WDM-KS: "Microphone (VDVAD Wave)" PortAudio: Windows WDM-KS: "Speakers (VDVAD Wave)" ... PortAudio: Sample rate is 48000 Hz, device output latency is 218.67 ms PortAudio: Allowed additional buffering latency is 18.00 ms/864 frames Example 2: mame suprmrio -sound portaudio -pa_api "Windows WASAPI" -pa_device device Choose which sound device to output through. This would typically be one of the outputs on your sound card or a USB headset. The default is none. Example: mame suprmrio -sound portaudio -pa_api "Windows WASAPI" -pa_device "NX-EDG27 (NVIDIA High Definition Audio)" -pa_latency latency Choose the buffer size for PortAudio output; this is specified in seconds. Lower numbers have less latency but may increase stutter in the sound. Decimal places are supported. Try starting from 0.20 and decrease or increase until you find the best number your hard- ware and OS are capable of handling. The default is 0. Example: mame suprmrio -sound portaudio -pa_api "Windows WASAPI" -pa_device "NX-EDG27 (NVIDIA High Definition Audio)" -pa_latency 0.20 Windows-Specific Command-line Options This section contains configuration options that are specific to the native (non-SDL) Windows version of MAME. Performance options -priority <priority> Sets the thread priority for the MAME threads. By default the prior- ity is left alone to guarantee proper cooperation with other appli- cations. The valid range is -15 to 1, with 1 being the highest pri- ority. The default is 0 (NORMAL priority). -profile [n] Enables profiling, specifying the stack depth of [n] to track. Full screen options -[no]triplebuffer / -[no]tb Enables or disables triple buffering. Normally, MAME just draws di- rectly to the screen, without any fancy buffering. But with this option enabled, MAME creates three buffers to draw to, and cycles between them in order. It attempts to keep things flowing such that one buffer is currently displayed, the second buffer is waiting to be displayed, and the third buffer is being drawn to. -triplebuffer will override -waitvsync, if the buffer is successfully created. This option does not work with -video gdi. The default is OFF (-notriplebuffer). -full_screen_brightness <value> / -fsb <value> Controls the brightness, or black level, of the entire display. The standard value is 1.0. Lower values (down to 0.1) will produce a darkened display, while higher values (up to 2.0) will give a brighter display. Note that not all video cards have hardware to support this option. This option does not work with -video gdi. The default is 1.0. -full_screen_contrast <value> / -fsc <value> Controls the contrast, or white level, of the entire display. The standard value is 1.0. Lower values (down to 0.1) will produce a dimmer display, while higher values (up to 2.0) will give a more saturated display. Note that not all video cards have hardware to support this option. This option does not work with -video gdi. The default is 1.0. -full_screen_gamma <value> / -fsg <value> Controls the gamma, which produces a potentially nonlinear black to white ramp, for the entire display. The standard value is 1.0, which gives a linear ramp from black to white. Lower values (down to 0.1) will increase the nonlinearity toward black, while higher values (up to 3.0) will push the nonlinearity toward white. Note that not all video cards have hardware to support this option. This option does not work with -video gdi. The default is 1.0. Input device options -[no]dual_lightgun / -[no]dual Controls whether or not MAME attempts to track two lightguns that appear as a single mouse. This option requires the lightgun option to be on and the lightgunprovider option to be set to win32. This option supports certain older dual lightgun setups that work by setting the mouse pointer location at the moment a lightgun trigger is activated. The primary and secondary triggers on the first lightgun correspond to the first and second mouse buttons, and the primary and secondary triggers on the second lightgun correspond to the third and fourth mouse buttons. If you have multiple lightguns connected, you will probably just need to enable the lightgun option, use the default lightgunprovider option of rawinput, and configure each lightgun individually. The default is OFF (-nodual_lightgun). SDL-Specific Command-line Options This section contains configuration options that are specific to any build supported by SDL (including Windows when built with SDL instead of native). Performance Options -[no]sdlvideofps Enable output of benchmark data on the SDL video subsystem, includ- ing your systems video driver, X server (if applicable), and OpenGL stack in -video opengl mode. Video Options -[no]centerh Center horizontally within the view area. Default is ON (-centerh). -[no]centerv Center vertically within the view area. Default is ON (-centerv). Video Soft-Specific Options -scalemode Scale mode: none, async, yv12, yuy2, yv12x2, yuy2x2 (-video soft only). Default is none. SDL Keyboard Mapping -keymap Enable keymap. Default is OFF (-nokeymap) -keymap_file <file> Keymap file name. Default is keymap.dat. SDL Input Options -enable_touch Enable support for touch input. If this option is switched off, mouse input simulated from touch devices will be used instead. De- fault is OFF (-noenable_touch) -sixaxis Use special handling for PlayStation 3 SixAxis controllers. May cause undesirable behaviour with other controllers. Only affects the sdljoy joystick provider. Default is OFF (-nosixaxis) -[no]dual_lightgun / -[no]dual Controls whether or not MAME attempts to track two lightguns that appear as a single mouse. This option requires the lightgun option to be on and the lightgunprovider option to be set to sdl. This option supports dual lightgun setups that work by setting the mouse pointer location at the moment a lightgun trigger is acti- vated. The primary and secondary triggers on the first lightgun correspond to the first and second mouse buttons, and the primary and secondary triggers on the second lightgun correspond to the third and fourth mouse buttons. The default is OFF (-nodual_lightgun). SDL Lightgun Mapping -lightgun_index1 <name> -lightgun_index2 <name> ... -lightgun_index8 <name> Device name or ID mapped to a given lightgun slot. SDL Low-level Driver Options -videodriver <driver> SDL video driver to use ('x11', 'directfb', ... or 'auto' for SDL default) -audiodriver <driver> SDL audio driver to use ('alsa', 'arts', ... or 'auto' for SDL de- fault) -gl_lib <driver> Alternative libGL.so to use; 'auto' for system default Command-line Index This is a complete index of all command-line options and verbs for MAME, suitable for quickly finding a given option. Universal Command-line Options This section contains configuration options that are applicable to all MAME configurations (including both SDL and Windows native). Core Verbs help validate Configuration Verbs createconfig showconfig showusage Frontend Verbs listxml listfull listsource listclones listbrothers listcrc listroms listbios listsamples verifyroms verifysamples romident listdevices listslots listmedia listsoftware verifysoftware getsoftlist verifysoftlist OSD-related Options uimodekey controller_map background_input uifontprovider keyboardprovider mouseprovider lightgunprovider joystickprovider midiprovider networkprovider OSD CLI Verbs listmidi listnetwork OSD Output Options output Configuration Options noreadconfig Core Search Path Options homepath rompath hashpath samplepath artpath ctrlrpath inipath fontpath cheatpath crosshairpath pluginspath languagepath swpath Core Output Directory Options cfg_directory nvram_directory input_directory state_directory snapshot_directory diff_directory comment_directory Core State/Playback Options [no]rewind / rewind rewind_capacity state [no]autosave playback [no]exit_after_playback record mngwrite aviwrite wavwrite snapname snapsize snapview [no]snapbilinear statename [no]burnin Core Performance Options [no]autoframeskip frameskip seconds_to_run [no]throttle [no]sleep speed [no]refreshspeed numprocessors bench [no]lowlatency Core Rotation Options [no]rotate [no]ror [no]rol [no]autoror [no]autorol [no]flipx [no]flipy Core Video Options video numscreens [no]window [no]maximize [no]keepaspect [no]waitvsync [no]syncrefresh prescale [no]filter [no]unevenstretch Core Full Screen Options [no]switchres Core Per-Window Video Options screen aspect resolution view Core Artwork Options [no]artwork_crop fallback_artwork override_artwork Core Screen Options brightness contrast gamma pause_brightness effect Core Vector Options beam_width_min beam_width_max beam_intensity_weight beam_dot_size flicker Core Video OpenGL Debugging Options [no]gl_forcepow2texture [no]gl_notexturerect [no]gl_vbo [no]gl_pbo Core Video OpenGL GLSL Options [no]gl_glsl gl_glsl_filter glsl_shader_mame[0-9] glsl_shader_screen[0-9] Core Sound Options samplerate [no]samples [no]compressor volume sound audio_latency Core Input Options [no]coin_lockout ctrlr [no]mouse [no]joystick [no]lightgun [no]multikeyboard [no]multimouse [no]steadykey [no]ui_active [no]offscreen_reload joystick_map joystick_deadzone joystick_saturation joystick_threshold [no]natural [no]joystick_contradictory coin_impulse Core Input Automatic Enable Options paddle_device adstick_device pedal_device dial_device trackball_device lightgun_device positional_device mouse_device Core Debugging Options [no]verbose [no]oslog [no]log [no]debug debugger debugscript [no]update_in_pause watchdog debugger_host debugger_port debugger_font debugger_font_size Core Communication Options comm_localhost comm_localport comm_remotehost comm_remoteport [no]comm_framesync Core Misc Options [no]drc [no]drc_use_c [no]drc_log_uml [no]drc_log_native bios [no]cheat [no]skip_gameinfo uifont ui ramsize [no]confirm_quit [no]ui_mouse language [no]nvram_save Scripting Options autoboot_command autoboot_delay autoboot_script [no]console [no]plugins plugin noplugin HTTP Server Options http http_port http_root PortAudio Options pa_api pa_device pa_latency Windows-Specific Command-line Options This section contains configuration options that are specific to the native (non-SDL) Windows version of MAME. Windows Performance Options priority profile Windows Full Screen Options [no]triplebuffer full_screen_brightness full_screen_contrast full_screen_gamma Windows Input Device Options [no]dual_lightgun SDL-Specific Command-line Options This section contains configuration options that are specific to any build supported by SDL (including Windows when built with SDL instead of native). SDL Performance Options [no]sdlvideofps SDL Video Options [no]centerh [no]centerv SDL Video Soft-Specific Options scalemode SDL Keyboard Mapping keymap keymap_file SDL Input Options [no]enable_touch [no]sixaxis [no]dual_lightgun SDL Lightgun Mapping lightgun_index SDL Low-level Driver Options videodriver audiodriver gl_lib PLUGINS • Introduction • Using plugins • Included plugins Introduction MAME supports plugins that can provide additional functionality. Plug- ins have been written to communicate with external programs, play games automatically, display internal game structures like hitboxes, provide alternate user interfaces, and automatically test emulation. See Lua Scripting Interface for more information about MAMEs Lua API. Using plugins To enable plugins, you need to turn on the plugins option, and make sure the pluginspath option includes the folder where your plugins are stored. You can set the plugins option in an INI file or on the com- mand line. You can set the pluginspath option by selecting Configure Options from the system selection menu, then selecting Configure Direc- tories, and then selecting Plugins (you can also set it in an INI file or on the command line). Many plugins need to store settings and/or data. The homepath option sets the folder where plugins should save data (defaults to the working directory). You can change this by selecting Configure Options from the system selection menu, then selecting Configure Directories, and then selecting Plugin Data. To turn individual plugins on or off, first make sure plugins are en- abled, then select Configure Options from the system selection menu, and then select Plugins. You will need to completely exit MAME and start it again for changes to the enabled plugins to take effect. You can also use the plugin option on the command line, or change the set- tings in the plugin.ini file. If an enabled plugin needs additional configuration, or if it needs to show information, a Plugin Options item will appear in the main menu (accessed by pressing Tab during emulation by default). Included plugins MAME includes several plugins providing useful functionality, and serv- ing as sample code that you can use as a starting point when writing your own plugins. Autofire Plugin • Introduction • Autofire buttons settings • Notes and potential pitfalls Introduction The autofire plugin allows you to simulate repeatedly pressing an emu- lated button by holding down a key or button combination. This can help people with certain disabilities or injuries play shooting games, and may help reduce the risk of repetitive strain injuries (or keyboard damage). To configure the autofire plugin, activate the main menu (press Tab during emulation by default), select Plugin Options, and then select Autofire. Configured autofire buttons for the current system are listed, along with their repetition rates and activation hotkeys (ini- tially there will be no autofire buttons configured). Select an aut- ofire button to change settings, or choose Add autofire button to set up a new autofire button. See Autofire buttons settings for details on setting up an autofire button. You can delete an autofire button by highlighting it in the menu and pressing the UI Clear key (Del/Delete/Forward Delete on the keyboard by default). Autofire settings are saved in the autofire folder in the plugin data folder (see the homepath option). A file is created for each system with autofire buttons configured, named according to the systems short name (or ROM set name), with the extension .cfg. For example, autofire settings for Super-X will be saved in the file superx.cfg in the aut- ofire folder in your plugin data folder. The autofire settings are stored in JSON format. Autofire buttons settings The options for adding a new autofire button or modifying an existing autofire button are the same. Select Input to set the emulated button that you want to simulate pressing repeatedly. Currently, only player buttons are supported. Typically youll set this to the primary fire button for shooting games. This is most often P1 Button 1 or the equivalent for another player, but it might have a different name. On Konamis Gradius games, P1 Button 2 is the primary fire button. Select Hotkey to set the control (or combination of controls) youll use to activate the autofire button. This can be any combination that MAME supports for activating a digital input. On frames and Off frames are the number of consecutive emulated video frames that the emulated button will be held and released for, respec- tively. Adjust the value with the UI Left/Right keys, or click the ar- rows. Press the UI Clear key to reset the values to one frame. Lower values correspond to pressing the button at a faster rate. Depending on how fast the system reads inputs, you may need higher numbers than 1 for the system to recognise the button being released and pressed again (e.g. 2 on frames and 2 off frames works for Alcon). Experiment with different values to get the best effect. When adding a new autofire button, there is a Cancel option that changes to Create after you set the input and hotkey. Select Create to finish creating the autofire button and return to the list of autofire buttons. The new autofire button will be added at the end of the list. Press the UI Back key (Escape/Esc on the keyboard by default), or se- lect Cancel before setting the input/hotkey, to return to the previous menu without creating the new autofire button. When modifying an existing autofire button, select Done or press the UI Cancel key to return to the list of autofire buttons. Changes take ef- fect immediately. Notes and potential pitfalls Autofire buttons act as if theyre wired in parallel with MAMEs regular controls. This means that if you set the activation hotkey for an aut- ofire button to a button or key thats also assigned to one of the emu- lated inputs directly, you may get unexpected results. Using Gradius as an example: • Suppose you set button 1 on your controller to fire, and set an aut- ofire hotkey to button 1 as well. Holding the button down to shoot will not trigger the autofire effect: the button will never be re- leased as youre holding the non-autofire button 1 down. This will also happen if you set a different button as autofire (say, button 3 in this case), and hold button 1 down while also pressing button 3. • If you set button 3 on your controller to autofire and assign button 3 to powerup as well, you will trigger the powerup action every time you grab a powerup because the powerup button is also being held down along with the autofire button. It is recommended that you choose control combinations for autofire hotkeys that are not assigned to any other emulated inputs in the sys- tem. Autofire is not necessarily desirable in all situations. For example using autofire in Super-X with the blue lightning weapon equipped at high power levels will only produce a single beam, greatly reducing the weapons effectiveness. The fire button must be held down to produce all beams. Some shooting games (e.g. Raiden Fighters) require the pri- mary fire button to be held down for a charged special attack. This means its often necessary to have a non-autofire input for the primary fire button assigned to play effectively. Console Plugin The console plugin provides functionality for MAMEs interactive Lua console. It is not used directly. Use the console option to activate the interactive Lua console. See Lua Scripting Interface for more in- formation about MAMEs Lua API. Data Plugin The data plugin loads information from various external support files so it can be displayed in MAME. If the plugin is enabled, info is show in the Infos tab of the right-hand pane on the system and software se- lection menus. The info viewer can be shown by clicking the toolbar button on the system and software selection menus, or by choosing Ex- ternal DAT View from the main menu during emulation (this menu item will not appear if the data plugin is not enabled, or if no information is available for the emulated system). To set the folders where the data plugin looks for supported files, choose Configure Options on the system selection menu, then choose Con- figure Directories, and then choose DATs. You can also set the histo- rypath option in your ui.ini file. Loading large data files like history.xml can take quite a while, so please be patient the first time you start MAME after updating or adding new data files. The following files are supported: history.xml From Gaming-History (formerly Arcade-History) mameinfo.dat From MASHs MAMEINFO messinfo.dat From progetto-SNAPS MESSINFO.dat gameinit.dat From progetto-SNAPS GameInit.dat command.dat from progetto-SNAPS Command.dat score3.htm Top Scores from the MAME Action Replay Page Japanese mameinfo.dat and command.dat From MAME E2J sysinfo.dat From the defunct Progetto EMMA site story.dat From the defunct MAMESCORE site If you install hi2txt, the data plugin can also show high scores from non-volatile memory or saved by the hiscore support plugin for sup- ported games. Note that you can only use a single file of each type at a time. You cannot, for example, use the English and Japanese mameinfo.dat files simultaneously. The data plugin creates a history.db file in the data folder in the plugin data folder (see the homepath option). This file stores the in- formation from the support files in a format suitable for rapid load- ing. It uses the SQLite3 database format. Discord Presence Plugin The Discord presence plugin works with the Discord app for Windows, ma- cOS or Linux to set your activity to show what youre doing in MAME. The activity is set to In menu if youre using the system or software selection menu, Playing if emulation is running, or Paused if emulation is paused. The details are set to show the system name and software description if applicable. Dummy Test Plugin This is a sample plugin that shows how to set necessary plugin meta- data, register callbacks, and display a simple menu. It prints status messages, and it adds a Dummy option to the Plugin Options menu. GDB Stub Plugin The GDB stub plugin acts as a remote debugging server for the GNU de- bugger (GDB). This allows you to connect to MAME and debug supported systems using GDB. The plugin listens for connections on port 2159 on the IPv4 loopback address (127.0.0.1). Only Intel 80386 (i386) family processors are supported. See the debugger option for another GDB remote debugging implementation with support for more CPUs and configurable listening ports. Hiscore Support Plugin The hiscore support plugin saves and restores high scores for games that did not originally save high scores in non-volatile memory. Note that this plugin modifies the contents of memory directly with no coor- dination with the emulated software, and hence changes behaviour. This may have undesirable effects, including broken gameplay or causing the emulated software to crash. The plugin includes a hiscore.dat file that contains the information on how to save and restore high scores for supported systems. This file must be kept up-to-date when system definitions change in MAME. High scores can be saved automatically either on exit, or a few seconds after theyre updated in memory. To change the setting, activate the main menu (press Tab during emulation by default), select Plugin Op- tions, and then select Hiscore Support. Change the Save scores option by highlighting it and using the UI Left/Right keys, or clicking the arrows. High score data is saved in the hiscore folder in the plugin data folder (see the homepath option). A file with a name corresponding the system short name (or ROM set name) with the extension .hi. For exam- ple, high scores for the game Moon Cresta will be saved in the file mooncrst.hi in the hiscore folder in your plugin data folder. The set- tings for the hiscore support plugin are stored in the file plugin.cfg in the hiscore folder in the plugin data folder (this file is in JSON format). Input Macro Plugin • Introduction • Editing input macros • Example macros • Raiden autofire • Track & Field sprint cheat • Street Fighter II Shoryuken Introduction The input macro plugin allows you to trigger a sequence of emulated in- put actions with a key or button combination. This can help people with disabilities or injuries that make some input sequences difficult. It can also be used as a way to cheat in games that require rapid se- quences of inputs, like the running events in Track & Field, or the eating minigame in Daisu-Kiss. To configure the input macro plugin, activate the main menu (press Tab during emulation by default), select Plugin Options, and then select Input Macros. Configured input macros for the current system are listed, along with their activation sequences (initially there will be no input macros configured). Select a macro to edit it, or choose Add macro to set up a new input macro. See Editing input macros for de- tails on editing input macros. You can delete an input macro by high- lighting it in the menu and pressing the UI Clear key (Del/Delete/For- ward Delete on the keyboard by default). Input macros are saved in the inputmacro folder in the plugin data folder (see the homepath option). A file is created for each system with input macros configured, named according to the systems short name (or ROM set name), with the extension .cfg. For example, input macros for Daisu-Kiss will be saved in the file daiskiss.cfg in the inputmacro folder in your plugin data folder. The input macros are stored in JSON format. Editing input macros The options for editing input macros are the same whether youre creat- ing a new macro or editing an existing macro. Input macros consist of a sequence of steps. Each step optionally waits for a configurable de- lay, then activates one or more emulated inputs for a specified dura- tion. You can choose what should happen if the activation sequence is still held when the final step of the macro completes: the emulated in- puts can be released, the final step can be prolonged, or the macro can loop back to any step in the sequence. The settings in first section of the macro editing menu apply to the macro as a whole: • The Name will be used in the list of input macros, so it helps to make it descriptive. Press the UI Select key (Return/Enter on the keyboard or the first button on the first joystick by default) to edit the current name, or press the UI Clear key to type a new name. Press the UI Select key before moving to another menu item to save the new name; press the UI Back key (Escape/Esc on the keyboard by default) to change discard the new name. • Select Activation combination to set the control (or combination of controls) you want to use to activate the macro. Keep in mind that regular input assignments still apply, so you will probably want to use a combination that isnt being used for any other emulated input in the system. • Set On release to specify what should happen if the activation se- quence is released before the macro completes. When set to Stop im- mediately, any emulated inputs activated by the macro will be re- leased immediately, and no further steps will be processed; when set to Complete macro, the macro will continue to be processed until the end of the final step. • Set When held to specify what should happen if the activation se- quence is held after the final step of the macro completes. When set to Release, any inputs activated by the macro will be released, and the macro will not be reactivated until the activation sequence is released and pressed again; when set to Prolong step <n> where <n> is the number of the final step of the macro, the emulated inputs acti- vated by the final step of the macro will remain active until the ac- tivation sequence is released; when set to Loop to step <n> where <n> is a step number, macro processing will return to that step, includ- ing its delay, if the activation sequence is held after the final step completes. Each step has delay, duration and input settings: • Set the Delay to the number of emulated video frame intervals to wait before activating the inputs for the step. During the delay, no emu- lated inputs will be activated by the macro. You can reset the set- ting to zero by pressing the UI Clear key. • Set the Duration to the number of emulated video frame intervals to hold the emulated inputs for the step active before moving to the next step (or completing the macro in the case of the final step). You can reset the setting to one frame by pressing the UI Clear key. • Set the Input settings to the emulated inputs to activate for the step. Only non-toggle digital inputs are supported. Select Add in- put to set multiple inputs for a step (this option will only appear after you set the first input for the initially created step when creating a new macro). If the step has multiple inputs, you can highlight an input on the menu and press the UI Clear key to delete it (all steps must have at least one input, so you cant delete the only input for a step). • If the macro has multiple steps, you can select Delete step to delete a step (this options does not appear if the macro only has a single step). Remember to check that the On release and When held settings are correct after deleting steps. To add a step to the macro, highlight Add step at position (below the existing steps), use the UI Left/Right keys or click the arrows to set the position where youd like to insert the new step, and then press the UI Select key (or double-click the menu item) to add the new step. You will be prompted to set the first input for the new step. Remember to check the On release and When held settings after adding steps. The Add step at position item will only appear after you set the first in- put for the initially created step when creating a new macro. When creating a new macro, there is a Cancel option that changes to Create after you set the activating sequence and the first input for the initially created step. Select Create to finish creating the macro and return to the list of input macros. The new macro will be added at the end of the list. Press the UI Back key, or select Cancel before setting the activation sequence/input, to return to the previous menu without creating the new macro. When editing an existing macro, select Done or press the UI Back key to return to the list of input macros. Changes take effect immediately. Example macros Raiden autofire This provides player 1 autofire functionality using the space bar. The same thing could be achieved using the Autofire Plugin, but this demon- strates a simple looping macro: • Name: P1 Autofire • Activation combination: Kbd Space • On release: Stop immediately • When held: Loop to step 2 • Step 1: • Delay (frames): 0 • Duration (frames): 2 • Input 1: P1 Button 1 • Step 2: • Delay (frames): 4 • Duration (frames): 2 • Input 1: P1 Button 1 The first step has no delay so that firing begins as soon as the space bar is pressed. The second step has sufficient delay to ensure the game recognises the button being pressed and released again. The sec- ond step is repeated as long as the space bar is held down. Track & Field sprint cheat This allows you to run in Konami Track & Field by holding a single but- ton. This takes most of the skill (and fun) out of the game: • Name: P1 Sprint • Activation combination: Kbd Shift • On release: Stop immediately • When held: Loop to step 2 • Step 1: • Delay (frames): 0 • Duration (frames): 1 • Input 1: P1 Button 1 • Step 2: • Delay (frames): 1 • Duration (frames): 1 • Input 1: P1 Button 3 • Step 3: • Delay (frames): 1 • Duration (frames): 1 • Input 1: P1 Button 1 This macro rapidly alternates pressing buttons 1 and 3 the pattern re- quired to run in the game. Street Fighter II Shoryuken This macro allows you to perform a right-facing Shryken (Dragon Punch) by pressing a single key: • Name: 1P Shoryuken LP • Activation combination: Kbd M • On release: Complete macro • When held: Prolong step 6 • Step 1: • Delay (frames): 0 • Duration (frames): 1 • Input 1: P1 Right • Step 2: • Delay (frames): 1 • Duration (frames): 1 • Input 1: P1 Down • Step 3: • Delay (frames): 0 • Duration (frames): 1 • Input 1: P1 Down • Input 2: P1 Right • Step 4: • Delay (frames): 0 • Duration (frames): 1 • Input 1: P1 Right • Step 5: • Delay (frames): 0 • Duration (frames): 1 • Input 1: P1 Right • Input 2: P1 Jab Punch • Step 6: • Delay (frames): 0 • Duration (frames): 1 • Input 1: P1 Jab Punch This macro involves steps that activate multiple inputs. The macro will complete if the activation sequence is released early, allowing you to tap the key momentarily to perform the move. Holding the acti- vation sequence holds down the attack button. Layout Plugin When enabled, the layout plugin allows embedded Lua scripts in layout files to run. Built-in artwork for some machines and some external artwork packages can use Lua scripts to provide enhanced interactive features. See MAME Layout Scripting for an introduction to layout file scripting. Timecode Recorder Plugin The timecode recorder plugin logs time codes to a text file in conjunc- tion with creating an input recording file to assist people creating gameplay videos. The time code log file is only created when making an input recording. The time code log file has the same name as the input recording file with the extension .timecode appended. Use the record and input_directory options to create an input recording and specify the location for the output files. By default, the plugin records a time code when you press the F12 key on the keyboard while not pressing either Shift or Alt key. You can change this setting in the options menu for the plugin (choose Plugin Options from the main menu during emulation, and then choose Timecode Recorder). Settings for the plugin are stored in JSON format in the file plu- gin.cfg in the timecode folder inside your plugin data folder (see the homepath option). Game Play Timer Plugin The timer plugin records the total time spent emulating each combina- tion of a system and a software list item, as well as the number of times each combination has been launched. To see the statistics, bring up the main menu (press Tab during emulation by default), choose Plugin Options, and then choose Timer. This plugin records wall clock time (the real time duration elapsed while emulation is running, according to the host OS) as well as emu- lated time. The elapsed wall clock time may be shorter than the elapsed emulated time if you turn off throttling or use MAMEs fast for- ward feature, or it may be longer than the elapsed emulated time if you pause the emulation of if the emulation is too demanding to run at full speed. The statistics are stored in the file timer.db in the timer folder in- side your plugin data folder (see the homepath option). The file is a SQLite3 database. ADVANCED CONFIGURATION Multiple Configuration Files MAME has a very powerful configuration file system that can allow you to tweak settings on a per-game, per-system, or even per-monitor type basis, but requires careful thought about how you arrange your configs. Order of Config Loading 1. The command line is parsed first, and any settings passed that way will take precedence over anything in an INI file. 2. mame.ini (or other platform INI; e.g. mess.ini) is parsed twice. The first pass may change various path settings, so the second pass is done to see if there is a valid configuration file at that new location (and if so, change settings using that file). 3. debug.ini if the debugger is enabled. This is an advanced config file, most people won't need to use it or be concerned by it. 4. Screen orientation INI file (either horizont.ini or vertical.ini). For example Pac-Man has a vertical screen, so it loads vertical.ini, while Street Fighter Alpha uses a horizontal screen, so it loads horizont.ini. Systems with no monitors, multiple monitors with different orienta- tions, or monitors connected to slot devices will usually load hori- zont.ini. 5. Monitor type INI file (vector.ini for vector monitors, raster.ini for CRT raster monitors, or lcd.ini for LCD/EL/plasma matrix moni- tors). Pac-Man and Street Fighter Alpha use raster CRTs, so raster.ini is loaded here, while Tempest uses a vector monitor, so vector.ini is loaded here. For systems that have multiple monitor types, such as House Man- nequin with its CRT raster monitor and dual LCD matrix monitors, the INI file relevant to the first monitor is used (raster.ini in this case). Systems without monitors or with other kinds of monitors will not load an INI file for this step. 6. Driver source file INI file. MAME will attempt to load source/<sourcefile>.ini where <sourcefile> is the base name of the source code file where the system driver is defined. A system's source file can be found using mame -listsource <pattern> at the command line. For instance, Banpresto's Sailor Moon, Atlus's Dodonpachi, and Nihon System's Dangun Feveron all run on similar hardware and are defined in the cave.cpp source file, so they will all load source/cave.ini at this step. 7. BIOS set INI file (if applicable). For example The Last Soldier uses the Neo-Geo MVS BIOS, so it will load neogeo.ini. Systems that don't use a BIOS set won't load an INI file for this step. 8. Parent system INI file. For example The Last Soldier is a clone of The Last Blade / Bakumatsu Roman - Gekka no Kenshi, so it will load lastblad.ini. Parent systems will not load an INI file for this step. 9. System INI file. Using the previous example, The Last Soldier will load lastsold.ini. Examples of Config Loading Order • Brix, which is a clone of Zzyzzyxx. (mame brix) 1. Command line 2. mame.ini (global) 3. (debugger not enabled, no extra INI file loaded) 4. vertical.ini (screen orientation) 5. raster.ini (monitor type) 6. source/jack.ini (driver source file) 7. (no BIOS set) 8. zzyzzyxx.ini (parent system) 9. brix.ini (system) • Super Street Fighter 2 Turbo (mame ssf2t) 1. Command line 2. mame.ini (global) 3. (debugger not enabled, no extra INI file loaded) 4. horizont.ini (screen orientation) 5. raster.ini (monitor type) 6. source/cps2.ini (driver source file) 7. (no BIOS set) 8. (no parent system) 9. ssf2t.ini (system) • Final Arch (mame finlarch) 1. Command line 2. mame.ini (global) 3. (debugger not enabled, no extra INI file loaded) 4. horizont.ini (screen orientation) 5. raster.ini (monitor type) 6. source/stv.ini (driver source file) 7. stvbios.ini (BIOS set) 8. smleague.ini (parent system) 9. finlarch.ini (system) Remember command line parameters take precedence over all else! Tricks to Make Life Easier Some users may have a wall-mounted or otherwise rotatable monitor, and may wish to actually play vertical games with the rotated display. The easiest way to accomplish this is to put your rotation modifiers into vertical.ini, where they will only affect vertical games. MAME Path Handling MAME has a specific order it uses when checking for user files such as ROM sets and cheat files. Order of Path Loading Let's use an example of the cheat file for AfterBurner 2 for Sega Gene- sis/MegaDrive (aburner2 in the megadrive softlist), and your cheatpath is set to "cheat" (as per the default) -- this is how MAME will search for that cheat file: 1. cheat/megadriv/aburner2.xml 2. cheat/megadriv.zip -> aburner2.xml Notice that it checks for a .ZIP file first before a .7Z file. 3. cheat/megadriv.zip -> <arbitrary path>/aburner2.xml It will look for the first (if any) aburner2.xml file it can find inside that zip, no matter what the path is. 4. cheat.zip -> megadriv/aburner2.xml Now it is specifically looking for the file and folder combination, but inside the cheat.zip file. 5. cheat.zip -> <arbitrary path>/megadriv/aburner2.xml Like before, ex- cept looking for the first (if any) aburner2.xml inside a megadriv folder inside the zip. 6. cheat/megadriv.7z -> aburner2.xml Now we start checking 7ZIP files. 7. cheat/megadriv.7z -> <arbitrary path>/aburner2.xml 8. cheat.7z -> megadriv/aburner2.xml 9. cheat.7z -> <arbitrary path>/megadriv/aburner2.xml Similar to zip, except now 7ZIP files. [todo: ROM set loading is slightly more complicated, adding CRC. Get that documented in the next day or two.] Shifter Toggle Disable This is an advanced feature for alternative shifter handling for cer- tain older arcade machines such as Spy Hunter and Outrun that used a two-way toggle switch for the shifter. By default, the shifter is treated as a toggle switch. One press of the mapped control for the shifter will switch it from low to high, and another will switch it back. This may not be ideal if you have access to a physical shifter that works identically to how the original machines did. (The input is on when in one gear, the input is off otherwise) Note that this feature will not help controller users and will not help with games that have more than two shifter states (e.g. five gears in modern racing games) This feature is not exposed through the graphical user interface in any way, as it is an extremely advanced tweak intended explicitly for peo- ple who have this specific need, have the hardware to take advantage of it, and the knowledge to use it correctly. Disabling and Enabling Shifter Toggle This example will use the game Spy Hunter (set spyhunt) to demonstrate the exact change needed: You will need to manually edit the game .CFG file in the CFG folder (e.g. spyhunt.cfg) Start by loading MAME with the game in question. In our case, that will be mame spyhunt. Set up the controls as you would please, including mapping the shifter. Exit MAME, open the .cfg file in your text editor of choice. Inside the spyhunt.cfg file, you will find the following for the input. The actual input code in the middle can and will vary depending on the controller number and what input you have mapped. <port tag=":ssio:IP0" type="P1_BUTTON2" mask="16" defvalue="16"> <newseq type="standard"> JOYCODE_1_RYAXIS_NEG_SWITCH OR JOYCODE_1_RYAXIS_POS_SWITCH </newseq> </port> The line you need to edit will be the port line defining the actual in- put. For Spy Hunter, that's going to be P1_BUTTON2. Add toggle="no" to the end of the tag, like follows: <port tag=":ssio:IP0" type="P1_BUTTON2" mask="16" defvalue="16" toggle="no"> <newseq type="standard"> JOYCODE_1_RYAXIS_NEG_SWITCH OR JOYCODE_1_RYAXIS_POS_SWITCH </newseq> </port> Save and exit. To disable this, simply remove the toggle="no" from each desired .CFG input. BGFX Effects for (nearly) Everyone • Introduction • Resolution and Aspect Ratio • Getting Started with BGFX • Configuration Settings • Tweaking BGFX HLSL Settings inside MAME • Using the included pillarbox filters Introduction By default, MAME outputs an idealized version of the video as it would be on the way to the arcade cabinets monitor, with minimal modification of the output (primarily to stretch the game image back to the aspect ratio the monitor would traditionally have, usually 4:3). This works well, but misses some of the nostalgia factor. Arcade monitors were never ideal, even in perfect condition, and the nature of a CRT display distorts that image in ways that change the appearance significantly. Modern LCD monitors simply do not look the same, and even computer CRT monitors cannot match the look of an arcade monitor without help. Thats where the new BGFX renderer with HLSL comes into the picture. HLSL simulates most of the effects that a CRT arcade monitor has on the video, making the result look a lot more authentic. However, HLSL re- quires some effort on the users part: the settings you use are going to be tailored to your PCs system specs, and especially the monitor youre using. Additionally, there were hundreds of thousands of monitors out there in arcades. Each was tuned and maintained differently, meaning there is no one correct appearance to judge by either. Basic guide- lines will be provided here to help you, but you may also wish to ask for opinions on popular MAME-centric forums. Resolution and Aspect Ratio Resolution is a very important subject for HLSL settings. You will want MAME to be using the native resolution of your monitor to avoid additional distortion and lag caused by your monitor upscaling the dis- play image. While most arcade machines used a 4:3 ratio display (or 3:4 for verti- cally oriented monitors like Pac-Man), its difficult to find a consumer display that is 4:3 at this point. The good news is that that extra space on the sides isnt wasted. Many arcade cabinets used bezel art- work around the main display, and should you have the necessary artwork files, MAME will display that artwork. Turn the Zoom to Screen Area setting in the video options menu to scale and crop the artwork so the emulated screen fills your display in one direction. Some older LCD displays used a native resolution of 12801024 and were a 5:4 aspect ratio. Theres not enough extra space to display artwork, and youll end up with some very slight pillarboxing, but the results will be still be good and on-par with a 4:3 monitor. Getting Started with BGFX You will need to have followed the initial MAME setup instructions elsewhere in this manual before beginning. Official MAME distributions include BGFX as of MAME 0.172, so you dont need to download any addi- tional files. Open your mame.ini file in your text editor of choice (e.g. Notepad), and make sure the following options are set correctly: • video bgfx Now, you may want to take a moment to look below at the Configuration Settings section to see how to set up these next options. As explained in Order of Config Loading, MAME has a order in which it processes INI files. The BGFX settings can be edited in mame.ini, but to take full advantage of the power of MAMEs configuration files, youll want to copy the BGFX settings from mame.ini to one of the other con- figuration files and make changes there. In particular, you will want the bgfx_screen_chains to be specific to each game. Save your INI file(s) and youre ready to begin. Configuration Settings bgfx_path This is where your BGFX shader files are stored. By default, this will be the bgfx folder in your MAME installation folder. bgfx_backend Selects a rendering backend for BGFX to use. Possible choices include d3d9, d3d11, d3d12, opengl, gles, metal, and `vulkan. The default is **auto**, which will let MAME choose the best se- lection for you. • d3d9 -- Direct3D 9.0 Renderer (Requires Windows XP or higher) • d3d11 -- Direct3D 11.0 Renderer (Requires Windows Vista with Direct3D 11 update, or Windows 7 or higher) • d3d12 -- Direct3D 12.0 Renderer (Requires Windows 10 or higher) • opengl -- OpenGL Renderer (Requires OpenGL drivers, may work better on some video cards, supported on Linux and macOS) • gles -- OpenGL ES Renderer (Supported with some low-power GPUs) • metal -- Apple Metal Graphics API (Requires macOS 10.11 El Capitan or newer) • vulkan -- Vulkan Renderer (Requires Windows or Linux with com- patible GPU drivers. bgfx_debug Enables BGFX debugging features. Most users will not need to use this. bgfx_screen_chains This dictates how to handle BGFX rendering on a per-display ba- sis. Possible choices include hlsl, unfiltered, and default. • default -- default bilinear filtered output • unfiltered -- nearest neighbor sampled output • hlsl -- display simulation through shaders • crt-geom -- lightweight CRT simulation • crt-geom-deluxe -- more detailed CRT simulation • lcd-grid -- LCD matrix simulation We make a distinction between emulated screens (which well call a screen) and output windows or monitors (which well call a win- dow, set by the -numscreens option) here. Use colons (:) to separate windows, and commas (,) to separate screens in the -bgfx_screen_chains setting value. For the simple single window, single screen case, such as Pac-Man on one physical PC monitor, you can specify one entry like: bgfx_screen_chains hlsl Things get only slightly more complicated when we get to multi- ple windows and multiple screens. On a single window, multiple screen game, such as Darius on one physical PC monitor, specify screen chains (one per window) like: bgfx_screen_chains hlsl,hlsl,hlsl This also works with single screen games where you are mirroring the output to more than one physical display. For instance, you could set up Pac-Man to have one unfiltered output for use with video broadcasting while a second display is set up HLSL for playing on. On a multiple window, multiple screen game, such as Darius on three physical PC monitors, specify multiple entries (one per window) like: bgfx_screen_chains hlsl:hlsl:hlsl Another example game would be Taisen Hot Gimmick, which used two CRTs to show individual player hands to just that player. If using two windows (two physical displays): bgfx_screen_chains hlsl:hlsl One more special case is that Nichibutsu had a special cocktail mahjong cabinet that used a CRT in the middle along with two LCD displays to show each player their hand. We would want the LCDs to be unfiltered and untouched as they were, while the CRT would be improved through HLSL. Since we want to give each player their own full screen display (two physical monitors) along with the LCD, well go with: -numscreens 2 -view0 "Player 1" -view1 "Player 2" -video bgfx -bgfx_screen_chains hlsl,unfiltered:hlsl,unfiltered This sets up the view for each display respectively, keeping HLSL effect on the CRT for each window (physical display) while going unfiltered for the LCD screens. If using only one window (one display), keep in mind the game still has three screens, so we would use: bgfx_screen_chains hlsl,unfiltered,unfiltered Note that the commas are on the outside edges, and any colons are in the middle. bgfx_shadow_mask This specifies the shadow mask effect PNG file. By default this is slot-mask.png. Tweaking BGFX HLSL Settings inside MAME Start by loading MAME with the game of your choice (e.g. mame pacman). The tilde key (~) brings up the on-screen display options. Use up and down to go through the various settings, while left and right will al- low you to change that setting. Results will be shown in real time as youre changing these settings. Note that settings are individually changeable on a per-screen basis. BGFX slider settings are saved per-system in CFG files. If the bgfx_screen_chains setting has been set (either in an INI file or on the command line), it will set the initial effects. If the bgfx_screen_chains setting has not been set, MAME will use the effects you chose the last time you ran the system. Using the included pillarbox filters MAME includes example BGFX shaders and layouts for filling unused space on a 16:9 widescreen display with a blurred version of the emulated video. The all the necessary files are included, and just need to be enabled. For systems using 4:3 horizontal monitors, use these options: -override_artwork bgfx/border_blur -view Horizontal -bgfx_screen_chains crt-geom,pillarbox_left_horizontal,pillarbox_right_horizontal For systems using 3:4 vertical monitors, use these options: -override_artwork bgfx/border_blur -view Vertical -bgfx_screen_chains crt-geom,pillarbox_left_vertical,pillarbox_right_vertical • You can use a different setting in place of crt-geom for the effect to apply to the primary screen image in the centre (e.g. default, hlsl or lcd-grid). • If youve previously changed the view for the system in MAME, the cor- rect pillarboxed view will not be selected by default. Use the video options menu to select the correct view. • You can add these settings to an INI file to have them apply to cer- tain systems automatically (e.g. horizont.ini or vertical.ini, or the INI file for a specific system). HLSL Effects for Windows By default, MAME outputs an idealized version of the video as it would be on the way to the arcade cabinet's monitor, with minimal modifica- tion of the output (primarily to stretch the game image back to the as- pect ratio the monitor would traditionally have, usually 4:3) -- this works well, but misses some of the nostalgia factor. Arcade monitors were never ideal, even in perfect condition, and the nature of a CRT display distorts that image in ways that change the appearance signifi- cantly. Modern LCD monitors simply do not look the same, and even computer CRT monitors cannot match the look of an arcade monitor without help. That's where HLSL comes into the picture. HLSL simulates most of the effects that a CRT arcade monitor has on the video, making the result look a lot more authentic. However, HLSL re- quires some effort on the user's part: the settings you use are going to be tailored to your PC's system specs, and especially the monitor you're using. Additionally, there were hundreds of thousands of moni- tors out there in arcades. Each was tuned and maintained differently, meaning there is no one correct appearance to judge by either. Basic guidelines will be provided here to help you, but you may also wish to ask for opinions on popular MAME-centric forums. Resolution and Aspect Ratio Resolution is a very important subject for HLSL settings. You will want MAME to be using the native resolution of your monitor to avoid addi- tional distortion and lag created by your monitor upscaling the display image. While most arcade machines used a 4:3 ratio display (or 3:4 for verti- cally oriented monitors like Pac-Man), it's difficult to find a con- sumer display that is 4:3 at this point. The good news is that that ex- tra space on the sides isn't wasted. Many arcade cabinets used bezel artwork around the main display, and should you have the necessary art- work files, MAME will display that artwork. Turn the artwork view to Cropped for best results. Some older LCD displays used a native resolution of 1280x1024 and were a 5:4 aspect ratio. There's not enough extra space to display artwork, and you'll end up with some very slight pillarboxing, but the results will be still be good and on-par with a 4:3 monitor. Getting Started with HLSL You will need to have followed the initial MAME setup instructions elsewhere in this manual before beginning. Official MAME distributions include HLSL by default, so you don't need to download any additional files. Open your mame.ini in your text editor of choice (e.g. Notepad), and make sure the following options are set correctly: • video d3d • filter 0 The former is required because HLSL requires Direct3D support. The lat- ter turns off extra filtering that interferes with HLSL output. Lastly, one more edit will turn HLSL on: • hlsl_enable 1 Save the .INI file and you're ready to begin. Several presets have been included in the INI folder with MAME, allow- ing for good quick starting points for Nintendo Game Boy, Nintendo Game Boy Advance, Raster, and Vector monitor settings. Tweaking HLSL Settings inside MAME For multiple, complicated to explain reasons, HLSL settings are no longer saved when you exit MAME. This means that while tweaking set- tings is a little more work on your part, the results will always come out as expected. Start by loading MAME with the game of your choice (e.g. mame pacman) The tilde key (~) brings up the on-screen display options. Use up and down to go through the various settings, while left and right will al- low you to change that setting. Results will be shown in real time as you're changing these settings. Once you've found settings you like, write the numbers down on a notepad and exit MAME. Configuration Editing As referenced in Order of Config Loading, MAME has a order in which it processes INI files. The HLSL settings can be edited in mame.ini, but to take full advantage of the power of MAME's config files, you'll want to copy the HLSL settings from mame.ini to one of the other config files and make changes there. For instance, once you've found HLSL settings you think are appropriate for Neo Geo games, you can put those settings into neogeo.ini so that all Neo-Geo games will be able to take advantage of those settings without needing to add it to every game INI manually. Configuration Settings hlslpath This is where your HLSL files are stored. By default, this will be the HLSL folder in your MAME installation. hlsl_snap_width hlsl_snap_height Sets the resolution that Alt+F12 HLSL screenshots are output at. shadow_mask_alpha (Shadow Mask Amount) This defines how strong the effect of the shadowmask is. Acceptable range is from 0 to 1, where 0 will show no shadowmask effect, 1 will be a completely opaque shadowmask, and 0.5 will be 50% transparent. shadow_mask_tile_mode (Shadow Mask Tile Mode) This defines whether the shadowmask should be tiled based on the screen resolution of your monitor or based on the source resolution of the emulated system. Valid values are 0 for Screen mode and 1 for Source mode. shadow_mask_texture shadow_mask_x_count (Shadow Mask Pixel X Count) shadow_mask_y_count (Shadow Mask Pixel Y Count) shadow_mask_usize (Shadow Mask U Size) shadow_mask_vsize (Shadow Mask V Size) shadow_mask_x_count (Shadow Mask U Offset) shadow_mask_y_count (Shadow Mask V Offset) These settings need to be set in unison with one another. In particular, shadow_mask_texture sets rules for how you need to set the other options. shadow_mask_texture sets the texture of the shadowmask effect. Three shadowmasks are included with MAME: aperture-grille.png, shadow-mask.png, and slot-mask.png shadow_mask_usize and shadow_mask_vsize define the used size of the shadow_mask_texture in percentage, staring at the top-left corner. The means for a texture with the actual size of 24x24 pixel and an u/v size of 0.5,0.5 the top-left 12x12 pixel will be used. Keep in mind to define an u/v size that makes is possible to tile the texture without gaps or glitches. 0.5,0.5 is fine for any shadowmask texture that is included with MAME. shadow_mask_x_count and shadow_mask_y_count define how many screen pixel should be used to display the u/v sized texture. e.g. if you use the example from above and define a x/y count of 12,12 every pixel of the texture will be displayed 1:1 on the screen, if you define a x/y count of 24,24 the texture will be displayed twice as large. example settings for shadow_mask.png: shadow_mask_texture shadow-mask.png shadow_mask_x_count 12 shadow_mask_y_count 6 or 12 shadow_mask_usize 0.5 shadow_mask_vsize 0.5 example settings for slot-mask.png: shadow_mask_texture slot-mask.png shadow_mask_x_count 12 shadow_mask_y_count 8 or 16 shadow_mask_usize 0.5 shadow_mask_vsize 0.5 example settings for aperture-grille: shadow_mask_texture aperture-grille.png shadow_mask_x_count 12 shadow_mask_y_count 12 or any shadow_mask_usize 0.5 shadow_mask_vsize 0.5 shadow_mask_uoffset and shadow_mask_voffset can be used to tweak the alignment of the final shadowmask in subpixel range. Range is from -1.00 to 1.00, where 0.5 moves the shadowmask by 50 percent of the u/v sized texture. distortion (Quadric Distortion Amount) This setting determines strength of the quadric distortion of the screen image. cubic_distortion (Cubic Distortion Amount) This setting determines strength of the cubic distortion of the screen image. Both distortion factors can be negative to compensate each other. e.g. distortion 0.5 and cubic_distortion -0.5 distort_corner (Distorted Corner Amount) This setting determines strength of distortion of the screen corners, which does not affect the distortion of screen image itself. round_corner (Rounded Corner Amount) The corners of the display can be rounded off through the use of this setting. smooth_border (Smooth Border Amount) Sets a smoothened/blurred border around the edges of the screen. reflection (Reflection Amount) If set above 0, this creates a white reflective blotch on the display. By default, this is put in the upper right corner of the display. By editing the POST.FX file's GetSpotAddend section, you can change the location. Range is from 0.00 to 1.00. vignetting (Vignetting Amount) When set above 0, will increasingly darken the outer edges of the display in a pseudo-3D effect. Range is from 0.00 to 1.00. scanline_alpha (Scanline Amount) This defines how strong the effect of the scanlines are. Acceptable range is from 0 to 1, where 0 will show no scanline effect, 1 will be a completely black line, and 0.5 will be 50% transparent. Note that arcade monitors did not have completely black scanlines. scanline_size (Overall Scanline Scale) The overall spacing of the scanlines is set with this option. Setting it at 1 represents consistent alternating spacing between display lines and scanlines. scanline_height (Individual Scanline Scale) This determines the overall size of each scanline. Setting lower than 1 makes them thinner, larger than 1 makes them thicker. scanline_variation (Scanline Variation) This affects the size of each scanline depending on its brightness. Brighter scanlines will be thicker than darker scanline. Acceptable range is from 0 to 2.0, with the default being 1.0. At 0.0 all scanlines will have the same size independent of their brightness. scanline_bright_scale (Scanline Brightness Scale) Specifies how bright the scanlines are. Larger than 1 will make them brighter, lower will make them dimmer. Setting to 0 will make scanlines disappear entirely. scanline_bright_offset (Scanline Brightness Offset) This will give scanlines a glow/overdrive effect, softening and smoothing the top and bottom of each scanline. scanline_jitter (Scanline Jitter Amount) Specifies the wobble or jitter of the scanlines, causing them to jitter on the monitor. Warning: Higher settings may hurt your eyes. hum_bar_alpha (Hum Bar Amount) Defines the strength of the hum bar effect. defocus (Defocus) This option will defocus the display, blurring individual pixels like an extremely badly maintained monitor. Specify as X,Y values (e.g. defocus 1,1) converge_x (Linear Convergence X, RGB) converge_y (Linear Convergence Y, RGB) radial_converge_x (Radial Convergence X, RGB) radial_converge_y (Radial Convergence Y, RGB) Adjust the convergence of the red, green, and blue channels in a given direction. Many badly maintained monitors with bad convergence would bleed colored ghosting off-center of a sprite, and this simulates that. red_ratio (Red Output from RGB) grn_ratio (Green Output from RGB) blu_ratio (Blue Output from RGB) Defines a 3x3 matrix that is multiplied with the RGB signals to simulate color channel interference. For instance, a green channel of (0.100, 1.000, 0.250) is weakened 10% by the red channel and strengthened 25% through the blue channel. offset (Signal Offset) Strengthen or weakens the current color value of a given channel. For instance, a red signal of 0.5 with an offset of 0.2 will be raised to 0.7 scale (Signal Scale) Applies scaling to the current color value of the channel. For instance, a red signal of 0.5 with a scale of 1.1 will result in a red signal of 0.55 power (Signal Exponent, RGB) Exponentiate the current color value of the channel, also called gamma. For instance, a red signal of 0.5 with red power of 2 will result in a red signal of 0.25 This setting also can be used to adjust line thickness in vector games. floor (Signal Floor, RGB) Sets the absolute minimum color value of a channel. For instance, a red signal of 0.0 (total absence of red) with a red floor of 0.2 will result in a red signal of 0.2 Typically used in conjunction with artwork turned on to make the screen have a dim raster glow. phosphor_life (Phosphor Persistence, RGB) How long the color channel stays on the screen, also called phosphor ghosting. 0 gives absolutely no ghost effect, and 1 will leave a contrail behind that is only overwritten by a higher color value. This also affects vector games quite a bit. saturation (Color Saturation) Color saturation can be adjusted here. bloom_blend_mode (Bloom Blend Mode) Determines the mode of the bloom effect. Valid values are 0 for Brighten mode and 1 for Darken mode, last is only useful for systems with STN LCD. bloom_scale (Bloom Scale) Determines the intensity of bloom effect. Arcade CRT displays had a tendency towards bloom, where bright colors could bleed out into neighboring pixels. This effect is extremely graphics card intensive, and can be turned completely off to save GPU power by setting it to 0 bloom_overdrive (Bloom Overdrive, RGB) Sets a RGB color, separated by commas, that has reached the brightest possible color and will be overdriven to white. This is only useful on color raster, color LCD, or color vector games. bloom_lvl0_weight (Bloom Level 0 Scale) bloom_lvl1_weight (Bloom Level 1 Scale) . . . . bloom_lvl7_weight (Bloom Level 7 Scale) bloom_lvl8_weight (Bloom Level 8 Scale) These define the bloom effect. Range is from 0.00 to 1.00. If used carefully in conjunction with phosphor_life, glowing/ghosting for moving objects can be achieved. hlsl_write Enables writing of an uncompressed AVI video with the HLSL effects included with set to 1. This uses a massive amount of disk space very quickly, so a large HD with fast write speeds is highly recommended. Default is 0, which is off. Suggested defaults for raster-based games: +----------------------------+----------------------+---------------------------------+ | bloom_lvl0_weight 1.00 | Bloom level 0 weight | Full-size target. | | bloom_lvl1_weight 0.64 | Bloom level 1 weight | 1/4 smaller that level 0 target | | bloom_lvl2_weight 0.32 | Bloom level 2 weight | 1/4 smaller that level 1 target | | bloom_lvl3_weight 0.16 | Bloom level 3 weight | 1/4 smaller that level 2 target | | bloom_lvl4_weight 0.08 | Bloom level 4 weight | 1/4 smaller that level 3 target | | bloom_lvl5_weight 0.06 | Bloom level 5 weight | 1/4 smaller that level 4 target | | bloom_lvl6_weight 0.04 | Bloom level 6 weight | 1/4 smaller that level 5 target | | bloom_lvl7_weight 0.02 | Bloom level 7 weight | 1/4 smaller that level 6 target | | bloom_lvl8_weight 0.01 | Bloom level 8 weight | 1/4 smaller that level 7 target | +----------------------------+----------------------+---------------------------------+ Vector Games HLSL effects can also be used with vector games. Due to a wide variance of vector settings to optimize for each individual game, it is heavily suggested you add these to per-game INI files (e.g. tempest.ini) Shadowmasks were only present on color vector games, and should not be used on monochrome vector games. Additionally, vector games did not use scanlines, so that should also be turned off. Open your INI file in your text editor of choice (e.g. Notepad), and make sure the following options are set correctly: • video d3d • filter 0 • hlsl_enable 1 In the Core Vector Options section: • beam_width_min 1.0 (Beam Width Minimum) • beam_width_max 1.0 (Beam Width Maximum) • beam_intensity_weight 0.0 (Beam Intensity Weight) • flicker 0.0 (Vector Flicker) In the Vector Post-Processing Options section: • vector_beam_smooth 0.0 (Vector Beam Smooth Amount) • vector_length_scale 0.5 (Vector Attenuation Maximum) • vector_length_ratio 0.5 (Vector Attenuation Length Minimum) Suggested settings for vector games: • bloom_scale should typically be set higher for vector games than raster games. Try between 0.4 and 1.0 for best effect. • bloom_overdrive should only be used with color vector games. • bloom_lvl_weights should be set as follows: +----------------------------+----------------------+---------------------------------+ | bloom_lvl0_weight 1.00 | Bloom level 0 weight | Full-size target. | | bloom_lvl1_weight 0.48 | Bloom level 1 weight | 1/4 smaller that level 0 target | | bloom_lvl2_weight 0.32 | Bloom level 2 weight | 1/4 smaller that level 1 target | | bloom_lvl3_weight 0.24 | Bloom level 3 weight | 1/4 smaller that level 2 target | | bloom_lvl4_weight 0.16 | Bloom level 4 weight | 1/4 smaller that level 3 target | | bloom_lvl5_weight 0.24 | Bloom level 5 weight | 1/4 smaller that level 4 target | | bloom_lvl6_weight 0.32 | Bloom level 6 weight | 1/4 smaller that level 5 target | | bloom_lvl7_weight 0.48 | Bloom level 7 weight | 1/4 smaller that level 6 target | | bloom_lvl8_weight 0.64 | Bloom level 8 weight | 1/4 smaller that level 7 target | +----------------------------+----------------------+---------------------------------+ GLSL Effects for *nix, OS X, and Windows By default, MAME outputs an idealized version of the video as it would be on the way to the arcade cabinet's monitor, with minimal modifica- tion of the output (primarily to stretch the game image back to the as- pect ratio the monitor would traditionally have, usually 4:3) -- this works well, but misses some of the nostalgia factor. Arcade monitors were never ideal, even in perfect condition, and the nature of a CRT display distorts that image in ways that change the appearance signifi- cantly. Modern LCD monitors simply do not look the same, and even computer CRT monitors cannot match the look of an arcade monitor without help. That's where GLSL comes into the picture. GLSL simulates most of the effects that a CRT arcade monitor has on the video, making the result look a lot more authentic. However, GLSL re- quires some effort on the user's part: the settings you use are going to be tailored to your PC's system specs, and especially the monitor you're using. Additionally, there were hundreds of thousands of moni- tors out there in arcades. Each was tuned and maintained differently, meaning there is no one correct appearance to judge by either. Basic guidelines will be provided here to help you, but you may also wish to ask for opinions on popular MAME-centric forums. Resolution and Aspect Ratio Resolution is a very important subject for GLSL settings. You will want MAME to be using the native resolution of your monitor to avoid addi- tional distortion and lag created by your monitor upscaling the display image. While most arcade machines used a 4:3 ratio display (or 3:4 for verti- cally oriented monitors like Pac-Man), it's difficult to find a con- sumer display that is 4:3 at this point. The good news is that that ex- tra space on the sides isn't wasted. Many arcade cabinets used bezel artwork around the main display, and should you have the necessary art- work files, MAME will display that artwork. Turn the artwork view to Cropped for best results. Some older LCD displays used a native resolution of 1280x1024, which is a 5:4 aspect ratio. There's not enough extra space to display artwork, and you'll end up with some very slight pillarboxing, but the results will be on-par with a 4:3 monitor. Getting Started with GLSL You will need to have followed the initial MAME setup instructions elsewhere in this manual before beginning. Official MAME distributions include GLSL support by default, but do NOT include the GLSL shader files. You will need to obtain the shader files from third party online sources. Open your mame.ini in your text editor of choice (e.g. Notepad), and make sure the following options are set correctly: • video opengl • filter 0 The former is required because GLSL requires OpenGL support. The latter turns off extra filtering that interferes with GLSL output. Lastly, one more edit will turn GLSL on: • gl_glsl 1 Save the .INI file and you're ready to begin. Tweaking GLSL Settings inside MAME For multiple, complicated to explain reasons, GLSL settings are no longer saved when you exit MAME. This means that while tweaking set- tings is a little more work on your part, the results will always come out as expected. Start by loading MAME with the game of your choice (e.g. mame pacman) The tilde key (~) brings up the on-screen display options. Use up and down to go through the various settings, while left and right will al- low you to change that setting. Results will be shown in real time as you're changing these settings. Once you've found settings you like, write the numbers down on a notepad and exit MAME. Configuration Editing As referenced in Order of Config Loading, MAME has a order in which it processes INI files. The GLSL settings can be edited in mame.ini, but to take full advantage of the power of MAME's config files, you'll want to copy the GLSL settings from mame.ini to one of the other config files and make changes there. For instance, once you've found GLSL settings you think are appropriate for Neo Geo games, you can put those settings into neogeo.ini so that all Neo-Geo games will be able to take advantage of those settings without needing to add it to every game INI manually. Configuration Settings gl_glsl Enables GLSL when set to 1, disabled if set to 0. Defaults to 0. gl_glsl_filter Enables filtering to GLSL output. Reduces jagginess at the cost of blurriness. glsl_shader_mame0 ... glsl_shader_mame9 Specifies the shaders to run, in the order from 0 to 9. See your shader pack author for details on which to run in which order for best effect. glsl_shader_screen0 ... glsl_shader_screen9 Specifies screen to apply the shaders on. Controller Configuration Files • Introduction • Basic structure • Substituting default controls • Overriding defaults by input type • Overriding defaults for specific inputs • Assigning input device numbers • Setting pointer input options Introduction Controller configuration files can be used to modify MAMEs default in- put settings. Controller configuration files may be supplied with an input device to provide more suitable defaults, or used as profiles that can be selected for different situations. MAME includes a few sample controller configuration files in the ctrlr folder, designed to provide useful defaults for certain arcade-style controllers. Controller configuration files are an XML application, using the .cfg filename extension. MAME searches for controller configuration files in the directories specified using the ctrlrpath option. A controller configuration file is selected by setting the ctrlr option to its file- name, excluding the .cfg extension (e.g. set the ctrlr option to scor- pionxg to use scorpionxg.cfg). It is an error if the specified con- troller configuration file does not exist, or if it contains no sec- tions applicable to the emulated system. Controller configuration files use implementation-dependent input to- kens. The values available and their precise meanings depend on the exact version of MAME used, the input devices connected, the selected input provider modules (keyboardprovider, mouseprovider, lightgun- provider and joystickprovider options), and possibly other settings. Basic structure Controller configuration files follow a similar format to the system configuration files that MAME uses to save things like input settings and bookkeeping data (created in the folder specified using the cfg_directory option). This example shows the overall structure of a controller configuration file: <?xml version="1.0"?> <mameconfig version="10"> <system name="default"> <input> <!-- settings affecting all emulated systems go here --> </input> </system> <system name="neogeo"> <input> <!-- settings affecting neogeo and clones go here --> </input> </system> <system name="intellec4.cpp"> <input> <!-- settings affecting all systems defined in intellec4.cpp go here --> </input> </system> </mameconfig> The root of a controller configuration file must be a mameconfig ele- ment, with a version attribute specifying the configuration format ver- sion (currently 10 MAME will not load a file using a different ver- sion). The mameconfig element contains one or more system elements, each of which has a name attribute specifying the system(s) it applies to. Each system element may contain an input element which holds the actual remap and port configuration elements, which will be described later. Each system element may also contain a pointer_input element to set pointer input options for systems with interactive artwork. When launching an emulated system, MAME will apply configuration from system elements where the value of the name attribute meets one of the following criteria: • If the name attribute has the value default, it will always be ap- plied (including for the system/software selection menus). • If the value of the name attribute matches the systems short name, the short name of its parent system, or the short name of its BIOS system (if applicable). • If the value of the name attribute matches the name of the source file where the system is defined. For example, for the game DaeJeon! SanJeon SuJeon (AJTUE 990412 V1.000), system elements will be applied if their name attribute has the value default (applies to all systems), sanjeon (short name of the system itself), sasissu (short name of the parent system), stvbios (short name of the BIOS system), or stv.cpp (source file where the sys- tem is defined). As another example, a system element whose name attribute has the value zac2650.cpp will be applied for the systems The Invaders, Super Invader Attack (bootleg of The Invaders), and Dodgem. Applicable system elements are applied in the order they appear in the controller configuration file. Settings from elements that appear later in the file may modify or override settings from elements that appear earlier. Within a system element, remap elements are applied before port elements. Substituting default controls You can use a remap element to substitute one host input for another in MAMEs default input configuration. For example, this substitutes keys on the numeric keypad for the cursor direction keys: <input> <remap origcode="KEYCODE_UP" newcode="KEYCODE_8PAD" /> <remap origcode="KEYCODE_DOWN" newcode="KEYCODE_2PAD" /> <remap origcode="KEYCODE_LEFT" newcode="KEYCODE_4PAD" /> <remap origcode="KEYCODE_RIGHT" newcode="KEYCODE_6PAD" /> </input> The origcode attribute specifies the token for the host input to be substituted, and the newcode attribute specifies the token for the re- placement host input. In this case, assignments using the cursor up, down, left and right arrows will be replaced with the numeric 8, 2, 4 and 6 keys on the numeric keypad, respectively. Note that substitutions specified using remap elements only apply to inputs that use MAMEs default assignment for the input type. That is, they only apply to default assignments for control types set in the In- put Assignments (general) menus. They do not apply to default control assignments set in driver/device I/O port definitions (using the PORT_CODE macro). MAME applies remap elements found inside any applicable system element. Overriding defaults by input type Use port elements with type attributes but without tag attributes to override the default control assignments for emulated inputs by type: <input> <port type="UI_MENU"> <newseq type="standard">KEYCODE_TAB OR KEYCODE_1 KEYCODE_5</newseq> </port> <port type="UI_CANCEL"> <newseq type="standard">KEYCODE_ESC OR KEYCODE_2 KEYCODE_6</newseq> </port> <port type="P1_BUTTON1"> <newseq type="standard">KEYCODE_C OR JOYCODE_1_BUTTON1</newseq> </port> <port type="P1_BUTTON2"> <newseq type="standard">KEYCODE_LSHIFT OR JOYCODE_1_BUTTON2</newseq> </port> <port type="P1_BUTTON3"> <newseq type="standard">KEYCODE_Z OR JOYCODE_1_BUTTON3</newseq> </port> <port type="P1_BUTTON4"> <newseq type="standard">KEYCODE_X OR JOYCODE_1_BUTTON4</newseq> </port> </input> This sets the following default input assignments: Show/Hide Menu (User Interface) Tab key, or 1 and 2 keys pressed simultaneously UI Cancel (User Interface) Escape key, or 2 and 6 keys pressed simultaneously P1 Button 1 (Player 1 Controls) C key, or joystick 1 button 1 P1 Button 2 (Player 1 Controls) Left Shift key, or joystick 1 button 2 P1 Button 3 (Player 1 Controls) Z key, or joystick 1 button 3 P1 Button 4 (Player 1 Controls) X key, or joystick 1 button 4 Note that this will only apply for inputs that use MAMEs default as- signment for the input type. That is, port elements without tag at- tributes only override default assignments for control types set in the Input Assignments (general) menus. They do not override default con- trol assignments set in driver/device I/O port definitions (using the PORT_CODE macro). MAME applies port elements without tag attributes found inside any ap- plicable system element. Overriding defaults for specific inputs Use port elements with tag, type, mask and defvalue attributes to over- ride defaults for specific inputs. These port elements should only oc- cur inside system elements that apply to particular systems or source files (i.e. they should not occur inside system elements where the name attribute has the value default). The default control assignments can be overridden, as well as the toggle setting for digital inputs. The tag, type, mask and defvalue are used to identify the affected in- put. You can find out the values to use for a particular input by changing its control assignment, exiting MAME, and checking the values in the system configuration file (created in the folder specified using the cfg_directory option). Note that these values are not guaranteed to be stable, and may change between MAME versions. Heres an example that overrides defaults for 280-ZZZAP: <system name="280zzzap"> <input> <port tag=":IN0" type="P1_BUTTON2" mask="16" defvalue="0" toggle="no" /> <port tag=":IN1" type="P1_PADDLE" mask="255" defvalue="127"> <newseq type="increment">KEYCODE_K</newseq> <newseq type="decrement">KEYCODE_J</newseq> </port> </input> </system> This sets the controls to steer left and right to the K and J keys, re- spectively, and disables the toggle setting for the gear shift input. Assigning input device numbers Use mapdevice elements with device and controller attributes to assign stable numbers to input devices. Note that all devices explicitly con- figured in this way must be connected when MAME starts for this to work as expected. Set the device attribute to the device ID of the input device, and set the controller attribute to the desired input device token (device type and number). Heres an example numbering two light guns and two XInput game con- trollers: <system name="default"> <input> <mapdevice device="VID_D209&PID_1601" controller="GUNCODE_1" /> <mapdevice device="VID_D209&PID_1602" controller="GUNCODE_2" /> <mapdevice device="XInput Player 1" controller="JOYCODE_1" /> <mapdevice device="XInput Player 2" controller="JOYCODE_2" /> </input> </system> MAME applies mapdevice elements found inside the first applicable sys- tem element only. To avoid confusion, its simplest to place the system element applying to all systems (name attribute set to default) first in the file, and use it to assign input device numbers. Setting pointer input options A pointer_input element may contain target elements to set pointer in- put options for each output screen or window. Each target element must have an index attribute containing the zero-based index of the screen to which it applies. Each target element may have an activity_timeout attribute to set the time after which a mouse pointer that has not moved and has no buttons pressed will be considered inactive. The value is specified in sec- onds, and must be in the range of 0.1 seconds to 10 seconds, inclusive. Each target element may have a hide_inactive element to set whether in- active pointers may be hidden. If the value is 0 (zero), inactive pointers will not be hidden. If the value is 1, inactive pointers may be hidden, but layout views can still specify that inactive pointers should not be hidden. Heres an example demonstrating the use of this feature: <system name="default"> <pointer_input> <target index="0" activity_timeout="1.5" /> </pointer_input> </system> <system name="intellec4.cpp"> <pointer_input> <target index="0" hide_inactive="0" /> </pointer_input> </system> For all systems, pointers over the first output screen or window will be considered inactive after not moving for 1.5 seconds with no buttons pressed. For systems defined in intellec4.cpp, inactive pointers over the first window will not be hidden. Stable Controller IDs By default, MAME does not assign stable numbers to input devices. For instance, a game pad controller may be assigned to Joy 1 initially, but after restarting, the same game pad may be reassigned to Joy 3. The reason is that MAME assigns numbers to input devices in the based on enumeration order. Factors that can cause this to change include disconnecting and reconnecting USB or Bluetooth devices, changing ports/hubs, and even just restarting the computer. Input device num- bers can be quite unpredictable. This is where the mapdevice configuration setting comes into the pic- ture. By adding this setting to a controller configuration file, you can ensure that a given input device is always assigned the same number in MAME. Using mapdevice The mapdevice XML element is added to the input XML element in the con- troller configuration file. It requires two attributes, device and con- troller. Note that mapdevice elements only take effect in the con- troller configuration file (set using the -ctrlr option) they are ig- nored in system configuration files and the default configuration file. The device attribute specifies the device ID of the input device to match. It may also be a substring of the device ID. To obtain the de- vice ID for an input device, select it in the Input Devices menu, and then select Copy Device ID. The device ID will be copied to the clip- board. You can also see input device IDs by turning on verbose logging (more on this later). The format of device IDs depends the type of de- vice, selected input provider module and operating system. Your input device IDs may look very different to the examples here. The controller attribute specifies the input token for the input device type (i.e. JOYCODE, GUNCODE, MOUSECODE) and number to assign to the de- vice, separated by an underscore. Numbering starts from 1. For exam- ple the token for the first joystick device will be JOYCODE_1, the sec- ond will be JOYCODE_2, and so on. Example Heres an example: <mameconfig version="10"> <system name="default"> <input> <mapdevice device="VID_D209&PID_1601" controller="GUNCODE_1" /> <mapdevice device="VID_D209&PID_1602" controller="GUNCODE_2" /> <mapdevice device="XInput Player 1" controller="JOYCODE_1" /> <mapdevice device="XInput Player 2" controller="JOYCODE_2" /> <port type="P1_JOYSTICK_UP"> <newseq type="standard"> JOYCODE_1_YAXIS_UP_SWITCH OR KEYCODE_8PAD </newseq> </port> ... In the above example, we have four device mappings specified: • The first two mapdevice elements map player 1 and 2 light guns to Gun 1 and Gun 2, respectively. We use a substring of the full device IDs to match each devices. Note that, since this is XML, we needed to escape the ampersands (&) as &. • The last two mapdevices elements map player 1 and player 2 gamepad controllers to Joy 1 and Joy 2, respectively. In this case, these are XInput game controllers. Listing Available Devices There are two ways to obtain device IDs: by copying them from the Input Devices menu, or by turning on verbose logging and finding the messages logged when input devices are added. To reach the Input Devices menu from the system selection menu, select General Settings, and the select Input Devices. To reach the input de- vices menu from the main menu, select Input Settings, then select Input Devices. From the Input Devices menu, select a device, then select Copy Device ID to copy its device ID to the clipboard. To use verbose logging, run MAME with the -v or -verbose option on the command line. Search the output for messages starting with Input: Adding that show recognised input devices and their respective IDs. Here an example: Input: Adding lightgun #1: Input: Adding lightgun #2: Input: Adding lightgun #3: HID-compliant mouse (device id: \\?\HID#VID_045E&PID_0053#7&18297dcb&0&0000#{378de44c-56ef-11d1-bc8c-00a0c91405dd}) Input: Adding lightgun #4: HID-compliant mouse (device id: \\?\HID#IrDeviceV2&Col08#2&2818a073&0&0007#{378de44c-56ef-11d1-bc8c-00a0c91405dd}) Input: Adding lightgun #5: HID-compliant mouse (device id: \\?\HID#VID_D209&PID_1602&MI_02#8&389ab7f3&0&0000#{378de44c-56ef-11d1-bc8c-00a0c91405dd}) Input: Adding lightgun #6: HID-compliant mouse (device id: \\?\HID#VID_D209&PID_1601&MI_02#9&375eebb1&0&0000#{378de44c-56ef-11d1-bc8c-00a0c91405dd}) Input: Adding lightgun #7: HID-compliant mouse (device id: \\?\HID#VID_1241&PID_1111#8&198f3adc&0&0000#{378de44c-56ef-11d1-bc8c-00a0c91405dd}) Skipping DirectInput for XInput compatible joystick Controller (XBOX 360 For Windows). Input: Adding joystick #1: ATRAK Device #1 (device id: ATRAK Device #1) Skipping DirectInput for XInput compatible joystick Controller (XBOX 360 For Windows). Input: Adding joystick #2: ATRAK Device #2 (device id: ATRAK Device #2) Input: Adding joystick #3: XInput Player 1 (device id: XInput Player 1) Input: Adding joystick #4: XInput Player 2 (device id: XInput Player 2) Furthermore, when devices are reassigned using mapdevice elements in the controller configuration file, youll see that in the verbose log output, too, such as: Input: Remapped lightgun #1: HID-compliant mouse (device id: \\?\HID#VID_D209&PID_1601&MI_02#9&375eebb1&0&0000#{378de44c-56ef-11d1-bc8c-00a0c91405dd}) Input: Remapped lightgun #2: HID-compliant mouse (device id: \\?\HID#VID_D209&PID_1602&MI_02#8&389ab7f3&0&0000#{378de44c-56ef-11d1-bc8c-00a0c91405dd}) Input: Remapped joystick #1: XInput Player 1 (device id: XInput Player 1) Input: Remapped joystick #2: XInput Player 2 (device id: XInput Player 2) Limitations You can only assign stable numbers to devices if MAME receives stable, unique device IDs from the input device provider and operating system. This is not always the case. For example the SDL joystick provider is not capable of providing unique IDs for many USB game controllers. If not all configured devices are connected when MAME starts, the de- vices that are connected may not be numbered as expected. Linux Lightguns Many lightguns (especially the Ultimarc AimTrak) may work better in MAME under Linux when using a slightly more complicated configuration. The instructions here are for getting an AimTrak working on Ubuntu us- ing udev and Xorg, but other Linux distributions and lightguns may work with some changes to the steps. Configure udev rules For the AimTrak, each lightgun exposes several USB devices once con- nected: 2 mouse emulation devices, and 1 joystick emulation device. We need to instruct libinput via udev to ignore all but the correct emu- lated mouse device. This prevents each lightgun from producing multiple mouse devices, which would result in non-deterministic selection be- tween the "good" and "bad" emulated mouse devices by Xorg. Create a new file named /etc/udev/rules.d/65-aimtrak.rules and place the following contents into it: # Set mode (0666) & disable libinput handling to avoid X11 picking up the wrong # interfaces/devices. SUBSYSTEMS=="usb", ATTRS{idVendor}=="d209", ATTRS{idProduct}=="160*", MODE="0666", ENV{ID_INPUT}="", ENV{LIBINPUT_IGNORE_DEVICE}="1" # For ID_USB_INTERFACE_NUM==2, re-enable libinput handling. SUBSYSTEMS=="usb", ATTRS{idVendor}=="d209", ATTRS{idProduct}=="160*", ENV{ID_USB_INTERFACE_NUM}=="02", ENV{ID_INPUT}="1", ENV{LIBINPUT_IGNORE_DEVICE}="0" This configuration will be correct for the AimTrak lightguns, however each brand of lightgun will require their own settings. Configure Xorg inputs Next, we'll configure Xorg to treat the lightguns as a "Floating" de- vice. This is important for multiple lightguns to work correctly and ensures each gun's emulated mouse pointer is NOT merged with the main system mouse pointer. In /etc/X11/xorg.conf.d/60-aimtrak.conf we will need: Section "InputClass" Identifier "AimTrak Guns" MatchDevicePath "/dev/input/event*" MatchUSBID "d209:160*" Driver "libinput" Option "Floating" "yes" Option "AutoServerLayout" "no" EndSection Configure MAME Next, we'll need to configure MAME via mame.ini to use the new lightgun device(s). • lightgun 1 • lightgun_device lightgun • lightgunprovider x11 These first three lines tell MAME to enable lightgun support, to tell MAME that we're using a lightgun instead of a mouse, and to use the x11 provider. • lightgun_index1 "Ultimarc ATRAK Device #1" • lightgun_index2 "Ultimarc ATRAK Device #2" • lightgun_index3 "Ultimarc ATRAK Device #3" • lightgun_index4 "Ultimarc ATRAK Device #4" These next lines then tell MAME to keep lightguns consistent across sessions. • offscreen_reload 1 Lastly, as most lightgun games require offscreen reloading and we're using a device that actually can point away from the screen, we enable that functionality. MAME DEBUGGER • Introduction • Debugger commands • Specifying devices and address spaces • Debugger expression syntax • Numbers • Boolean values • Memory accesses • Functions Introduction MAME includes an interactive low-level debugger that targets the emu- lated system. This can be a useful tool for diagnosing emulation is- sues, developing software to run on vintage systems, creating cheats, ROM hacking, or just investigating how software works. Use the -debug command line option to start MAME with the debugger ac- tivated. By default, pressing the backtick/tilde (~) during emulation breaks into the debugger (this can be changed by reassigning the Break in Debugger input). The exact appearance of the debugger depends on your operating system and the options MAME was built with. All variants of the debugger pro- vide a multi-window interface for viewing the contents of memory and disassembled code. The debugger console window is a special window that shows the contents of CPU registers and disassembled code around the current program counter address, and provides a command-line interface to most of the debugging functionality. Debugger commands Debugger commands are described in the sections below. You can also type help <topic> in the debugger console, where <topic> is the name of a command, to see documentation directly in MAME. General Debugger Commands help displays built-in help in the console do evaluates the given expression symlist lists registered symbols softreset executes a soft reset hardreset executes a hard reset print prints one or more <item>s to the console printf prints one or more <item>s to the console using <format> logerror outputs one or more <item>s to the error.log tracelog outputs one or more <item>s to the trace file using <format> tracesym outputs one or more <item>s to the trace file history displays recently visited PC addresses and opcodes trackpc visually track visited opcodes trackmem record which PC writes to each memory address pcatmem query which PC wrote to a given memory address rewind go back in time by loading the most recent rewind state statesave save a state file for the emulated system stateload load a state file for the emulated system snap save a screen snapshot source read commands from file and executes them one by one time prints the current machine time to the console quit exit the debugger and end the emulation session help help [<topic>] Displays built-in debugger help in the debugger console. If no <topic> is specified, top-level topics are listed. Most debugger commands have correspondingly named help topics. Examples: help Lists top-level help topics. help expressions Displays built-in help for debugger expression syntax. help wpiset Displays built-in help for the wpiset command. Back to General Debugger Commands do do <expression> The do command simply evaluates the supplied expression. This is often used to set or modify device state variable (e.g. CPU registers), or to write to memory. See Debugger expression syntax for details about ex- pression syntax. Examples: do pc = 0 Sets the register pc to 0. Back to General Debugger Commands symlist symlist [<cpu>] Lists registered symbols and their values. If <cpu> is not specified, symbols in the global symbol table are displayed; otherwise, symbols specific to the device <cpu> are displayed. Symbols are listed alpha- betically. Read-only symbols are noted. See Specifying devices and address spaces for details on how to specify a CPU. Examples: symlist Displays the global symbol table. symlist 2 Displays the symbols for the third CPU in the system (zero-based index). symlist audiocpu Displays symbols for the CPU with the absolute tag :audiocpu. Back to General Debugger Commands softreset softreset Executes a soft reset. This calls the reset member functions of all the devices in the system (by default, pressing F3 during emulation has the same effect). Examples: softreset Executes a soft reset. Back to General Debugger Commands hardreset hardreset Executes a hard reset. This tears down the emulation session and starts another session with the same system and options (by default, pressing Shift+F3 during emulation has the same effect). Note that this will lose history in the debugger console and error log. Examples: hardreset Executes a hard reset. Back to General Debugger Commands print print <item>[,] The print command prints the results of one or more expressions to the debugger console as hexadecimal numbers. Examples: print pc Prints the value of the pc register the console as a hex number. print a,b,a+b Prints a, b, and the value of a+b to the console as hex numbers. Back to General Debugger Commands printf printf <format>[,<argument>[,]] Prints a C-style formatted message to the debugger console. Only a very limited subset of format specifiers and escape sequences are available: %c Prints the corresponding argument as an 8-bit character. %[-][0][<n>]d Prints the corresponding argument as a decimal number with op- tional left justification, zero fill and minimum field width. %[-][0][<n>]o Prints the corresponding argument as an octal number with op- tional left justification, zero fill and minimum field width. %[-][0][<n>]x Prints the corresponding argument as a lowercase hexadecimal number with optional left justification, zero fill and minimum field width. %[-][0][<n>]X Prints the corresponding argument as an uppercase hexadecimal number with optional left justification, zero fill and minimum field width. %[-][<n>][.[<n>]]s Prints a null-terminated string of 8-bit characters from the ad- dress and address space given by the corresponding argument, with optional left justification, minimum and maximum field widths. %% Prints a literal percent symbol. \n Prints a line break. \\ Prints a literal backslash. All other format specifiers are ignored. Examples: printf "PC=%04X",pc Prints PC=<pcval> where <pcval> is the hexadecimal value of the pc register with a minimum of four digits and zero fill. printf "A=%d, B=%d\\nC=%d",a,b,a+b Prints A=<aval>, B=<bval> on one line, and C=<a+bval> on a sec- ond line. Back to General Debugger Commands logerror logerror <format>[,<argument>[,]] Prints a C-style formatted message to the error log. See printf for details about the limited set of supported format specifiers and escape sequences. Examples: logerror "PC=%04X",pc Logs PC=<pcval> where <pcval> is the hexadecimal value of the pc register with a minimum of four digits and zero fill. logerror "A=%d, B=%d\\nC=%d",a,b,a+b Logs A=<aval>, B=<bval> on one line, and C=<a+bval> on a second line. Back to General Debugger Commands tracelog tracelog <format>[,<argument>[,]] Prints a C-style formatted message to the currently open trace file (see trace for more information). If no trace file is open, this com- mand has no effect. See printf for details about the limited set of supported format specifiers and escape sequences. Examples: tracelog "PC=%04X",pc Outputs PC=<pcval> where <pcval> is the hexadecimal value of the pc register with a minimum of four digits and zero fill if a trace log file is open. tracelog "A=%d, B=%d\\nC=%d",a,b,a+b Outputs A=<aval>, B=<bval> on one line, and C=<a+bval> on a sec- ond line if a trace log file is open. Back to General Debugger Commands tracesym tracesym <item>[,] Prints the specified symbols to the currently open trace file (see trace for more information). If no trace file is open, this command has no effect. Examples: tracesym pc Outputs PC=<pcval> where <pcval> is the value of the pc register in its default format if a trace log file is open. Back to General Debugger Commands history history [<CPU>[,<length>]] Displays recently visited PC addresses, and disassembly of the instruc- tions at those addresses. If present, the first argument selects the CPU (see Specifying devices and address spaces for details); if no CPU is specified, the visible CPU is assumed. The second argument, if present, limits the maximum number of addresses shown. Addresses are shown in order from least to most recently visited. Examples: history ,5 Displays up to five most recently visited PC addresses and in- structions for the visible CPU. history 3 Displays recently visited PC addresses and instructions for the fourth CPU in the system (zero-based index). history audiocpu,1 Displays the most recently visited PC address and instruction for the CPU with the absolute tag :audiocpu. trackpc trackpc [<enable>[,<CPU>[,<clear>]]] Turns visited PC address tracking for disassembly views on or off. In- structions at addresses visited while tracking is on are highlighted in debugger disassembly views. The first argument is a Boolean specifying whether tracking should be turned on or off (defaults to on). The sec- ond argument specifies the CPU to enable or disable tracking for (see Specifying devices and address spaces for details); if no CPU is speci- fied, the visible CPU is assumed. The third argument is a Boolean specifying whether existing data should be cleared (defaults to false). Examples: trackpc 1 Begin or tracking the current CPUs PC. trackpc 1,0,1 Begin or continue tracking PC on the first CPU in the system (zero-based index), but clear the history tracked so far. Back to General Debugger Commands trackmem trackmem [<enable>,[<CPU>,[<clear>]]] Enables or disables logging the PC address each time a memory address is written to. The first argument is a Boolean specifying whether tracking should be enabled or disabled (defaults to enabled). The sec- ond argument specifies the CPU to enable or disable tracking for (see Specifying devices and address spaces for details); if no CPU is speci- fied, the visible CPU is assumed. The third argument is a Boolean specifying whether existing data should be cleared (defaults to false). Use pcatmem to retrieve this data. Right-clicking a debugger memory view will also display the logged PC value for the given address in some configurations. Examples: trackmem Begin or continue tracking memory writes for the visible CPU. trackmem 1,0,1 Begin or continue tracking memory writes for the first CPU in the system (zero-based index), but clear existing tracking data. Back to General Debugger Commands pcatmem pcatmem[{d|i|o}] <address>[:<space>] Returns the PC value at the time the specified address was most re- cently written to. The argument is the requested address, optionally followed by a colon and a CPU and/or address space (see Specifying de- vices and address spaces for details). The optional d, i or o suffix controls the default address space for the command. Tracking must be enabled for the data this command uses to be recorded (see trackmem). Right-clicking a debugger memory view will also dis- play the logged PC value for the given address in some configurations. Examples: pcatmem 400000 Print the PC value when location 400000 in the visible CPUs pro- gram space was most recently written. pcatmem 3bc:io Print the PC value when location 3bc in the visible CPUs io space was most recently written. pcatmem 1400:audiocpu Print the PC value when location 1400 in the CPU :audiocpus pro- gram space was most recently written. Back to General Debugger Commands rewind rewind Loads the most recent RAM-based saved state. When enabled, rewind states are saved when step, over and out commands are used, storing the machine state as of the moment before stepping. May be abbreviated to rw. Consecutively loading rewind states can work like reverse execution. Depending on which steps forward were taken previously, the behavior can be similar to GDB's reverse-stepi and reverse-next commands. All output for this command is currently echoed into the running machine window. Previous memory and PC tracking statistics are cleared. Actual reverse execution does not occur. Examples: rewind Load the previous RAM-based save state. rw Abbreviated form of the command. Back to General Debugger Commands statesave statesave <filename> Creates a save state at the current moment in emulated time. The state file is written to the configured save state directory (see the state_directory option), and the .sta extension is automatically ap- pended to the specified file name. May be abbreviates to ss. All output from this command is currently echoed into the running ma- chine window. Examples: statesave foo Saves the emulated machine state to the file foo.sta in the con- figured save state directory. ss bar Abbreviated form of the command saves the emulated machine state to bar.sta. Back to General Debugger Commands stateload stateload <filename> Restores a saved state file from disk. The specified state file is read from the configured save state directory (see the state_directory option), and the .sta extension is automatically appended to the speci- fied file name. May be abbreviated to sl. All output for this command is currently echoed into the running ma- chine window. Previous memory and PC tracking statistics are cleared. Examples: stateload foo Loads state from file foo.sta to the configured save state di- rectory. sl bar Abbreviated form of the command loads the file bar.sta. Back to General Debugger Commands snap snap [<filename>[,<scrnum>]] Takes a snapshot of the emulated video display and saves it to the con- figured snapshot directory (see the snapshot_directory option). If a file name is specified, a single screenshot for the specified screen is saved using the specified filename (or the first emulated screen in the system if a screen is not specified). If a file name is not specified, the configured snapshot view and file name pattern are used (see the snapview and snapname options). If a file name is specified, the .png extension is automatically ap- pended. The screen number is specified as a zero-based index, as seen in the names of automatically-generated single-screen views in MAMEs video options menus. Examples: snap Takes a snapshot using the configured snapshot view and file name options. snap shinobi Takes a snapshot of the first emulated video screen and saves it as shinobi.png in the configured snapshot directory. Back to General Debugger Commands source source <filename> Reads the specified file in text mode and executes each line as a de- bugger command. This is similar to running a shell script or batch file. Examples: source break_and_trace.cmd Reads and executes debugger commands from break_and_trace.cmd. Back to General Debugger Commands time Prints the total elapsed emulated time to the debugger console. Examples: time Prints the elapsed emulated time. Back to General Debugger Commands quit quit Closes the debugger and ends the emulation session immediately. Either exits MAME or returns to the system selection menu, depending on whether the system was specified on the command line when starting MAME. Examples: quit Exits the emulation session immediately. Back to General Debugger Commands Memory Debugger Commands dasm disassemble code to a file find search emulated memory for data fill fill emulated memory with specified pattern dump dump emulated memory to a file as text strdump dump delimited strings from emulated memory to a file save save binary data from emulated memory to a file saver save binary data from a memory region to a file load load binary data from a file to emulated memory loadr load binary data from a file to a memory region map map a logical address to the corresponding physical address and handler memdump dump current memory maps to a file dasm dasm <filename>,<address>,<length>[,<opcodes>[,<CPU>]] Disassembles program memory to the file specified by the <filename> pa- rameter. The <address> parameter specifies the address to start disas- sembling from, and the <length> parameter specifies how much memory to disassemble. The range <address> through <address>+<length>-1, inclu- sive, will be disassembled to the file. By default, raw opcode data is output with each line. The optional <opcodes> parameter is a Boolean that enables disables this feature. By default, program memory for the visible CPU is disassembled. To disassemble program memory for a dif- ferent CPU, specify it using the optional fifth parameter (see Specifying devices and address spaces for details). Examples: dasm venture.asm,0,10000 Disassembles addresses 0-ffff for the visible CPU, including raw opcode data, to the file venture.asm. dasm harddriv.asm,3000,1000,0,2 Disassembles addresses 3000-3fff for the third CPU in the system (zero-based index), without raw opcode data, to the file hard- driv.asm. Back to Memory Debugger Commands find f[ind][{d|i|o}] <address>[:<space>],<length>[,<data>[,]] Search through memory for the specified sequence of data. The <ad- dress> is the address to begin searching from, optionally followed by a device and/or address space (see Specifying devices and address spaces for details); the <length> specifies how much memory to search. If an address space is not specified, the command suffix sets the address space: find defaults to the first address space exposed by the device, findd defaults to the space with index 1 (data), findi default to the space with index 2 (I/O), and findo defaults to the space with index 3 (opcodes). The <data> can either be a quoted string, a numeric value or expres- sion, or the wildcard character ?. By default, strings imply a byte-sized search; by default non-string data is searched using the na- tive word size of the address space. To override the search size for non-string data, you can prefix values with b. to force byte-sized search, w. for word-sized search, d. for double word-sized search, and q. for quadruple word-sized search. Overrides propagate to subsequent values, so if you want to search for a sequence of words, you need only prefix the first value with w.. Also note that you can intermix sizes to perform more complex searches. The entire range <address> through <address>+<length>-1, inclusive, will be searched for the sequence, and all occurrences will be dis- played. Examples: find 0,10000,"HIGH SCORE",0 Searches the address range 0-ffff in the program space of the visible CPU for the string HIGH SCORE followed by a 0 byte. find 300:tms9918a,100,w.abcd,4567 Searches the address range 300-3ff in the first address space exposed by the device with the absolute tag :tms9918a for the word-sized value abcd followed by the word-sized value 4567. find 0,8000,"AAR",d.0,"BEN",w.0 Searches the address range 0000-7fff for the string AAR followed by a dword-sized 0 followed by the string BEN, followed by a word-sized 0. Back to Memory Debugger Commands fill fill[{d|i|o}] <address>[:<space>],<length>[,<data>[,]] Overwrite a block of memory with copies of the supplied data sequence. The <address> specifies the address to begin writing at, optionally followed by a device and/or address space (see Specifying devices and address spaces for details); the <length> specifies how much memory to fill. If an address space is not specified, the command suffix sets the address space: fill defaults to the first address space exposed by the device, filld defaults to the space with index 1 (data), filli de- fault to the space with index 2 (I/O), and fillo defaults to the space with index 3 (opcodes). The <data> can either be a quoted string, or a numeric value or expres- sion. By default, non-string data is written using the native word size of the address space. To override the data size for non-string data, you can prefix values with b. to force byte-sized fill, w. for word-sized fill, d. for double word-sized fill, and q. for quadruple word-sized fill. Overrides propagate to subsequent values, so if you want to fill with a series of words, you need only prefix the first value with w.. Also note that you can intermix sizes to perform more complex fills. The fill operation may be truncated if a page fault oc- curs or if part of the sequence or string would fall beyond <ad- dress>+<length>-1. Back to Memory Debugger Commands dump dump[{d|i|o}] <filename>,<ad- dress>[:<space>],<length>[,<group>[,<ascii>[,<rowsize>]]] Dump memory to the text file specified by the <filename> parameter. The <address> specifies the address to start dumping from, optionally followed by a device and/or address space (see Specifying devices and address spaces for details); the <length> specifies how much memory to dump. If an address space is not specified, the command suffix sets the address space: dump defaults to the first address space exposed by the device, dumpd defaults to the space with index 1 (data), dumpi de- fault to the space with index 2 (I/O), and dumpo defaults to the space with index 3 (opcodes). The range <address> through <address>+<length>-1, inclusive, will be output to the file. By default, the data will be output using the na- tive word size of the address space. You can override this by specify- ing the <group> parameter, which can be used to group the data in 1-, 2-, 4- or 8-byte chunks. The optional <ascii> parameter is a Boolean value used to enable or disable output of ASCII characters on the right of each line (enabled by default). The optional <rowsize> parameter specifies the amount of data on each line in address units (defaults to 16 bytes). Examples: dump venture.dmp,0,10000 Dumps addresses 0-ffff from the program space of the visible CPU in 1-byte chunks, including ASCII data, to the file venture.dmp. dumpd harddriv.dmp,3000:3,1000,4,0 Dumps data memory addresses 3000-3fff from the fourth CPU in the system (zero-based index) in 4-byte chunks, without ASCII data, to the file harddriv.dmp. dump vram.dmp,0:sms_vdp:videoram,4000,1,false,8 Dumps videoram space addresses 0000-3fff from the device with the absolute tag path :sms_vdp in 1-byte chunks, without ASCII data, with 8 bytes per line, to the file vram.dmp. Back to Memory Debugger Commands strdump strdump[{d|i|o}] <filename>,<address>[:<space>],<length>[,<term>] Dump memory to the text file specified by the <filename> parameter. The <address> specifies the address to start dumping from, optionally followed by a device and/or address space (see Specifying devices and address spaces for details); the <length> specifies how much memory to dump. If an address space is not specified, the command suffix sets the address space: strdump defaults to the first address space exposed by the device, strdumpd defaults to the space with index 1 (data), str- dumpi default to the space with index 2 (I/O), and strdumpo defaults to the space with index 3 (opcodes). By default, the data will be interpreted as a series of NUL-terminated (ASCIIZ) strings, the dump will have one string per line, and C-style escapes sequences will be used for bytes that do not represent print- able ASCII characters. The optional <term> parameter can be used to specify a different string terminator character. Back to Memory Debugger Commands save save[{d|i|o}] <filename>,<address>[:<space>],<length> Save raw memory to the binary file specified by the <filename> parame- ter. The <address> specifies the address to start saving from, option- ally followed by a device and/or address space (see Specifying devices and address spaces for details); the <length> specifies how much memory to save. If an address space is not specified, the command suffix sets the address space: save defaults to the first address space exposed by the device, saved defaults to the space with index 1 (data), savei de- fault to the space with index 2 (I/O), and saveo defaults to the space with index 3 (opcodes). The range <address> through <address>+<length>-1, inclusive, will be output to the file. Examples: save venture.bin,0,10000 Saves addresses 0-ffff from the program space of the current CPU to the binary file venture.bin saved harddriv.bin,3000:3,1000 Saves data memory addresses 3000-3fff from the fourth CPU in the system (zero-based index) to the binary file harddriv.bin. save vram.bin,0:sms_vdp:videoram,4000 Saves videoram space addresses 0000-3fff from the device with the absolute tag path :sms_vdp to the binary file vram.bin. Back to Memory Debugger Commands saver saver <filename>,<address>,<length>,<region> Save raw content of memory region specified by the <region> parameter to the binary file specified by the <filename> parameter. Regions tags follow the same rules as device tags (see Specifying devices and ad- dress spaces). The <address> specifies the address to start saving from, and the <length> specifies how much memory to save. The range <address> through <address>+<length>-1, inclusive, will be output to the file. Examples: saver data.bin,200,100,:monitor Saves :monitor region addresses 200-2ff to the binary file data.bin. saver cpurom.bin,1000,400,. Saves addresses 1000-13ff from the memory region with the same tag as the visible CPU to the binary file cpurom.bin. Back to Memory Debugger Commands load load[{d|i|o}] <filename>,<address>[:<space>][,<length>] Load raw memory from the binary file specified by the <filename> para- meter. The <address> specifies the address to start loading to, op- tionally followed by a device and/or address space (see Specifying de- vices and address spaces for details); the <length> specifies how much memory to load. If an address space is not specified, the command suf- fix sets the address space: load defaults to the first address space exposed by the device, loadd defaults to the space with index 1 (data), loadi default to the space with index 2 (I/O), and loado defaults to the space with index 3 (opcodes). The range <address> through <address>+<length>-1, inclusive, will be read in from the file. If the <length> is omitted, if it is zero, or if it is greater than the total length of the file, the entire contents of the file will be loaded but no more. Note that this has the same effect as writing to the address space from a debugger memory view, or using the b@, w@, d@ or q@ memory accessors in debugger expressions. Read-only memory will not be overwritten, and writing to I/O addresses may have effects beyond setting register val- ues. Examples: load venture.bin,0,10000 Loads addresses 0-ffff in the program space for the visible CPU from the binary file venture.bin. loadd harddriv.bin,3000,1000,3 Loads data memory addresses 3000-3fff in the program space for the fourth CPU in the system (zero-based index) from the binary file harddriv.bin. load vram.bin,0:sms_vdp:videoram Loads the videoram space for the device with the absolute tag path :sms_vdp starting at address 0000 with the entire content of the binary file vram.bin. Back to Memory Debugger Commands loadr loadr <filename>,<address>,<length>,<region> Load memory in the memory region specified by the <region> with raw data from the binary file specified by the <filename> parameter. Re- gions tags follow the same rules as device tags (see Specifying devices and address spaces). The <address> specifies the address to start loading to, and the <length> specifies how much memory to load. The range <address> through <address>+<length>-1, inclusive, will be read in from the file. If the <length> is zero, or is greater than the to- tal length of the file, the entire contents of the file will be loaded but no more. Examples: loadr data.bin,200,100,:monitor Loads :monitor region addresses 200-2ff from the binary file data.bin. loadr cpurom.bin,1000,400,. Loads addresses 1000-13ff in the memory region with the same tag as the visible CPU from the binary file cpurom.bin. Back to Memory Debugger Commands map map[{d|i|o}] <address>[:<space>] Map a logical memory address to the corresponding physical address, as well as reporting the handler name. The address may optionally be followed by a colon and device and/or address space (see Specifying de- vices and address spaces for details). If an address space is not specified, the command suffix sets the address space: map defaults to the first address space exposed by the device, mapd defaults to the space with index 1 (data), mapi default to the space with index 2 (I/O), and mapo defaults to the space with index 3 (opcodes). Examples: map 152d0 Gives the physical address and handler name for logical address 152d0 in program memory for the visible CPU. map 107:sms_vdp Gives the physical address and handler name for logical address 107 in the first address space for the device with the absolute tag path :sms_vdp. Back to Memory Debugger Commands memdump memdump [<filename>,[<device>]] Dumps the current memory maps to the file specified by <filename>, or memdump.log if omitted. If <device> is specified (see Specifying de- vices and address spaces), only memory maps for the part of the device tree rooted at this device will be dumped. Examples: memdump mylog.log Dumps memory maps for all devices in the system to the file my- log.log. memdump Dumps memory maps for all devices in the system to the file mem- dump.log. memdump audiomaps.log,audiopcb Dumps memory maps for the device with the absolute tag path :au- diopcb and all its child devices to the file audiomaps.log. memdump mylog.log,1 Dumps memory maps for the second CPU device in the system (zero-based index) and all its child devices to the file my- log.log. Back to Memory Debugger Commands Execution Debugger Commands step single step for <count> instructions (F11) over single step over <count> instructions (F10) out single step until the current subroutine/exception handler re- turns (Shift-F11) go resume execution (F5) gbt resume execution until next true branch is executed gbf resume execution until next false branch is executed gex resume execution until exception is raised gint resume execution until interrupt is taken (F7) gni resume execution until next further instruction gtime resume execution until the given delay has elapsed gvblank resume execution until next vertical blanking interval (F8) next resume execution until the next CPU switch (F6) focus focus debugger only on <CPU> ignore stop debugging on <CPU> observe resume debugging on <CPU> trace trace the specified CPU to a file traceover trace the specified CPU to a file skipping subroutines traceflush flush all open trace files. step s[tep] [<count>] Single steps one or more instructions on the currently executing CPU. Executes one instruction if <count> is omitted, or steps <count> in- structions if it is supplied. Examples: s Steps forward one instruction on the current CPU. step 4 Steps forward four instructions on the current CPU. Back to Execution Debugger Commands over o[ver] [<count>] The over command single steps over one or more instructions on the cur- rently executing CPU, stepping over subroutine calls and exception han- dler traps and counting them as a single instruction. Note that when stepping over a subroutine call, code may execute on other CPUs before the subroutine returns. Steps over one instruction if <count> is omitted, or steps over <count> instructions if it is supplied. Note that the step over functionality may not be implemented for all CPU types. If it is not implemented, then over will behave exactly like step. Examples: o Steps forward over one instruction on the current CPU. over 4 Steps forward over four instructions on the current CPU. Back to Execution Debugger Commands out out Single steps until a return from subroutine or return from exception instruction is encountered. Note that because it detects return from exception conditions, if you attempt to step out of a subroutine and an interrupt/exception occurs before the subroutine completes, execution may stop prematurely at the end of the exception handler. Note that the step out functionality may not be implemented for all CPU types. If it is not implemented, then out will behave exactly like step. Example: out Steps until a subroutine or exception handler returns. Back to Execution Debugger Commands go g[o] [<address>] Resumes execution. Control will not be returned to the debugger until a breakpoint or watchpoint is triggered, or a debugger break is manu- ally requested. If the optional <address> is supplied, a temporary un- conditional breakpoint will be set for the visible CPU at the specified address. It will be cleared automatically when triggered. Examples: g Resume execution until a breakpoint/watchpoint is triggered, or a break is manually requested. g 1234 Resume execution, stopping at address 1234, unless another con- dition causes execution to stop before then. Back to Execution Debugger Commands gbf gbf [<condition>] Resumes execution. Control will not be returned to the debugger until a breakpoint or watchpoint is triggered, or until a conditional branch or skip instruction is not taken, following any delay slots. The optional <condition> parameter lets you specify an expression that will be evaluated each time a conditional branch is encountered. If the result of the expression is true (non-zero), execution will be halted after the branch if it is not taken; otherwise, execution will continue with no notification. Examples: gbf Resume execution until a breakpoint/watchpoint is triggered, or until the next false branch. gbf {pc != 1234} Resume execution until the next false branch, disregarding the instruction at address 1234. Back to Execution Debugger Commands gbt gbt [<condition>] Resumes execution. Control will not be returned to the debugger until a breakpoint or watchpoint is triggered, or until a conditional branch or skip instruction is taken, following any delay slots. The optional <condition> parameter lets you specify an expression that will be evaluated each time a conditional branch is encountered. If the result of the expression is true (non-zero), execution will be halted after the branch if it is taken; otherwise, execution will con- tinue with no notification. Examples: gbt Resume execution until a breakpoint/watchpoint is triggered, or until the next true branch. gbt {pc != 1234} Resume execution until the next true branch, disregarding the instruction at address 1234. Back to Execution Debugger Commands gex ge[x] [<exception>,[<condition>]] Resumes execution. Control will not be returned to the debugger until a breakpoint or watchpoint is triggered, or until an exception condi- tion is raised on the current CPU. Use the optional <exception> para- meter to stop execution only for a specific exception condition. If <exception> is omitted, execution will stop for any exception condi- tion. The optional <condition> parameter lets you specify an expression that will be evaluated each time the specified exception condition is raised. If the result of the expression is true (non-zero), the excep- tion will halt execution; otherwise, execution will continue with no notification. Examples: gex Resume execution until a breakpoint/watchpoint is triggered, or until any exception condition is raised on the current CPU. ge 2 Resume execution until a breakpoint/watchpoint is triggered, or until exception condition 2 is raised on the current CPU. Back to Execution Debugger Commands gint gi[nt] [<irqline>] Resumes execution. Control will not be returned to the debugger until a breakpoint or watchpoint is triggered, or until an interrupt is as- serted and acknowledged on the current CPU. Use the optional <irqline> parameter to stop execution only for a specific interrupt line being asserted and acknowledged. If <irqline> is omitted, execution will stop when any interrupt is acknowledged. Examples: gi Resume execution until a breakpoint/watchpoint is triggered, or any interrupt is asserted and acknowledged on the current CPU. gint 4 Resume execution until a breakpoint/watchpoint is triggered, or interrupt request line 4 is asserted and acknowledged on the current CPU. Back to Execution Debugger Commands gni gni [<count>] Resumes execution. Control will not be returned to the debugger until a breakpoint or watchpoint is triggered. A temporary unconditional breakpoint is set at the program address <count> instructions sequen- tially past the current one. When this breakpoint is hit, it is auto- matically removed. The <count> parameter is optional and defaults to 1 if omitted. If <count> is specified as zero, the command does nothing. <count> is not permitted to exceed 512 decimal. Examples: gni Resume execution until a breakpoint/watchpoint is triggered, in- cluding the temporary breakpoint set at the address of the fol- lowing instruction. gni 2 Resume execution until a breakpoint/watchpoint is triggered. A temporary breakpoint is set two instructions past the current one. Back to Execution Debugger Commands gtime gt[ime] <milliseconds> Resumes execution. Control will not be returned to the debugger until a specified interval of emulated time has elapsed. The interval is specified in milliseconds. Example: gtime #10000 Resume execution for ten seconds of emulated time. Back to Execution Debugger Commands gvblank gv[blank] Resumes execution. Control will not be returned to the debugger until a breakpoint or watchpoint is triggered, or until the beginning of the vertical blanking interval for an emulated screen. Example: gv Resume execution until a breakpoint/watchpoint is triggered, or a vertical blanking interval starts. Back to Execution Debugger Commands next n[ext] Resumes execution until a different CPU is scheduled. Execution will not stop when a CPU is scheduled if it is ignored due to the use of ignore or focus. Example: n Resume execution, stopping when a different CPU that is not ig- nored is scheduled. Back to Execution Debugger Commands focus focus <CPU> Focus exclusively on to the specified <CPU>, ignoring all other CPUs. The <CPU> argument can be a device tag or debugger CPU number (see Specifying devices and address spaces for details). This is equivalent to using the ignore command to ignore all CPUs besides the specified CPU. Examples: focus 1 Focus exclusively on the second CPU in the system (zero-based index), ignoring all other CPUs. focus audiopcb:melodycpu Focus exclusively on the CPU with the absolute tag path :au- diopcb:melodycpu. Back to Execution Debugger Commands ignore ignore [<CPU>[,<CPU>[,]]] Ignores the specified CPUs in the debugger. CPUs can be specified by tag or debugger CPU number (see Specifying devices and address spaces for details). The debugger never shows execution for ignored CPUs, and breakpoints or watchpoints on ignored CPUs have no effect. If no CPUs are specified, currently ignored CPUs will be listed. Use the observe command to stop ignoring a CPU. Note that you cannot ignore all CPUs; at least CPU must be observed at all times. Examples: ignore audiocpu Ignore the CPU with the absolute tag path :audiocpu when using the debugger. ignore 2,3,4 Ignore the third, fourth and fifth CPUs in the system (zero-based indices) when using the debugger. ignore List the CPUs that are currently being ignored by the debugger. Back to Execution Debugger Commands observe observe [<CPU>[,<CPU>[,]]] Allow interaction with the specified CPUs in the debugger. CPUs can be specified by tag or debugger CPU number (see Specifying devices and ad- dress spaces for details). This command reverses the effects of the ignore command. If no CPUs are specified, currently observed CPUs will be listed. Examples: observe audiocpu Stop ignoring the CPU with the absolute tag path :audiocpu when using the debugger. observe 2,3,4 Stop ignoring the third, fourth and fifth CPUs in the system (zero-based indices) when using the debugger. observe List the CPUs that are currently being observed by the debugger. Back to Execution Debugger Commands trace trace {<filename>|off}[,<CPU>[,[noloop|logerror][,<action>]]] Starts or stops tracing for execution of the specified <CPU>, or the currently visible CPU if no CPU is specified. To enable tracing, spec- ify the trace log file name in the <filename> parameter. To disable tracing, use the keyword off for the <filename> parameter. If the <filename> argument begins with two right angle brackets (>>), it is treated as a directive to open the file for appending rather than over- writing. The optional third parameter is a flags field. The supported flags are noloop and logerror. Multiple flags must be separated by | (pipe) characters. By default, loops are detected and condensed to a single line. If the noloop flag is specified, loops will not be detected and every instruction will be logged as executed. If the logerror flag is specified, error log output will be included in the trace log. The optional <action> parameter is a debugger command to execute before each trace message is logged. Generally, this will include a tracelog or tracesym command to include additional information in the trace log. Note that you may need to surround the action within braces { } to en- sure commas and semicolons within the command are not interpreted in the context of the trace command itself. Examples: trace joust.tr Begin tracing the execution of the currently visible CPU, log- ging output to the file joust.tr. trace dribling.tr,maincpu Begin tracing the execution of the CPU with the absolute tag path :maincpu:, logging output to the file dribling.tr. trace starswep.tr,,noloop Begin tracing the execution of the currently visible CPU, log- ging output to the file starswep.tr, with loop detection dis- abled. trace starswep.tr,1,logerror Begin tracing the execution of the second CPU in the system (zero-based index), logging output along with error log output to the file starswep.tr. trace starswep.tr,0,logerror|noloop Begin tracing the execution of the first CPU in the system (zero-based index), logging output along with error log output to the file starswep.tr, with loop detection disabled. trace >>pigskin.tr Begin tracing execution of the currently visible CPU, appending log output to the file pigskin.tr. trace off,0 Turn off tracing for the first CPU in the system (zero-based in- dex). trace asteroid.tr,,,{tracelog "A=%02X ",a} Begin tracing the execution of the currently visible CPU, log- ging output to the file asteroid.tr. Before each line, output A=<aval> to the trace log. Back to Execution Debugger Commands traceover traceover {<filename>|off}[,<CPU>[,[noloop|logerror][,<action>]]] Starts or stops tracing for execution of the specified <CPU>, or the currently visible CPU if no CPU is specified. When a subroutine call is encountered, tracing will skip over the subroutine. The same algo- rithm is used as is used in the step over command. It will not work properly with recursive functions, or if the return address does not immediately follow the call instruction. This command accepts the same parameters as the trace command. Please refer to the corresponding section for a detailed description of op- tions and more examples. Examples: traceover joust.tr Begin tracing the execution of the currently visible CPU, log- ging output to the file joust.tr. traceover dribling.tr,maincpu Begin tracing the execution of the CPU with the absolute tag path :maincpu:, logging output to the file dribling.tr. traceover starswep.tr,,noloop Begin tracing the execution of the currently visible CPU, log- ging output to the file starswep.tr, with loop detection dis- abled. traceover off,0 Turn off tracing for the first CPU in the system (zero-based in- dex). traceover asteroid.tr,,,{tracelog "A=%02X ",a} Begin tracing the execution of the currently visible CPU, log- ging output to the file asteroid.tr. Before each line, output A=<aval> to the trace log. Back to Execution Debugger Commands traceflush traceflush Flushes all open trace log files to disk. Example: traceflush Flush trace log files. Back to Execution Debugger Commands Breakpoint Debugger Commands bpset sets a breakpoint at <address> bpclear clears a specific breakpoint or all breakpoints bpdisable disables a specific breakpoint or all breakpoints bpenable enables a specific breakpoint or all breakpoints bplist lists breakpoints Breakpoints halt execution and activate the debugger before a CPU exe- cutes an instruction at a particular address. bpset bp[set] <address>[:<CPU>][,<condition>[,<action>]] Sets a new execution breakpoint at the specified <address>. The <ad- dress> may optionally be followed by a colon and a tag or debugger CPU number to set a breakpoint for a specific CPU. If no CPU is specified, the breakpoint will be set for the CPU currently visible in the debug- ger. The optional <condition> parameter lets you specify an expression that will be evaluated each time the breakpoint address is hit. If the re- sult of the expression is true (non-zero), the breakpoint will halt ex- ecution; otherwise, execution will continue with no notification. The optional <action> parameter provides a command to be executed whenever the breakpoint is hit and the <condition> is true. Note that you may need to surround the action with braces { } to ensure commas and semi- colons within the command are not interpreted in the context of the bpset command itself. Each breakpoint that is set is assigned a numeric index which can be used to refer to it in other breakpoint commands. Breakpoint indices are unique throughout a session. Examples: bp 1234 Set a breakpoint for the visible CPU that will halt execution whenever the PC is equal to 1234. bp 23456,a0 == 0 && a1 == 0 Set a breakpoint for the visible CPU that will halt execution whenever the PC is equal to 23456 and the expression a0 == 0 && a1 == 0 is true. bp 3456:audiocpu,1,{ printf "A0=%08X\n",a0 ; g } Set a breakpoint for the CPU with the absolute tag path :au- diocpu that will halt execution whenever the PC is equal to 3456. When this happens, print A0=<a0val> to the debugger con- sole and resume execution. bp 45678:2,a0==100,{ a0 = ff ; g } Set a breakpoint on the third CPU in the system (zero-based in- dex) that will halt execution whenever the PC is equal to 45678 and the expression a0 == 100 is true. When that happens, set a0 to ff and resume execution. temp0 = 0 ; bp 567890,++temp0 >= 10 Set a breakpoint for the visible CPU that will halt execution whenever the PC is equal to 567890 and the expression ++temp0 >= 10 is true. This effectively breaks only after the breakpoint has been hit sixteen times. Back to Breakpoint Debugger Commands bpclear bpclear [<bpnum>[,]] Clear breakpoints. If <bpnum> is specified, the breakpoints referred to will be cleared. If <bpnum> is not specified, all breakpoints will be cleared. Examples: bpclear 3 Clear the breakpoint with index 3. bpclear Clear all breakpoints. Back to Breakpoint Debugger Commands bpdisable bpdisable [<bpnum>[,]] Disable breakpoints. If <bpnum> is specified, the breakpoints referred to will be disabled. If <bpnum> is not specified, all breakpoints will be disabled. Note that disabling a breakpoint does not delete it, it just temporar- ily marks the breakpoint as inactive. Disabled breakpoints will not cause execution to halt, their associated condition expressions will not be evaluated, and their associated commands will not be executed. Examples: bpdisable 3 Disable the breakpoint with index 3. bpdisable Disable all breakpoints. Back to Breakpoint Debugger Commands bpenable bpenable [<bpnum>[,]] Enable breakpoints. If <bpnum> is specified, the breakpoint referred to will be enabled. If <bpnum> is not specified, all breakpoints will be enabled. Examples: bpenable 3 Enable the breakpoint with index 3. bpenable Enable all breakpoints. Back to Breakpoint Debugger Commands bplist bplist [<CPU>] List current breakpoints, along with their indices and any associated conditions or actions. If no <CPU> is specified, breakpoints for all CPUs in the system will be listed; if a <CPU> is specified, only break- points for that CPU will be listed. The <CPU> can be specified by tag or by debugger CPU number (see Specifying devices and address spaces for details). Examples: bplist List all breakpoints. bplist . List all breakpoints for the visible CPU. bplist maincpu List all breakpoints for the CPU with the absolute tag path :maincpu. Back to Breakpoint Debugger Commands Watchpoint Debugger Commands wpset sets memory access watchpoints wpclear clears watchpoints wpdisable disables watchpoints wpenable enables enables watchpoints wplist lists watchpoints Watchpoints halt execution and activate the debugger when a CPU ac- cesses a location in a particular memory range. wpset wp[{d|i|o}][set] <address>[:<space>],<length>,<type>[,<condition>[,<ac- tion>]] Sets a new watchpoint starting at the specified <address> and extending for <length>. The range of the watchpoint is <address> through <ad- dress>+<length>-1, inclusive. The <address> may optionally be followed by a CPU and/or address space (see Specifying devices and address spaces for details). If an address space is not specified, the command suffix sets the address space: wpset defaults to the first address space exposed by the CPU, wpdset defaults to the space with index 1 (data), wpiset defaults to the space with index 2 (I/O), and wposet de- faults to the space with index 3 (opcodes). The <type> parameter spec- ifies the access types to trap on it can be one of three values: r for read accesses, w for write accesses, or rw for both read and write ac- cesses. The optional <condition> parameter lets you specify an expression that will be evaluated each time the watchpoint is triggered. If the result of the expression is true (non-zero), the watchpoint will halt execu- tion; otherwise, execution will continue with no notification. The op- tional <action> parameter provides a command to be executed whenever the watchpoint is triggered and the <condition> is true. Note that you may need to surround the action with braces { } to ensure commas and semicolons within the command are not interpreted in the context of the wpset command itself. Each watchpoint that is set is assigned a numeric index which can be used to refer to it in other watchpoint commands. Watchpoint indices are unique throughout a session. To make <condition> expressions more useful, two variables are avail- able: for all watchpoints, the variable wpaddr is set to the access ad- dress that triggered the watchpoint; for write watchpoints, the vari- able wpdata is set to the data being written. Examples: wp 1234,6,rw Set a watchpoint for the visible CPU that will halt execution whenever a read or write to the first address space occurs in the address range 1234-1239, inclusive. wp 23456:data,a,w,wpdata == 1 Set a watchpoint for the visible CPU that will halt execution whenever a write to the data space occurs in the address range 23456-2345f and the data written is equal to 1. wp 3456:maincpu,20,r,1,{ printf "Read @ %08X\n",wpaddr ; g } Set a watchpoint for the CPU with the absolute tag path :maincpu that will halt execution whenever a read from the first address space occurs in the address range 3456-3475. When this happens, print Read @ <wpaddr> to the debugger console and resume execu- tion. temp0 = 0 ; wp 45678,1,w,wpdata==f0,{ temp0++ ; g } Set a watchpoint for the visible CPU that will halt execution whenever a write to the first address space occurs at address 45678 where the value being written is equal to f0. When this happens, increment the variable temp0 and resume execution. Back to Watchpoint Debugger Commands wpclear wpclear [<wpnum>[,]] Clear watchpoints. If <wpnum> is specified, the watchpoints referred to will be cleared. If <wpnum> is not specified, all watchpoints will be cleared. Examples: wpclear 3 Clear the watchpoint with index 3. wpclear Clear all watchpoints. Back to Watchpoint Debugger Commands wpdisable wpdisable [<wpnum>[,]] Disable watchpoints. If <wpnum> is specified, the watchpoints referred to will be disabled. If <wpnum> is not specified, all watchpoints will be disabled. Note that disabling a watchpoint does not delete it, it just temporar- ily marks the watchpoint as inactive. Disabled watchpoints will not cause execution to halt, their associated condition expressions will not be evaluated, and their associated commands will not be executed. Examples: wpdisable 3 Disable the watchpoint with index 3. wpdisable Disable all watchpoints. Back to Watchpoint Debugger Commands wpenable wpenable [<wpnum>[,]] Enable watchpoints. If <wpnum> is specified, the watchpoints referred to will be enabled. If <wpnum> is not specified, all watchpoints will be enabled. Examples: wpenable 3 Enable the watchpoint with index 3. wpenable Enable all watchpoints. Back to Watchpoint Debugger Commands wplist wplist [<CPU>] List current watchpoints, along with their indices and any associated conditions or actions. If no <CPU> is specified, watchpoints for all CPUs in the system will be listed; if a <CPU> is specified, only watch- points for that CPU will be listed. The <CPU> can be specified by tag or by debugger CPU number (see Specifying devices and address spaces for details). Examples: wplist List all watchpoints. wplist . List all watchpoints for the visible CPU. wplist maincpu List all watchpoints for the CPU with the absolute tag path :maincpu. Back to Watchpoint Debugger Commands Registerpoint Debugger Commands rpset sets a registerpoint to trigger on a condition rpclear clears registerpoints rpdisable disables a registerpoint rpenable enables registerpoints rplist lists registerpoints Registerpoints evaluate an expression each time a CPU executes an in- struction and halt execution and activate the debugger if the result is true (non-zero). rpset rp[set] <condition>[,<action>] Sets a new registerpoint which will be triggered when the expression supplied as the <condition> evaluates to true (non-zero). Note that the condition may need to be surrounded with braces { } to prevent it from being interpreted as an assignment. The optional <action> parame- ter provides a command to be executed whenever the registerpoint is triggered. Note that you may need to surround the action with braces { } to ensure commas and semicolons within the command are not inter- preted in the context of the rpset command itself. Each registerpoint that is set is assigned a numeric index which can be used to refer to it in other registerpoint commands. Registerpoint in- dices are unique throughout a session. Examples: rp {PC==150} Set a registerpoint that will halt execution whenever the PC register equals 150. temp0=0; rp {PC==150},{temp0++; g} Set a registerpoint that will increment the variable temp0 when- ever the PC register equals 150. rp {temp0==5} Set a registerpoint that will halt execution whenever the temp0 variable equals 5. Back to Registerpoint Debugger Commands rpclear rpclear [<rpnum>,[,]] Clears registerpoints. If <rpnum> is specified, the registerpoints re- ferred to will be cleared. If <rpnum> is not specified, all register- points will be cleared. Examples: rpclear 3 Clear the registerpoint with index 3. rpclear Clear all registerpoints. Back to Registerpoint Debugger Commands rpdisable rpdisable [<rpnum>[,]] Disables registerpoints. If <rpnum> is specified, the registerpoints referred to will be disabled. If <rpnum> is not specified, all regis- terpoints will be disabled. Note that disabling a registerpoint does not delete it, it just tem- porarily marks the registerpoint as inactive. Disabled registerpoints will not cause execution to halt, their condition expressions will not be evaluated, and their associated commands will not be executed. Examples: rpdisable 3 Disable the registerpoint with index 3. rpdisable Disable all registerpoints. Back to Registerpoint Debugger Commands rpenable rpenable [<rpnum>[,]] Enables registerpoints. If <rpnum> is specified, the registerpoints referred to will be enabled. If <rpnum> is not specified, all regis- terpoints will be enabled. Examples: rpenable 3 Enable the registerpoint with index 3. rpenable Enable all registerpoints. Back to Registerpoint Debugger Commands rplist rplist [<CPU>] List current registerpoints, along with their indices and conditions, and any associated actions. If no <CPU> is specified, registerpoints for all CPUs in the system will be listed; if a <CPU> is specified, only registerpoints for that CPU will be listed. The <CPU> can be specified by tag or by debugger CPU number (see Specifying devices and address spaces for details). Examples: rplist List all registerpoints. rplist . List all registerpoints for the visible CPU. rplist maincpu List all registerpoints for the CPU with the absolute tag path :maincpu. Back to Registerpoint Debugger Commands Exception Point Debugger Commands epset sets a new exception point epclear clears a specific exception point or all exception points epdisable disables a specific exception point or all exception points epenable enables a specific exception point or all exception points eplist lists exception points Exception points halt execution and activate the debugger when a CPU raises a particular exception number. epset ep[set] <type>[,<condition>[,<action>]] Sets a new exception point for exceptions of type <type>. The optional <condition> parameter lets you specify an expression that will be eval- uated each time the exception point is hit. If the result of the ex- pression is true (non-zero), the exception point will actually halt ex- ecution at the start of the exception handler; otherwise, execution will continue with no notification. The optional <action> parameter provides a command that is executed whenever the exception point is hit and the <condition> is true. Note that you may need to embed the ac- tion within braces { } in order to prevent commas and semicolons from being interpreted as applying to the epset command itself. The numbering of exceptions depends upon the CPU type. Causes of ex- ceptions may include internally or externally vectored interrupts, er- rors occurring within instructions and system calls. Each exception point that is set is assigned an index which can be used in other exception point commands to reference this exception point. Examples: ep 2 Set an exception that will halt execution whenever the visible CPU raises exception number 2. Back to Exception Point Debugger Commands epclear epclear [<epnum>[,]] The epclear command clears exception points. If <epnum> is specified, only the requested exception points are cleared, otherwise all excep- tion points are cleared. Examples: epclear 3 Clear exception point index 3. epclear Clear all exception points. Back to Exception Point Debugger Commands epdisable epdisable [<epnum>[,]] The epdisable command disables exception points. If <epnum> is speci- fied, only the requested exception points are disabled, otherwise all exception points are disabled. Note that disabling an exception point does not delete it, it just temporarily marks the exception point as inactive. Examples: epdisable 3 Disable exception point index 3. epdisable Disable all exception points. Back to Exception Point Debugger Commands epenable epenable [<epnum>[,]] The epenable command enables exception points. If <epnum> is speci- fied, only the requested exception points are enabled, otherwise all exception points are enabled. Examples: epenable 3 Enable exception point index 3. epenable Enable all exception points. Back to Exception Point Debugger Commands eplist eplist The eplist command lists all the current exception points, along with their index and any conditions or actions attached to them. Back to Exception Point Debugger Commands Code Annotation Debugger Commands comadd adds a comment to the disassembled code at given address comdelete removes a comment from the given address comsave save the current comments to file comlist list comments stored in the comment file for the system commit combined comadd and comsave command comadd comadd <address>,<comment> Sets the specified comment for the specified address in the disassem- bled code for the visible CPU. This command may be abbreviated to //. Examples: comadd 0,hello world. Adds the comment hello world. to the code at address 0. // 10,undocumented opcode! Adds the comment undocumented opcode! to the code at address 10. comdelete comdelete Deletes the comment at the specified address for the visible CPU. Examples: comdelete 10 Deletes the comment at code address 10 for the visible CPU. comsave comsave Saves the current comments to the XML comment file for the emulated system. This file will be loaded by the debugger the next time the system is run with debugging enabled. The directory for saving these files is set using the comment_directory option. Examples: comsave Saves the current comments to the comment file for the system. comlist comlist Reads the comments stored in the XML comment file for the emulated sys- tem and prints them to the debugger console. This command does not af- fect the comments for the current session, it reads the file directly. The directory for these files is set using the comment_directory op- tion. Examples: comlist Shows comments stored in the comment file for the system. commit commit <address>,<comment> Sets the specified comment for the specified address in the disassem- bled code for the visible CPU, and saves comments to the file for the current emulated system (equivalent to comadd followed by comsave). This command may be abbreviated to /*. Examples: commit 0,hello world. Adds the comment hello world. to the code at address 0 for the visible CPU and saves comments. /* 10,undocumented opcode! Adds the comment undocumented opcode! to the code at address 10 for the visible CPU and saves comments. Cheat Debugger Commands cheatinit initialize the cheat search to the selected memory area cheatrange add selected memory area to cheat search cheatnext filter cheat candidates by comparing to previous values cheatnextf filter cheat candidates by comparing to initial value cheatlist show the list of cheat search matches or save them to a file cheatundo undo the last cheat search (state only) The debugger includes basic cheat search functionality, which works by saving the contents of memory, and then filtering locations according to how the values change. Well demonstrate use of the cheat search functionality to make an infi- nite lives cheat for Raiden (raiden): • Start the game with the debugger active. Allow the game to run, in- sert a coin, and start a game, then break into the debugger. • Ensure the main CPU is visible, and start a search for 8-bit unsigned values using the cheatinit command: >cheatinit ub 36928 cheat locations initialized for NEC V30 ':maincpu' program space • Allow the game to run, lose a life and break into the debugger. • Use the cheatnext command to filter locations that have decreased by 1: >cheatnext -,1 12 cheats found • Allow the game to run, lose another life, break into the debugger, and filter locations that have decreased by 1 again: >cheatnext -,1 Address=0B85 Start=03 Current=01 1 cheats found • Use the cheatlist command to save the cheat candidate to a file: >cheatlist raiden-p1-lives.xml • The file now contains an XML fragment with cheat to set the candidate location to the initial value: <cheat desc="Possibility 1: 00B85 (01)"> <script state="run"> <action>:maincpu.pb@0x00B85=0x03</action> </script> </cheat> cheatinit cheatinit [[<sign>[<width>[<swap>]]],[<address>,<length>[,<space>]]] Initialize the cheat search to writable RAM areas in the specified ad- dress space. May be abbreviated to ci. The first argument specifies the data format to search for. The <sign> may be u for unsigned or s for signed, the <width> may be b for 8-bit (byte), w for 16-bit (word), d for 32-bit (double word), or q for 64-bit (quadruple word); <swap> may be s for reversed byte order. If the first argument is omitted or empty, the data format from the previ- ous cheat search is used, or unsigned 8-bit format if this is the first cheat search. The <address> specifies the address to start searching from, and the <length> specifies how much memory to search. If specified, writable RAM in the range <address> through <address>+<length>-1, inclusive, will be searched; otherwise, all writable RAM in the address space will be searched. See Specifying devices and address spaces for details on specifying ad- dress spaces. If the address space is not specified, it defaults to the first address space exposed by the visible CPU. Examples: cheatinit ub,0x1000,0x10 Initialize the cheat search for unsigned 8-bit values in ad- dresses 0x1000-0x100f in the program space of the visible CPU. cheatinit sw,0x2000,0x1000,1 Initialize the cheat search for signed 16-bit values in ad- dresses 0x2000-0x2fff in the program space of the second CPU in the system (zero-based index). cheatinit uds,0x0000,0x1000 Initialize the cheat search for unsigned 64-bit values with re- verse byte order in addresses 0x0000-0x0fff in the program space of the visible CPU. Back to Cheat Debugger Commands cheatrange cheatrange <address>,<length> Add writable RAM areas to the cheat search. May be abbreviated to cr. Before using this command, the cheatinit command must be used to ini- tialize the cheat search and set the address space and data format. The <address> specifies the address to start searching from, and the <length> specifies how much memory to search. Writable RAM in the range <address> through <address>+<length>-1, inclusive, will be added to the areas to search. Examples: cheatrange 0x1000,0x10 Add addresses 0x1000-0x100f to the areas to search for cheats. Back to Cheat Debugger Commands cheatnext cheatnext <condition>[,<comparisonvalue>] Filter candidates by comparing to the previous search values. If five or fewer candidates remain, they will be shown in the debugger console. May be abbreviated to cn. Possible <condition> arguments: all Use to update the last value without changing the current matches (the <comparisonvalue> is not used). equal (eq) Without <comparisonvalue>, search for values that are equal to the previous search; with <comparisonvalue>, search for values that are equal to the <comparisonvalue>. notequal (ne) Without <comparisonvalue>, search for values that are not equal to the previous search; with <comparisonvalue>, search for val- ues that are not equal to the <comparisonvalue>. decrease (de, -) Without <comparisonvalue>, search for values that have decreased since the previous search; with <comparisonvalue>, search for values that have decreased by the <comparisonvalue> since the previous search. increase (in, +) Without <comparisonvalue>, search for values that have increased since the previous search; with <comparisonvalue>, search for values that have increased by the <comparisonvalue> since the previous search. decreaseorequal (deeq) Search for values that have decreased or are unchanged since the previous search (the <comparisonvalue> is not used). increaseorequal (ineq) Search for values that have increased or are unchanged since the previous search (the <comparisonvalue> is not used). smallerof (lt, <) Search for values that are less than the <comparisonvalue> (the <comparisonvalue> is required). greaterof (gt, >) Search for values that are greater than the <comparisonvalue> (the <comparisonvalue> is required). changedby (ch, ~) Search for values that have changed by the <comparisonvalue> since the previous search (the <comparisonvalue> is required). Examples: cheatnext increase Search for all values that have increased since the previous search. cheatnext decrease,1 Search for all values that have decreased by 1 since the previ- ous search. Back to Cheat Debugger Commands cheatnextf cheatnextf <condition>[,<comparisonvalue>] Filter candidates by comparing to the initial search values. If five or fewer candidates remain, they will be shown in the debugger console. May be abbreviated to cn. Possible <condition> arguments: all Use to update the last value without changing the current matches (the <comparisonvalue> is not used). equal (eq) Without <comparisonvalue>, search for values that are equal to the initial search; with <comparisonvalue>, search for values that are equal to the <comparisonvalue>. notequal (ne) Without <comparisonvalue>, search for values that are not equal to the initial search; with <comparisonvalue>, search for values that are not equal to the <comparisonvalue>. decrease (de, -) Without <comparisonvalue>, search for values that have decreased since the initial search; with <comparisonvalue>, search for values that have decreased by the <comparisonvalue> since the initial search. increase (in, +) Without <comparisonvalue>, search for values that have increased since the initial search; with <comparisonvalue>, search for values that have increased by the <comparisonvalue> since the initial search. decreaseorequal (deeq) Search for values that have decreased or are unchanged since the initial search (the <comparisonvalue> is not used). increaseorequal (ineq) Search for values that have increased or are unchanged since the initial search (the <comparisonvalue> is not used). smallerof (lt, <) Search for values that are less than the <comparisonvalue> (the <comparisonvalue> is required). greaterof (gt, >) Search for values that are greater than the <comparisonvalue> (the <comparisonvalue> is required). changedby (ch, ~) Search for values that have changed by the <comparisonvalue> since the initial search (the <comparisonvalue> is required). Examples: cheatnextf increase Search for all values that have increased since the initial search. cheatnextf decrease,1 Search for all values that have decreased by 1 since the initial search. Back to Cheat Debugger Commands cheatlist cheatlist [<filename>] Without <filename>, show the current cheat matches in the debugger con- sole; with <filename>, save the current cheat matches in basic XML for- mat to the specified file. May be abbreviated to cl. Examples: cheatlist Show the current matches in the console. cheatlist cheat.xml Save the current matches to the file cheat.xml in XML format. Back to Cheat Debugger Commands cheatundo cheatundo Undo filtering of cheat candidates by the most recent cheatnext or cheatnextf command. Note that the previous values are not rolled back. May be abbreviated to cu. Examples: cheatundo Restore cheat candidates filtered out by the most recent cheatnext or cheatnextf command. Back to Cheat Debugger Commands Media Image Debugger Commands images lists all image devices and mounted media images mount mounts a media image file to an image device unmount unmounts the media image from a device images images Lists the instance names for media images devices in the system and the currently mounted media images, if any. Brief instance names, as al- lowed for command line media options, are listed. Mounted software list items are displayed as the list name, software item short name, and part name, separated by colons; other mounted images are displayed as file names. Example: images Lists image device instance names and mounted media. Back to Media Image Debugger Commands mount mount <instance>,<filename> Mounts a file on a media device. The device may be specified by its instance name or brief instance name, as allowed for command line media options. Some media devices allow software list items to be mounted using this command by supplying the short name of the software list item in place of a filename for the <filename> parameter. Examples: mount flop1,os1xutls.td0 Mount the file os1xutls.td0 on the media device with instance name flop1. mount cart,10yard Mount the software list item with short name 10yard on the media device with instance name cart. Back to Media Image Debugger Commands unmount unmount <instance> Unmounts the mounted media image (if any) from a device. The device may be specified by its instance name or brief instance name, as al- lowed for command line media options. Examples: unmount cart Unmounts any media image mounted on the device with instance name cart. Back to Media Image Debugger Commands Specifying devices and address spaces Many debugger commands accept parameters specifying which device to op- erate on. If a device is not specified explicitly, the CPU currently visible in the debugger is used. Devices can be specified by tag, or by CPU number: • Tags are the colon-separated paths that MAME uses to identify devices within a system. You see them in options for configuring slot de- vices, in debugger disassembly and memory viewer source lists, and various other places within MAMEs UI. • CPU numbers are monotonically incrementing numbers that the debugger assigns to CPU-like devices within a system, starting at zero. The cpunum symbol holds the CPU number for the currently visible CPU in the debugger (you can see it by entering the command print cpunum in the debugger console). If a tag starts with a caret (^) or dot (.), it is interpreted relative to the CPU currently visible in the debugger, otherwise it is inter- preted relative to the root machine device. If a device argument is ambiguously valid as both a tag and a CPU number, it will be inter- preted as a tag. Examples: maincpu The device with the absolute tag :maincpu. ^melodypsg The sibling device of the visible CPU with the tag melodypsg. .:adc The child device of the visible CPU with the tag adc. 2 The third CPU-like device in the system (zero-based index). Commands that operate on memory extend this by allowing the device tag or CPU number to be optionally followed by an address space identifier. Address space identifiers are tag-like strings. You can see them in debugger memory viewer source lists. If the address space identifier is omitted, a default address space will be used. Usually, this is the address space that appears first for the device. Many commands have variants with d, i and o (data, I/O and opcodes) suffixes that default to the address spaces at indices 1, 2 and 3, respectively, as these have special significance for CPU-like devices. In ambiguous cases, the default address space of a child device will be used rather than a specific address space. Examples: ram The default address space of the device with the absolute tag :ram, or the ram space of the visible CPU. .:io The default address space of the child device of the visible CPU with the tag io, or the io space of the visible CPU. :program The default address space of the device with the absolute tag :program, or the program space of the root machine device. ^vdp The default address space of the sibling device of the visible CPU with the tag vdp. ^:data The default address space of the sibling device of the visible CPU with the tag data, or the data space of the parent device of the visible CPU. 1:rom The default address space of the child device of the second CPU in the system (zero-based index) with the tag rom, or the rom space of the second CPU in the system. 2 The default address space of the third CPU-like device in the system (zero-based index). If a command takes an emulated memory address as a parameter, the ad- dress may optionally be followed by an address space specification, as described above. Examples: 0220 Address 0220 in the default address space for the visible CPU. 0378:io Address 0378 in the default address space of the device with the absolute tag :io, or the io space of the visible CPU. 1234:.:rom Address 1234 in the default address space of the child device of the visible CPU with the tag :rom, or the rom space of the visi- ble CPU. 1260:^vdp Address 1260 in the default address space of the sibling device of the visible CPU with the tag vdp. 8008:^:data Address 8008 in the default address space of the sibling device of the visible CPU with the tag data, or the data space of the parent device of the visible CPU. 9660::ram Address 9660 in the default address space of the device with the absolute tag :ram, or the ram space of the root machine device. The examples here include a lot of corner cases, but in general the de- bugger should take the most likely meaning for a device or address space specification. Debugger expression syntax Expressions can be used anywhere a numeric or Boolean parameter is ex- pected. The syntax for expressions is similar to a subset of C-style expression syntax, with full operator precedence and parentheses. There are a few operators missing (notably the ternary conditional op- erator), and a few new ones (memory accessors). The table below lists all the operators, ordered from highest to lowest precedence: ( ) Standard parentheses ++ -- Postfix increment/decrement ++ -- ~ ! - + b@ w@ d@ q@ b! w! d! q! Prefix increment/decrement, binary complement, logical comple- ment, unary identity/negation, memory access * / % Multiplication, division, modulo + - Addition, subtraction << >> Bitwise left/right shift < <= > >= Less than, less than or equal, greater than, greater than or equal == != Equal, not equal & Bitwise intersection (and) ^ Bitwise exclusive or | Bitwise union (or) && Logical conjunction (and) || Logical disjunction (or) = *= /= %= += -= <<= >>= &= |= ^= Assignment and modifying assignment , Separate terms, function parameters Major differences from C expression semantics: • All numbers are unsigned 64-bit values. In particular, this means negative numbers are not possible. • The logical conjunction and disjunction operators && and || do not have short-circuit properties both sides of the expression are al- ways evaluated. Numbers Literal numbers are prefixed according to their bases: • Hexadecimal (base-16) with $ or 0x • Decimal (base-10) with # • Octal (base-8) with 0o • Binary (base-2) with 0b • Unprefixed numbers are hexadecimal (base-16). Examples: • 123 is 123 hexadecimal (291 decimal) • $123 is 123 hexadecimal (291 decimal) • 0x123 is 123 hexadecimal (291 decimal) • #123 is 123 decimal • 0o123 is 123 octal (83 decimal) • 0b1001 is 1001 binary (9 decimal) • 0b123 is invalid Boolean values Any expression that evaluates to a number can be used where a Boolean value is required. Zero is treated as false, and all non-zero values are treated as true. Additionally, the string true is treated as true, and the string false is treated as false. An empty string may be supplied as an argument for Boolean parameters to debugger commands to use the default value, even when subsequent pa- rameters are specified. Memory accesses The memory access prefix operators allow reading from and writing to emulated address spaces. The memory prefix operators specify the ac- cess size and whether side effects are disabled, and may optionally be preceded by an address space specification. The supported access sizes and side effect modes are as follows: • b specifies an 8-bit access (byte) • w specifies a 16-bit access (word) • d specifies a 32-bit access (double word) • q specifies a 64-bit access (quadruple word) • @ suppress side effects • ! do not suppress side effects Suppressing side effects of a read access yields the value reading from address would, with no further effects. For example reading a mailbox with side effects disabled will not clear the pending flag, and reading a FIFO with side effects disabled will not remove an item. For write accesses, suppressing side effects doesnt change behaviour in most cases you want to see the effects of writing to a location. How- ever, there are some exceptions where it is useful to separate multiple effects of a write access. For example: • Some registers need to be written in sequence to avoid race condi- tions. The debugger can issue multiple writes at the same point in emulated time, so these race conditions can be avoided trivially. For example writing to the MC68HC05 output compare register high byte (OCRH) inhibits compare until the output compare register low byte (OCRL) is written to prevent race conditions. Since the debugger can write to both locations at the same instant from the emulated ma- chines point of view, the race condition is not usually relevant. Its more error-prone if you can accidentally set hidden state when all you really want to do is change the value, so writing to OCRH with side effects suppressed does not inhibit compare, it just changes the value in the output compare register. • Writing to some registers has multiple effects that may be useful to separate for debugging purposes. Using the MC68HC05 as an example again, writing to OCRL changes the value in the output compare regis- ter, and also clears the output compare flag (OCF) and enables com- pare if it was previously inhibited by writing to OCRH. Writing to OCRL with side effects disabled just changes the value in the regis- ter without clearing OCF or enabling compare, since its useful for debugging purposes. Writing to OCRL with side effects enabled has the additional effects. The size may optionally be preceded by an access type specification: • p or lp specifies a logical address defaulting to space 0 (program) • d or ld specifies a logical address defaulting to space 1 (data) • i or li specifies a logical address defaulting to space 2 (I/O) • 3 or l3 specifies a logical address defaulting to space 3 (opcodes) • pp specifies a physical address defaulting to space 0 (program) • pd specifies a physical address defaulting to space 1 (data) • pi specifies a physical address defaulting to space 2 (I/O) • p3 specifies a physical address defaulting to space 3 (opcodes) • r specifies direct read/write pointer access defaulting to space 0 (program) • o specifies direct read/write pointer access defaulting to space 3 (opcodes) • m specifies a memory region Finally, this may be preceded by a tag and/or address space name fol- lowed by a dot (.). That may seem like a lot to digest, so lets look at the simplest exam- ples: b@<addr> Refers to the byte at <addr> in the program space of the current CPU while suppressing side effects b!<addr> Refers to the byte at <addr> in the program space of the current CPU, not suppressing side effects such as reading a mailbox clearing the pending flag, or reading a FIFO removing an item w@<addr> and w!<addr> Refer to the word at <addr> in the program space of the current CPU, suppressing or not suppressing side effects, respectively. d@<addr> and d!<addr> Refer to the double word at <addr> in the program space of the current CPU, suppressing or not suppressing side effects, re- spectively. q@<addr> and q!<addr> Refer to the quadruple word at <addr> in the program space of the current CPU, suppressing or not suppressing side effects, respectively. Adding access types gives additional possibilities: dw@300 Refers to the word at 300 in the data space of the current CPU while suppressing side effects id@400 Refers to the double word at 400 in the I/O space of the current CPU while suppressing side effects ppd!<addr> Refers to the double word at physical address <addr> in the pro- gram space of the current CPU while not suppressing side effects rw@<addr> Refers to the word at address <addr> in the program space of the current CPU using direct read/write pointer access If we want to access an address space of a device other than the cur- rent CPU, an address space beyond the first four indices, or a memory region, we need to include a tag or name: ramport.b@<addr> Refers to the byte at address <addr> in the ramport space of the current CPU audiocpu.dw@<addr> Refers to the word at address <addr> in the data space of the CPU with absolute tag :audiocpu maincpu:status.b@<addr> Refers to the byte at address <addr> in the status space of the CPU with the absolute tag :maincpu monitor.mb@78 Refers to the byte at 78 in the memory region with the absolute tag :monitor ..md@202 Refers to the double word at address 202 in the memory region with the same tag path as the current CPU. Some combinations are not useful. For example physical and logical ad- dresses are equivalent for some CPUs, and direct read/write pointer ac- cesses never have side effects. Accessing a memory region (m access type) requires a tag to be specified. Memory accesses can be used as both lvalues and rvalues, so you can write b@100 = ff to store a byte in memory. Functions The debugger supports a number of useful utility functions in expres- sions. min(<a>, <b>) Returns the lesser of the two arguments. max(<a>, <b>) Returns the greater of the two arguments. if(<cond>, <trueval>, <falseval>) Returns <trueval> if <cond> is true (non-zero), or <falseval> otherwise. Note that the expressions for <trueval> and <false- val> are both evaluated irrespective of whether <cond> is true or false. abs(<x>) Reinterprets the argument as a 64-bit signed integer and returns the absolute value. bit(<x>, <n>[, <w>]) Extracts and right-aligns a bit field <w> bits wide from <x> with least significant bit position <n>, counting from the least significant bit. If <w> is omitted, a single bit is extracted. s8(<x>) Sign-extends the argument from 8 bits to 64 bits (overwrites bits 8 through 63, inclusive, with the value of bit 7, counting from the least significant bit). s16(<x>) Sign-extends the argument from 16 bits to 64 bits (overwrites bits 16 through 63, inclusive, with the value of bit 15, count- ing from the least significant bit). s32(<x>) Sign-extends the argument from 32 bits to 64 bits (overwrites bits 32 through 63, inclusive, with the value of bit 31, count- ing from the least significant bit). LUA SCRIPTING INTERFACE • Introduction • Features • API reference • Interactive Lua console tutorial Introduction MAME provides Lua script bindings for a useful set of core functional- ity. This feature first appeared in version 0.148, when a minimal Lua interface was implemented. Today, the Lua interface is rich enough to let you inspect and manipulate device state, access CPU registers, read and write memory, and draw custom graphical overlays. There are three ways to use MAMEs Lua scripting capabilities: • Using the interactive Lua console, enabled by the console option. • By providing a script file to run using the -autoboot_script option. The -autoboot_delay option controls how long MAME waits after start- ing the emulated system before running the script. • By writing Lua plugins. Several plugins are included with MAME. Internally, MAME makes extensive use of Sol3 to implement Lua bindings. The Lua API is not yet declared stable and may suddenly change without prior notice. However, we expose methods to let you know at runtime which API version you are running against, and most objects support some level of runtime introspection. Features The API is not yet complete, but this is a partial list of capabilities exposed to Lua scripts: • Session information (application version, current emulated system) • Session control (starting, pausing, resetting, stopping) • Event hooks (on frame painting and on user events) • Device introspection (device tree listing, memory and register enu- meration) • Screen introspection (screens listing, screen details, frame count- ing) • Screen overlay drawing (text, lines, boxes on multiple screens) • Memory read/write (8/16/32/64 bits, signed and unsigned) • Register and state control (state enumeration, get and set) API reference Lua Common Types and Globals • Containers • Emulator interface Containers Many properties yield container wrappers. Container wrappers are cheap to create, and provide an interface that is similar to a read-only ta- ble. The complexity of operations may vary. Container wrappers usu- ally provide most of these operations: #c Get the number of items in the container. c[k] Returns the item corresponding to the key k, or nil if the key is not present. pairs(c) Iterate over container by key and value. The key is what you would pass to the index operator or the get method to get the value. ipairs(c) Iterate over container by index and value. The index is what you would pass to the at method to get the value (this may be the same as the key for some containers). c:empty() Returns a Boolean indicating whether there are no items in the container. c:get(k) Returns the item corresponding to the key k, or nil if the key is not present. Usually equivalent to the index operator. c:at(i) Returns the value at the 1-based index i, or nil if it is out of range. c:find(v) Returns the key for item v, or nil if it is not in the con- tainer. The key is what you would pass to the index operator to get the value. c:index_of(v) Returns the 1-based index for item v, or nil if it is not in the container. The index is what you would pass to the at method to get the value. Emulator interface The emulator interface emu provides access to core functionality. Many classes are also available as properties of the emulator interface. Methods emu.wait(duration, ) Yields for the specified duration in terms of emulated time. The duration may be specified as an attotime or a number in sec- onds. Any additional arguments are returned from the coroutine. Returns a Boolean indicating whether the duration expired nor- mally. All outstanding calls to emu.wait will return false immediately if a saved state is loaded or the emulation session ends. Call- ing this function from callbacks that are not run as coroutines will raise an error. emu.wait_next_update() Yields until the next video/UI update. Any arguments are re- turned from the coroutine. Calling this function from callbacks that are not run as coroutines will raise an error. emu.wait_next_frame() Yields until the next emulated frame completes. Any arguments are returned from the coroutine. Calling this function from callbacks that are not run as coroutines will raise an error. emu.add_machine_reset_notifier(callback) Add a callback to receive notifications when the emulated system is reset. Returns a notifier subscription. emu.add_machine_stop_notifier(callback) Add a callback to receive notifications when the emulated system is stopped. Returns a notifier subscription. emu.add_machine_pause_notifier(callback) Add a callback to receive notifications when the emulated system is paused. Returns a notifier subscription. emu.add_machine_resume_notifier(callback) Add a callback to receive notifications when the emulated system is resumed after being paused. Returns a notifier subscription. emu.add_machine_frame_notifier(callback) Add a callback to receive notifications when an emulated frame completes. Returns a notifier subscription. emu.add_machine_pre_save_notifier(callback) Add a callback to receive notification before the emulated sys- tem state is saved. Returns a notifier subscription. emu.add_machine_post_load_notifier(callback) Add a callback to receive notification after the emulated system is restored to a previously saved state. Returns a notifier subscription. emu.print_error(message) Print an error message. emu.print_warning(message) Print a warning message. emu.print_info(message) Print an informational message. emu.print_verbose(message) Print a verbose diagnostic message (disabled by default). emu.print_debug(message) Print a debug message (only enabled for debug builds by de- fault). emu.lang_translate([context], message) Look up a message with optional context in the current localised message catalog. Returns the message unchanged if no corre- sponding localised message is found. emu.subst_env(string) Substitute environment variables in a string. The syntax is de- pendent on the host operating system. Lua Core Classes Many of MAMEs core classes used to implement an emulation session are available to Lua scripts. • Notifier subscription • Attotime • MAME machine manager • Running machine • Video manager • Sound manager • Output manager • Parameters manager • UI manager • System driver metadata • Lua plugin Notifier subscription Wraps MAMEs util::notifier_subscription class, which manages a sub- scription to a broadcast notification. Methods subscription:unsubscribe() Unsubscribes from notifications. The subscription will become inactive and no future notifications will be received. Properties subscription.is_active (read-only) A Boolean indicating whether the subscription is active. A sub- scription becomes inactive after explicitly unsubscribing or if the underlying notifier is destroyed. Attotime Wraps MAMEs attotime class, which represents a high-precision time in- terval. Attotime values support addition and subtraction with other attotime values, and multiplication and division by integers. Instantiation emu.attotime() Creates an attotime value representing zero (i.e. no elapsed time). emu.attotime(seconds, attoseconds) Creates an attotime with the specified whole and fractional parts. emu.attotime(attotime) Creates a copy of an existing attotime value. emu.attotime.from_double(seconds) Creates an attotime value representing the specified number of seconds. emu.attotime.from_ticks(periods, frequency) Creates an attotime representing the specified number of periods of the specified frequency in Hertz. emu.attotime.from_seconds(seconds) Creates an attotime value representing the specified whole num- ber of seconds. emu.attotime.from_msec(milliseconds) Creates an attotime value representing the specified whole num- ber of milliseconds. emu.attotime.from_usec(microseconds) Creates an attotime value representing the specified whole num- ber of microseconds. emu.attotime.from_nsec(nanoseconds) Creates an attotime value representing the specified whole num- ber of nanoseconds. Methods t:as_double() Returns the time interval in seconds as a floating-point value. t:as_hz() Interprets the interval as a period and returns the correspond- ing frequency in Hertz as a floating-point value. Returns zero if t.is_never is true. The interval must not be zero. t:as_khz() Interprets the interval as a period and returns the correspond- ing frequency kilohertz as a floating-point value. Returns zero if t.is_never is true. The interval must not be zero. t:as_mhz() Interprets the interval as a period and returns the correspond- ing frequency megahertz as a floating-point value. Returns zero if t.is_never is true. The interval must not be zero. t:as_ticks(frequency) Returns the interval as a whole number of periods at the speci- fied frequency. The frequency is specified in Hertz. Properties t.is_zero (read-only) A Boolean indicating whether the value represents no elapsed time. t.is_never (read-only) A Boolean indicating whether the value is greater than the maxi- mum number of whole seconds that can be represented (treated as an unreachable time in the future or overflow). t.attoseconds (read-only) The fraction seconds portion of the interval in attoseconds. t.seconds (read-only) The number of whole seconds in the interval. t.msec (read-only) The number of whole milliseconds in the fractional seconds por- tion of the interval. t.usec (read-only) The number of whole microseconds in the fractional seconds por- tion of the interval. t.nsec (read-only) The number of whole nanoseconds in the fractional seconds por- tion of the interval. MAME machine manager Wraps MAMEs mame_machine_manager class, which holds the running ma- chine, UI manager, and other global components. Instantiation manager The MAME machine manager is available as a global variable in the Lua environment. Properties manager.machine (read-only) The running machine for the current emulation session. manager.ui (read-only) The UI manager for the current session. manager.options (read-only) The emulation options for the current session. manager.plugins[] (read-only) Gets information about the Lua plugins that are present, indexed by name. The index get, at and index_of methods have O(n) com- plexity. Running machine Wraps MAMEs running_machine class, which represents an emulation ses- sion. It provides access to the other core objects that implement an emulation session as well as the emulated device tree. Instantiation manager.machine Gets the running machine instance for the current emulation ses- sion. Methods machine:exit() Schedules an exit from the current emulation session. This will either return to the system selection menu or exit the applica- tion, depending on how it was started. This method returns im- mediately, before the scheduled exit takes place. machine:hard_reset() Schedules a hard reset. This is implemented by tearing down the emulation session and starting another emulation session for the same system. This method returns immediately, before the sched- uled reset takes place. machine:soft_reset() Schedules a soft reset. This is implemented by calling the re- set method of the root device, which is propagated down the de- vice tree. This method returns immediately, before the sched- uled reset takes place. machine:save(filename) Schedules saving machine state to the specified file. If the file name is a relative path, it is considered to be relative to the first configured save state directory. This method returns immediately, before the machine state is saved. If this method is called when a save or load operation is already pending, the previously pending operation will be cancelled. machine:load(filename) Schedules loading machine state from the specified file. If the file name is a relative path, the configured save state directo- ries will be searched. This method returns immediately, before the machine state is saved. If this method is called when a save or load operation is already pending, the previously pend- ing operation will be cancelled. machine:popmessage([msg]) Displays a pop-up message to the user. If the message is not provided, the currently displayed pop-up message (if any) will be hidden. machine:logerror(msg) Writes the message to the machine error log. This may be dis- played in a debugger window, written to a file, or written to the standard error output. Properties machine.time (read-only) The elapsed emulated time for the current session as an attotime. machine.system (read-only) The driver metadata for the current system. machine.parameters (read-only) The parameters manager for the current emulation session. machine.video (read-only) The video manager for the current emulation session. machine.sound (read-only) The sound manager for the current emulation session. machine.output (read-only) The output manager for the current emulation session. machine.memory (read-only) The emulated memory manager for the current session. machine.ioport (read-only) The I/O port manager for the current emulation session. machine.input (read-only) The input manager for the current emulation session. machine.natkeyboard (read-only) Gets the natural keyboard manager, used for controlling keyboard and keypad input to the emulated system. machine.uiinput (read-only) The UI input manager for the current emulation session. machine.render (read-only) The render manager for the current emulation session. machine.debugger (read-only) The debugger manager for the current emulation session, or nil if the debugger is not enabled. machine.options (read-only) The user-specified options for the current emulation session. machine.samplerate (read-only) The output audio sample rate in Hertz. machine.paused (read-only) A Boolean indicating whether emulation is not currently running, usually because the session has been paused or the emulated sys- tem has not completed starting. machine.exit_pending (read-only) A Boolean indicating whether the emulation session is scheduled to exit. machine.hard_reset_pending (read-only) A Boolean indicating whether a hard reset of the emulated system is pending. machine.devices (read-only) A device enumerator that yields all devices in the emulated sys- tem. machine.palettes (read-only) A device enumerator that yields all palette devices in the emu- lated system. machine.screens (read-only) A device enumerator that yields all screen devices in the emu- lated system. machine.cassettes (read-only) A device enumerator that yields all cassette image devices in the emulated system. machine.images (read-only) A device enumerator that yields all media image devices in the emulated system. machine.slots (read-only) A device enumerator that yields all slot devices in the emulated system. Video manager Wraps MAMEs video_manager class, which is responsible for coordinating emulated video drawing, speed throttling, and reading host inputs. Instantiation manager.machine.video Gets the video manager for the current emulation session. Methods video:frame_update() Updates emulated screens, reads host inputs, and updates video output. video:snapshot() Saves snapshot files according to the current configuration. If MAME is configured to take native emulated screen snapshots, one snapshot will be saved for each emulated screen that is visible in a host window/screen with the current view configuration. If MAME is not configured to use take native emulated screen snap- shots or if the system has no emulated screens, a single snap- shot will be saved using the currently selected snapshot view. video:begin_recording([filename], [format]) Stops any video recordings currently in progress and starts recording either the visible emulated screens or the current snapshot view, depending on whether MAME is configured to take native emulated screen snapshots. If the file name is not supplied, the configured snapshot file name is used. If the file name is a relative path, it is inter- preted relative to the first configured snapshot directory. If the format is supplied, it must be "avi" or "mng". If the for- mat is not supplied, it defaults to AVI. video:end_recording() Stops any video recordings that are in progress. video:snapshot_size() Returns the width and height in pixels of snapshots created with the current snapshot target configuration and emulated screen state. This may be configured explicitly by the user, or calcu- lated based on the selected snapshot view and the resolution of any visible emulated screens. video:snapshot_pixels() Returns the pixels of a snapshot created using the current snap- shot target configuration as 32-bit integers packed into a bi- nary string in host Endian order. Pixels are organised in row-major order, from left to right then top to bottom. Pixel values are colours in RGB format packed into 32-bit integers. Properties video.speed_factor (read-only) Configured emulation speed adjustment in per mille (i.e. the ra- tio to normal speed multiplied by 1,000). video.throttled (read/write) A Boolean indicating whether MAME should wait before video up- dates to avoid running faster than the target speed. video.throttle_rate (read/write) The target emulation speed as a ratio of full speed adjusted by the speed factor (i.e. 1 is normal speed adjusted by the speed factor, larger numbers are faster, and smaller numbers are slower). video.frameskip (read/write) The number of emulated video frames to skip drawing out of every twelve, or -1 to automatically adjust the number of frames to skip to maintain the target emulation speed. video.speed_percent (read-only) The current emulated speed as a percentage of the full speed ad- justed by the speed factor. video.effective_frameskip (read-only) The number of emulated frames that are skipped out of every twelve. video.skip_this_frame (read-only) A Boolean indicating whether the video manager will skip drawing emulated screens for the current frame. video.snap_native (read-only) A Boolean indicating whether the video manager will take native emulated screen snapshots. In addition to the relevant configu- ration setting, the emulated system must have at least one emu- lated screen. video.is_recording (read-only) A Boolean indicating whether any video recordings are currently in progress. video.snapshot_target (read-only) The render target used to produce snapshots and video record- ings. Sound manager Wraps MAMEs sound_manager class, which manages the emulated sound stream graph and coordinates sound output. Instantiation manager.machine.sound Gets the sound manager for the current emulation session. Methods sound:start_recording([filename]) Starts recording to a WAV file. Has no effect if currently recording. If the file name is not supplied, uses the config- ured WAV file name (from command line or INI file), or has no effect if no WAV file name is configured. Returns true if recording started, or false if recording is already in progress, opening the output file failed, or no file name was supplied or configured. sound:stop_recording() Stops recording and closes the file if currently recording to a WAV file. sound:get_samples() Returns the current contents of the output sample buffer as a binary string. Samples are 16-bit integers in host byte order. Samples for left and right stereo channels are interleaved. Properties sound.muted (read-only) A Boolean indicating whether sound output is muted for any rea- son. sound.ui_mute (read/write) A Boolean indicating whether sound output is muted at the re- quest of the user. sound.debugger_mute (read/write) A Boolean indicating whether sound output is muted at the re- quest of the debugger. sound.system_mute (read/write) A Boolean indicating whether sound output is muted at the re- quest of the emulated system. sound.attenuation (read/write) The output volume attenuation in decibels. Should generally be a negative integer or zero. sound.recording (read-only) A Boolean indicating whether sound output is currently being recorded to a WAV file. Output manager Wraps MAMEs output_manager class, providing access to system outputs that can be used for interactive artwork or consumed by external pro- grams. Instantiation manager.machine.output Gets the output manager for the current emulation session. Methods output:set_value(name, val) Sets the specified output value. The value must be an integer. The output will be created if it does not already exist. output:set_indexed_value(prefix, index, val) Appends the index (formatted as a decimal integer) to the prefix and sets the value of the corresponding output. The value must be an integer. The output will be created if it does not al- ready exist. output:get_value(name) Returns the value of the specified output, or zero if it doesnt exist. output:get_indexed_value(prefix, index) Appends the index (formatted as a decimal integer) to the prefix and returns the value of the corresponding output, or zero if it doesnt exist. output:name_to_id(name) Gets the per-session unique integer ID for the specified output, or zero if it doesnt exist. output:id_to_name(id) Gets the name for the output with the specified per-session unique ID, or nil if it doesnt exist. This method has O(n) com- plexity, so avoid calling it when performance is important. Parameters manager Wraps MAMEs parameters_manager class, which provides a simple key-value store for metadata from system ROM definitions. Instantiation manager.machine.parameters Gets the parameters manager for the current emulation session. Methods parameters:lookup(tag) Gets the value for the specified parameter if it is set, or an empty string if it is not set. parameters:add(tag, value) Sets the specified parameter if it is not set. Has no effect if the specified parameter is already set. UI manager Wraps MAMEs mame_ui_manager class, which handles menus and other user interface functionality. Instantiation manager.ui Gets the UI manager for the current session. Methods ui:get_char_width(ch) Gets the width of a Unicode character as a proportion of the width of the UI container in the current font at the configured UI line height. ui:get_string_width(str) Gets the width of a string as a proportion of the width of the UI container in the current font at the configured UI line height. ui:set_aggressive_input_focus(enable) On some platforms, this controls whether MAME should accept in- put focus in more situations than when its windows have UI fo- cus. ui:get_general_input_setting(type, [player]) Gets a description of the configured input sequence for the specified input type and player suitable for using in prompts. The input type is an enumerated value. The player number is a zero-based index. If the player number is not supplied, it is assumed to be zero. Properties ui.options (read-only) The UI options for the current session. ui.line_height (read-only) The configured UI text line height as a proportion of the height of the UI container. ui.menu_active (read-only) A Boolean indicating whether an interactive UI element is cur- rently active. Examples include menus and slider controls. ui.ui_active (read/write) A Boolean indicating whether UI control inputs are currently en- abled. ui.single_step (read/write) A Boolean controlling whether the emulated system should be au- tomatically paused when the next frame is drawn. This property is automatically reset when the automatic pause happens. ui.show_fps (read/write) A Boolean controlling whether the current emulation speed and frame skipping settings should be displayed. ui.show_profiler (read/write) A Boolean controlling whether profiling statistics should be displayed. System driver metadata Provides some metadata for an emulated system. Instantiation emu.driver_find(name) Gets the driver metadata for the system with the specified short name, or nil if no such system exists. manager.machine.system Gets the driver metadata for the current system. Properties driver.name (read-only) The short name of the system, as used on the command line, in configuration files, and when searching for resources. driver.description (read-only) The full display name for the system. driver.year (read-only) The release year for the system. May contain question marks if not known definitively. driver.manufacturer (read-only) The manufacturer, developer or distributor of the system. driver.parent (read-only) The short name of parent system for organisation purposes, or "0" if the system has no parent. driver.compatible_with (read-only) The short name of a system that this system is compatible with software for, or nil if the system is not listed as compatible with another system. driver.source_file (read-only) The source file where this system driver is defined. The path format depends on the toolchain the emulator was built with. driver.rotation (read-only) A string indicating the rotation applied to all screens in the system after the screen orientation specified in the machine configuration is applied. Will be one of "rot0", "rot90", "rot180" or "rot270". driver.not_working (read-only) A Boolean indicating whether the system is marked as not work- ing. driver.supports_save (read-only) A Boolean indicating whether the system supports save states. driver.no_cocktail (read-only) A Boolean indicating whether screen flipping in cocktail mode is unsupported. driver.is_bios_root (read-only) A Boolean indicating whether this system represents a system that runs software from removable media without media present. driver.requires_artwork (read-only) A Boolean indicating whether the system requires external art- work to be usable. driver.unofficial (read-only) A Boolean indicating whether this is an unofficial but common user modification to a system. driver.no_sound_hw (read-only) A Boolean indicating whether the system has no sound output hardware. driver.mechanical (read-only) A Boolean indicating whether the system depends on mechanical features that cannot be properly simulated. driver.is_incomplete (read-only) A Boolean indicating whether the system is a prototype with in- complete functionality. Lua plugin Provides a description of an available Lua plugin. Instantiation manager.plugins[name] Gets the description of the Lua plugin with the specified name, or nil if no such plugin is available Properties plugin.name (read-only) The short name of the plugin, used in configuration and when ac- cessing the plugin programmatically. plugin.description (read-only) The display name for the plugin. plugin.type (read-only) The plugin type. May be "plugin" for user-loadable plugins, or "library" for libraries providing common functionality to multi- ple plugins. plugin.directory (read-only) The path to the directory containing the plugins files. plugin.start (read-only) A Boolean indicating whether the plugin enabled. Lua Device Classes Several device classes and device mix-ins classes are exposed to Lua. Devices can be looked up by tag or enumerated. • Device enumerators • Device • Palette device • Screen device • Cassette image device • Image device interface • Slot device interface • Device state entry • Media image format • Slot option Device enumerators Device enumerators are special containers that allow iterating over de- vices and looking up devices by tag. A device enumerator can be cre- ated to find any kind of device, to find devices of a particular type, or to find devices that implement a particular interface. When iterat- ing using pairs or ipairs, devices are returned by walking the device tree depth-first in creation order. The index get operator looks up a device by tag. It returns nil if no device with the specified tag is found, or if the device with the spec- ified tag does not meet the type/interface requirements of the device enumerator. The complexity is O(1) if the result is cached, but an un- cached device lookup is expensive. The at method has O(n) complexity. If you create a device enumerator with a starting point other than the root machine device, passing an absolute tag or a tag containing parent references to the index operator may return a device that would not be discovered by iteration. If you create a device enumerator with re- stricted depth, devices that would not be found due to being too deep in the hierarchy can still be looked up by tag. Creating a device enumerator with depth restricted to zero can be used to downcast a device or test whether a device implements a certain in- terface. For example this will test whether a device implements the media image interface: image_intf = emu.image_enumerator(device, 0):at(1) if image_intf then print(string.format("Device %s mounts images", device.tag)) end Instantiation manager.machine.devices Returns a device enumerator that will iterate over devices in the system. manager.machine.palettes Returns a device enumerator that will iterate over palette de- vices in the system. manager.machine.screens Returns a device enumerator that will iterate over screen de- vices in the system. manager.machine.cassettes Returns a device enumerator that will iterate over cassette im- age devices in the system. manager.machine.images Returns a device enumerator that will iterate over media image devices in the system. manager.machine.slots Returns a device enumerator that will iterate over slot devices in the system. emu.device_enumerator(device, [depth]) Returns a device enumerator that will iterate over devices in the sub-tree starting at the specified device. The specified device will be included. If the depth is provided, it must be an integer specifying the maximum number of levels to iterate below the specified device (i.e. 1 will limit iteration to the device and its immediate children). emu.palette_enumerator(device, [depth]) Returns a device enumerator that will iterate over palette de- vices in the sub-tree starting at the specified device. The specified device will be included if it is a palette device. If the depth is provided, it must be an integer specifying the max- imum number of levels to iterate below the specified device (i.e. 1 will limit iteration to the device and its immediate children). emu.screen_enumerator(device, [depth]) Returns a device enumerator that will iterate over screen de- vices in the sub-tree starting at the specified device. The specified device will be included if it is a screen device. If the depth is provided, it must be an integer specifying the max- imum number of levels to iterate below the specified device (i.e. 1 will limit iteration to the device and its immediate children). emu.cassette_enumerator(device, [depth]) Returns a device enumerator that will iterate over cassette im- age devices in the sub-tree starting at the specified device. The specified device will be included if it is a cassette image device. If the depth is provided, it must be an integer speci- fying the maximum number of levels to iterate below the speci- fied device (i.e. 1 will limit iteration to the device and its immediate children). emu.image_enumerator(device, [depth]) Returns a device enumerator that will iterate over media image devices in the sub-tree starting at the specified device. The specified device will be included if it is a media image device. If the depth is provided, it must be an integer specifying the maximum number of levels to iterate below the specified device (i.e. 1 will limit iteration to the device and its immediate children). emu.slot_enumerator(device, [depth]) Returns a device enumerator that will iterate over slot devices in the sub-tree starting at the specified device. The specified device will be included if it is a slot device. If the depth is provided, it must be an integer specifying the maximum number of levels to iterate below the specified device (i.e. 1 will limit iteration to the device and its immediate children). Device Wraps MAMEs device_t class, which is a base of all device classes. Instantiation manager.machine.devices[tag] Gets a device by tag relative to the root machine device, or nil if no such device exists. manager.machine.devices[tag]:subdevice(tag) Gets a device by tag relative to another arbitrary device, or nil if no such device exists. Methods device:subtag(tag) Converts a tag relative to the device to an absolute tag. device:siblingtag(tag) Converts a tag relative to the devices parent device to an ab- solute tag. device:memshare(tag) Gets a memory share by tag relative to the device, or nil if no such memory share exists. device:membank(tag) Gets a memory bank by tag relative to the device, or nil if no such memory bank exists. device:memregion(tag) Gets a memory region by tag relative to the device, or nil if no such memory region exists. device:ioport(tag) Gets an I/O port by tag relative to the device, or nil if no such I/O port exists. device:subdevice(tag) Gets a device by tag relative to the device. device:siblingdevice(tag) Gets a device by tag relative to the devices parent. device:parameter(tag) Gets a parameter value by tag relative to the device, or an empty string if the parameter is not set. Properties device.tag (read-only) The devices absolute tag in canonical form. device.basetag (read-only) The last component of the devices tag (i.e. its tag relative to its immediate parent), or "root" for the root machine device. device.name (read-only) The full display name for the devices type. device.shortname (read-only) The short name of the devices type (this is used, e.g. on the command line, when looking for resource like ROMs or artwork, and in various data files). device.owner (read-only) The devices immediate parent in the device tree, or nil for the root machine device. device.configured (read-only) A Boolean indicating whether the device has completed configura- tion. device.started (read-only) A Boolean indicating whether the device has completed starting. device.debug (read-only) The debugger interface to the device if it is a CPU device, or nil if it is not a CPU device or the debugger is not enabled. device.state[] (read-only) The state entries for devices that expose the register state in- terface, indexed by symbol, or nil for other devices. The index operator and index_of methods have O(n) complexity; all other supported operations have O(1) complexity. device.spaces[] (read-only) A table of the devices address spaces, indexed by name. Only valid for devices that implement the memory interface. Note that the names are specific to the device type and have no spe- cial significance. Palette device Wraps MAMEs device_palette_interface class, which represents a device that translates pen values to colours. Colours are represented in alpha/red/green/blue (ARGB) format. Channel values range from 0 (transparent or off) to 255 (opaque or full inten- sity), inclusive. Colour channel values are not pre-multiplied by the alpha value. Channel values are packed into the bytes of 32-bit un- signed integers, in the order alpha, red, green, blue from most-signif- icant to least-significant byte. Instantiation manager.machine.palettes[tag] Gets a palette device by tag relative to the root machine de- vice, or nil if no such device exists or it is not a palette de- vice. Methods palette:pen(index) Gets the remapped pen number for the specified palette index. palette:pen_color(pen) Gets the colour for the specified pen number. palette:pen_contrast(pen) Gets the contrast value for the specified pen number. The con- trast is a floating-point number. palette:pen_indirect(index) Gets the indirect pen index for the specified palette index. palette:indirect_color(index) Gets the indirect pen colour for the specified palette index. palette:set_pen_color(pen, color) Sets the colour for the specified pen number. The colour may be specified as a single packed 32-bit value; or as individual red, green and blue channel values, in that order. palette:set_pen_red_level(pen, level) Sets the red channel value of the colour for the specified pen number. Other channel values are not affected. palette:set_pen_green_level(pen, level) Sets the green channel value of the colour for the specified pen number. Other channel values are not affected. palette:set_pen_blue_level(pen, level) Sets the blue channel value of the colour for the specified pen number. Other channel values are not affected. palette:set_pen_contrast(pen, factor) Sets the contrast value for the specified pen number. The value must be a floating-point number. palette:set_pen_indirect(pen, index) Sets the indirect pen index for the specified pen number. palette:set_indirect_color(index, color) Sets the indirect pen colour for the specified palette index. The colour may be specified as a single packed 32-bit value; or as individual red, green and blue channel values, in that order. palette:set_shadow_factor(factor) Sets the contrast value for the current shadow group. The value must be a floating-point number. palette:set_highlight_factor(factor) Sets the contrast value for the current highlight group. The value must be a floating-point number. palette:set_shadow_mode(mode) Sets the shadow mode. The value is the index of the desired shadow table. Properties palette.palette (read-only) The underlying palette managed by the device. palette.entries (read-only) The number of colour entries in the palette. palette.indirect_entries (read-only) The number of indirect pen entries in the palette. palette.black_pen (read-only) The index of the fixed black pen entry. palette.white_pen (read-only) The index of the fixed white pen. palette.shadows_enabled (read-only) A Boolean indicating whether shadow colours are enabled. palette.highlights_enabled (read-only) A Boolean indicating whether highlight colours are enabled. palette.device (read-only) The underlying device. Screen device Wraps MAMEs screen_device class, which represents an emulated video output. Instantiation manager.machine.screens[tag] Gets a screen device by tag relative to the root machine device, or nil if no such device exists or it is not a screen device. Base classes • Device Methods screen:orientation() Returns the rotation angle in degrees (will be one of 0, 90, 180 or 270), whether the screen is flipped left-to-right, and whether the screen is flipped top-to-bottom. This is the final screen orientation after the screen orientation specified in the machine configuration and the rotation for the system driver are applied. screen:time_until_pos(v, [h]) Gets the time remaining until the raster reaches the specified position. If the horizontal component of the position is not specified, it defaults to zero (0, i.e. the beginning of the line). The result is a floating-point number in units of sec- onds. screen:time_until_vblank_start() Gets the time remaining until the start of the vertical blanking interval. The result is a floating-point number in units of seconds. screen:time_until_vblank_end() Gets the time remaining until the end of the vertical blanking interval. The result is a floating-point number in units of seconds. screen:snapshot([filename]) Saves a screen snapshot in PNG format. If no filename is sup- plied, the configured snapshot path and name format will be used. If the supplied filename is not an absolute path, it is interpreted relative to the first configured snapshot path. The filename may contain conversion specifiers that will be replaced by the system name or an incrementing number. Returns a file error if opening the snapshot file failed, or nil otherwise. screen:pixel(x, y) Gets the pixel at the specified location. Coordinates are in pixels, with the origin at the top left corner of the visible area, increasing to the right and down. Returns either a palette index or a colour in RGB format packed into a 32-bit in- teger. Returns zero (0) if the specified point is outside the visible area. screen:pixels() Returns all visible pixels, the visible area width and visible area height. Pixels are returned as 32-bit integers packed into a binary string in host Endian order. Pixels are organised in row-major order, from left to right then top to bottom. Pixels values are either palette indices or colours in RGB format packed into 32-bit integers. screen:draw_box(left, top, right, bottom, [line], [fill]) Draws an outlined rectangle with edges at the specified posi- tions. Coordinates are floating-point numbers in units of emulated screen pixels, with the origin at (0, 0). Note that emulated screen pixels often arent square. The coordinate system is ro- tated if the screen is rotated, which is usually the case for vertical-format screens. Before rotation, the origin is at the top left, and coordinates increase to the right and downwards. Coordinates are limited to the screen area. The fill and line colours are in alpha/red/green/blue (ARGB) format. Channel values are in the range 0 (transparent or off) to 255 (opaque or full intensity), inclusive. Colour channel values are not pre-multiplied by the alpha value. The channel values must be packed into the bytes of a 32-bit unsigned inte- ger, in the order alpha, red, green, blue from most-significant to least-significant byte. If the line colour is not provided, the UI text colour is used; if the fill colour is not provided, the UI background colour is used. screen:draw_line(x0, y0, x1, y1, [color]) Draws a line from (x0, y0) to (x1, y1). Coordinates are floating-point numbers in units of emulated screen pixels, with the origin at (0, 0). Note that emulated screen pixels often arent square. The coordinate system is ro- tated if the screen is rotated, which is usually the case for vertical-format screens. Before rotation, the origin is at the top left, and coordinates increase to the right and downwards. Coordinates are limited to the screen area. The line colour is in alpha/red/green/blue (ARGB) format. Chan- nel values are in the range 0 (transparent or off) to 255 (opaque or full intensity), inclusive. Colour channel values are not pre-multiplied by the alpha value. The channel values must be packed into the bytes of a 32-bit unsigned integer, in the order alpha, red, green, blue from most-significant to least-significant byte. If the line colour is not provided, the UI text colour is used. screen:draw_text(x|justify, y, text, [foreground], [background]) Draws text at the specified position. If the screen is rotated the text will be rotated. If the first argument is a number, the text will be left-aligned at this X coordinate. If the first argument is a string, it must be "left", "center" or "right" to draw the text left-aligned at the left edge of the screen, horizontally cen- tred on the screen, or right-aligned at the right edge of the screen, respectively. The second argument specifies the Y coor- dinate of the maximum ascent of the text. Coordinates are floating-point numbers in units of emulated screen pixels, with the origin at (0, 0). Note that emulated screen pixels often arent square. The coordinate system is ro- tated if the screen is rotated, which is usually the case for vertical-format screens. Before rotation, the origin is at the top left, and coordinates increase to the right and downwards. Coordinates are limited to the screen area. The foreground and background colours are in al- pha/red/green/blue (ARGB) format. Channel values are in the range 0 (transparent or off) to 255 (opaque or full intensity), inclusive. Colour channel values are not pre-multiplied by the alpha value. The channel values must be packed into the bytes of a 32-bit unsigned integer, in the order alpha, red, green, blue from most-significant to least-significant byte. If the foreground colour is not provided, the UI text colour is used; if the background colour is not provided, it is fully transpar- ent. Properties screen.width (read-only) The width of the bitmap produced by the emulated screen in pix- els. screen.height (read-only) The height of the bitmap produced by the emulated screen in pix- els. screen.refresh (read-only) The screens configured refresh rate in Hertz (this may not re- flect the current value). screen.refresh_attoseconds (read-only) The screens configured refresh interval in attoseconds (this may not reflect the current value). screen.xoffset (read-only) The screens default X position offset. This is a floating-point number where one (1) corresponds to the X size of the screens container. This may be useful for restoring the default after adjusting the X offset via the screens container. screen.yoffset (read-only) The screens default Y position offset. This is a floating-point number where one (1) corresponds to the Y size of the screens container. This may be useful for restoring the default after adjusting the Y offset via the screens container. screen.xscale (read-only) The screens default X scale factor, as a floating-point number. This may be useful for restoring the default after adjusting the X scale via the screens container. screen.yscale (read-only) The screens default Y scale factor, as a floating-point number. This may be useful for restoring the default after adjusting the Y scale via the screens container. screen.pixel_period (read-only) The interval taken to draw a horizontal pixel, as a float- ing-point number in units of seconds. screen.scan_period (read-only) The interval taken to draw a scan line (including the horizontal blanking interval), as a floating-point number in units of sec- onds. screen.frame_period (read-only) The interval taken to draw a complete frame (including blanking intervals), as a floating-point number in units of seconds. screen.frame_number (read-only) The current frame number for the screen. This increments monot- onically each frame interval. screen.container (read-only) The render container used to draw the screen. screen.palette (read-only) The palette device used to translate pixel values to colours, or nil if the screen uses a direct colour pixel format. Cassette image device Wraps MAMEs cassette_image_device class, representing a compact cas- sette mechanism typically used by a home computer for program storage. Instantiation manager.machine.cassettes[tag] Gets a cassette image device by tag relative to the root machine device, or nil if no such device exists or it is not a cassette image device. Base classes • Device • Image device interface Methods cassette:stop() Disables playback. cassette:play() Enables playback. The cassette will play if the motor is en- abled. cassette:forward() Sets forward play direction. cassette:reverse() Sets reverse play direction. cassette:seek(time, whence) Jump to the specified position on the tape. The time is a floating-point number in units of seconds, relative to the point specified by the whence argument. The whence argument must be one of "set", "cur" or "end" to seek relative to the start of the tape, the current position, or the end of the tape, respec- tively. Properties cassette.is_stopped (read-only) A Boolean indicating whether the cassette is stopped (i.e. not recording and not playing). cassette.is_playing (read-only) A Boolean indicating whether playback is enabled (i.e. the cas- sette will play if the motor is enabled). cassette.is_recording (read-only) A Boolean indicating whether recording is enabled (i.e. the cas- sette will record if the motor is enabled). cassette.motor_state (read/write) A Boolean indicating whether the cassette motor is enabled. cassette.speaker_state (read/write) A Boolean indicating whether the cassette speaker is enabled. cassette.position (read-only) The current position as a floating-point number in units of sec- onds relative to the start of the tape. cassette.length (read-only) The length of the tape as a floating-point number in units of seconds, or zero (0) if no tape image is mounted. Image device interface Wraps MAMEs device_image_interface class which is a mix-in implemented by devices that can load media image files. Instantiation manager.machine.images[tag] Gets an image device by tag relative to the root machine device, or nil if no such device exists or it is not a media image de- vice. Methods image:load(filename) Loads the specified file as a media image. Returns nil if no error or a string describing an error if an error occurred. image:load_software(name) Loads a media image described in a software list. Returns nil if no error or a string describing an error if an error oc- curred. image:unload() Unloads the mounted image. image:create(filename) Creates and mounts a media image file with the specified name. Returns nil if no error or a string describing an error if an error occurred. image:display() Returns a front panel display string for the device, if sup- ported. This can be used to show status information, like the current head position or motor state. image:add_media_change_notifier(callback) Add a callback to receive notifications when a media image is loaded or unloaded for the device. The callback is passed a single string argument which will be "loaded" if a media image has been loaded or "unloaded" if the previously loaded media im- age has been unloaded. Returns a notifier subscription. Properties image.is_readable (read-only) A Boolean indicating whether the device supports reading. image.is_writeable (read-only) A Boolean indicating whether the device supports writing. image.must_be_loaded (read-only) A Boolean indicating whether the device requires a media image to be loaded in order to start. image.is_reset_on_load (read-only) A Boolean indicating whether the device requires a hard reset to change media images (usually for cartridge slots that contain hardware in addition to memory chips). image.image_type_name (read-only) A string for categorising the media device. image.instance_name (read-only) The instance name of the device in the current configuration. This is used for setting the media image to load on the command line or in INI files. This is not stable, it may have a number appended that may change depending on slot configuration. image.brief_instance_name (read-only) The brief instance name of the device in the current configura- tion. This is used for setting the media image to load on the command line or in INI files. This is not stable, it may have a number appended that may change depending on slot configuration. image.formatlist[] (read-only) The media image formats supported by the device, indexed by name. The index operator and index_of methods have O(n) com- plexity; all other supported operations have O(1) complexity. image.exists (read-only) A Boolean indicating whether a media image file is mounted. image.readonly (read-only) A Boolean indicating whether a media image file is mounted in read-only mode. image.filename (read-only) The full path to the mounted media image file, or nil if no me- dia image is mounted. image.crc (read-only) The 32-bit cyclic redundancy check of the content of the mounted image file if the mounted media image was not loaded from a software list, is mounted read-only and is not a CD-ROM, or zero (0) otherwise. image.loaded_through_softlist (read-only) A Boolean indicating whether the mounted media image was loaded from a software list, or false if no media image is mounted. image.software_list_name (read-only) The short name of the software list if the mounted media image was loaded from a software list. image.software_longname (read-only) The full name of the software item if the mounted media image was loaded from a software list, or nil otherwise. image.software_publisher (read-only) The publisher of the software item if the mounted media image was loaded from a software list, or nil otherwise. image.software_year (read-only) The release year of the software item if the mounted media image was loaded from a software list, or nil otherwise. image.software_parent (read-only) The short name of the parent software item if the mounted media image was loaded from a software list, or nil otherwise. image.device (read-only) The underlying device. Slot device interface Wraps MAMEs device_slot_interface class which is a mix-in implemented by devices that instantiate a user-specified child device. Instantiation manager.machine.slots[tag] Gets an slot device by tag relative to the root machine device, or nil if no such device exists or it is not a slot device. Properties slot.fixed (read-only) A Boolean indicating whether this is a slot with a card speci- fied in machine configuration that cannot be changed by the user. slot.has_selectable_options (read-only) A Boolean indicating whether the slot has any user-selectable options (as opposed to options that can only be selected pro- grammatically, typically for fixed slots or to load media im- ages). slot.options[] (read-only) The slot options describing the child devices that can be in- stantiated by the slot, indexed by option value. The at and in- dex_of methods have O(n) complexity; all other supported opera- tions have O(1) complexity. slot.device (read-only) The underlying device. Device state entry Wraps MAMEs device_state_entry class, which allows access to named reg- isters exposed by a device. Supports conversion to string for display. Instantiation manager.machine.devices[tag].state[symbol] Gets a state entry for a given device by symbol. Properties entry.value (read/write) The numeric value of the state entry, as either an integer or floating-point number. Attempting to set the value of a read-only state entry raises an error. entry.symbol (read-only) The state entrys symbolic name. entry.visible (read-only) A Boolean indicating whether the state entry should be displayed in the debugger register view. entry.writeable (read-only) A Boolean indicating whether it is possible to modify the state entrys value. entry.is_float (read-only) A Boolean indicating whether the state entrys value is a float- ing-point number. entry.datamask (read-only) A bit mask of the valid bits of the value for integer state en- tries. entry.datasize (read-only) The size of the underlying value in bytes for integer state en- tries. entry.max_length (read-only) The maximum display string length for the state entry. Media image format Wraps MAMEs image_device_format class, which describes a media file format supported by a media image device. Instantiation manager.machine.images[tag].formatlist[name] Gets a media image format supported by a given device by name. Properties format.name (read-only) An abbreviated name used to identify the format. This often matches the primary filename extension used for the format. format.description (read-only) The full display name of the format. format.extensions[] (read-only) Yields a table of filename extensions used for the format. format.option_spec (read-only) A string describing options available when creating a media im- age using this format. The string is not intended to be hu- man-readable. Slot option Wraps MAMEs device_slot_interface::slot_option class, which represents a child device that a slot device can be configured to instantiate. Instantiation manager.machine.slots[tag].options[name] Gets a slot option for a given slot device by name (i.e. the value used to select the option). Properties option.name (read-only) The name of the slot option. This is the value used to select this option on the command line or in an INI file. option.device_fullname (read-only) The full display name of the device type instantiated by this option. option.device_shortname (read-only) The short name of the device type instantiated by this option. option.selectable (read-only) A Boolean indicating whether the option may be selected by the user (options that are not user-selectable are typically used for fixed slots or to load media images). option.default_bios (read-only) The default BIOS setting for the device instantiated using this option, or nil if the default BIOS specified in the devices ROM definitions will be used. option.clock (read-only) The configured clock frequency for the device instantiated using this option. This is an unsigned 32-bit integer. If the eight most-significant bits are all set, it is a ratio of the parent devices clock frequency, with the numerator in bits 12-23 and the denominator in bits 0-11. If the eight most-significant bits are not all set, it is a frequency in Hertz. Lua Memory System Classes MAMEs Lua interface exposes various memory system objects, including address spaces, memory shares, memory banks, and memory regions. Scripts can read from and write to the emulated memory system. • Memory manager • Address space • Pass-through handler • Address map • Address map entry • Address map handler data • Memory share • Memory bank • Memory region Memory manager Wraps MAMEs memory_manager class, which allows the memory shares, banks and regions in a system to be enumerated. Instantiation manager.machine.memory Gets the global memory manager instance for the emulated system. Properties memory.shares[] The memory shares in the system, indexed by absolute tag. The at and index_of methods have O(n) complexity; all other sup- ported operations have O(1) complexity. memory.banks[] The memory banks in the system, indexed by absolute tag. The at and index_of methods have O(n) complexity; all other supported operations have O(1) complexity. memory.regions[] The memory regions in the system, indexed by absolute tag. The at and index_of methods have O(n) complexity; all other sup- ported operations have O(1) complexity. Address space Wraps MAMEs address_space class, which represents an address space be- longing to a device. Instantiation manager.machine.devices[tag].spaces[name] Gets the address space with the specified name for a given de- vice. Note that names are specific to the device type. Methods space:read_i{8,16,32,64}(addr) Reads a signed integer value of the size in bits from the speci- fied address. space:read_u{8,16,32,64}(addr) Reads an unsigned integer value of the size in bits from the specified address. space:write_i{8,16,32,64}(addr, val) Writes a signed integer value of the size in bits to the speci- fied address. space:write_u{8,16,32,64}(addr, val) Writes an unsigned integer value of the size in bits to the specified address. space:readv_i{8,16,32,64}(addr) Reads a signed integer value of the size in bits from the speci- fied virtual address. The address is translated with the debug read intent. Returns zero if address translation fails. space:readv_u{8,16,32,64}(addr) Reads an unsigned integer value of the size in bits from the specified virtual address. The address is translated with the debug read intent. Returns zero if address translation fails. space:writev_i{8,16,32,64}(addr, val) Writes a signed integer value of the size in bits to the speci- fied virtual address. The address is translated with the debug write intent. Does not write if address translation fails. space:writev_u{8,16,32,64}(addr, val) Writes an unsigned integer value of the size in bits to the specified virtual address. The address is translated with the debug write intent. Does not write if address translation fails. space:read_direct_i{8,16,32,64}(addr) Reads a signed integer value of the size in bits from the speci- fied address one byte at a time by obtaining a read pointer for each byte address. If a read pointer cannot be obtained for a byte address, the corresponding result byte will be zero. space:read_direct_u{8,16,32,64}(addr) Reads an unsigned integer value of the size in bits from the specified address one byte at a time by obtaining a read pointer for each byte address. If a read pointer cannot be obtained for a byte address, the corresponding result byte will be zero. space:write_direct_i{8,16,32,64}(addr, val) Writes a signed integer value of the size in bits to the speci- fied address one byte at a time by obtaining a write pointer for each byte address. If a write pointer cannot be obtained for a byte address, the corresponding byte will not be written. space:write_direct_u{8,16,32,64}(addr, val) Writes an unsigned integer value of the size in bits to the specified address one byte at a time by obtaining a write pointer for each byte address. If a write pointer cannot be ob- tained for a byte address, the corresponding byte will not be written. space:read_range(start, end, width, [step]) Reads a range of addresses as a binary string. The end address must be greater than or equal to the start address. The width must be 8, 16, 30 or 64. If the step is provided, it must be a positive number of elements. space:add_change_notifier(callback) Add a callback to receive notifications for handler changes in address space. The callback function is passed a single string as an argument, either r if read handlers have potentially changed, w if write handlers have potentially changed, or rw if both read and write handlers have potentially changed. Returns a notifier subscription. space:install_read_tap(start, end, name, callback) Installs a pass-through handler that will receive notifications on reads from the specified range of addresses in the address space. The start and end addresses are inclusive. The name must be a string, and the callback must be a function. The callback is passed three arguments for the access offset, the data read, and the memory access mask. The offset is the absolute offset into the address space. To modify the data be- ing read, return the modified value from the callback function as an integer. If the callback does not return an integer, the data will not be modified. space:install_write_tap(start, end, name, callback) Installs a pass-through handler that will receive notifications on write to the specified range of addresses in the address space. The start and end addresses are inclusive. The name must be a string, and the callback must be a function. The callback is passed three arguments for the access offset, the data written, and the memory access mask. The offset is the absolute offset into the address space. To modify the data be- ing written, return the modified value from the callback func- tion as an integer. If the callback does not return an integer, the data will not be modified. Properties space.name (read-only) The display name for the address space. space.shift (read-only) The address granularity for the address space specified as the shift required to translate a byte address to a native address. Positive values shift towards the most significant bit (left) and negative values shift towards the least significant bit (right). space.index (read-only) The zero-based space index. Some space indices have special meanings for the debugger. space.address_mask (read-only) The address mask for the space. space.data_width (read-only) The data width for the space in bits. space.endianness (read-only) The Endianness of the space ("big" or "little"). space.map (read-only) The configured address map for the space or nil. Pass-through handler Tracks a pass-through handler installed in an address space. A memory pass-through handler receives notifications on accesses to a specified range of addresses, and can modify the data that is read or written if desired. Note that pass-through handler callbacks are not run as coroutines. Instantiation manager.machine.devices[tag].spaces[name]:install_read_tap(start, end, name, callback) Installs a pass-through handler that will receive notifications on reads from the specified range of addresses in an address space. manager.machine.devices[tag].spaces[name]:install_write_tap(start, end, name, callback) Installs a pass-through handler that will receive notifications on writes to the specified range of addresses in an address space. Methods passthrough:reinstall() Reinstalls the pass-through handler in the address space. May be necessary if the handler is removed due to other changes to handlers in the address space. passthrough:remove() Removes the pass-through handler from the address space. The associated callback will not be called in response to future memory accesses. Properties passthrough.addrstart (read-only) The inclusive start address of the address range monitored by the pass-through handler (i.e. the lowest address that the han- dler will be notified for). passthrough.addrend (read-only) The inclusive end address of the address range monitored by the pass-through handler (i.e. the highest address that the handler will be notified for). passthrough.name (read-only) The display name for the pass-through handler. Address map Wraps MAMEs address_map class, used to configure handlers for an ad- dress space. Instantiation manager.machine.devices[tag].spaces[name].map Gets the configured address map for an address space, or nil if no map is configured. Properties map.spacenum (read-only) The address space number of the address space the map is associ- ated with. map.device (read-only) The device that owns the address space the map is associated with. map.unmap_value (read-only) The constant value to return from unmapped reads. map.global_mask (read-only) Global mask to be applied to all addresses when accessing the space. map.entries[] (read-only) The configured entries in the address map. Uses 1-based integer indices. The index operator and the at method have O(n) com- plexity. Address map entry Wraps MAMEs address_map_entry class, representing an entry in a config- ured address map. Instantiation manager.machine.devices[tag].spaces[name].map.entries[index] Gets an entry from the configured map for an address space. Properties entry.address_start (read-only) Start address of the entrys range. entry.address_end (read-only) End address of the entrys range (inclusive). entry.address_mirror (read-only) Address mirror bits. entry.address_mask (read-only) Address mask bits. Only valid for handlers. entry.mask (read-only) Lane mask, indicating which data lines on the bus are connected to the handler. entry.cswidth (read-only) The trigger width for a handler that isnt connected to all the data lines. entry.read (read-only) Additional data for the read handler. entry.write (read-only) Additional data for the write handler. entry.share (read-only) Memory share tag for making RAM entries accessible or nil. entry.region (read-only) Explicit memory region tag for ROM entries, or nil. For ROM en- tries, nil infers the region from the device tag. entry.region_offset (read-only) Starting offset in memory region for ROM entries. Address map handler data Wraps MAMEs map_handler_data class, which provides configuration data to handlers in address maps. Instantiation manager.machine.devices[tag].spaces[name].map.entries[index].read Gets the read handler data for an address map entry. manager.machine.devices[tag].spaces[name].map.entries[index].write Gets the write handler data for an address map entry. Properties data.handlertype (read-only) Handler type. Will be one of "none", "ram", "rom", "nop", "un- map", "delegate", "port", "bank", "submap", or "unknown". Note that multiple handler type values can yield "delegate" or "un- known". data.bits (read-only) Data width for the handler in bits. data.name (read-only) Display name for the handler, or nil. data.tag (read-only) Tag for I/O ports and memory banks, or nil. Memory share Wraps MAMEs memory_share class, representing a named allocated memory zone. Instantiation manager.machine.memory.shares[tag] Gets a memory share by absolute tag, or nil if no such memory share exists. manager.machine.devices[tag]:memshare(tag) Gets a memory share by tag relative to a device, or nil if no such memory share exists. Methods share:read_i{8,16,32,64}(offs) Reads a signed integer value of the size in bits from the speci- fied offset in the memory share. share:read_u{8,16,32,64}(offs) Reads an unsigned integer value of the size in bits from the specified offset in the memory share. share:write_i{8,16,32,64}(offs, val) Writes a signed integer value of the size in bits to the speci- fied offset in the memory share. share:write_u{8,16,32,64}(offs, val) Writes an unsigned integer value of the size in bits to the specified offset in the memory share. Properties share.tag (read-only) The absolute tag of the memory share. share.size (read-only) The size of the memory share in bytes. share.length (read-only) The length of the memory share in native width elements. share.endianness (read-only) The Endianness of the memory share ("big" or "little"). share.bitwidth (read-only) The native element width of the memory share in bits. share.bytewidth (read-only) The native element width of the memory share in bytes. Memory bank Wraps MAMEs memory_bank class, representing a named memory zone indi- rection. Instantiation manager.machine.memory.banks[tag] Gets a memory region by absolute tag, or nil if no such memory bank exists. manager.machine.devices[tag]:membank(tag) Gets a memory region by tag relative to a device, or nil if no such memory bank exists. Properties bank.tag (read-only) The absolute tag of the memory bank. bank.entry (read/write) The currently selected zero-based entry number. Memory region Wraps MAMEs memory_region class, representing a memory region used to store read-only data like ROMs or the result of fixed decryptions. Instantiation manager.machine.memory.regions[tag] Gets a memory region by absolute tag, or nil if no such memory region exists. manager.machine.devices[tag]:memregion(tag) Gets a memory region by tag relative to a device, or nil if no such memory region exists. Methods region:read(offs, len) Reads up to the specified length in bytes from the specified offset in the memory region. The bytes read will be returned as a string. If the specified length extends beyond the end of the memory region, the returned string will be shorter than re- quested. Note that the data will be in host byte order. region:read_i{8,16,32,64}(offs) Reads a signed integer value of the size in bits from the speci- fied offset in the memory region. The offset is specified in bytes. Reading beyond the end of the memory region returns zero. region:read_u{8,16,32,64}(offs) Reads an unsigned integer value of the size in bits from the specified offset in the memory region. The offset is specified in bytes. Reading beyond the end of the memory region returns zero. region:write_i{8,16,32,64}(offs, val) Writes a signed integer value of the size in bits to the speci- fied offset in the memory region. The offset is specified in bytes. Attempting to write beyond the end of the memory region has no effect. region:write_u{8,16,32,64}(offs, val) Writes an unsigned integer value of the size in bits to the specified offset in the memory region. The offset is specified in bytes. Attempting to write beyond the end of the memory re- gion has no effect. Properties region.tag (read-only) The absolute tag of the memory region. region.size (read-only) The size of the memory region in bytes. region.length (read-only) The length of the memory region in native width elements. region.endianness (read-only) The Endianness of the memory region ("big" or "little"). region.bitwidth (read-only) The native element width of the memory region in bits. region.bytewidth (read-only) The native element width of the memory region in bytes. Lua Input System Classes Allows scripts to get input from the user, and access I/O ports in the emulated system. • I/O port manager • Natural keyboard manager • Keyboard input device • I/O port • I/O port field • Live I/O port field state • Input type • Input manager • Input code poller • Input sequence poller • Input sequence • Host input device class • Host input device • Host input device item • UI input manager I/O port manager Wraps MAMEs ioport_manager class, which provides access to emulated I/O ports and handles input configuration. Instantiation manager.machine.ioport Gets the global I/O port manager instance for the emulated ma- chine. Methods ioport:count_players() Returns the number of player controllers in the system. ioport:type_pressed(type, [player]) Returns a Boolean indicating whether the specified input is cur- rently pressed. The input type may be an enumerated value or an input type entry. If the input type is an enumerated value, the player number may be supplied as a zero-based index; if the player number is not supplied, it is assumed to be zero. If the input type is an input type entry, the player number may not be supplied separately. ioport:type_name(type, [player]) Returns the display name for the specified input type and player number. The input type is an enumerated value. The player num- ber is a zero-based index. If the player number is not sup- plied, it is assumed to be zero. ioport:type_group(type, player) Returns the input group for the specified input type and player number. The input type is an enumerated value. The player num- ber is a zero-based index. Returns an integer giving the group- ing for the input. If the player number is not supplied, it is assumed to be zero. This should be called with values obtained from I/O port fields to provide canonical grouping in an input configuration UI. ioport:type_seq(type, [player], [seqtype]) Get the configured input sequence for the specified input type, player number and sequence type. The input type may be an enu- merated value or an input type entry. If the input type is an enumerated value, the player number may be supplied as a zero-based index; if the player number is not supplied, it is assumed to be zero. If the input type is an input type entry, the player number may not be supplied separately. If the se- quence type is supplied, it must be "standard", "increment" or "decrement"; if it is not supplied, it is assumed to be "stan- dard". This provides access to general input assignments. ioport:set_type_seq(type, [player], seqtype, seq) Set the configured input sequence for the specified input type, player number and sequence type. The input type may be an enu- merated value or an input type entry. If the input type is an enumerated value, the player number must be supplied as a zero-based index. If the input type is an input type entry, the player number may not be supplied separately. The sequence type must be "standard", "increment" or "decrement". This allows general input assignments to be set. ioport:token_to_input_type(string) Returns the input type and player number for the specified input type token string. ioport:input_type_to_token(type, [player]) Returns the token string for the specified input type and player number. If the player number is not supplied, it assumed to be zero. Properties ioport.types[] (read-only) Gets the supported input types. Keys are arbitrary indices. All supported operations have O(1) complexity. ioport.ports[] Gets the emulated I/O ports in the system. Keys are absolute tags. The at and index_of methods have O(n) complexity; all other supported operations have O(1) complexity. Natural keyboard manager Wraps MAMEs natural_keyboard class, which manages emulated keyboard and keypad inputs. Instantiation manager.machine.natkeyboard Gets the global natural keyboard manager instance for the emu- lated machine. Methods natkeyboard:post(text) Post literal text to the emulated machine. The machine must have keyboard inputs with character bindings, and the correct keyboard input device must be enabled. natkeyboard:post_coded(text) Post text to the emulated machine. Brace-enclosed codes are in- terpreted in the text. The machine must have keyboard inputs with character bindings, and the correct keyboard input device must be enabled. The recognised codes are {BACKSPACE}, {BS}, {BKSP}, {DEL}, {DELETE}, {END}, {ENTER}, {ESC}, {HOME}, {INS}, {INSERT}, {PGDN}, {PGUP}, {SPACE}, {TAB}, {F1}, {F2}, {F3}, {F4}, {F5}, {F6}, {F7}, {F8}, {F9}, {F10}, {F11}, {F12}, and {QUOTE}. natkeyboard:paste() Post the contents of the host clipboard to the emulated machine. The machine must have keyboard inputs with character bindings, and the correct keyboard input device must be enabled. natkeyboard:dump() Returns a string with a human-readable description of the key- board and keypad input devices in the system, whether they are enabled, and their character bindings. Properties natkeyboard.empty (read-only) A Boolean indicating whether the natural keyboard managers input buffer is empty. natkeyboard.full (read-only) A Boolean indicating whether the natural keyboard managers input buffer is full. natkeyboard.can_post (read-only) A Boolean indicating whether the emulated system supports post- ing character data via the natural keyboard manager. natkeyboard.is_posting (read-only) A Boolean indicating whether posted character data is currently being delivered to the emulated system. natkeyboard.in_use (read/write) A Boolean indicating whether natural keyboard mode is enabled. When natural keyboard mode is enabled, the natural keyboard man- ager translates host character input to emulated system key- strokes. natkeyboard.keyboards[] Gets the keyboard/keypad input devices in the emulated system, indexed by absolute device tag. Index get has O(n) complexity; all other supported operations have O(1) complexity. Keyboard input device Represents a keyboard or keypad input device managed by the natural keyboard manager. Note that this is not a device class. Instantiation manager.machine.natkeyboard.keyboards[tag] Gets the keyboard input device with the specified tag, or nil if the tag does not correspond to a keyboard input device. Properties keyboard.device (read-only) The underlying device. keyboard.tag (read-only) The absolute tag of the underlying device. keyboard.basetag (read-only) The last component of the tag of the underlying device, or "root" for the root machine device. keyboard.name (read-only) The human-readable description of the underlying device type. keyboard.shortname (read-only) The identifier for the underlying device type. keyboard.is_keypad (read-only) A Boolean indicating whether the underlying device has keypad inputs but no keyboard inputs. This is used when determining which keyboard input devices should be enabled by default. keyboard.enabled (read/write) A Boolean indicating whether the devices keyboard and/or keypad inputs are enabled. I/O port Wraps MAMEs ioport_port class, representing an emulated I/O port. Instantiation manager.machine.ioport.ports[tag] Gets an emulated I/O port by absolute tag, or nil if the tag does not correspond to an I/O port. manager.machine.devices[devtag]:ioport(porttag) Gets an emulated I/O port by tag relative to a device, or nil if no such I/O port exists. Methods port:read() Read the current input value. Returns a 32-bit integer. port:write(value, mask) Write to the I/O port output fields that are set in the speci- fied mask. The value and mask must be 32-bit integers. Note that this does not set values for input fields. port:field(mask) Get the first I/O port field corresponding to the bits that are set in the specified mask, or nil if there is no corresponding field. Properties port.device (read-only) The device that owns the I/O port. port.tag (read-only) The absolute tag of the I/O port port.active (read-only) A mask indicating which bits of the I/O port correspond to ac- tive fields (i.e. not unused or unassigned bits). port.live (read-only) The live state of the I/O port. port.fields[] (read-only) Gets a table of fields indexed by name. I/O port field Wraps MAMEs ioport_field class, representing a field within an I/O port. Instantiation manager.machine.ioport.ports[tag]:field(mask) Gets a field for the given port by bit mask. manager.machine.ioport.ports[tag].fields[name] Gets a field for the given port by display name. Methods field:set_value(value) Set the value of the I/O port field. For digital fields, the value is compared to zero to determine whether the field should be active; for analog fields, the value must be right-aligned and in the correct range. field:clear_value() Clear programmatically overridden value and restore the fields regular behaviour. field:set_input_seq(seqtype, seq) Set the input sequence for the specified sequence type. This is used to configure per-machine input settings. The sequence type must be "standard", "increment" or "decrement". field:input_seq(seq_type) Get the configured input sequence for the specified sequence type. This gets per-machine input assignments. The sequence type must be "standard", "increment" or "decrement". field:set_default_input_seq(seq_type, seq) Set the default input sequence for the specified sequence type. This overrides the default input assignment for a specific in- put. The sequence type must be "standard", "increment" or "decrement". field:default_input_seq(seq_type) Gets the default input sequence for the specified sequence type. If the default assignment is not overridden, this returns the general input assignment for the fields input type. The se- quence type must be "standard", "increment" or "decrement". field:keyboard_codes(shift) Gets a table of characters corresponding to the field for the specified shift state. The shift state is a bit mask of active shift keys. Properties field.device (read-only) The device that owns the port that the field belongs to. field.port (read-only) The I/O port that the field belongs to. field.live (read-only) The live state of the field. field.type (read-only) The input type of the field. This is an enumerated value. field.name (read-only) The display name for the field. field.default_name (read-only) The name for the field from the emulated systems configuration (cannot be overridden by scripts or plugins). field.player (read-only) Zero-based player number for the field. field.mask (read-only) Bits in the I/O port corresponding to this field. field.defvalue (read-only) The fields default value. field.minvalue (read-only) The minimum allowed value for analog fields, or nil for digital fields. field.maxvalue (read-only) The maximum allowed value for analog fields, or nil for digital fields. field.sensitivity (read-only) The sensitivity or gain for analog fields, or nil for digital fields. field.way (read-only) The number of directions allowed by the restrictor plate/gate for a digital joystick, or zero (0) for other inputs. field.type_class (read-only) The type class for the input field one of "keyboard", "con- troller", "config", "dipswitch" or "misc". field.is_analog (read-only) A Boolean indicating whether the field is an analog axis or po- sitional control. field.is_digital_joystick (read-only) A Boolean indicating whether the field corresponds to a digital joystick switch. field.enabled (read-only) A Boolean indicating whether the field is enabled. field.optional (read-only) A Boolean indicating whether the field is optional and not re- quired to use the emulated system. field.cocktail (read-only) A Boolean indicating whether the field is only used when the system is configured for a cocktail table cabinet. field.toggle (read-only) A Boolean indicating whether the field corresponds to a hardware toggle switch or push-on, push-off button. field.rotated (read-only) A Boolean indicating whether the field corresponds to a control that is rotated relative its standard orientation. field.analog_reverse (read-only) A Boolean indicating whether the field corresponds to an analog control that increases in the opposite direction to the conven- tion (e.g. larger values when a pedal is released or a joystick is moved to the left). field.analog_reset (read-only) A Boolean indicating whether the field corresponds to an incre- mental position input (e.g. a dial or trackball axis) that should be reset to zero for every video frame. field.analog_wraps (read-only) A Boolean indicating whether the field corresponds to an analog input that wraps from one end of its range to the other (e.g. an incremental position input like a dial or trackball axis). field.analog_invert (read-only) A Boolean indicating whether the field corresponds to an analog input that has its value ones-complemented. field.impulse (read-only) A Boolean indicating whether the field corresponds to a digital input that activates for a fixed amount of time. field.crosshair_scale (read-only) The scale factor for translating the fields range to crosshair position. A value of one (1) translates the fields full range to the full width or height the screen. field.crosshair_offset (read-only) The offset for translating the fields range to crosshair posi- tion. field.user_value (read/write) The value for DIP switch or configuration settings. field.settings[] (read-only) Gets a table of the currently enabled settings for a DIP switch or configuration field, indexed by value. Live I/O port field state Wraps MAMEs ioport_field_live class, representing the live state of an I/O port field. Instantiation manager.machine.ioport.ports[tag]:field(mask).live Gets the live state for an I/O port field. Properties live.name Display name for the field. Input type Wraps MAMEs input_type_entry class, representing an emulated input type or emulator UI input type. Input types are uniquely identified by the combination of their enumerated type value and player index. Instantiation manager.machine.ioport.types[index] Gets a supported input type. Properties type.type (read-only) An enumerated value representing the type of input. type.group (read-only) An integer giving the grouping for the input type. Should be used to provide canonical grouping in an input configuration UI. type.player (read-only) The zero-based player number, or zero for non-player controls. type.token (read-only) The token string for the input type, used in configuration files. type.name (read-only) The display name for the input type. type.is_analog (read-only) A Boolean indicating whether the input type is analog or digi- tal. Inputs that only have on and off states are considered digital, while all other inputs are considered analog, even if they can only represent discrete values or positions. Input manager Wraps MAMEs input_manager class, which reads host input devices and checks whether configured inputs are active. Instantiation manager.machine.input Gets the global input manager instance for the emulated system. Methods input:code_value(code) Gets the current value for the host input corresponding to the specified code. Returns a signed integer value, where zero is the neutral position. input:code_pressed(code) Returns a Boolean indicating whether the host input correspond- ing to the specified code has a non-zero value (i.e. it is not in the neutral position). input:code_pressed_once(code) Returns a Boolean indicating whether the host input correspond- ing to the specified code has moved away from the neutral posi- tion since the last time it was checked using this function. The input manager can track a limited number of inputs this way. input:code_name(code) Get display name for an input code. input:code_to_token(code) Get token string for an input code. This should be used when saving configuration. input:code_from_token(token) Convert a token string to an input code. Returns the invalid input code if the token is not valid or belongs to an input de- vice that is not present. input:seq_pressed(seq) Returns a Boolean indicating whether the supplied input sequence is currently pressed. input:seq_clean(seq) Remove invalid elements from the supplied input sequence. Re- turns the new, cleaned input sequence. input:seq_name(seq) Get display text for an input sequence. input:seq_to_tokens(seq) Convert an input sequence to a token string. This should be used when saving configuration. input:seq_from_tokens(tokens) Convert a token string to an input sequence. This should be used when loading configuration. input:axis_code_poller() Returns an input code poller for obtaining an analog host input code. input:switch_code_poller() Returns an input code poller for obtaining a host switch input code. input:keyboard_code_poller() Returns an input code poller for obtaining a host switch input code that only considers keyboard input devices. input:axis_sequence_poller() Returns an input sequence poller for obtaining an input sequence for configuring an analog input assignment. input:axis_sequence_poller() Returns an input sequence poller for obtaining an input sequence for configuring a digital input assignment. Properties input.device_classes[] (read-only) Gets a table of host input device classes indexed by name. Input code poller Wraps MAMEs input_code_poller class, used to poll for host inputs being activated. Instantiation manager.machine.input:axis_code_poller() Returns an input code poller that polls for analog inputs being activated. manager.machine.input:switch_code_poller() Returns an input code poller that polls for host switch inputs being activated. manager.machine.input:keyboard_code_poller() Returns an input code poller that polls for host switch inputs being activated, only considering keyboard input devices. Methods poller:reset() Resets the polling logic. Active switch inputs are cleared and initial analog input positions are set. poller:poll() Returns an input code corresponding to the first relevant host input that has been activated since the last time the method was called. Returns the invalid input code if no relevant input has been activated. Input sequence poller Wraps MAMEs input_sequence_poller poller class, which allows users to assign host input combinations to emulated inputs and other actions. Instantiation manager.machine.input:axis_sequence_poller() Returns an input sequence poller for assigning host inputs to an analog input. manager.machine.input:switch_sequence_poller() Returns an input sequence poller for assigning host inputs to a switch input. Methods poller:start([seq]) Start polling. If a sequence is supplied, it is used as a starting sequence: for analog inputs, the user can cycle between the full range, and the positive and negative portions of an axis; for switch inputs, an or code is appended and the user can add an alternate host input combination. poller:poll() Polls for user input and updates the sequence if appropriate. Returns a Boolean indicating whether sequence input is complete. If this method returns false, you should continue polling. Properties poller.sequence (read-only) The current input sequence. This is updated while polling. It is possible for the sequence to become invalid. poller.valid (read-only) A Boolean indicating whether the current input sequence is valid. poller.modified (read-only) A Boolean indicating whether the sequence was changed by any user input since starting polling. Input sequence Wraps MAMEs input_seq class, representing a combination of host inputs that can be read or assigned to an emulated input. Input sequences can be manipulated using input manager methods. Use an input sequence poller to obtain an input sequence from the user. Instantiation emu.input_seq() Creates an empty input sequence. emu.input_seq(seq) Creates a copy of an existing input sequence. Methods seq:reset() Clears the input sequence, removing all items. seq:set_default() Sets the input sequence to a single item containing the metavalue specifying that the default setting should be used. Properties seq.empty (read-only) A Boolean indicating whether the input sequence is empty (con- tains no items, indicating an unassigned input). seq.length (read-only) The number of items in the input sequence. seq.is_valid (read-only) A Boolean indicating whether the input sequence is a valid. To be valid, it must contain at least one item, all items must be valid codes, all product groups must contain at least one item that is not negated, and items referring to absolute and rela- tive axes must not be mixed within a product group. seq.is_default (read-only) A Boolean indicating whether the input sequence specifies that the default setting should be used. Host input device class Wraps MAMEs input_class class, representing a category of host input devices (e.g. keyboards or joysticks). Instantiation manager.machine.input.device_classes[name] Gets an input device class by name. Properties devclass.name (read-only) The device class name. devclass.enabled (read-only) A Boolean indicating whether the device class is enabled. devclass.multi (read-only) A Boolean indicating whether the device class supports multiple devices, or inputs from all devices in the class are combined and treated as a single device. devclass.devices[] (read-only) Gets a table of host input devices in the class. Keys are one-based indices. Host input device Wraps MAMEs input_device class, representing a host input device. Instantiation manager.machine.input.device_classes[name].devices[index] Gets a specific host input device. Properties inputdev.name (read-only) Display name for the device. This is not guaranteed to be unique. inputdev.id (read-only) Unique identifier string for the device. This may not be hu- man-readable. inputdev.devindex (read-only) Device index within the device class. This is not necessarily the same as the index in the devices property of the device class the devindex indices may not be contiguous. inputdev.items (read-only) Gets a table of input items, indexed by item ID. The item ID is an enumerated value. Host input device item Wraps MAMEs input_device_item class, representing a single host input (e.g. a key, button, or axis). Instantiation manager.machine.input.device_classes[name].devices[index].items[id] Gets an individual host input item. The item ID is an enumer- ated value. Properties item.name (read-only) The display name of the input item. Note that this is just the name of the item itself, and does not include the device name. The full display name for the item can be obtained by calling the code_name method on the input manager with the items code. item.code (read-only) The input items identification code. This is used by several input manager methods. item.token (read-only) The input items token string. Note that this is a token frag- ment for the item itself, and does not include the device por- tion. The full token for the item can be obtained by calling the code_to_token method on the input manager with the items code. item.current (read-only) The items current value. This is a signed integer where zero is the neutral position. UI input manager Wraps MAMEs ui_input_manager class, which is used for high-level input. Instantiation manager.machine.uiinput Gets the global UI input manager instance for the machine. Methods uiinput:reset() Clears pending events and UI input states. Should be called when leaving a modal state where input is handled directly (e.g. configuring an input combination). uiinput:pressed(type) Returns a Boolean indicating whether the specified UI input has been pressed. The input type is an enumerated value. uiinput:pressed_repeat(type, speed) Returns a Boolean indicating whether the specified UI input has been pressed or auto-repeat has been triggered at the specified speed. The input type is an enumerated value; the speed is an interval in sixtieths of a second. Properties uiinput.presses_enabled (read/write) Whether the UI input manager will check for UI inputs frame up- dates. Lua Render System Classes The render system is responsible for drawing what you see in MAMEs win- dows, including emulated screens, artwork, and UI elements. • Render bounds • Render colour • Palette • Bitmap • Render texture • Render manager • Render target • Render container • Container user settings • Layout file • Layout view • Layout view item • Layout element Render bounds Wraps MAMEs render_bounds class, which represents a rectangle using floating-point coordinates. Instantiation emu.render_bounds() Creates a render bounds object representing a unit square, with top left corner at (0, 0) and bottom right corner at (1, 1). Note that render target coordinates dont necessarily have equal X and Y scales, so this may not represent a square in the final output. emu.render_bounds(left, top, right, bottom) Creates a render bounds object representing a rectangle with top left corner at (x0, y0) and bottom right corner at (x1, y1). The arguments must all be floating-point numbers. Methods bounds:includes(x, y) Returns a Boolean indicating whether the specified point falls within the rectangle. The rectangle must be normalised for this to work (right greater than left and bottom greater than top). The arguments must both be floating-point numbers. bounds:set_xy(left, top, right, bottom) Set the rectangles position and size in terms of the positions of the edges. The arguments must all be floating-point numbers. bounds:set_wh(left, top, width, height) Set the rectangles position and size in terms of the top left corner position, and the width and height. The arguments must all be floating-point numbers. Properties bounds.x0 (read/write) The leftmost coordinate in the rectangle (i.e. the X coordinate of the left edge or the top left corner). bounds.x1 (read/write) The rightmost coordinate in the rectangle (i.e. the X coordinate of the right edge or the bottom right corner). bounds.y0 (read/write) The topmost coordinate in the rectangle (i.e. the Y coordinate of the top edge or the top left corner). bounds.y1 (read/write) The bottommost coordinate in the rectangle (i.e. the Y coordi- nate of the bottom edge or the bottom right corner). bounds.width (read/write) The width of the rectangle. Setting this property changes the position of the rightmost edge. bounds.height (read/write) The height of the rectangle. Setting this property changes the position of the bottommost edge. bounds.aspect (read-only) The width-to-height aspect ratio of the rectangle. Note that this is often in render target coordinates which dont necessar- ily have equal X and Y scales. A rectangle representing a square in the final output doesnt necessarily have an aspect ra- tio of 1. Render colour Wraps MAMEs render_color class, which represents an ARGB (alpha, red, green, blue) format colour. Channels are floating-point values ranging from zero (0, transparent alpha or colour off) to one (1, opaque or full colour intensity). Colour channel values are not pre-multiplied by the alpha channel value. Instantiation emu.render_color() Creates a render colour object representing opaque white (all channels set to 1). This is the identity value ARGB multipli- cation by this value will not change a colour. emu.render_color(a, r, g, b) Creates a render colour object with the specified alpha, red, green and blue channel values. The arguments must all be floating-point numbers in the range from zero (0) to one (1), inclusive. Methods color:set(a, r, g, b) Sets the colour objects alpha, red, green and blue channel val- ues. The arguments must all be floating-point numbers in the range from zero (0) to one (1), inclusive. Properties color.a (read/write) Alpha value, in the range of zero (0, transparent) to one (1, opaque). color.r (read/write) Red channel value, in the range of zero (0, off) to one (1, full intensity). color.g (read/write) Green channel value, in the range of zero (0, off) to one (1, full intensity). color.b (read/write) Blue channel value, in the range of zero (0, off) to one (1, full intensity). Palette Wraps MAMEs palette_t class, which represents a table of colours that can be looked up by zero-based index. Palettes always contain addi- tional special entries for black and white. Each colour has an associated contrast adjustment value. Each adjust- ment group has associated brightness and contrast adjustment values. The palette also has overall brightness, contrast and gamma adjustment values. Colours are represented in alpha/red/green/blue (ARGB) format. Channel values range from 0 (transparent or off) to 255 (opaque or full inten- sity), inclusive. Colour channel values are not pre-multiplied by the alpha value. Channel values are packed into the bytes of 32-bit un- signed integers, in the order alpha, red, green, blue from most-signif- icant to least-significant byte. Instantiation emu.palette(colors, [groups]) Creates a palette with the specified number of colours and brightness/contrast adjustment groups. The number of colour groups defaults to one if not specified. Colours are ini- tialised to black, brightness adjustment is initialised to 0.0, contrast adjustment initialised to 1.0, and gamma adjustment is initialised to 1.0. Methods palette:entry_color(index) Gets the colour at the specified zero-based index. Index values range from zero to the number of colours in the palette minus one. Returns black if the index is greater than or equal to the number of colours in the palette. palette:entry_contrast(index) Gets the contrast adjustment for the colour at the specified zero-based index. This is a floating-point number. Index values range from zero to the number of colours in the palette minus one. Returns 1.0 if the index is greater than or equal to the number of colours in the palette. palette:entry_adjusted_color(index, [group]) Gets a colour with brightness, contrast and gamma adjustments applied. If the group is specified, colour index values range from zero to the number of colours in the palette minus one, and group values range from zero to the number of adjustment groups in the palette minus one. If the group is not specified, index values range from zero to the number of colours multiplied by the number of adjustment groups plus one. Index values may be calculated by multiplying the zero-based group index by the number of colours in the palette, and adding the zero-based colour index. The last two index values correspond to the special entries for black and white, respectively. Returns black if the specified combination of index and adjust- ment group is invalid. palette:entry_set_color(index, color) Sets the colour at the specified zero-based index. The colour may be specified as a single packed 32-bit value; or as individ- ual red, green and blue channel values, in that order. Index values range from zero to the number of colours in the palette minus one. Raises an error if the index value is in- valid. palette:entry_set_red_level(index, level) Sets the red channel value of the colour at the specified zero-based index. Other channel values are not affected. Index values range from zero to the number of colours in the palette minus one. Raises an error if the index value is in- valid. palette:entry_set_green_level(index, level) Sets the green channel value of the colour at the specified zero-based index. Other channel values are not affected. Index values range from zero to the number of colours in the palette minus one. Raises an error if the index value is in- valid. palette:entry_set_blue_level(index, level) Sets the blue channel value of the colour at the specified zero-based index. Other channel values are not affected. Index values range from zero to the number of colours in the palette minus one. Raises an error if the index value is in- valid. palette:entry_set_contrast(index, level) Sets the contrast adjustment value for the colour at the speci- fied zero-based index. This must be a floating-point number. Index values range from zero to the number of colours in the palette minus one. Raises an error if the index value is in- valid. palette:group_set_brightness(group, brightness) Sets the brightness adjustment value for the adjustment group at the specified zero-based index. This must be a floating-point number. Group values range from zero to the number of adjustment groups in the palette minus one. Raises an error if the index value is invalid. palette:group_set_contrast(group, contrast) Sets the contrast adjustment value for the adjustment group at the specified zero-based index. This must be a floating-point number. Group values range from zero to the number of adjustment groups in the palette minus one. Raises an error if the index value is invalid. Properties palette.colors (read-only) The number of colour entries in each group of colours in the palette. palette.groups (read-only) The number of groups of colours in the palette. palette.max_index (read-only) The number of valid colour indices in the palette. palette.black_entry (read-only) The index of the special entry for the colour black. palette.white_entry (read-only) The index of the special entry for the colour white. palette.brightness (write-only) The overall brightness adjustment for the palette. This is a floating-point number. palette.contrast (write-only) The overall contrast adjustment for the palette. This is a floating-point number. palette.gamma (write-only) The overall gamma adjustment for the palette. This is a float- ing-point number. Bitmap Wraps implementations of MAMEs bitmap_t and bitmap_specific classes, which represent two-dimensional bitmaps stored in row-major order. Pixel coordinates are zero-based, increasing to the right and down. Several pixel formats are supported. Instantiation emu.bitmap_ind8(palette, [width, height], [xslop, yslop]) Creates an 8-bit indexed bitmap. Each pixel is a zero-based, unsigned 8-bit index into a palette. If no width and height are specified, they are assumed to be zero. If the width is specified, the height must also be speci- fied. The X and Y slop values set the amount of extra storage in pixels to reserve at the left/right of each row and top/bot- tom of each column, respectively. If an X slop value is speci- fied, a Y slop value must be specified as well. If no X and Y slop values are specified, they are assumed to be zero (the storage will be sized to fit the bitmap content). If the width and/or height is less than or equal to zero, no storage will be allocated, irrespective of the X and Y slop values, and the width and height of the bitmap will both be set to zero. The initial clipping rectangle is set to the entirety of the bitmap. emu.bitmap_ind16(palette, [width, height], [xslop, yslop]) Creates a 16-bit indexed bitmap. Each pixel is a zero-based, unsigned 16-bit index into a palette. If no width and height are specified, they are assumed to be zero. If the width is specified, the height must also be speci- fied. The X and Y slop values set the amount of extra storage in pixels to reserve at the left/right of each row and top/bot- tom of each column, respectively. If an X slop value is speci- fied, a Y slop value must be specified as well. If no X and Y slop values are specified, they are assumed to be zero (the storage will be sized to fit the bitmap content). If the width and/or height is less than or equal to zero, no storage will be allocated, irrespective of the X and Y slop values, and the width and height of the bitmap will both be set to zero. The initial clipping rectangle is set to the entirety of the bitmap. emu.bitmap_ind32(palette, [width, height], [xslop, yslop]) Creates a 32-bit indexed bitmap. Each pixel is a zero-based, unsigned 32-bit index into a palette. If no width and height are specified, they are assumed to be zero. If the width is specified, the height must also be speci- fied. The X and Y slop values set the amount of extra storage in pixels to reserve at the left/right of each row and top/bot- tom of each column, respectively. If an X slop value is speci- fied, a Y slop value must be specified as well. If no X and Y slop values are specified, they are assumed to be zero (the storage will be sized to fit the bitmap content). If the width and/or height is less than or equal to zero, no storage will be allocated, irrespective of the X and Y slop values, and the width and height of the bitmap will both be set to zero. The initial clipping rectangle is set to the entirety of the bitmap. emu.bitmap_ind64(palette, [width, height], [xslop, yslop]) Creates a 64-bit indexed bitmap. Each pixel is a zero-based, unsigned 64-bit index into a palette. If no width and height are specified, they are assumed to be zero. If the width is specified, the height must also be speci- fied. The X and Y slop values set the amount of extra storage in pixels to reserve at the left/right of each row and top/bot- tom of each column, respectively. If an X slop value is speci- fied, a Y slop value must be specified as well. If no X and Y slop values are specified, they are assumed to be zero (the storage will be sized to fit the bitmap content). If the width and/or height is less than or equal to zero, no storage will be allocated, irrespective of the X and Y slop values, and the width and height of the bitmap will both be set to zero. The initial clipping rectangle is set to the entirety of the bitmap. emu.bitmap_yuy16([width, height], [xslop], yslop]) Creates a Y'CbCr format bitmap with 4:2:2 chroma subsampling (horizontal pairs of pixels have individual luma values but share chroma values). Each pixel is a 16-bit integer value. The most significant byte of the pixel value is the unsigned 8-bit Y' (luma) component of the pixel colour. For each hori- zontal pair of pixels, the least significant byte of the first pixel (even zero-based X coordinate) value is the signed 8-bit Cb value for the pair of pixels, and the least significant byte of the second pixel (odd zero-based X coordinate) value is the signed 8-bit Cr value for the pair of pixels. If no width and height are specified, they are assumed to be zero. If the width is specified, the height must also be speci- fied. The X and Y slop values set the amount of extra storage in pixels to reserve at the left/right of each row and top/bot- tom of each column, respectively. If an X slop value is speci- fied, a Y slop value must be specified as well. If no X and Y slop values are specified, they are assumed to be zero (the storage will be sized to fit the bitmap content). If the width and/or height is less than or equal to zero, no storage will be allocated, irrespective of the X and Y slop values, and the width and height of the bitmap will both be set to zero. The initial clipping rectangle is set to the entirety of the bitmap. emu.bitmap_rgb32([width, height], [xslop, yslop]) Creates an RGB format bitmap with no alpha (transparency) chan- nel. Each pixel is represented by a 32-bit integer value. The most significant byte of the pixel value is ignored. The re- maining three bytes, from most significant to least significant, are the unsigned 8-bit unsigned red, green and blue channel val- ues (larger values correspond to higher intensities). If no width and height are specified, they are assumed to be zero. If the width is specified, the height must also be speci- fied. The X and Y slop values set the amount of extra storage in pixels to reserve at the left/right of each row and top/bot- tom of each column, respectively. If an X slop value is speci- fied, a Y slop value must be specified as well. If no X and Y slop values are specified, they are assumed to be zero (the storage will be sized to fit the bitmap content). If the width and/or height is less than or equal to zero, no storage will be allocated, irrespective of the X and Y slop values, and the width and height of the bitmap will both be set to zero. The initial clipping rectangle is set to the entirety of the bitmap. emu.bitmap_argb32([width, height], [xslop, yslop]) Creates an ARGB format bitmap. Each pixel is represented by a 32-bit integer value. The most significant byte of the pixel is the 8-bit unsigned alpha (transparency) channel value (smaller values are more transparent). The remaining three bytes, from most significant to least significant, are the unsigned 8-bit unsigned red, green and blue channel values (larger values cor- respond to higher intensities). Colour channel values are not pre-multiplied by the alpha channel value. If no width and height are specified, they are assumed to be zero. If the width is specified, the height must also be speci- fied. The X and Y slop values set the amount of extra storage in pixels to reserve at the left/right of each row and top/bot- tom of each column, respectively. If an X slop value is speci- fied, a Y slop value must be specified as well. If no X and Y slop values are specified, they are assumed to be zero (the storage will be sized to fit the bitmap content). If the width and/or height is less than or equal to zero, no storage will be allocated, irrespective of the X and Y slop values, and the width and height of the bitmap will both be set to zero. The initial clipping rectangle is set to the entirety of the bitmap. emu.bitmap_ind8(source, [x0, y0, x1, y1]) Creates an 8-bit indexed bitmap representing a view of a portion of an existing bitmap. The initial clipping rectangle is set to the bounds of the view. The source bitmap will be locked, pre- venting resizing and reallocation. If no coordinates are specified, the new bitmap will represent a view of the source bitmaps current clipping rectangle. If coor- dinates are specified, the new bitmap will represent a view of the rectangle with top left corner at (x0, y0) and bottom right corner at (x1, y1) in the source bitmap. Coordinates are in units of pixels. The bottom right coordinates are inclusive. The source bitmap must be owned by the Lua script and must use the 8-bit indexed format. Raises an error if coordinates are specified representing a rectangle not fully contained within the source bitmaps clipping rectangle. emu.bitmap_ind16(source, [x0, y0, x1, y1]) Creates a 16-bit indexed bitmap representing a view of a portion of an existing bitmap. The initial clipping rectangle is set to the bounds of the view. The source bitmap will be locked, pre- venting resizing and reallocation. If no coordinates are specified, the new bitmap will represent a view of the source bitmaps current clipping rectangle. If coor- dinates are specified, the new bitmap will represent a view of the rectangle with top left corner at (x0, y0) and bottom right corner at (x1, y1) in the source bitmap. Coordinates are in units of pixels. The bottom right coordinates are inclusive. The source bitmap must be owned by the Lua script and must use the 16-bit indexed format. Raises an error if coordinates are specified representing a rectangle not fully contained within the source bitmaps clipping rectangle. emu.bitmap_ind32(source, [x0, y0, x1, y1]) Creates a 32-bit indexed bitmap representing a view of a portion of an existing bitmap. The initial clipping rectangle is set to the bounds of the view. The source bitmap will be locked, pre- venting resizing and reallocation. If no coordinates are specified, the new bitmap will represent a view of the source bitmaps current clipping rectangle. If coor- dinates are specified, the new bitmap will represent a view of the rectangle with top left corner at (x0, y0) and bottom right corner at (x1, y1) in the source bitmap. Coordinates are in units of pixels. The bottom right coordinates are inclusive. The source bitmap must be owned by the Lua script and must use the 32-bit indexed format. Raises an error if coordinates are specified representing a rectangle not fully contained within the source bitmaps clipping rectangle. emu.bitmap_ind64(source, [x0, y0, x1, y1]) Creates a 64-bit indexed bitmap representing a view of a portion of an existing bitmap. The initial clipping rectangle is set to the bounds of the view. The source bitmap will be locked, pre- venting resizing and reallocation. If no coordinates are specified, the new bitmap will represent a view of the source bitmaps current clipping rectangle. If coor- dinates are specified, the new bitmap will represent a view of the rectangle with top left corner at (x0, y0) and bottom right corner at (x1, y1) in the source bitmap. Coordinates are in units of pixels. The bottom right coordinates are inclusive. The source bitmap must be owned by the Lua script and must use the 64-bit indexed format. Raises an error if coordinates are specified representing a rectangle not fully contained within the source bitmaps clipping rectangle. emu.bitmap_yuy16(source, [x0, y0, x1, y1]) Creates a Y'CbCr format bitmap with 4:2:2 chroma subsampling representing a view of a portion of an existing bitmap. The initial clipping rectangle is set to the bounds of the view. The source bitmap will be locked, preventing resizing and real- location. If no coordinates are specified, the new bitmap will represent a view of the source bitmaps current clipping rectangle. If coor- dinates are specified, the new bitmap will represent a view of the rectangle with top left corner at (x0, y0) and bottom right corner at (x1, y1) in the source bitmap. Coordinates are in units of pixels. The bottom right coordinates are inclusive. The source bitmap must be owned by the Lua script and must use the Y'CbCr format. Raises an error if coordinates are specified representing a rectangle not fully contained within the source bitmaps clipping rectangle. emu.bitmap_rgb32(source, [x0, y0, x1, y1]) Creates an RGB format bitmap representing a view of a portion of an existing bitmap. The initial clipping rectangle is set to the bounds of the view. The source bitmap will be locked, pre- venting resizing and reallocation. If no coordinates are specified, the new bitmap will represent a view of the source bitmaps current clipping rectangle. If coor- dinates are specified, the new bitmap will represent a view of the rectangle with top left corner at (x0, y0) and bottom right corner at (x1, y1) in the source bitmap. Coordinates are in units of pixels. The bottom right coordinates are inclusive. The source bitmap must be owned by the Lua script and must use the RGB format. Raises an error if coordinates are specified representing a rectangle not fully contained within the source bitmaps clipping rectangle. emu.bitmap_argb32(source, [x0, y0, x1, y1]) Creates an ARGB format bitmap representing a view of a portion of an existing bitmap. The initial clipping rectangle is set to the bounds of the view. The source bitmap will be locked, pre- venting resizing and reallocation. If no coordinates are specified, the new bitmap will represent a view of the source bitmaps current clipping rectangle. If coor- dinates are specified, the new bitmap will represent a view of the rectangle with top left corner at (x0, y0) and bottom right corner at (x1, y1) in the source bitmap. Coordinates are in units of pixels. The bottom right coordinates are inclusive. The source bitmap must be owned by the Lua script and must use the ARGB format. Raises an error if coordinates are specified representing a rectangle not fully contained within the source bitmaps clipping rectangle. emu.bitmap_argb32.load(data) Creates an ARGB format bitmap from data in PNG, JPEG (JFIF/EXIF) or Microsoft DIB (BMP) format. Raises an error if the data in- valid or not a supported format. Methods bitmap:cliprect() Returns the left, top, right and bottom coordinates of the bitmaps clipping rectangle. Coordinates are in units of pixels; the bottom and right coordinates are inclusive. bitmap:reset() Sets the width and height to zero, and frees the pixel storage if the bitmap owns its own storage, or releases the source bitmap if the it represents a view of another bitmap. The bitmap must be owned by the Lua script. Raises an error if the bitmaps storage is referenced by another bitmap or a texture. bitmap:allocate(width, height, [xslop, yslop]) Reallocates storage for the bitmap, sets its width and height, and sets the clipping rectangle to the entirety of the bitmap. If the bitmap already owns allocated storage, it will always be freed and reallocated; if the bitmap represents a view of an- other bitmap, the source bitmap will be released. The storage will be filled with pixel value zero. The X and Y slop values set the amount of extra storage in pix- els to reserve at the left/right of each row and top/bottom of each column, respectively. If an X slop value is specified, a Y slop value must be specified as well. If no X and Y slop values are specified, they are assumed to be zero (the storage will be sized to fit the bitmap content). If the width and/or height is less than or equal to zero, no storage will be allocated, irre- spective of the X and Y slop values, and the width and height of the bitmap will both be set to zero. The bitmap must be owned by the Lua script. Raises an error if the bitmaps storage is referenced by another bitmap or a texture. bitmap:resize(width, height, [xslop, yslop]) Changes the width and height, and sets the clipping rectangle to the entirety of the bitmap. The X and Y slop values set the amount of extra storage in pix- els to reserve at the left/right of each row and top/bottom of each column, respectively. If an X slop value is specified, a Y slop value must be specified as well. If no X and Y slop values are specified, they are assumed to be zero (rows will be stored contiguously, and the top row will be placed at the beginning of the bitmaps storage). If the bitmap already owns allocated storage and it is large enough for the updated size, it will be used without being freed; if it is too small for the updated size, it will always be freed and reallocated. If the bitmap represents a view of another bitmap, the source bitmap will be released. If storage is allocated, it will be filled with pixel value zero (if exist- ing storage is used, its contents will not be changed). Raises an error if the bitmaps storage is referenced by another bitmap or a texture. bitmap:wrap(source, [x0, y0, x1, y1]) Makes the bitmap represent a view of a portion of another bitmap and sets the clipping rectangle to the bounds of the view. If no coordinates are specified, the target bitmap will repre- sent a view of the source bitmaps current clipping rectangle. If coordinates are specified, the target bitmap will represent a view of the rectangle with top left corner at (x0, y0) and bot- tom right corner at (x1, y1) in the source bitmap. Coordinates are in units of pixels. The bottom right coordinates are inclu- sive. The source bitmap will be locked, preventing resizing and real- location. If the target bitmap owns allocated storage, it will be freed; if it represents a view of another bitmap, the current source bitmap will be released. The source and target bitmaps must both be owned by the Lua script and must use the same pixel format. Raises an error if coordinates are specified representing a rectangle not fully contained within the source bitmaps clipping rectangle; if the bitmaps storage is referenced by another bitmap or a texture; or if the source and target are the same bitmap. bitmap:pix(x, y) Returns the colour value of the pixel at the specified location. Coordinates are zero-based in units of pixels. bitmap:pixels([x0, y0, x1, y1]) Returns the pixels, width and height of the portion of the bitmap with top left corner at (x0, y0) and bottom right corner at (x1, y1). Coordinates are in units of pixels. The bottom right coordinates are inclusive. If coordinates are not speci- fied, the bitmaps clipping rectangle is used. Pixels are returned packed into a binary string in host Endian order. Pixels are organised in row-major order, from left to right then top to bottom. The size and format of the pixel val- ues depends on the format of the bitmap. Raises an error if co- ordinates are specified representing a rectangle not fully con- tained within the bitmaps clipping rectangle. bitmap:fill(color, [x0, y0, x1, y1]) Fills a portion of the bitmap with the specified colour value. If coordinates are not specified, the clipping rectangle is filled; if coordinates are specified, the intersection of the clipping rectangle and the rectangle with top left corner at (x0, y0) and bottom right corner at (x1, y1) is filled. Coordi- nates are in units of pixels. The bottom right coordinates are inclusive. bitmap:plot(x, y, color) Sets the colour value of the pixel at the specified location if it is within the clipping rectangle. Coordinates are zero-based in units of pixels. bitmap:plot_box(x, y, width, height, color) Fills the intersection of the clipping rectangle and the rectan- gle with top left (x, y) and the specified height and width with the specified colour value. Coordinates and dimensions are in units of pixels. bitmap:resample(dest, [color]) Copies the bitmap into the destination bitmap, scaling to fill the destination bitmap and using a re-sampling filter. Only ARGB format source and destination bitmaps are supported. The source pixel values will be multiplied by the colour if it is supplied. It must be a render colour. Properties bitmap.palette (read/write) The palette used to translate pixel values to colours. Only ap- plicable for bitmaps that use indexed pixel formats. bitmap.width (read-only) Width of the bitmap in pixels. bitmap.height (read-only) Height of the bitmap in pixels. bitmap.rowpixels (read-only) Row stride of the bitmaps storage in pixels. That is, the dif- ference in pixel offsets of the pixels at the same horizontal location in consecutive rows. May be greater than the width. bitmap.rowbytes (read-only) Row stride of the bitmaps storage in bytes. That is, the dif- ference in byte addresses of the pixels at the same horizontal location in consecutive rows. bitmap.bpp (read-only) Size of the type used to represent pixels in the bitmap in bits (may be larger than the number of significant bits). bitmap.valid (read-only) A Boolean indicating whether the bitmap has storage available (may be false for empty bitmaps). bitmap.locked (read-only) A Boolean indicating whether the bitmaps storage is referenced by another bitmap or a texture. Render texture Wraps MAMEs render_texture class, representing a texture that cam be drawn in a render container. Render textures must be freed before the emulation session ends. Instantiation manager.machine.render:texture_alloc(bitmap) Creates a render texture based on a bitmap. The bitmap must be owned by the Lua script, and must use the Y'CbCr, RGB or ARGB format. The bitmaps storage will be locked, preventing resizing and reallocation. Methods texture:free() Frees the texture. The storage of the underlying bitmap will be released. Properties texture.valid (read-only) A Boolean indicating whether the texture is valid (false if the texture has been freed). Render manager Wraps MAMEs render_manager class, responsible for managing render tar- gets and textures. Instantiation manager.machine.render Gets the global render manager instance for the emulation ses- sion. Methods render:texture_alloc(bitmap) Creates a render texture based on a bitmap. The bitmap must be owned by the Lua script, and must use the Y'CbCr, RGB or ARGB pixel format. The bitmaps storage will be locked, preventing resizing and reallocation. Render textures must be freed before the emulation session ends. Properties render.max_update_rate (read-only) The maximum update rate in Hertz. This is a floating-point num- ber. render.ui_target (read-only) The render target used to draw the user interface (including menus, sliders and pop-up messages). This is usually the first host window or screen. render.ui_container (read-only) The render container used for drawing the user interface. render.targets[] (read-only) The list of render targets, including output windows and screens, as well as hidden render targets used for things like rendering screenshots. Uses 1-based integer indices. The index operator and the at method have O(n) complexity. Render target Wraps MAMEs render_target class, which represents a video output chan- nel. This could be a host window or screen, or a hidden target used for rendering screenshots. Instantiation manager.machine.render.targets[index] Gets a render target by index. manager.machine.render.ui_target Gets the render target used to display the user interface (in- cluding menus, sliders and pop-up messages). This is usually the first host window or screen. manager.machine.video.snapshot_target Gets the render target used to produce snapshots and video recordings. Properties target.ui_container (read-only) The render container for drawing user interface elements over this render target, or nil for hidden render targets (targets that are not shown to the user directly). target.index (read-only) The 1-based index of the render target. This has O(n) complex- ity. target.width (read-only) The width of the render target in output pixels. This is an in- teger. target.height (read-only) The height of the render target in output pixels. This is an integer. target.pixel_aspect (read-only) The width-to-height aspect ratio of the render targets pixels. This is a floating-point number. target.hidden (read-only) A Boolean indicating whether this is an internal render target that is not displayed to the user directly (e.g. the render tar- get used to draw screenshots). target.is_ui_target (read-only) A Boolean indicating whether this is the render target used to display the user interface. target.max_update_rate (read/write) The maximum update rate for the render target in Hertz. target.orientation (read/write) The target orientation flags. This is an integer bit mask, where bit 0 (0x01) is set to mirror horizontally, bit 1 (0x02) is set to mirror vertically, and bit 2 (0x04) is set to mirror along the top left-bottom right diagonal. target.view_names[] The names of the available views for this render target. Uses 1-based integer indices. The find and index_of methods have O(n) complexity; all other supported operations have O(1) com- plexity. target.current_view (read-only) The currently selected view for the render target. This is a layout view object. target.view_index (read/write) The 1-based index of the selected view for this render target. target.visibility_mask (read-only) An integer bit mask indicating which item collections are cur- rently visible for the current view. target.screen_overlay (read/write) A Boolean indicating whether screen overlays are enabled. target.zoom_to_screen (read/write) A Boolean indicating whether the render target is configured to scale so that the emulated screen(s) fill as much of the output window/screen as possible. Render container Wraps MAMEs render_container class. Instantiation manager.machine.render.ui_container Gets the render container used to draw the user interface, in- cluding menus, sliders and pop-up messages. manager.machine.render.targets[index].ui_container Gets the render container used to draw user interface elements over a particular render target. manager.machine.screens[tag].container Gets the render container used to draw a given screen. Methods container:draw_box(left, top, right, bottom, [line], [fill]) Draws an outlined rectangle with edges at the specified posi- tions. Coordinates are floating-point numbers in the range of 0 (zero) to 1 (one), with (0, 0) at the top left and (1, 1) at the bottom right of the window or the screen that shows the user interface. Note that the aspect ratio is usually not square. Coordinates are limited to the window or screen area. The fill and line colours are in alpha/red/green/blue (ARGB) format. Channel values are in the range 0 (transparent or off) to 255 (opaque or full intensity), inclusive. Colour channel values are not pre-multiplied by the alpha value. The channel values must be packed into the bytes of a 32-bit unsigned inte- ger, in the order alpha, red, green, blue from most-significant to least-significant byte. If the line colour is not provided, the UI text colour is used; if the fill colour is not provided, the UI background colour is used. container:draw_line(x0, y0, x1, y1, [color]) Draws a line from (x0, y0) to (x1, y1). Coordinates are floating-point numbers in the range of 0 (zero) to 1 (one), with (0, 0) at the top left and (1, 1) at the bottom right of the window or the screen that shows the user interface. Note that the aspect ratio is usually not square. Coordinates are limited to the window or screen area. The line colour is in alpha/red/green/blue (ARGB) format. Chan- nel values are in the range 0 (transparent or off) to 255 (opaque or full intensity), inclusive. Colour channel values are not pre-multiplied by the alpha value. The channel values must be packed into the bytes of a 32-bit unsigned integer, in the order alpha, red, green, blue from most-significant to least-significant byte. If the line colour is not provided, the UI text colour is used. container:draw_quad(texture, x0, y0, x1, y1, [color]) Draws a textured rectangle with top left corner at (x0, y0) and bottom right corner at (x1, y1). If a colour is specified, the ARGB channel values of the textures pixels are multiplied by the corresponding values of the specified colour. Coordinates are floating-point numbers in the range of 0 (zero) to 1 (one), with (0, 0) at the top left and (1, 1) at the bottom right of the window or the screen that shows the user interface. Note that the aspect ratio is usually not square. If the rec- tangle extends beyond the containers bounds, it will be cropped. The colour is in alpha/red/green/blue (ARGB) format. Channel values are in the range 0 (transparent or off) to 255 (opaque or full intensity), inclusive. Colour channel values are not pre-multiplied by the alpha value. The channel values must be packed into the bytes of a 32-bit unsigned integer, in the order alpha, red, green, blue from most-significant to least-signifi- cant byte. container:draw_text(x|justify, y, text, [foreground], [background]) Draws text at the specified position. If the screen is rotated the text will be rotated. If the first argument is a number, the text will be left-aligned at this X coordinate. If the first argument is a string, it must be "left", "center" or "right" to draw the text left-aligned at the left edge of the window or screen, horizon- tally centred in the window or screen, or right-aligned at the right edge of the window or screen, respectively. The second argument specifies the Y coordinate of the maximum ascent of the text. Coordinates are floating-point numbers in the range of 0 (zero) to 1 (one), with (0, 0) at the top left and (1, 1) at the bottom right of the window or the screen that shows the user interface. Note that the aspect ratio is usually not square. Coordinates are limited to the window or screen area. The foreground and background colours are in al- pha/red/green/blue (ARGB) format. Channel values are in the range 0 (transparent or off) to 255 (opaque or full intensity), inclusive. Colour channel values are not pre-multiplied by the alpha value. The channel values must be packed into the bytes of a 32-bit unsigned integer, in the order alpha, red, green, blue from most-significant to least-significant byte. If the foreground colour is not provided, the UI text colour is used; if the background colour is not provided, it is fully transpar- ent. Properties container.user_settings (read/write) The containers user settings. This can be used to control a number of image adjustments. container.orientation (read/write) The container orientation flags. This is an integer bit mask, where bit 0 (0x01) is set to mirror horizontally, bit 1 (0x02) is set to mirror vertically, and bit 2 (0x04) is set to mirror along the top left-bottom right diagonal. container.xscale (read/write) The containers X scale factor. This is a floating-point number. container.yscale (read/write) The containers Y scale factor. This is a floating-point number. container.xoffset (read/write) The containers X offset. This is a floating-point number where one (1) corresponds to the X size of the container. container.yoffset (read/write) The containers Y offset. This is a floating-point number where one (1) corresponds to the Y size of the container. container.is_empty (read-only) A Boolean indicating whether the container has no items. Container user settings Wraps MAMEs render_container::user_settings class, representing image adjustments applied to a render container. Instantiation manager.machine.screens[tag].container Gets the current render container user settings for a given emu- lated screen. Properties settings.orientation (read/write) The container orientation flags. This is an integer bit mask, where bit 0 (0x01) is set to mirror horizontally, bit 1 (0x02) is set to mirror vertically, and bit 2 (0x04) is set to mirror along the top left-bottom right diagonal. settings.brightness (read/write) The brightness adjustment applied to the container. This is a floating-point number. settings.contrast (read/write) The contrast adjustment applied to the container. This is a floating-point number. settings.gamma (read/write) The gamma adjustment applied to the container. This is a float- ing-point number. settings.xscale (read/write) The containers X scale factor. This is a floating-point number. settings.yscale (read/write) The containers Y scale factor. This is a floating-point number. settings.xoffset (read/write) The containers X offset. This is a floating-point number where one (1) represents the X size of the container. settings.yoffset (read/write) The containers Y offset. This is a floating-point number where one (1) represents the Y size of the container. Layout file Wraps MAMEs layout_file class, representing the views loaded from a layout file for use by a render target. Note that layout file call- backs are not run as coroutines. Instantiation A layout file object is supplied to its layout script in the file vari- able. Layout file objects are not instantiated directly from Lua scripts. Methods layout:set_resolve_tags_callback(cb) Set a function to perform additional tasks after the emulated machine has finished starting, tags in the layout views have been resolved, and the default view item handlers have been set up. The function must accept no arguments. Call with nil to remove the callback. Properties layout.device (read-only) The device that caused the layout file to be loaded. Usually the root machine device for external layouts. layout.elements[] (read-only) The elements created from the layout file. Elements are indexed by name (i.e. the value of the name attribute). The index get method has O(1) complexity, and the at and index_of methods have O(n) complexity. layout.views[] (read-only) The views created from the layout file. Views are indexed by unqualified name (i.e. the value of the name attribute). Views are ordered how they appear in the layout file when iterating or using the at method. The index get, at and index_of methods have O(n) complexity. Note that some views in the XML file may not be created. For example views that reference screens provided by slot card de- vices will not be created if said slot card devices are not present in the emulated system. Layout view Wraps MAMEs layout_view class, representing a view that can be dis- played in a render target. Views are created from XML layout files, which may be loaded from external artwork, internal to MAME, or auto- matically generated based on the screens in the emulated system. Note that layout view callbacks are not run as coroutines. Instantiation manager.machine.render.targets[index].current_view Gets the currently selected view for a given render target. file.views[name] Gets the view with the specified name from a layout file. This is how layout scripts generally obtain views. Methods view:has_screen(screen) Returns a Boolean indicating whether the screen is present in the view. This is true for screens that are present but not visible because the user has hidden the item collection they be- long to. view:set_prepare_items_callback(cb) Set a function to perform additional tasks before the view items are added to the render target in preparation for drawing a video frame. The function must accept no arguments. Call with nil to remove the callback. view:set_preload_callback(cb) Set a function to perform additional tasks after preloading vis- ible view items. The function must accept no arguments. Call with nil to remove the callback. This function may be called when the user selects a view or makes an item collection visible. It may be called multiple times for a view, so avoid repeating expensive tasks. view:set_recomputed_callback(cb) Set a function to perform additional tasks after the views di- mensions are recomputed. The function must accept no arguments. Call with nil to remove the callback. View coordinates are recomputed in various events, including the window being resized, entering or leaving full-screen mode, and changing the zoom to screen area setting. view:set_pointer_updated_callback(cb) Set a function to receive notifications when a pointer enters, moves or changes button states over the view. The function must accept nine arguments: • The pointer type (mouse, pen, touch or unknown). • The pointer ID (a non-negative integer that will not change for the lifetime of a pointer). • The device ID for grouping pointers to recognise multi-touch gestures (non-negative integer). • Horizontal position in layout coordinates. • Vertical position in layout coordinates. • A bit mask representing the currently pressed buttons. • A bit mask representing the buttons that were pressed in this update. • A bit mask representing the buttons that were released in this update. • The click count (positive for multi-click actions, or negative if a click is turned into a hold or drag). Call with nil to remove the callback. view:set_pointer_left_callback(cb) Set a function to receive notifications when a pointer leaves the view normally. The function must accept seven arguments: • The pointer type (mouse, pen, touch or unknown). • The pointer ID (a non-negative integer that will not change for the lifetime of a pointer). The ID may be reused for a new pointer after receiving this notification. • The device ID for grouping pointers to recognise multi-touch gestures (non-negative integer). • Horizontal position in layout coordinates. • Vertical position in layout coordinates. • A bit mask representing the buttons that were released in this update. • The click count (positive for multi-click actions, or negative if a click is turned into a hold or drag). Call with nil to remove the callback. view:set_pointer_aborted_callback(cb) Set a function to receive notifications when a pointer leaves the view abnormally. The function must accept seven arguments: • The pointer type (mouse, pen, touch or unknown). • The pointer ID (a non-negative integer that will not change for the lifetime of a pointer). The ID may be reused for a new pointer after receiving this notification. • The device ID for grouping pointers to recognise multi-touch gestures (non-negative integer). • Horizontal position in layout coordinates. • Vertical position in layout coordinates. • A bit mask representing the buttons that were released in this update. • The click count (positive for multi-click actions, or negative if a click is turned into a hold or drag). Call with nil to remove the callback. view:set_forget_pointers_callback(cb) Set a function to receive notifications when the view should stop processing pointer input. The function must accept no ar- guments. Call with nil to remove the callback. This can happen in a number of situations, including the view configuration changing or a menu taking over input handling. Properties view.items[] (read-only) The screen and layout element items in the view. This container does not support iteration by key using pairs; only iteration by index using ipairs is supported. The key is the value of the id attribute if present. Only items with id attributes can be looked up by key. The index get method has O(1) complexity, and the at and index_of methods have O(n) complexity. view.name (read-only) The display name for the view. This may be qualified to indi- cate the device that caused the layout file to be loaded when it isnt the root machine device. view.unqualified_name (read-only) The unqualified name of the view, exactly as it appears in the name attribute in the XML layout file. view.visible_screen_count (read-only) The number of screens items currently enabled in the view. view.effective_aspect (read-only) The effective width-to-height aspect ratio of the view in its current configuration. view.bounds (read-only) A render bounds object representing the effective bounds of the view in its current configuration. The coordinates are in view units, which are arbitrary but assumed to have square aspect ra- tio. view.has_art (read-only) A Boolean indicating whether the view has any non-screen items, including items that are not visible because the user has hidden the item collection that they belong to. view.show_pointers (read/write) A Boolean that sets whether mouse and pen pointers should be displayed for the view. view.hide_inactive_pointers (read/write) A Boolean that sets whether mouse pointers for the view should be hidden after a period of inactivity. Layout view item Wraps MAMEs layout_view_item class, representing an item in a layout view. An item is drawn as a rectangular textured surface. The texture is supplied by an emulated screen or a layout element. Note that lay- out view item callbacks are not run as coroutines. Instantiation layout.views[name].items[id] Get a view item by ID. The item must have an id attribute in the XML layout file to be looked up by ID. Methods item:set_state(state) Set the value used as the element state and animation state in the absence of bindings. The argument must be an integer. item:set_element_state_callback(cb) Set a function to call to obtain the element state for the item. The function must accept no arguments and return an integer. Call with nil to restore the default element state callback (based on bindings in the XML layout file). Note that the function must not access the items element_state property, as this will result in infinite recursion. This callback will not be used to obtain the animation state for the item, even if the item lacks explicit animation state bind- ings in the XML layout file. item:set_animation_state_callback(cb) Set a function to call to obtain the animation state for the item. The function must accept no arguments and return an inte- ger. Call with nil to restore the default animation state call- back (based on bindings in the XML layout file). Note that the function must not access the items animation_state property, as this will result in infinite recursion. item:set_bounds_callback(cb) Set a function to call to obtain the bounds for the item. The function must accept no arguments and return a render bounds ob- ject in render target coordinates. Call with nil to restore the default bounds callback (based on the items animation state and bounds child elements in the XML layout file). Note that the function must not access the items bounds prop- erty, as this will result in infinite recursion. item:set_color_callback(cb) Set a function to call to obtain the multiplier colour for the item. The function must accept no arguments and return a render colour object. Call with nil to restore the default colour callback (based on the items animation state and color child el- ements in the XML layout file). Note that the function must not access the items color property, as this will result in infinite recursion. item:set_scroll_size_x_callback(cb) Set a function to call to obtain the size of the horizontal scroll window as a proportion of the associated elements width. The function must accept no arguments and return a float- ing-point value. Call with nil to restore the default horizon- tal scroll window size callback (based on the xscroll child ele- ment in the XML layout file). Note that the function must not access the items scroll_size_x property, as this will result in infinite recursion. item:set_scroll_size_y_callback(cb) Set a function to call to obtain the size of the vertical scroll window as a proportion of the associated elements height. The function must accept no arguments and return a floating-point value. Call with nil to restore the default vertical scroll window size callback (based on the yscroll child element in the XML layout file). Note that the function must not access the items scroll_size_y property, as this will result in infinite recursion. item:set_scroll_pos_x_callback(cb) Set a function to call to obtain the horizontal scroll position. A value of zero places the horizontal scroll window at the left edge of the associated element. If the item does not wrap hori- zontally, a value of 1.0 places the horizontal scroll window at the right edge of the associated element; if the item wraps hor- izontally, a value of 1.0 corresponds to wrapping back to the left edge of the associated element. The function must accept no arguments and return a floating-point value. Call with nil to restore the default horizontal scroll position callback (based on bindings in the xscroll child element in the XML lay- out file). Note that the function must not access the items scroll_pos_x property, as this will result in infinite recursion. item:set_scroll_pos_y_callback(cb) Set a function to call to obtain the vertical scroll position. A value of zero places the vertical scroll window at the top edge of the associated element. If the item does not wrap ver- tically, a value of 1.0 places the vertical scroll window at the bottom edge of the associated element; if the item wraps verti- cally, a value of 1.0 corresponds to wrapping back to the left edge of the associated element. The function must accept no ar- guments and return a floating-point value. Call with nil to re- store the default vertical scroll position callback (based on bindings in the yscroll child element in the XML layout file). Note that the function must not access the items scroll_pos_y property, as this will result in infinite recursion. Properties item.id (read-only) Get the optional item identifier. This is the value of the id attribute in the XML layout file if present, or nil. item.element (read-only) The element used to draw the item, or nil for screen items. item.bounds_animated (read-only) A Boolean indicating whether the items bounds depend on its ani- mation state. item.color_animated (read-only) A Boolean indicating whether the items colour depends on its an- imation state. item.bounds (read-only) The items bounds for the current state. This is a render bounds object in render target coordinates. item.color (read-only) The items colour for the current state. The colour of the screen or element texture is multiplied by this colour. This is a render colour object. item.scroll_wrap_x (read-only) A Boolean indicating whether the item wraps horizontally. item.scroll_wrap_y (read-only) A Boolean indicating whether the item wraps vertically. item.scroll_size_x (read/write) Get the items horizontal scroll window size for the current state, or set the horizontal scroll window size to use in the absence of bindings. This is a floating-point value represent- ing a proportion of the associated elements width. item.scroll_size_y (read/write) Get the items vertical scroll window size for the current state, or set the vertical scroll window size to use in the absence of bindings. This is a floating-point value representing a propor- tion of the associated elements height. item.scroll_pos_x (read/write) Get the items horizontal scroll position for the current state, or set the horizontal scroll position size to use in the absence of bindings. This is a floating-point value. item.scroll_pos_y (read/write) Get the items vertical scroll position for the current state, or set the vertical position size to use in the absence of bind- ings. This is a floating-point value. item.blend_mode (read-only) Get the items blend mode. This is an integer value, where 0 means no blending, 1 means alpha blending, 2 means RGB multipli- cation, 3 means additive blending, and -1 allows the items within a container to specify their own blending modes. item.orientation (read-only) Get the item orientation flags. This is an integer bit mask, where bit 0 (0x01) is set to mirror horizontally, bit 1 (0x02) is set to mirror vertically, and bit 2 (0x04) is set to mirror along the top left-bottom right diagonal. item.element_state (read-only) Get the current element state. This will call the element state callback function to handle bindings. item.animation_state (read-only) Get the current animation state. This will call the animation state callback function to handle bindings. Layout element Wraps MAMEs layout_element class, representing a visual element that can be drawn in a layout view. Elements are created from XML layout files, which may be loaded from external artwork or internal to MAME. Note that layout element callbacks are not run as coroutines. Instantiation layout.elements[name] Gets a layout element by name. layout.views[name].items[id].element Gets the layout element used to draw a view item. Methods element:invalidate() Invalidate all cached textures for the element, ensuring it will be redrawn when the next video frame is drawn. element.set_draw_callback(cb) Set a function to call the perform additional drawing after the elements components have been drawn. The function is passed two arguments: the element state (an integer) and the 32-bit ARGB bitmap at the required size. The function must not attempt to resize the bitmap. Call with nil to remove the callback. Properties element.default_state (read-only) The integer default state for the element if set or nil. Lua Debugger Classes Some of MAMEs core debugging features can be controlled from Lua script. The debugger must be enabled to use the debugger features (usually by passing -debug on the command line). • Symbol table • Parsed expression • Symbol entry • Debugger manager • Device debugger interface • Breakpoint • Watchpoint • Expression error Symbol table Wraps MAMEs symbol_table class, providing named symbols that can be used in expressions. Note that symbol tables can be created and used even when the debugger is not enabled. Instantiation emu.symbol_table(machine) Creates a new symbol table in the context of the specified ma- chine, emu.symbol_table(parent, [device]) Creates a new symbol table with the specified parent symbol ta- ble. If a device is specified and it implements device_mem- ory_interface, it will be used as the base for looking up ad- dress spaces and memory regions. Note that if a device that does not implement device_memory_interface is supplied, it will not be used (address spaces and memory regions will be looked up relative to the root device). emu.symbol_table(device) Creates a new symbol table in the context of the specified de- vice. If the device implements device_memory_interface, it will be used as the base for looking up address spaces and memory re- gions. Note that if a device that does not implement de- vice_memory_interface is supplied, it will only be used to de- termine the machine context (address spaces and memory regions will be looked up relative to the root device). Methods symbols:set_memory_modified_func(cb) Set a function to call when memory is modified via the symbol table. No arguments are passed to the function and any return values are ignored. Call with nil to remove the callback. symbols:add(name, [value]) Adds a named integer symbol. The name must be a string. If a value is supplied, it must be an integer. If a value is sup- plied, a read-only symbol is added with the supplied value. If no value is supplied, a read/write symbol is created with and initial value of zero. If a symbol entry with the specified name already exists in the symbol table, it will be replaced. Returns the new symbol entry. symbols:add(name, getter, [setter], [format]) Adds a named integer symbol using getter and optional setter callbacks. The name must be a string. The getter must be a function returning an integer for the symbol value. If sup- plied, the setter must be a function that accepts a single inte- ger argument for the new value of the symbol. A format string for displaying the symbol value may optionally be supplied. If a symbol entry with the specified name already exists in the symbol table, it will be replaced. Returns the new symbol entry. symbols:add(name, minparams, maxparams, execute) Adds a named function symbol. The name must be a string. The minimum and maximum numbers of parameters must be integers. If a symbol entry with the specified name already exists in the symbol table, it will be replaced. Returns the new symbol entry. symbols:find(name) Returns the symbol entry with the specified name, or nil if there is no symbol with the specified name in the symbol table. symbols:find_deep(name) Returns the symbol entry with the specified name, or nil if there is no symbol with the specified name in the symbol table or any of its parent symbol tables. symbols:value(name) Returns the integer value of the symbol with the specified name, or zero if there is no symbol with the specified name in the symbol table or any of its parent symbol tables. Raises an er- ror if the symbol with specified name is a function symbol. symbols:set_value(name, value) Sets the value of the symbol with the specified name. Raises an error if the symbol with the specified name is a read-only inte- ger symbol or if it is a function symbol. Has no effect if there is no symbol with the specified name in the symbol table or any of its parent symbol tables. symbols:memory_value(name, space, offset, size, disable_se) Read a value from memory. Supply the name or tag of the address space or memory region to read from, or nil to use the address space or memory region implied by the space argument. See memory accesses in debugger expressions for access type specifi- cations that can be used for the space argument. The access size is specified in bytes, and must be 1, 2, 4 or 8. The dis- able_se argument specifies whether memory access side effects should be disabled. symbols:set_memory_value(name, space, offset, value, size, disable_se) Write a value to memory. Supply the name or tag of the address space or memory region to write to, or nil to use the address space or memory region implied by the space argument. See memory accesses in debugger expressions for access type specifi- cations that can be used for the space argument. The access size is specified in bytes, and must be 1, 2, 4 or 8. The dis- able_se argument specifies whether memory access side effects should be disabled. symbols:read_memory(space, address, size, apply_translation) Read a value from an address space. The access size is speci- fied in bytes, and must be 1, 2, 4, or 8. If the apply_transla- tion argument is true, the address will be translated with debug read intention. Returns a value of the requested size with all bits set if address translation fails. symbols:write_memory(space, address, data, size, apply_translation) Write a value to an address space. The access size is specified in bytes, and must be 1, 2, 4, or 8. If the apply_translation argument is true, the address will be translated with debug write intention. The symbol tables memory modified function will be called after the value is written. The value will not be written and the symbol tables memory modified function will not be called if address translation fails. Properties symbols.entries[] The symbol entries in the symbol table, indexed by name. The at and index_of methods have O(n) complexity; all other supported operations have O(1) complexity. symbols.parent (read-only) The parent symbol table, or nil if the symbol table has no par- ent. Parsed expression Wraps MAMEs parsed_expression class, which represents a tokenised de- bugger expression. Note that parsed expressions can be created and used even when the debugger is not enabled. Instantiation emu.parsed_expression(symbols) Creates an empty expression that will use the supplied symbol table to look up symbols. emu.parsed_expression(symbols, string, [default_base]) Creates an expression by parsing the supplied string, looking up symbols in the supplied symbol table. If the default base for interpreting integer literals is not supplied, 16 is used (hexa- decimal). Raises an expression error if the string contains syntax errors or uses undefined symbols. Methods expression:set_default_base(base) Set the default base for interpreting numeric literals. The base must be a positive integer. expression:parse(string) Parse a debugger expression string. Replaces the current con- tents of the expression if it is not empty. Raises an expression error if the string contains syntax errors or uses undefined symbols. The previous content of the expression is not preserved when attempting to parse an invalid expression string. expression:execute() Evaluates the expression, returning an unsigned integer result. Raises an expression error if the expression cannot be evaluated (e.g. attempting to call a function with an invalid number of arguments). Properties expression.is_empty (read-only) A Boolean indicating whether the expression contains no tokens. expression.original_string (read-only) The original string that was parsed to create the expression. expression.symbols (read/write) The symbol table used for to look up symbols in the expression. Symbol entry Wraps MAMEs symbol_entry class, which represents an entry in a symbol table. Note that symbol entries must not be used after the symbol ta- ble they belong to is destroyed. Instantiation symbols:add(name, [value]) Adds an integer symbol to a symbol table, returning the new sym- bol entry. symbols:add(name, getter, [setter], [format]) Adds an integer symbol to a symbol table, returning the new sym- bol entry. symbols:add(name, minparams, maxparams, execute) Adds function symbol to a symbol table, returning the new symbol entry. Properties entry.name (read-only) The name of the symbol entry. entry.format (read-only) The format string used to convert the symbol entry to text for display. entry.is_function (read-only) A Boolean indicating whether the symbol entry is a callable function. entry.is_lval (read-only) A Boolean indicating whether the symbol entry is an integer sym- bol that can be set (i.e. whether it can be used on the left-hand side of assignment expressions). entry.value (read/write) The integer value of the symbol entry. Attempting to set the value raises an error if the symbol entry is read-only. At- tempting to get or set the value of a function symbol raises an error. Debugger manager Wraps MAMEs debugger_manager class, providing the main interface to control the debugger. Instantiation manager.machine.debugger Returns the global debugger manager instance, or nil if the de- bugger is not enabled. Methods debugger:command(str) Execute a debugger console command. The argument is the command string. The output is sent to both the debugger console and the Lua console. Properties debugger.consolelog[] (read-only) The lines in the console log (output from debugger commands). This container only supports index and length operations. debugger.errorlog[] (read-only) The lines in the error log (logerror output). This container only supports index and length operations. debugger.visible_cpu (read/write) The CPU device with debugger focus. Changes become visible in the debugger console after the next step. Setting to a device that is not a CPU has no effect. debugger.execution_state (read/write) Either "run" if the emulated system is running, or "stop" if it is stopped in the debugger. Device debugger interface Wraps MAMEs device_debug class, providing the debugger interface to an emulated CPU device. Instantiation manager.machine.devices[tag].debug Returns the debugger interface for an emulated CPU device, or nil if the device is not a CPU. Methods debug:step([cnt]) Step by the specified number of instructions. If the instruc- tion count is not provided, it defaults to a single instruction. debug:go() Run the emulated CPU. debug:bpset(addr, [cond], [act]) Set a breakpoint at the specified address, with an optional con- dition and action. If the action is not specified, it defaults to just breaking into the debugger. Returns the breakpoint num- ber for the new breakpoint. If specified, the condition must be a debugger expression that will be evaluated each time the breakpoint is hit. Execution will only be stopped if the expression evaluates to a non-zero value. If the condition is not specified, it defaults to always active. debug:bpenable([bp]) Enable the specified breakpoint, or all breakpoints for the de- vice if no breakpoint number is specified. Returns whether the specified number matched a breakpoint if a breakpoint number is specified, or nil if no breakpoint number is specified. debug:bpdisable([bp]) Disable the specified breakpoint, or all breakpoints for the de- vice if no breakpoint number is specified. Returns whether the specified number matched a breakpoint if a breakpoint number is specified, or nil if no breakpoint number is specified. debug:bpclear([bp]) Clear the specified breakpoint, or all breakpoints for the de- vice if no breakpoint number is specified. Returns whether the specified number matched a breakpoint if a breakpoint number is specified, or nil if no breakpoint number is specified. debug:bplist() Returns a table of breakpoints for the device. The keys are the breakpoint numbers, and the values are breakpoint objects. debug:wpset(space, type, addr, len, [cond], [act]) Set a watchpoint over the specified address range, with an op- tional condition and action. The type must be "r", "w" or "rw" for a read, write or read/write breakpoint. If the action is not specified, it defaults to just breaking into the debugger. Returns the watchpoint number for the new watchpoint. If specified, the condition must be a debugger expression that will be evaluated each time the breakpoint is hit. Execution will only be stopped if the expression evaluates to a non-zero value. The variable 'wpaddr' is set to the address that actu- ally triggered the watchpoint, the variable 'wpdata' is set to the data that is being read or written, and the variable 'wp- size' is set to the size of the data in bytes. If the condition is not specified, it defaults to always active. debug:wpenable([wp]) Enable the specified watchpoint, or all watchpoints for the de- vice if no watchpoint number is specified. Returns whether the specified number matched a watchpoint if a watchpoint number is specified, or nil if no watchpoint number is specified. debug:wpdisable([wp]) Disable the specified watchpoint, or all watchpoints for the de- vice if no watchpoint number is specified. Returns whether the specified number matched a watchpoint if a watchpoint number is specified, or nil if no watchpoint number is specified. debug:wpclear([wp]) Clear the specified watchpoint, or all watchpoints for the de- vice if no watchpoint number is specified. Returns whether the specified number matched a watchpoint if a watchpoint number is specified, or nil if no watchpoint number is specified. debug:wplist(space) Returns a table of watchpoints for the specified address space of the device. The keys are the watchpoint numbers, and the values are watchpoint objects. Breakpoint Wraps MAMEs debug_breakpoint class, representing a breakpoint for an emulated CPU device. Instantiation manager.machine.devices[tag].debug:bplist()[bp] Gets the specified breakpoint for an emulated CPU device, or nil if no breakpoint corresponds to the specified index. Properties breakpoint.index (read-only) The breakpoints index. The can be used to enable, disable or clear the breakpoint via the CPU debugger interface. breakpoint.enabled (read/write) A Boolean indicating whether the breakpoint is currently en- abled. breakpoint.address (read-only) The breakpoints address. breakpoint.condition (read-only) A debugger expression evaluated each time the breakpoint is hit. The action will only be triggered if this expression evaluates to a non-zero value. An empty string if no condition was speci- fied. breakpoint.action (read-only) An action the debugger will run when the breakpoint is hit and the condition evaluates to a non-zero value. An empty string if no action was specified. Watchpoint Wraps MAMEs debug_watchpoint class, representing a watchpoint for an emulated CPU device. Instantiation manager.machine.devices[tag].debug:wplist(space)[wp] Gets the specified watchpoint for an address space of an emu- lated CPU device, or nil if no watchpoint in the address space corresponds to the specified index. Properties watchpoint.index (read-only) The watchpoints index. The can be used to enable, disable or clear the watchpoint via the CPU debugger interface. watchpoint.enabled (read/write) A Boolean indicating whether the watchpoint is currently en- abled. watchpoint.type (read-only) Either "r", "w" or "rw" for a read, write or read/write watch- point. watchpoint.address (read-only) The starting address of the watchpoints address range. watchpoint.length (read-only) The length of the watchpoints address range. watchpoint.condition (read-only) A debugger expression evaluated each time the watchpoint is hit. The action will only be triggered if this expression evaluates to a non-zero value. An empty string if no condition was speci- fied. watchpoint.action (read-only) An action the debugger will run when the watchpoint is hit and the condition evaluates to a non-zero value. An empty string if no action was specified. Expression error Wraps MAMEs expression_error class, describing an error occurring while parsing or executing a debugger expression. Raised on errors when us- ing parsed expressions. Can be converted to a string to provide a de- scription of the error. Properties err.code (read-only) An implementation-dependent number representing the category of error. Should not be displayed to the user. err.offset (read-only) The offset within the expression string where the error was en- countered. Interactive Lua console tutorial First run an arcade game in MAME at the command prompt with the -con- sole and -window options to enable the Lua console: $ mame -console -window YOUR_SYSTEM /| /| /| /| /| _______ / | / | / | / | / | / / / |/ | / | / |/ | / ____/ / | / | / | / /_ / |/ | / |/ __/ / /| /| /| |/ /| /| /____ / / | / | / | / | / | / / _/ |/ / / |___/ |/ /_______/ / / / _/ mame 0.255 Copyright (C) Nicola Salmoria and the MAME team Lua 5.4 Copyright (C) Lua.org, PUC-Rio [MAME]> At this point, your game is probably running in attract mode. Lets pause it: [MAME]> emu.pause() [MAME]> Even without textual feedback on the console, youll notice the game is now paused. In general, commands are quiet and only print error mes- sages. You can check the version of MAME you are running with: [MAME]> print(emu.app_name() .. " " .. emu.app_version()) mame 0.255 Lets examine the emulated screens. First, enumerate the screen devices in the system: [MAME]> for tag, screen in pairs(manager.machine.screens) do print(tag) end :screen manager.machine is the running machine object for the current emulation session. We will be using this frequently. screens is a device enu- merator that yields all emulated screens in the system. Most arcade games only have one main screen. In our case, the main and only screen has the absolute tag :screen. We can examine it further: [MAME]> -- keep a reference to the main screen in a variable [MAME]> s = manager.machine.screens[':screen'] [MAME]> print(s.width .. 'x' .. s.height) 320x224 Several methods are available for drawing an overlay on the screen us- ing lines, rectangles and text: [MAME]> -- define a function for drawing an overlay and call it [MAME]> function draw_overlay() [MAME]>> s:draw_text(40, 40, 'foo') -- (x0, y0, msg) [MAME]>> s:draw_box(20, 20, 80, 80, 0xff00ffff, 0) -- (x0, y0, x1, y1, line-color, fill-color) [MAME]>> s:draw_line(20, 20, 80, 80, 0xff00ffff) -- (x0, y0, x1, y1, line-color) [MAME]>> end [MAME]> draw_overlay() This will draw some useless lines and text over the screen. However, when the emulated system is resumed, your overlay needs to be refreshed or it will just disappear. In order to do this, you have to register your function to be called on every video update: [MAME]> emu.register_frame_done(draw_overlay, 'frame') All colors are specified in ARGB format (eight bits per channel). The coordinate origin (0,0) normally corresponds to the top-left corner of the screen. As with screens, you can examine all the emulated devices in the run- ning system: [MAME]> for tag, device in pairs(manager.machine.devices) do print(tag) end :audiocpu :maincpu :saveram :screen :palette [...] For some of them, you can also inspect and manipulate memory and state: [MAME]> cpu = manager.machine.devices[':maincpu'] [MAME]> -- enumerate, read and write register state [MAME]> for k, v in pairs(cpu.state) do print(k) end CURPC rPC IR CURFLAGS SSR D0 [...] [MAME]> print(cpu.state["D0"].value) 303 [MAME]> cpu.state['D0'].value = 255 [MAME]> print(cpu.state['D0'].value) 255 [MAME]> -- inspect memory [MAME]> for name, space in pairs(cpu.spaces) do print(name) end program cpu_space [MAME]> mem = cpu.spaces['program'] [MAME]> print(mem:read_i8(0xc000)) 41 Note that many objects support symbol completion if you type part of a method or property name and press the Tab key: [MAME]>print(mem:read_<TAB> read_direct_i8 read_u16 read_range read_direct_u16 read_direct_i64 read_i64 read_i32 read_direct_u64 read_i8 read_u32 read_u8 read_u64 read_direct_u32 read_direct_i16 read_direct_i32 read_direct_u8 read_i16 [MAME]>print(mem:read_direct_i8 MAME EXTERNAL TOOLS This section describes additional tools that are built alongside and typically distributed with MAME. chdman CHD (Compressed Hunks of Data) File Manager chdman can be used to create, convert, check the integrity of and ex- tract data from media images in CHD (Compressed Hunks of Data) format. The basic usage is chdman <command> <option>... • Common options • Commands • info • verify • createraw • createhd • createcd • createdvd • createld • extractraw • extracthd • extractcd • extractdvd • extractld • addmeta • delmeta • dumpmeta • listtemplates • Compression algorithms Common options The options available depend on the command, but the following options are used by multiple commands: --input <file> / -i <file> Specify the input file. This option is required for most com- mands. The input file formats supported depend on the command --inputparent <chdfile> / -ip <chdfile> Specify the parent CHD file for the input file. This option is supported for most commands that operate on CHD format input files. This option must be used if the input file is a delta CHD, storing only the hunks that differ from its parent CHD, --inputstartbyte <offset> / -isb <offset> Specify the offset to the data in the input file in bytes. This is useful for creating CHD format files from input files that contain a header before the start of the data, or for extracting partial content from a CHD format file. May not be specified in combination with the --inputstarthunk/-ish option. --inputstarthunk <offset> / -ish <offset> Specify the offset to the data in the input file in hunks. May not be specified in combination with the --inputstartbyte/-isb option. --inputbytes <length> / -ib <length> Specify the amount of input data to use in bytes, starting from the offset to the data in the input file. This is useful for creating CHD format files from input files that contain addi- tional content after the data, or for extracting partial content from a CHD format file. May not be specified in combination with the --inputhunks/-ih option. --inputhunks <length> / -ih <length> Specify the amount of input data to use in hunks, starting from the offset to the data in the input file. May not be specified in combination with the --inputbytes/-ib option. --output <file> / -o <file> Specify the output file name. This option is required for com- mands that produce output files. The output file formats sup- ported depend on the command. --outputparent <chdfile> / -op <chdfile> Specify the parent CHD file for the output file. This option is supported for commands that produce CHD format output files. Using this option produces a delta CHD, storing only the hunks that differ from its parent CHD. The parent CHD should be the same media type and size, with the same hunk size. --compression none|<type>[,<type>]... / -c none|<type>[,<type>]... Specify compression algorithms to use. This option is supported for commands that produce CHD format output files. Specify none to disable compression, or specify up to four comma-separated compression algorithms. See compression algorithms for sup- ported compression algorithms. Compression must be disable to create writable media image files. --hunksize <bytes> / -hs <bytes> Specifies the hunk size in bytes. This option is supported for commands that produce CHD format output files. The hunk size must be no smaller than 16 bytes and no larger than 1048576 bytes (1 MiB). The hunk size must be a multiple of the sector size or unit size of the media. Larger hunk sizes may give bet- ter compression ratios, but reduce performance for small random reads as an entire hunk needs to be read and decompressed at a time. --force / -f Overwrite output files if they already exist. This option is supported for commands that produce output files. --verbose / -v Enable verbose output. This prints more detailed information for some commands. --numprocessors <count> / -np <count> Limit the maximum number of concurrent threads used for data compression. This option is supported for commands that produce CHD format output files. Commands info Display information about a CHD format file. Information includes: • CHD format version and compression algorithms used. • Compressed and uncompressed sizes and overall compression ratio. • Hunk size, unit size and number of hunks in the file. • SHA1 digests of the data and metadata. Common options supported: • --input <file> / -i <file> (required) • --verbose / -v verify Verify the integrity of a CHD format file. The input file must be a read-only CHD format file (the integrity of writable CHD files cannot be verified). Note that this command modifies its input file if the --fix/-f option is specified. Common options supported: • --input <file> / -i <file> (required) • --inputparent <chdfile> / -ip <chdfile> Additional options: • --fix / -f createraw Create a CHD format file from a raw media image. Common options supported: • --input <file> / -i <file> (required) • --inputstartbyte <offset> / -isb <offset> • --inputstarthunk <offset> / -ish <offset> • --inputbytes <length> / -ib <length> • --inputhunks <length> / -ih <length> • --output <file> / -o <file> (required) • --outputparent <chdfile> / -op <chdfile> • --compression none|<type>[,<type>]... / -c none|<type>[,<type>]... • --hunksize <bytes> / -hs <bytes> • --force / -f • --numprocessors <count> / -np <count> Additional options: --unitsize <bytes> / -us <bytes> (required) The unit size for the output CHD file in bytes. This is the smallest unit of data that can be addressed within the CHD file. It should match the sector size or page size of the source me- dia. The hunk size must be a whole multiple of the unit size. The unit size must be specified if no parent CHD file for the output is supplied. If a parent CHD file for the output is sup- plied, the unit size must match the unit size of the parent CHD file. If the --hunksize or -hs option is not supplied, the default will be: • The hunk size of the parent CHD file if a parent CHD file for the output is supplied. • The smallest whole multiple of the unit size not larger than 4 KiB if the unit size is not larger than 4 KiB (4096 bytes). • The unit size if it is larger than 4 KiB (4096 bytes). If the --compression or -c option is not supplied, it defaults to lzma,zlib,huff,flac. createhd Create a CHD format hard disk image file. Common options supported: • --input <file> / -i <file> • --inputstartbyte <offset> / -isb <offset> • --inputstarthunk <offset> / -ish <offset> • --inputbytes <length> / -ib <length> • --inputhunks <length> / -ih <length> • --output <file> / -o <file> (required) • --outputparent <chdfile> / -op <chdfile> • --compression none|<type>[,<type>]... / -c none|<type>[,<type>]... • --hunksize <bytes> / -hs <bytes> (required) • --force / -f • --numprocessors <count> / -np <count> Additional options: • --sectorsize <bytes> / -ss <bytes> • --size <bytes> / -s <bytes> • --chs <cylinders>,<heads>,<sectors> / -chs <cylinders>,<heads>,<sec- tors> • --template <template> / -tp <template> Creates a blank (zero-filled) hard disk image if no input file is sup- plied. The input start/length (--inputstartbyte/-isb, --input- starthunk/-ish, --inputbytes/-ib and --inputhunks/-ih options) cannot be used if no input file is supplied. If the --hunksize or -hs option is not supplied, the default will be: • The hunk size of the parent CHD file if a parent CHD file for the output is supplied. • The smallest whole multiple of the sector size not larger than 4 KiB if the sector size is not larger than 4 KiB (4096 bytes). • The sector size if it is larger than 4 KiB (4096 bytes). If the --compression or -c option is not supplied, it defaults to lzma,zlib,huff,flac if an input file is supplied, or none if no input file is supplied. createcd Create a CHD format CD-ROM image file. Common options supported: • --input <file> / -i <file> (required) • --output <file> / -o <file> (required) • --outputparent <chdfile> / -op <chdfile> • --compression none|<type>[,<type>]... / -c none|<type>[,<type>]... • --hunksize <bytes> / -hs <bytes> (required) • --force / -f • --numprocessors <count> / -np <count> If the --hunksize or -hs option is not supplied, the default will be the hunk size of the parent CHD if a parent CHD file for the output is supplied, or eight sectors per hunk (18,816 bytes) otherwise. If the --compression or -c option is not supplied, it defaults to cdlz,cdzl,cdfl. createdvd Create a CHD format DVD-ROM image file. Common options supported: • --input <file> / -i <file> (required) • --inputstartbyte <offset> / -isb <offset> • --inputstarthunk <offset> / -ish <offset> • --inputbytes <length> / -ib <length> • --inputhunks <length> / -ih <length> • --output <file> / -o <file> (required) • --outputparent <chdfile> / -op <chdfile> • --compression none|<type>[,<type>]... / -c none|<type>[,<type>]... • --hunksize <bytes> / -hs <bytes> (required) • --force / -f • --numprocessors <count> / -np <count> If the --hunksize or -hs option is not supplied, the default will be the hunk size of the parent CHD if a parent CHD file for the output is supplied, or two sectors per hunk (4096 bytes) otherwise. If the --compression or -c option is not supplied, it defaults to lzma,zlib,huff,flac. createld Create a CHD format LaserDisc image file. Common options supported: • --input <file> / -i <file> (required) • --output <file> / -o <file> (required) • --outputparent <chdfile> / -op <chdfile> • --compression none|<type>[,<type>]... / -c none|<type>[,<type>]... • --hunksize <bytes> / -hs <bytes> (required) • --force / -f • --numprocessors <count> / -np <count> Additional options: • --inputstartframe <offset> / -isf <offset> • --inputframes <length> / -if <length> If the --compression or -c option is not supplied, it defaults to avhu. extractraw Extract data from a CHD format raw media image. Common options supported: • --input <file> / -i <file> (required) • --inputparent <chdfile> / -ip <chdfile> • --inputstartbyte <offset> / -isb <offset> • --inputstarthunk <offset> / -ish <offset> • --inputbytes <length> / -ib <length> • --inputhunks <length> / -ih <length> • --output <file> / -o <file> (required) • --force / -f extracthd Extract data from a CHD format hard disk image. Common options supported: • --input <file> / -i <file> (required) • --inputparent <chdfile> / -ip <chdfile> • --inputstartbyte <offset> / -isb <offset> • --inputstarthunk <offset> / -ish <offset> • --inputbytes <length> / -ib <length> • --inputhunks <length> / -ih <length> • --output <file> / -o <file> (required) • --force / -f extractcd Extract data from a CHD format CD-ROM image. Common options supported: • --input <file> / -i <file> (required) • --inputparent <chdfile> / -ip <chdfile> • --output <file> / -o <file> (required) • --force / -f Additional options: • --outputbin <file> / -ob <file> • --splitbin / -sb extractdvd Extract data from a CHD format DVD-ROM image. Common options supported: • --input <file> / -i <file> (required) • --inputparent <chdfile> / -ip <chdfile> • --inputstartbyte <offset> / -isb <offset> • --inputstarthunk <offset> / -ish <offset> • --inputbytes <length> / -ib <length> • --inputhunks <length> / -ih <length> • --output <file> / -o <file> (required) • --force / -f extractld Extract data from a CHD format DVD-ROM image. Common options supported: • --input <file> / -i <file> (required) • --inputparent <chdfile> / -ip <chdfile> • --output <file> / -o <file> (required) • --force / -f Additional options: • --inputstartframe <offset> / -isf <offset> • --inputframes <length> / -if <length> addmeta Add a metadata item to a CHD format file. Note that this command modi- fies its input file. Common options supported: • --input <file> / -i <file> (required) Additional options: • --tag <tag> / -t <tag> (required) • --index <index> / -ix <index> • --valuetext <text> / -vt <text> • --valuefile <file> / -vf <file> • --nochecksum / -nocs delmeta Delete a metadata item from a CHD format file. Note that this command modifies its input file. Common options supported: • --input <file> / -i <file> (required) Additional options: • --tag <tag> / -t <tag> (required) • --index <index> / -ix <index> dumpmeta Extract metadata items from a CHD format file to the standard output or to a file. Common options supported: • --input <file> / -i <file> (required) • --output <file> / -o <file> • --force / -f Additional options: • --tag <tag> / -t <tag> (required) • --index <index> / -ix <index> listtemplates List available hard disk templates. This command does not accept any options. Compression algorithms The following compression algorithms are supported: zlib zlib deflate Compresses data using the zlib deflate algorithm. zstd Zstandard Compresses data using the Zstandard algorithm. This gives very good compression and decompression performance with better com- pression ratios than zlib deflate, but older software may not support CHD files that use Zstandard compression. lzma Lempel-Ziv-Markov chain algorithm Compresses data using the Lempel-Ziv-Markov-chain algorithm (LZMA). This gives high compression ratios at the cost of poor compression and decompression performance. huff Huffman coding Compresses data using 8-bit Huffman entropy coding. flac Free Lossless Audio Codec Compresses data as two-channel (stereo) 16-bit 44.1 kHz PCM au- dio using the Free Lossless Audio Codec (FLAC). This gives good compression ratios if the media contains 16-bit PCM audio data. cdzl zlib deflate for CD-ROM data Compresses audio data and subchannel data from CD-ROM sectors separately using the zlib deflate algorithm. cdzs Zstandard for CD-ROM data Compresses audio data and subchannel data from CD-ROM sectors separately using the Zstandard algorithm. This gives very good compression and decompression performance with better compres- sion ratios than zlib deflate, but older software may not sup- port CHD files that use Zstandard compression. cdlz - Lempel-Ziv-Markov chain algorithm/zlib deflate for CD-ROM data Compresses audio data and subchannel data from CD-ROM sectors separately using the Lempel-Ziv-Markov chain algorithm (LZMA) for audio data and the zlib deflate algorithm for subchannel data. This gives high compression ratios at the cost of poor compression and decompression performance. cdfl Free Lossless Audio Codec/zlib deflate for CD-ROM data Compresses audio data and subchannel data from CD-ROM sectors separately using the Free Lossless Audio Codec (FLAC) for audio data and the zlib deflate algorithm for subchannel data. This gives good compression ratios for audio CD tracks. avhu Huffman coding for audio-visual data This is a specialised compression algorithm for audio-visual (A/V) data. It should only be used for LaserDisc CHD files. Imgtool - A generic image manipulation tool for MAME Imgtool is a tool for the maintenance and manipulation of disk and other types of images that MAME users need to deal with. Functions in- clude retrieving and storing files and CRC checking/validation. Imgtool is part of the MAME project. It shares large portions of code with MAME, and its existence would not be if it were not for MAME. As such, the distribution terms are the same as MAME. Please read the MAME license thoroughly. Some portions of Imgtool are Copyright (c) 1989, 1993 The Regents of the University of California. All rights reserved. Using Imgtool Imgtool is a command line program that contains several "subcommands" that actually do all of the work. Most commands are invoked in a man- ner along the lines of this: imgtool <subcommand> <format> <image> ... • <subcommand> is the name of the subcommand • <format> is the format of the image • <image> is the filename of the image Example usage: imgtool dir coco_jvc_rsdos myimageinazip.zip imgtool get coco_jvc_rsdos myimage.dsk myfile.bin mynewfile.txt imgtool getall coco_jvc_rsdos myimage.dsk Further details vary with each subcommand. Also note that not all sub- commands are applicable or supported for different image formats. Imgtool Subcommands create imgtool create <format> <imagename> [--(createoption)=value] • <format> is the image format, e.g. coco_jvc_rsdos • <imagename> is the image filename; can specify a ZIP file for im- age name Creates an image dir imgtool dir <format> <imagename> [path] • <format> is the image format, e.g. coco_jvc_rsdos • <imagename> is the image filename; can specify a ZIP file for im- age name Lists the contents of an image get imgtool get <format> <imagename> <filename> [newname] [--filter=fil- ter] [--fork=fork] • <format> is the image format, e.g. coco_jvc_rsdos • <imagename> is the image filename; can specify a ZIP file for im- age name Gets a single file from an image put imgtool put <format> <imagename> <filename>... <destname> [--(fileoption)=value] [--filter=filter] [--fork=fork] • <format> is the image format, e.g. coco_jvc_rsdos • <imagename> is the image filename; can specify a ZIP file for im- age name Puts a single file on an image (wildcards supported) getall imgtool getall <format> <imagename> [path] [--filter=filter] • <format> is the image format, e.g. coco_jvc_rsdos • <imagename> is the image filename; can specify a ZIP file for im- age name Gets all files off an image del imgtool del <format> <imagename> <filename>... • <format> is the image format, e.g. coco_jvc_rsdos • <imagename> is the image filename; can specify a ZIP file for im- age name Deletes a file on an image mkdir imgtool mkdir <format> <imagename> <dirname> • <format> is the image format, e.g. coco_jvc_rsdos • <imagename> is the image filename; can specify a ZIP file for im- age name Creates a subdirectory on an image rmdir imgtool rmdir <format> <imagename> <dirname>... • <format> is the image format, e.g. coco_jvc_rsdos • <imagename> is the image filename; can specify a ZIP file for im- age name Deletes a subdirectory on an image readsector imgtool readsector <format> <imagename> <track> <head> <sector> <filename> • <format> is the image format, e.g. coco_jvc_rsdos • <imagename> is the image filename; can specify a ZIP file for im- age name Read a sector on an image and output it to specified <filename> writesector imgtool writesector <format> <imagename> <track> <head> <sector> <filename> • <format> is the image format, e.g. coco_jvc_rsdos • <imagename> is the image filename; can specify a ZIP file for im- age name Write a sector to an image from specified <filename> identify • <format> is the image format, e.g. coco_jvc_rsdos • <imagename> is the image filename; can specify a ZIP file for im- age name imgtool identify <imagename> listformats Lists all image file formats supported by imgtool listfilters Lists all filters supported by imgtool listdriveroptions imgtool listdriveroptions <format> • <format> is the image format, e.g. coco_jvc_rsdos Lists all format-specific options for the 'put' and 'create' com- mands Imgtool Filters Filters are a means to process data being written into or read out of an image in a certain way. Filters can be specified on the get, put, and getall commands by specifying --filter=xxxx on the command line. Currently, the following filters are supported: ascii Translates end-of-lines to the appropriate format cocobas Processes tokenized TRS-80 Color Computer (CoCo) BASIC programs dragonbas Processes tokenized Tano/Dragon Data Dragon 32/64 BASIC programs macbinary Processes Apple MacBinary-formatted (merged forks) files vzsnapshot [todo: VZ Snapshot? Find out what this is...] vzbas Processes Laser/VZ Tokenized Basic Files thombas5 Thomson MO5 w/ BASIC 1.0, Tokenized Files (read-only, auto-decrypt) thombas7 Thomson TO7 w/ BASIC 1.0, Tokenized Files (read-only, auto-decrypt) thombas128 Thomson w/ BASIC 128/512, Tokenized Files (read-only, auto-decrypt) thomcrypt Thomson BASIC, Protected file encryption (no tokenization) bm13bas Basic Master Level 3 Tokenized Basic Files Imgtool Format Info Amiga floppy disk image (OFS/FFS format) - (amiga_floppy) Driver specific options for module 'amiga_floppy': No image specific file options Image specific creation options (usable on the 'create' command): +--------------+----------------+---------------------+ | Option | Allowed values | Description | +--------------+----------------+---------------------+ | --density | dd/hd | Density | +--------------+----------------+---------------------+ | --filesystem | ofs/ffs | File system | +--------------+----------------+---------------------+ | --mode | none/intl/dirc | File system options | +--------------+----------------+---------------------+ Apple ][ DOS order disk image (ProDOS format) - (apple2_do_prodos_525) Driver specific options for module 'apple2_do_prodos_525': No image specific file options Image specific creation options (usable on the 'create' command): +-----------------+----------------+--------------+ | Option | Allowed values | Description | +-----------------+----------------+--------------+ | --heads | 1 | Heads | +-----------------+----------------+--------------+ | --tracks | 35 | Tracks | +-----------------+----------------+--------------+ | --sectors | 16 | Sectors | +-----------------+----------------+--------------+ | --sectorlength | 256 | Sector Bytes | +-----------------+----------------+--------------+ | --firstsectorid | 0 | First Sector | +-----------------+----------------+--------------+ Apple ][ Nibble order disk image (ProDOS format) - (apple2_nib_prodos_525) Driver specific options for module 'apple2_nib_prodos_525': No image specific file options Image specific creation options (usable on the 'create' command): +-----------------+----------------+--------------+ | Option | Allowed values | Description | +-----------------+----------------+--------------+ | --heads | 1 | Heads | +-----------------+----------------+--------------+ | --tracks | 35 | Tracks | +-----------------+----------------+--------------+ | --sectors | 16 | Sectors | +-----------------+----------------+--------------+ | --sectorlength | 256 | Sector Bytes | +-----------------+----------------+--------------+ | --firstsectorid | 0 | First Sector | +-----------------+----------------+--------------+ Apple ][ ProDOS order disk image (ProDOS format) - (apple2_po_prodos_525) Driver specific options for module 'apple2_po_prodos_525': No image specific file options Image specific creation options (usable on the 'create' command): +-----------------+----------------+--------------+ | Option | Allowed values | Description | +-----------------+----------------+--------------+ | --heads | 1 | Heads | +-----------------+----------------+--------------+ | --tracks | 35 | Tracks | +-----------------+----------------+--------------+ | --sectors | 16 | Sectors | +-----------------+----------------+--------------+ | --sectorlength | 256 | Sector Bytes | +-----------------+----------------+--------------+ | --firstsectorid | 0 | First Sector | +-----------------+----------------+--------------+ Apple ][gs 2IMG disk image (ProDOS format) - (apple35_2img_prodos_35) Driver specific options for module 'apple35_2img_prodos_35': No image specific file options Image specific creation options (usable on the 'create' command): +-----------------+----------------+--------------+ | Option | Allowed values | Description | +-----------------+----------------+--------------+ | --heads | 1-2 | Heads | +-----------------+----------------+--------------+ | --tracks | 80 | Tracks | +-----------------+----------------+--------------+ | --sectorlength | 512 | Sector Bytes | +-----------------+----------------+--------------+ | --firstsectorid | 0 | First Sector | +-----------------+----------------+--------------+ Apple DiskCopy disk image (Mac HFS Floppy) - (apple35_dc_mac_hfs) Driver specific options for module 'apple35_dc_mac_hfs': No image specific file options Image specific creation options (usable on the 'create' command): +-----------------+----------------+--------------+ | Option | Allowed values | Description | +-----------------+----------------+--------------+ | --heads | 1-2 | Heads | +-----------------+----------------+--------------+ | --tracks | 80 | Tracks | +-----------------+----------------+--------------+ | --sectorlength | 512 | Sector Bytes | +-----------------+----------------+--------------+ | --firstsectorid | 0 | First Sector | +-----------------+----------------+--------------+ Apple DiskCopy disk image (Mac MFS Floppy) - (apple35_dc_mac_mfs) Driver specific options for module 'apple35_dc_mac_mfs': No image specific file options Image specific creation options (usable on the 'create' command): +-----------------+----------------+--------------+ | Option | Allowed values | Description | +-----------------+----------------+--------------+ | --heads | 1-2 | Heads | +-----------------+----------------+--------------+ | --tracks | 80 | Tracks | +-----------------+----------------+--------------+ | --sectorlength | 512 | Sector Bytes | +-----------------+----------------+--------------+ | --firstsectorid | 0 | First Sector | +-----------------+----------------+--------------+ Apple DiskCopy disk image (ProDOS format) - (apple35_dc_prodos_35) Driver specific options for module 'apple35_dc_prodos_35': No image specific file options Image specific creation options (usable on the 'create' command): +-----------------+----------------+--------------+ | Option | Allowed values | Description | +-----------------+----------------+--------------+ | --heads | 1-2 | Heads | +-----------------+----------------+--------------+ | --tracks | 80 | Tracks | +-----------------+----------------+--------------+ | --sectorlength | 512 | Sector Bytes | +-----------------+----------------+--------------+ | --firstsectorid | 0 | First Sector | +-----------------+----------------+--------------+ Apple raw 3.5" disk image (Mac HFS Floppy) - (apple35_raw_mac_hfs) Driver specific options for module 'apple35_raw_mac_hfs': No image specific file options Image specific creation options (usable on the 'create' command): +-----------------+----------------+--------------+ | Option | Allowed values | Description | +-----------------+----------------+--------------+ | --heads | 1-2 | Heads | +-----------------+----------------+--------------+ | --tracks | 80 | Tracks | +-----------------+----------------+--------------+ | --sectorlength | 512 | Sector Bytes | +-----------------+----------------+--------------+ | --firstsectorid | 0 | First Sector | +-----------------+----------------+--------------+ Apple raw 3.5" disk image (Mac MFS Floppy) - (apple35_raw_mac_mfs) Driver specific options for module 'apple35_raw_mac_mfs': No image specific file options Image specific creation options (usable on the 'create' command): +-----------------+----------------+--------------+ | Option | Allowed values | Description | +-----------------+----------------+--------------+ | --heads | 1-2 | Heads | +-----------------+----------------+--------------+ | --tracks | 80 | Tracks | +-----------------+----------------+--------------+ | --sectorlength | 512 | Sector Bytes | +-----------------+----------------+--------------+ | --firstsectorid | 0 | First Sector | +-----------------+----------------+--------------+ Apple raw 3.5" disk image (ProDOS format) - (apple35_raw_prodos_35) Driver specific options for module 'apple35_raw_prodos_35': No image specific file options Image specific creation options (usable on the 'create' command): +-----------------+----------------+--------------+ | Option | Allowed values | Description | +-----------------+----------------+--------------+ | --heads | 1-2 | Heads | +-----------------+----------------+--------------+ | --tracks | 80 | Tracks | +-----------------+----------------+--------------+ | --sectorlength | 512 | Sector Bytes | +-----------------+----------------+--------------+ | --firstsectorid | 0 | First Sector | +-----------------+----------------+--------------+ CoCo DMK disk image (OS-9 format) - (coco_dmk_os9) Driver specific options for module 'coco_dmk_os9': No image specific file options Image specific creation options (usable on the 'create' command): +-----------------+---------------------------------+--------------+ | Option | Allowed values | Description | +-----------------+---------------------------------+--------------+ | --heads | 1-2 | Heads | +-----------------+---------------------------------+--------------+ | --tracks | 35-255 | Tracks | +-----------------+---------------------------------+--------------+ | --sectors | 1-18 | Sectors | +-----------------+---------------------------------+--------------+ | --sectorlength | 128/256/512/1024/2048/4096/8192 | Sector Bytes | +-----------------+---------------------------------+--------------+ | --interleave | 0-17 | Interleave | +-----------------+---------------------------------+--------------+ | --firstsectorid | 0-1 | First Sector | +-----------------+---------------------------------+--------------+ CoCo DMK disk image (RS-DOS format) - (coco_dmk_rsdos) Driver specific options for module 'coco_dmk_rsdos': Image specific file options (usable on the 'put' command): +---------+----------------+-------------+ | Option | Allowed values | Description | +---------+----------------+-------------+ | --ftype | basic/data/bi- | File type | | | nary/assembler | | +---------+----------------+-------------+ | --ascii | ascii/binary | ASCII flag | +---------+----------------+-------------+ Image specific creation options (usable on the 'create' command): +-----------------+---------------------------------+--------------+ | Option | Allowed values | Description | +-----------------+---------------------------------+--------------+ | --heads | 1-2 | Heads | +-----------------+---------------------------------+--------------+ | --tracks | 35-255 | Tracks | +-----------------+---------------------------------+--------------+ | --sectors | 1-18 | Sectors | +-----------------+---------------------------------+--------------+ | --sectorlength | 128/256/512/1024/2048/4096/8192 | Sector Bytes | +-----------------+---------------------------------+--------------+ | --interleave | 0-17 | Interleave | +-----------------+---------------------------------+--------------+ | --firstsectorid | 0-1 | First Sector | +-----------------+---------------------------------+--------------+ CoCo JVC disk image (OS-9 format) - (coco_jvc_os9) Driver specific options for module 'coco_jvc_os9': No image specific file options Image specific creation options (usable on the 'create' command): +-----------------+------------------+--------------+ | Option | Allowed values | Description | +-----------------+------------------+--------------+ | --heads | 1-2 | Heads | +-----------------+------------------+--------------+ | --tracks | 35-255 | Tracks | +-----------------+------------------+--------------+ | --sectors | 1-255 | Sectors | +-----------------+------------------+--------------+ | --sectorlength | 128/256/512/1024 | Sector Bytes | +-----------------+------------------+--------------+ | --firstsectorid | 0-1 | First Sector | +-----------------+------------------+--------------+ CoCo JVC disk image (RS-DOS format) - (coco_jvc_rsdos) Driver specific options for module 'coco_jvc_rsdos': Image specific file options (usable on the 'put' command): +---------+----------------+-------------+ | Option | Allowed values | Description | +---------+----------------+-------------+ | --ftype | basic/data/bi- | File type | | | nary/assembler | | +---------+----------------+-------------+ | --ascii | ascii/binary | ASCII flag | +---------+----------------+-------------+ Image specific creation options (usable on the 'create' command): +-----------------+------------------+--------------+ | Option | Allowed values | Description | +-----------------+------------------+--------------+ | --heads | 1-2 | Heads | +-----------------+------------------+--------------+ | --tracks | 35-255 | Tracks | +-----------------+------------------+--------------+ | --sectors | 1-255 | Sectors | +-----------------+------------------+--------------+ | --sectorlength | 128/256/512/1024 | Sector Bytes | +-----------------+------------------+--------------+ | --firstsectorid | 0-1 | First Sector | +-----------------+------------------+--------------+ CoCo OS-9 disk image (OS-9 format) - (coco_os9_os9) Driver specific options for module 'coco_os9_os9': No image specific file options Image specific creation options (usable on the 'create' command): +-----------------+------------------+--------------+ | Option | Allowed values | Description | +-----------------+------------------+--------------+ | --heads | 1-2 | Heads | +-----------------+------------------+--------------+ | --tracks | 35-255 | Tracks | +-----------------+------------------+--------------+ | --sectors | 1-255 | Sectors | +-----------------+------------------+--------------+ | --sectorlength | 128/256/512/1024 | Sector Bytes | +-----------------+------------------+--------------+ | --firstsectorid | 1 | First Sector | +-----------------+------------------+--------------+ CoCo VDK disk image (OS-9 format) - (coco_vdk_os9) Driver specific options for module 'coco_vdk_os9': No image specific file options Image specific creation options (usable on the 'create' command): +-----------------+----------------+--------------+ | Option | Allowed values | Description | +-----------------+----------------+--------------+ | --heads | 1-2 | Heads | +-----------------+----------------+--------------+ | --tracks | 35-255 | Tracks | +-----------------+----------------+--------------+ | --sectors | 18 | Sectors | +-----------------+----------------+--------------+ | --sectorlength | 256 | Sector Bytes | +-----------------+----------------+--------------+ | --firstsectorid | 1 | First Sector | +-----------------+----------------+--------------+ CoCo VDK disk image (RS-DOS format) - (coco_vdk_rsdos) Driver specific options for module 'coco_vdk_rsdos': Image specific file options (usable on the 'put' command): +---------+----------------+-------------+ | Option | Allowed values | Description | +---------+----------------+-------------+ | --ftype | basic/data/bi- | File type | | | nary/assembler | | +---------+----------------+-------------+ | --ascii | ascii/binary | ASCII flag | +---------+----------------+-------------+ Image specific creation options (usable on the 'create' command): +-----------------+----------------+--------------+ | Option | Allowed values | Description | +-----------------+----------------+--------------+ | --heads | 1-2 | Heads | +-----------------+----------------+--------------+ | --tracks | 35-255 | Tracks | +-----------------+----------------+--------------+ | --sectors | 18 | Sectors | +-----------------+----------------+--------------+ | --sectorlength | 256 | Sector Bytes | +-----------------+----------------+--------------+ | --firstsectorid | 1 | First Sector | +-----------------+----------------+--------------+ Concept floppy disk image - (concept) Driver specific options for module 'concept': No image specific file options No image specific creation options CopyQM floppy disk image (Basic Master Level 3 format) - (cqm_bml3) Driver specific options for module 'cqm_bml3': Image specific file options (usable on the 'put' command): +---------+----------------+-------------+ | Option | Allowed values | Description | +---------+----------------+-------------+ | --ftype | basic/data/bi- | File type | | | nary/assembler | | +---------+----------------+-------------+ | --ascii | ascii/binary | ASCII flag | +---------+----------------+-------------+ No image specific creation options CopyQM floppy disk image (FAT format) - (cqm_fat) Driver specific options for module 'cqm_fat': No image specific file options No image specific creation options CopyQM floppy disk image (Mac HFS Floppy) - (cqm_mac_hfs) Driver specific options for module 'cqm_mac_hfs': No image specific file options No image specific creation options CopyQM floppy disk image (Mac MFS Floppy) - (cqm_mac_mfs) Driver specific options for module 'cqm_mac_mfs': No image specific file options No image specific creation options CopyQM floppy disk image (OS-9 format) - (cqm_os9) Driver specific options for module 'cqm_os9': No image specific file options No image specific creation options CopyQM floppy disk image (ProDOS format) - (cqm_prodos_35) Driver specific options for module 'cqm_prodos_35': No image specific file options No image specific creation options CopyQM floppy disk image (ProDOS format) - (cqm_prodos_525) Driver specific options for module 'cqm_prodos_525': No image specific file options No image specific creation options CopyQM floppy disk image (RS-DOS format) - (cqm_rsdos) Driver specific options for module 'cqm_rsdos': Image specific file options (usable on the 'put' command): +---------+----------------+-------------+ | Option | Allowed values | Description | +---------+----------------+-------------+ | --ftype | basic/data/bi- | File type | | | nary/assembler | | +---------+----------------+-------------+ | --ascii | ascii/binary | ASCII flag | +---------+----------------+-------------+ No image specific creation options CopyQM floppy disk image (VZ-DOS format) - (cqm_vzdos) Driver specific options for module 'cqm_vzdos': Image specific file options (usable on the 'put' command): +---------+-------------------+-------------+ | Option | Allowed values | Description | +---------+-------------------+-------------+ | --ftype | basic/binary/data | File type | +---------+-------------------+-------------+ | --fname | intern/extern | Filename | +---------+-------------------+-------------+ No image specific creation options Cybiko Classic File System - (cybiko) Driver specific options for module 'cybiko': No image specific file options Image specific creation options (usable on the 'create' command): +---------+-------------------------------+-------------+ | Option | Allowed values | Description | +---------+-------------------------------+-------------+ | --flash | AT45DB041/AT45DB081/AT45DB161 | Flash Type | +---------+-------------------------------+-------------+ Cybiko Xtreme File System - (cybikoxt) Driver specific options for module 'cybikoxt': No image specific file options No image specific creation options D88 Floppy Disk image (Basic Master Level 3 format) - (d88_bml3) Driver specific options for module 'd88_bml3': Image specific file options (usable on the 'put' command): +---------+----------------+-------------+ | Option | Allowed values | Description | +---------+----------------+-------------+ | --ftype | basic/data/bi- | File type | | | nary/assembler | | +---------+----------------+-------------+ | --ascii | ascii/binary | ASCII flag | +---------+----------------+-------------+ No image specific creation options D88 Floppy Disk image (FAT format) - (d88_fat) Driver specific options for module 'd88_fat': No image specific file options No image specific creation options D88 Floppy Disk image (Mac HFS Floppy) - (d88_mac_hfs) Driver specific options for module 'd88_mac_hfs': No image specific file options No image specific creation options D88 Floppy Disk image (Mac MFS Floppy) - (d88_mac_mfs) Driver specific options for module 'd88_mac_mfs': No image specific file options No image specific creation options D88 Floppy Disk image (OS-9 format) - (d88_os9) Driver specific options for module 'd88_os9': No image specific file options No image specific creation options D88 Floppy Disk image (OS-9 format) - (d88_os9) Driver specific options for module 'd88_prodos_35': No image specific file options No image specific creation options D88 Floppy Disk image (ProDOS format) - (d88_prodos_525) Driver specific options for module 'd88_prodos_525': No image specific file options No image specific creation options D88 Floppy Disk image (RS-DOS format) - (d88_rsdos) Driver specific options for module 'd88_rsdos': Image specific file options (usable on the 'put' command): +---------+----------------+-------------+ | Option | Allowed values | Description | +---------+----------------+-------------+ | --ftype | basic/data/bi- | File type | | | nary/assembler | | +---------+----------------+-------------+ | --ascii | ascii/binary | ASCII flag | +---------+----------------+-------------+ No image specific creation options D88 Floppy Disk image (VZ-DOS format) - (d88_vzdos) Driver specific options for module 'd88_vzdos': Image specific file options (usable on the 'put' command): +---------+-------------------+-------------+ | Option | Allowed values | Description | +---------+-------------------+-------------+ | --ftype | basic/binary/data | File type | +---------+-------------------+-------------+ | --fname | intern/extern | Filename | +---------+-------------------+-------------+ No image specific creation options DSK floppy disk image (Basic Master Level 3 format) - (dsk_bml3) Driver specific options for module 'dsk_bml3': Image specific file options (usable on the 'put' command): +---------+----------------+-------------+ | Option | Allowed values | Description | +---------+----------------+-------------+ | --ftype | basic/data/bi- | File type | | | nary/assembler | | +---------+----------------+-------------+ | --ascii | ascii/binary | ASCII flag | +---------+----------------+-------------+ No image specific creation options DSK floppy disk image (FAT format) - (dsk_fat) Driver specific options for module 'dsk_fat': No image specific file options No image specific creation options DSK floppy disk image (Mac HFS Floppy) - (dsk_mac_hfs) Driver specific options for module 'dsk_mac_hfs': No image specific file options No image specific creation options DSK floppy disk image (Mac MFS Floppy) - (dsk_mac_mfs) Driver specific options for module 'dsk_mac_mfs': No image specific file options No image specific creation options DSK floppy disk image (OS-9 format) - (dsk_os9) Driver specific options for module 'dsk_os9': No image specific file options No image specific creation options DSK floppy disk image (ProDOS format) - (dsk_prodos_35) Driver specific options for module 'dsk_prodos_35': No image specific file options No image specific creation options DSK floppy disk image (ProDOS format) - (dsk_prodos_525) Driver specific options for module 'dsk_prodos_525': No image specific file options No image specific creation options DSK floppy disk image (RS-DOS format) - (dsk_rsdos) Driver specific options for module 'dsk_rsdos': Image specific file options (usable on the 'put' command): +---------+----------------+-------------+ | Option | Allowed values | Description | +---------+----------------+-------------+ | --ftype | basic/data/bi- | File type | | | nary/assembler | | +---------+----------------+-------------+ | --ascii | ascii/binary | ASCII flag | +---------+----------------+-------------+ No image specific creation options DSK floppy disk image (VZ-DOS format) - (dsk_vzdos) Driver specific options for module 'dsk_vzdos': Image specific file options (usable on the 'put' command): +---------+-------------------+-------------+ | Option | Allowed values | Description | +---------+-------------------+-------------+ | --ftype | basic/binary/data | File type | +---------+-------------------+-------------+ | --fname | intern/extern | Filename | +---------+-------------------+-------------+ No image specific creation options Formatted Disk Image (Basic Master Level 3 format) - (fdi_bml3) Driver specific options for module 'fdi_bml3': Image specific file options (usable on the 'put' command): +---------+----------------+-------------+ | Option | Allowed values | Description | +---------+----------------+-------------+ | --ftype | basic/data/bi- | File type | | | nary/assembler | | +---------+----------------+-------------+ | --ascii | ascii/binary | ASCII flag | +---------+----------------+-------------+ No image specific creation options Formatted Disk Image (FAT format) - (fdi_fat) Driver specific options for module 'fdi_fat': No image specific file options No image specific creation options Formatted Disk Image (Mac HFS Floppy) - (fdi_mac_hfs) Driver specific options for module 'fdi_mac_hfs': No image specific file options No image specific creation options Formatted Disk Image (Mac MFS Floppy) - (fdi_mac_mfs) Driver specific options for module 'fdi_mac_mfs': No image specific file options No image specific creation options Formatted Disk Image (OS-9 format) - (fdi_os9) Driver specific options for module 'fdi_os9': No image specific file options No image specific creation options Formatted Disk Image (ProDOS format) - (fdi_prodos_35) Driver specific options for module 'fdi_prodos_35': No image specific file options No image specific creation options Formatted Disk Image (ProDOS format) - (fdi_prodos_525) Driver specific options for module 'fdi_prodos_525': No image specific file options No image specific creation options Formatted Disk Image (RS-DOS format) - (fdi_rsdos) Driver specific options for module 'fdi_rsdos': Image specific file options (usable on the 'put' command): +---------+----------------+-------------+ | Option | Allowed values | Description | +---------+----------------+-------------+ | --ftype | basic/data/bi- | File type | | | nary/assembler | | +---------+----------------+-------------+ | --ascii | ascii/binary | ASCII flag | +---------+----------------+-------------+ No image specific creation options Formatted Disk Image (VZ-DOS format) - (fdi_vzdos) Driver specific options for module 'fdi_vzdos': Image specific file options (usable on the 'put' command): +---------+-------------------+-------------+ | Option | Allowed values | Description | +---------+-------------------+-------------+ | --ftype | basic/binary/data | File type | +---------+-------------------+-------------+ | --fname | intern/extern | Filename | +---------+-------------------+-------------+ No image specific creation options HP48 SX/GX memory card - (hp48) Driver specific options for module 'hp48': No image specific file options Image specific creation options (usable on the 'create' command): +--------+----------------------------------+-------------+ | Option | Allowed values | Description | +--------+----------------------------------+-------------+ | --size | 32/64/128/256/512/1024/2048/4096 | Size in KB | +--------+----------------------------------+-------------+ IMD floppy disk image (Basic Master Level 3 format) - (imd_bml3) Driver specific options for module 'imd_bml3': Image specific file options (usable on the 'put' command): +---------+----------------+-------------+ | Option | Allowed values | Description | +---------+----------------+-------------+ | --ftype | basic/data/bi- | File type | | | nary/assembler | | +---------+----------------+-------------+ | --ascii | ascii/binary | ASCII flag | +---------+----------------+-------------+ No image specific creation options IMD floppy disk image (FAT format) - (imd_fat) Driver specific options for module 'imd_fat': No image specific file options No image specific creation options IMD floppy disk image (Mac HFS Floppy) - (imd_mac_hfs) Driver specific options for module 'imd_mac_hfs': No image specific file options No image specific creation options IMD floppy disk image (Mac MFS Floppy) - (imd_mac_mfs) Driver specific options for module 'imd_mac_mfs': No image specific file options No image specific creation options IMD floppy disk image (OS-9 format) - (imd_os9) Driver specific options for module 'imd_os9': No image specific file options No image specific creation options IMD floppy disk image (ProDOS format) - (imd_prodos_35) Driver specific options for module 'imd_prodos_35': No image specific file options No image specific creation options IMD floppy disk image (ProDOS format) - (imd_prodos_525) Driver specific options for module 'imd_prodos_525': No image specific file options No image specific creation options IMD floppy disk image (RS-DOS format) - (imd_rsdos) Driver specific options for module 'imd_rsdos': Image specific file options (usable on the 'put' command): +---------+----------------+-------------+ | Option | Allowed values | Description | +---------+----------------+-------------+ | --ftype | basic/data/bi- | File type | | | nary/assembler | | +---------+----------------+-------------+ | --ascii | ascii/binary | ASCII flag | +---------+----------------+-------------+ No image specific creation options IMD floppy disk image (VZ-DOS format) - (imd_vzdos) Driver specific options for module 'imd_vzdos': Image specific file options (usable on the 'put' command): +---------+-------------------+-------------+ | Option | Allowed values | Description | +---------+-------------------+-------------+ | --ftype | basic/binary/data | File type | +---------+-------------------+-------------+ | --fname | intern/extern | Filename | +---------+-------------------+-------------+ No image specific creation options MESS hard disk image - (mess_hd) Driver specific options for module 'mess_hd': No image specific file options Image specific creation options (usable on the 'create' command): +-------------+---------------------------------------------------+-------------------+ | Option | Allowed values | Description | +-------------+---------------------------------------------------+-------------------+ | --blocksize | 1-2048 | Sectors Per Block | +-------------+---------------------------------------------------+-------------------+ | --cylinders | 1-65536 | Cylinders | +-------------+---------------------------------------------------+-------------------+ | --heads | 1-64 | Heads | +-------------+---------------------------------------------------+-------------------+ | --sectors | 1-4096 | Total Sectors | +-------------+---------------------------------------------------+-------------------+ | --seclen | 128/256/512/1024/2048/4096/8192/16384/32768/65536 | Sector Bytes | +-------------+---------------------------------------------------+-------------------+ TI99 Diskette (PC99 FM format) - (pc99fm) Driver specific options for module 'pc99fm': No image specific file options No image specific creation options TI99 Diskette (PC99 MFM format) - (pc99mfm) Driver specific options for module 'pc99mfm': No image specific file options No image specific creation options PC CHD disk image - (pc_chd) Driver specific options for module 'pc_chd': No image specific file options Image specific creation options (usable on the 'create' command): +-------------+------------------------------------------------------------------------+-------------+ | Option | Allowed values | Description | +-------------+------------------------------------------------------------------------+-------------+ | --cylinders | 10/20/30/40/50/60/70/80/90/100/110/120/130/140/150/160/170/180/190/200 | Cylinders | +-------------+------------------------------------------------------------------------+-------------+ | --heads | 1-16 | Heads | +-------------+------------------------------------------------------------------------+-------------+ | --sectors | 1-63 | Sectors | +-------------+------------------------------------------------------------------------+-------------+ PC floppy disk image (FAT format) - (pc_dsk_fat) Driver specific options for module 'pc_dsk_fat': No image specific file options Image specific creation options (usable on the 'create' command): +-----------+-----------------+-------------+ | Option | Allowed values | Description | +-----------+-----------------+-------------+ | --heads | 1-2 | Heads | +-----------+-----------------+-------------+ | --tracks | 40/80 | Tracks | +-----------+-----------------+-------------+ | --sectors | 8/9/10/15/18/36 | Sectors | +-----------+-----------------+-------------+ Psion Organiser II Datapack - (psionpack) Driver specific options for module 'psionpack': Image specific file options (usable on the 'put' command): +--------+----------------+-------------+ | Option | Allowed values | Description | +--------+----------------+-------------+ | --type | OB3/OPL/ODB | file type | +--------+----------------+-------------+ | --id | 0/145-255 | File ID | +--------+----------------+-------------+ Image specific creation options (usable on the 'create' command): +-----------+---------------------+---------------------+ | Option | Allowed values | Description | +-----------+---------------------+---------------------+ | --size | 8k/16k/32k/64k/128k | datapack size | +-----------+---------------------+---------------------+ | --ram | 0/1 | EPROM/RAM datapack | +-----------+---------------------+---------------------+ | --paged | 0/1 | linear/paged data- | | | | pack | +-----------+---------------------+---------------------+ | --protect | 0/1 | write-protected | | | | datapack | +-----------+---------------------+---------------------+ | --boot | 0/1 | bootable datapack | +-----------+---------------------+---------------------+ | --copy | 0/1 | copyable datapack | +-----------+---------------------+---------------------+ Teledisk floppy disk image (Basic Master Level 3 format) - (td0_bml3) Driver specific options for module 'td0_bml3': Image specific file options (usable on the 'put' command): +---------+----------------+-------------+ | Option | Allowed values | Description | +---------+----------------+-------------+ | --ftype | basic/data/bi- | File type | | | nary/assembler | | +---------+----------------+-------------+ | --ascii | ascii/binary | ASCII flag | +---------+----------------+-------------+ No image specific creation options Teledisk floppy disk image (FAT format) - (td0_fat) Driver specific options for module 'td0_fat': No image specific file options No image specific creation options Teledisk floppy disk image (Mac HFS Floppy) - (td0_mac_hfs) Driver specific options for module 'td0_mac_hfs': No image specific file options No image specific creation options Teledisk floppy disk image (Mac MFS Floppy) - (td0_mac_mfs) Driver specific options for module 'td0_mac_mfs': No image specific file options No image specific creation options Teledisk floppy disk image (OS-9 format) - (td0_os9) Driver specific options for module 'td0_os9': No image specific file options No image specific creation options Teledisk floppy disk image (ProDOS format) - (td0_prodos_35) Driver specific options for module 'td0_prodos_35': No image specific file options No image specific creation options Teledisk floppy disk image (ProDOS format) - (td0_prodos_525) Driver specific options for module 'td0_prodos_525': No image specific file options No image specific creation options Teledisk floppy disk image (RS-DOS format) - (td0_rsdos) Driver specific options for module 'td0_rsdos': Image specific file options (usable on the 'put' command): +---------+----------------+-------------+ | Option | Allowed values | Description | +---------+----------------+-------------+ | --ftype | basic/data/bi- | File type | | | nary/assembler | | +---------+----------------+-------------+ | --ascii | ascii/binary | ASCII flag | +---------+----------------+-------------+ No image specific creation options Teledisk floppy disk image (VZ-DOS format) - (td0_vzdos) Driver specific options for module 'td0_vzdos': Image specific file options (usable on the 'put' command): +---------+-------------------+-------------+ | Option | Allowed values | Description | +---------+-------------------+-------------+ | --ftype | basic/binary/data | File type | +---------+-------------------+-------------+ | --fname | intern/extern | Filename | +---------+-------------------+-------------+ No image specific creation options Thomson .fd disk image, BASIC format - (thom_fd) Driver specific options for module 'thom_fd': Image specific file options (usable on the 'put' command): +-----------+----------------+-------------+ | Option | Allowed values | Description | +-----------+----------------+-------------+ | --ftype | auto/B/D/M/A | File type | +-----------+----------------+-------------+ | --format | auto/B/A | Format flag | +-----------+----------------+-------------+ | --comment | (string) | Comment | +-----------+----------------+-------------+ Image specific creation options (usable on the 'create' command): +-----------+----------------+-------------+ | Option | Allowed values | Description | +-----------+----------------+-------------+ | --heads | 1-2 | Heads | +-----------+----------------+-------------+ | --tracks | 40/80 | Tracks | +-----------+----------------+-------------+ | --density | SD/DD | Density | +-----------+----------------+-------------+ | --name | (string) | Floppy name | +-----------+----------------+-------------+ Thomson .qd disk image, BASIC format - (thom_qd) Driver specific options for module 'thom_qd': Image specific file options (usable on the 'put' command): +-----------+----------------+-------------+ | Option | Allowed values | Description | +-----------+----------------+-------------+ | --ftype | auto/B/D/M/A | File type | +-----------+----------------+-------------+ | --format | auto/B/A | Format flag | +-----------+----------------+-------------+ | --comment | (string) | Comment | +-----------+----------------+-------------+ Image specific creation options (usable on the 'create' command): +-----------+----------------+-------------+ | Option | Allowed values | Description | +-----------+----------------+-------------+ | --heads | 1-2 | Heads | +-----------+----------------+-------------+ | --tracks | 25 | Tracks | +-----------+----------------+-------------+ | --density | SD/DD | Density | +-----------+----------------+-------------+ | --name | (string) | Floppy name | +-----------+----------------+-------------+ Thomson .sap disk image, BASIC format - (thom_sap) Driver specific options for module 'thom_sap': Image specific file options (usable on the 'put' command): +-----------+----------------+-------------+ | Option | Allowed values | Description | +-----------+----------------+-------------+ | --ftype | auto/B/D/M/A | File type | +-----------+----------------+-------------+ | --format | auto/B/A | Format flag | +-----------+----------------+-------------+ | --comment | (string) | Comment | +-----------+----------------+-------------+ Image specific creation options (usable on the 'create' command): +-----------+----------------+-------------+ | Option | Allowed values | Description | +-----------+----------------+-------------+ | --heads | 1 | Heads | +-----------+----------------+-------------+ | --tracks | 40/80 | Tracks | +-----------+----------------+-------------+ | --density | SD/DD | Density | +-----------+----------------+-------------+ | --name | (string) | Floppy name | +-----------+----------------+-------------+ TI990 Hard Disk - (ti990hd) Driver specific options for module 'ti990hd': No image specific file options Image specific creation options (usable on the 'create' command): +--------------------+-------------------+---------------------+ | Option | Allowed values | Description | +--------------------+-------------------+---------------------+ | --cylinders | 1-2047 | Cylinders | +--------------------+-------------------+---------------------+ | --heads | 1-31 | Heads | +--------------------+-------------------+---------------------+ | --sectors | 1-256 | Sectors | +--------------------+-------------------+---------------------+ | --bytes per sector | (typically | Bytes Per Sector | | | 25256-512 256-512 | [Todo: This section | | | | is glitched in img- | | | | tool] | +--------------------+-------------------+---------------------+ TI99 Diskette (old MESS format) - (ti99_old) Driver specific options for module 'ti99_old': No image specific file options Image specific creation options (usable on the 'create' command): +--------------+----------------+---------------------+ | Option | Allowed values | Description | +--------------+----------------+---------------------+ | --sides | 1-2 | Sides | +--------------+----------------+---------------------+ | --tracks | 1-80 | Tracks | +--------------+----------------+---------------------+ | --sectors | 1-36 | Sectors (1->9 for | | | | SD, 1->18 for DD, | | | | 1->36 for HD) | +--------------+----------------+---------------------+ | --protection | 0-1 | Protection (0 for | | | | normal, 1 for pro- | | | | tected) | +--------------+----------------+---------------------+ | --density | Auto/SD/DD/HD | Density | +--------------+----------------+---------------------+ TI99 Harddisk - (ti99hd) Driver specific options for module 'ti99hd': No image specific file options No image specific creation options TI99 Diskette (V9T9 format) - (v9t9) Driver specific options for module 'v9t9': No image specific file options Image specific creation options (usable on the 'create' command): +--------------+----------------+---------------------+ | Option | Allowed values | Description | +--------------+----------------+---------------------+ | --sides | 1-2 | Sides | +--------------+----------------+---------------------+ | --tracks | 1-80 | Tracks | +--------------+----------------+---------------------+ | --sectors | 1-36 | Sectors (1->9 for | | | | SD, 1->18 for DD, | | | | 1->36 for HD) | +--------------+----------------+---------------------+ | --protection | 0-1 | Protection (0 for | | | | normal, 1 for pro- | | | | tected) | +--------------+----------------+---------------------+ | --density | Auto/SD/DD/HD | Density | +--------------+----------------+---------------------+ Laser/VZ disk image (VZ-DOS format) - (vtech1_vzdos) Driver specific options for module 'vtech1_vzdos': Image specific file options (usable on the 'put' command): +---------+-------------------+-------------+ | Option | Allowed values | Description | +---------+-------------------+-------------+ | --ftype | basic/binary/data | File type | +---------+-------------------+-------------+ | --fname | intern/extern | Filename | +---------+-------------------+-------------+ Image specific creation options (usable on the 'create' command): +-----------------+----------------+--------------+ | Option | Allowed values | Description | +-----------------+----------------+--------------+ | --heads | 1 | Heads | +-----------------+----------------+--------------+ | --tracks | 40 | Tracks | +-----------------+----------------+--------------+ | --sectors | 16 | Sectors | +-----------------+----------------+--------------+ | --sectorlength | 154 | Sector Bytes | +-----------------+----------------+--------------+ | --firstsectorid | 0 | First Sector | +-----------------+----------------+--------------+ [todo: fill out the command structures, describe commands better. These descriptions came from the imgtool.txt file and are barebones] Castool - A generic cassette image manipulation tool for MAME Castool is a tool for the maintenance and manipulation of cassette im- ages that MAME users need to deal with. MAME directly supports .WAV au- dio formatted images, but many of the existing images out there may come in forms such as .TAP for Commodore 64 tapes, .CAS for Tandy Color Computer tapes, and so forth. Castool will convert these other formats to .WAV for use in MAME. Castool is part of the MAME project. It shares large portions of code with MAME, and its existence would not be if it were not for MAME. As such, the distribution terms are the same as MAME. Please read the MAME license thoroughly. Using Castool Castool is a command line program that contains a simple set of in- structions. Commands are invoked in a manner along the lines of this: castool convert <format> <inputfile> <outputfile> • <format> is the format of the image • <inputfile> is the filename of the image you're converting from • <outputfile> is the filename of the output WAV file Example usage: castool convert coco zaxxon.cas zaxxon.wav castool convert cbm arkanoid.tap arkanoid.wav castool convert ddp mybasicprogram.ddp mybasicprogram.wav Castool Formats These are the formats supported by Castool for conversion to .WAV files. A26 Atari 2600 SuperCharger image File extension: a26 APF APF Imagination Machine File extensions: cas, cpf, apt ATOM Acorn Atom File extensions: tap, csw, uef BBC Acorn BBC & Electron File extensions: csw, uef CBM Commodore 8-bit series File extensions: tap CDT Amstrad CPC File extensions: cdt CGENIE EACA Colour Genie File extensions: cas COCO Tandy Radio Shack Color Computer File extensions: cas CSW Compressed Square Wave File extensions: csw DDP Coleco ADAM File extensions: ddp FM7 Fujitsu FM-7 File extensions: t77 FMSX MSX File extensions: tap, cas GTP Elektronika inzenjering Galaksija File extensions: gtp HECTOR Micronique Hector & Interact Family Computer File extensions: k7, cin, for JUPITER Jupiter Cantab Jupiter Ace File extensions: tap KC85 VEB Mikroelektronik KC 85 File extensions: kcc, kcb, tap, 853, 854, 855, tp2, kcm, sss KIM1 MOS KIM-1 File extensions: kim, kim1 LVIV PK-01 Lviv File extensions: lvt, lvr, lv0, lv1, lv2, lv3 MO5 Thomson MO-series File extensions: k5, k7 MZ Sharp MZ-700 File extensions: m12, mzf, mzt ORAO PEL Varazdin Orao File extensions: tap ORIC Tangerine Oric File extensions: tap PC6001 NEC PC-6001 File extensions: cas PHC25 Sanyo PHC-25 File extensions: phc PMD85 Tesla PMD-85 File extensions: pmd, tap, ptp PRIMO Microkey Primo File extensions: ptp RKU UT-88 File extensions: rku RK8 Mikro-80 File extensions: rk8 RKS Specialist File extensions: rks RKO Orion File extensions: rko RKR Radio-86RK File extensions: rk, rkr, gam, g16, pki RKA Zavod BRA Apogee BK-01 File extensions: rka RKM Mikrosha File extensions: rkm RKP SAM SKB VM Partner-01.01 File extensions: rkp SC3000 Sega SC-3000 File extensions: bit SOL20 PTC SOL-20 File extensions: svt SORCERER Exidy Sorcerer File extensions: tape SORDM5 Sord M5 File extensions: cas SPC1000 Samsung SPC-1000 File extensions: tap, cas SVI Spectravideo SVI-318 & SVI-328 File extensions: cas TO7 Thomson TO-series File extensions: k7 TRS8012 TRS-80 Level 2 File extensions: cas TVC64 Videoton TVC 64 File extensions: cas TZX Sinclair ZX Spectrum File extensions: tzx, tap, blk VG5K Philips VG 5000 File extensions: k7 VTECH1 Video Technology Laser 110-310 File extensions: cas VTECH2 Video Technology Laser 350-700 File extensions: cas X07 Canon X-07 File extensions: k7, lst, cas X1 Sharp X1 File extensions: tap ZX80_O Sinclair ZX80 File extensions: o, 80 ZX81_P Sinclair ZX81 File extensions: p, 81 Floptool - A generic floppy image manipulation tool for MAME Floptool is a tool for the maintenance and manipulation of floppy im- ages that MAME users need to deal with. MAME directly supports .WAV au- dio formatted images, but many of the existing images out there may come in forms such as .TAP for Commodore 64 tapes, .CAS for Tandy Color Computer tapes, and so forth. Castool will convert these other formats to .WAV for use in MAME. Floptool is part of the MAME project. It shares large portions of code with MAME, and its existence would not be if it were not for MAME. As such, the distribution terms are the same as MAME. Please read the MAME license thoroughly. Using Floptool Floptool is a command line program that contains a simple set of in- structions. Commands are invoked in a manner along the lines of this: floptool identify <inputfile> [<inputfile> ...] floptool convert [input_format|auto] output_format <inputfile> <outputile> • <format> is the format of the image • <input_format> is the format of the inputfile, use auto if not known • <output_format> is the format of the converted file • <inputfile> is the filename of the image you're identifying/convert- ing from • <outputfile> is the filename of the converted file Example usage: floptool convert coco zaxxon.cas zaxxon.wav floptool convert cbm arkanoid.tap arkanoid.wav floptool convert ddp mybasicprogram.ddp mybasicprogram.wav Floptool Formats These are the formats supported by Floptool for conversion to other formats. MFI MAME floppy image File extension: mfi DFI DiscFerret flux dump format File extensions: dfi IPF SPS floppy disk image File extensions: ipf MFM HxC Floppy Emulator floppy disk image File extensions: mfm ADF Amiga ADF floppy disk image File extensions: adf ST Atari ST floppy disk image File extensions: st MSA Atari MSA floppy disk image File extensions: msa PASTI Atari PASTI floppy disk image File extensions: stx DSK CPC DSK format File extensions: dsk D88 D88 disk image File extensions: d77, d88, 1dd IMD IMD disk image File extensions: imd TD0 Teledisk disk image File extensions: td0 CQM CopyQM disk image File extensions: cqm, cqi, dsk PC PC floppy disk image File extensions: dsk, ima, img, ufi, 360 NASLITE NASLite disk image File extensions: img DC42 DiskCopy 4.2 image File extensions: dc42 A2_16SECT Apple II 16-sector disk image File extensions: dsk, do, po A2_RWTS18 Apple II RWTS18-type image File extensions: rti A2_EDD Apple II EDD image File extensions: edd ATOM Acorn Atom disk image File extensions: 40t, dsk SSD Acorn SSD disk image File extensions: ssd, bbc, img DSD Acorn DSD disk image File extensions: dsd DOS Acorn DOS disk image File extensions: img ADFS_O Acorn ADFS (OldMap) disk image File extensions: adf, ads, adm, adl ADFS_N Acorn ADFS (NewMap) disk image File extensions: adf ORIC_DSK Oric disk image File extensions: dsk APPLIX Applix disk image File extensions: raw HPI HP9845A floppy disk image File extensions: hpi Other tools included with MAME ledutil.exe/ledutil.sh On Microsoft Windows, ledutil.exe can take control of your keyboard LEDs to mirror those that were present on some early arcade games (e.g. Asteroids) Start ledutil.exe from the command line to enable LED handling. Run ledutil.exe -kill to stop the handler. On SDLMAME platforms such as Mac OS X and Linux, ledutil.sh can be used. Use ledutil.sh -a to have it automatically close when you exit SDLMAME. Developer-focused tools included with MAME pngcmp This tool is used in regression testing to compare PNG screenshot re- sults with the runtest.cmd script found in the source archive. This script works only on Microsoft Windows. nltool Discrete component conversion tool. nlwav Discrete component conversion and testing tool. jedutil PAL/PLA/PLD/GAL dump handling tool. It can convert between the indus- try-standard JED format and MAME's proprietary packed binary format and it can show logic equations for the types of devices it knows the in- ternal logic of. ldresample This tool recompresses video data for laserdisc and VHS dumps. ldverify This tool is used for comparing laserdisc or VHS CHD images with the source AVI. romcmp This tool is used to perform basic data comparisons and integrity checks on binary dumps. With the -h switch, it can also be used to cal- culate hash functions. unidasm Universal disassembler for many of the architectures supported in MAME. CONTRIBUTING TO MAME So you want to contribute to MAME but arent sure where to start? Well the great news is that theres always plenty to do for people with a va- riety of skill sets. Testing and reporting bugs One thing MAME can always do with is more testing and bug reports. If youre familiar with a system that MAME emulates and notice something wrong, or if you find a bug in MAMEs user interface, you can head over to MAME Testers and, assuming it isnt already reported, register an ac- count and open an issue. Be sure to read the FAQ and rules first to ensure you start out on the right foot. Please note that MAME Testers only accepts user-facing bugs in tagged release versions. For other kinds of issues, we have GitHub Issues. Theres a bit more leeway here. For example we accept developer-facing issues (e.g. bugs in internal APIs, or build system inadequacies), feature requests, and major regressions before they make it into a released version. Please respect the fact that the issue tracker is not a discussion or support forum, its only for reporting reproducible issues. Dont open issues to ask questions or request support. Also, keep in mind that the master branch is unstable. If the current revision doesnt compile at all or is completely broken, were probably already aware of it and dont need issues opened for that. Wait a while and see if theres an update. You might want to comment on the commit in question with the compiler error message, particularly if youre compiling in an unorthodox but supported configuration. When opening an issue, remember to provide as much information as pos- sible to help others understand, reproduce, and diagnose the issue. Things that are helpful to include: • The incorrect behaviour, and expected or correct behaviour. Be spe- cific: just saying it doesnt work usually isnt enough detail. • Environment details, including your operating system, CPU architec- ture, system locale, and display language, if applicable. For video output bugs, note your video hardware (GPU), driver version, and the MAME video output module youre using. For input handling bugs, in- clude the input peripherals and MAME input modules youre using. • The exact version of MAME youre using, including a git commit digest if it isnt a tagged release version, and any non-standard build op- tions. • The exact system and software being emulated (may not be applicable for issues with parts of MAMEs UI, like the system selection menu). Include things like the selected BIOS version, and emulated periph- eral (slot device) configuration. • Steps to reproduce the issue. Assume the person reading is familiar with MAME itself, but not necessarily familiar with the emulated sys- tem and software in question. For emulation issues, input recordings and/or saved state files for reproducing the issue can be invaluable. • An original reference for the correct behaviour. If you have access to the original hardware for the emulated system, it helps to make a recording of the correct behaviour for comparison. Contributing to MAMEs source code MAME itself is written in C++, but that isnt the sum total of the source code. The source code also includes: • The documentation hosted on this site (and also included in releases as a PDF), written in reStructuredText markup. • The supplied plugins, written in Lua 5.3. • Internal layouts for emulated machines that need to display more than a simple video screen. These are an XML application described here. • The software lists, describing known software media for systems that MAME emulates. MAME software lists are an XML application. • The user interface translations, in GNU gettext PO format. They can be edited with a good text editor, or a dedicated tool like Poedit. Our primary source code repository is hosted on GitHub. We prefer to receive source code contributions in the form of pull requests. Youll need to learn the basics of git distributed version control and famil- iarise yourself with the git tools. The basic process for creating a pull request is as follows: • Sign up for an account on GitHub. • Create a fork of the mamedev/mame repository. • Create a new branch off the master branch in your forked repository. • Clone your forked repository, and check out your new branch. • Make your changes, and build and test them locally. • Commit your changes, and push your branch to GitHub. • Optionally enable GitHub Actions for your forked repository, allowing your changes to be built on Windows, macOS and Linux. • Open a pull request to merge your changes into the master branch in the mamedev/mame repository. Please keep the following in mind (note that not all points are rele- vant to all kinds of changes): • Make your commit messages descriptive. Please include what the change affects, and what its supposed to achieve. A person reading the commit log shouldnt need to resort to examining the diff to get a basic idea of what a commit is supposed to do. The default commit messages provided by GitHub are completely useless, as they dont give any indication of what a change is supposed to do. • Test your changes. Ensure that a full build of MAME completes, and that the code you changed works. Its a good idea to build with DE- BUG=1 to check that assertions compile and dont trigger. • Use an enlightening pull request title and description. The title should give a one-line summary of what the overall change affects and what its supposed to do. The description should contain more detail. Dont leave the description empty and describe the change in comments, as this makes searching and filtering more difficult. • Be aware that GitHub Actions has opaque resource limits. It isnt clear when youre close to the limits, and weve had contributors banned from GitHub Actions for violating the limits. Even if you ap- peal the ban, they still wont tell you what the actual limits are, justifying this by saying that if you know the limits, you can take steps to evade them. If you enable GitHub Actions, consider not pushing individual commits if you dont need them to be automatically built, or cancelling workflow runs when you dont need the results. • If your submission is a computer or other device such as a synthe- sizer or sampler which requires a disk, tape, cartridge, or other me- dia to start up and run, please consider creating a software list containing at least one example of that media. This helps everyone making changes to shared MAME components to easily verify if the changes negatively impact your code. • When submitting any new non-arcade machine, but especially a machine which does not auto-boot and requires some interaction to start up and be usable, consider adding usage instructions to the System-Specific Setup and Information page of the MAME Wiki. Anyone can edit the wiki after creating an account, and sub-pages for your system which discuss technical details of the system are also wel- come. We have guidelines for specific parts of the source: C++ Coding Guidelines • Introduction • Definitions • Source file format • Naming conventions • Variables and literals • Bracing and indentation • Spacing • Scoping • Const Correctness • Comments • MAME-Specific Helpers • Logging • Structural organization Introduction In terms of coding conventions, the style present within an existing source file should be favoured over the standards found below. When a new source file is being created, the following coding conven- tions should be observed if creating a new file within the MAME core (src/emu and src/lib). If the source file is outside the core, defer- ence can be given to a contributors preferred style, although it is strongly encouraged to code with the understanding that the file may need to be comprehensible by more than one person as time marches for- ward. Definitions Snake case All lowercase letters with words separated by underscores: this_is_snake_case Screaming snake case All uppercase letters with words separated by underscores: SCREAMING_SNAKE_CASE Camel case: Lowercase initial letter, first letter of each subsequent word capitalised, with no separators between words: exampleCamelCase Llama case: Uppercase initial letter, first letter of each subsequent word capitalised, with no separators between words: LlamaCaseSample Source file format MAME C++ source files are encoded as UTF-8 text, assuming fixed-width characters, with tab stops at four-space intervals. Source files should end with a terminating end-of-line. Any valid printable Unicode text is permitted in comments. Outside comments and strings, only the printable ASCII subset of Unicode is permitted. The srcclean tool is used to enforce file format rules before each re- lease. You can build this tool and apply it to the files you modify before opening a pull request to avoid conflicts or surprising changes later. Naming conventions Preprocessor macros Macro names should use screaming snake case. Macros are always global and name conflicts can cause confusing errors think carefully about what macros really need to be in headers and name them carefully. Include guards Include guard macros should begin with MAME_, and end with a capitalised version of the file name, with separators replaced by underscores. Constants Constants should use screaming snake case, whether they are con- stant globals, constant data members, enumerators or preproces- sor constants. Functions Free functions names should use snake case. (There are some utility function that were previously implemented as preproces- sor macros that still use screaming snake case.) Classes Class names should use snake case. Abstract class names should end in _base. Public member functions (including static member functions) should use snake case. Device classes Concrete driver driver_device implementation names convention- ally end in _state, while other concrete device class names end in _device. Concrete device_interface names conventionally be- gin with device_ and end with _interface. Device types Device types should use screaming snake case. Remember that de- vice types are names in the global namespace, so choose ex- plicit, unambiguous names. Enumerations The enumeration name should use snake case. The enumerators should use screaming snake case. Template parameters Template parameters should use llama case (both type and value parameters). Identifiers containing two consecutive underscores or starting with an underscore followed by an uppercase letter are always reserved and should not be used. Type names and other identifiers with a leading underscore should be avoided within the global namespace, as they are explicitly reserved according to the C++ standard. Additionally, identifiers suffixed with _t should be avoided within the global namespace, as they are also re- served according to POSIX standards. While MAME violates this policy occasionally most notably with device_t its considered to be an un- fortunate legacy decision that should be avoided in any new code. Variables and literals Octal literals are discouraged from use outside of specific cases. They lack the obvious letter-based prefixes found in hexadecimal and binary literals, and therefore can be difficult to distinguish at a glance from a decimal literal to coders who are unfamiliar with octal notation. Lower-case hexadecimal literals are preferred, e.g. 0xbadc0de rather than 0xBADC0DE. For clarity, try not to exceed the bit width of the variable which will be used to store it. Binary literals have rarely been used in the MAME source code due to the 0b prefix not being standardised until C++14, but there is no pol- icy to avoid their use. Integer suffix notation should be used when specifying 64-bit literals, but is not strictly required in other cases. It can, however, clarify the intended use of a given literal at a glance. Uppercase long inte- ger literal suffixes should be used to avoid confusion with the digit 1, e.g. 7LL rather than 7ll. Digit grouping should be used for longer numeric literals, as it aids in recognising order of magnitude or bit field positions at a glance. Decimal literals should use groups of three digits, and hexadecimal literals should use groups of four digits, outside of specific situa- tions where different grouping would be easier to understand, e.g. 4'433'619 or 0xfff8'1fff. Types that do not have a specifically defined size should be avoided if they are to be registered with MAMEs save-state system, as it harms portability. In general, this means avoiding the use of int for these members. It's encouraged, but not required, for class data members to be pre- fixed with m_ for non-static instance members and s_ for static mem- bers. This does not apply to nested classes or structs. Bracing and indentation Tabs are used for initial indentation of lines, with one tab used per nested scope level. Statements split across multiple lines should be indented by two tabs. Spaces are used for alignment at other places within a line. Either K&R or Allman-style bracing is preferred. There is no specific preference for bracing on single-line statements, although bracing should be consistent for a given if/else block, as shown: if (x == 0) { return; } else { call_some_function(); x--; } When using a series of if/else or if/else if/else blocks with comments at the top indentation level, avoid extraneous newlines. The use of additional newlines may lead to else if or else blocks being missed due to the newlines pushing the blocks outside the visible editor height: // Early-out if our hypothetical counter has run out. if (x == 0) { return; } // We should do something if the counter is running. else { call_some_function(); x--; } Indentation for case statements inside a switch body can either be on the same level as the switch statement or inward by one level. There is no specific style which is used across all core files, although in- denting by one level appears to be used most often. Spacing Consistent single-spacing between binary operators, variables, and lit- erals is strongly preferred. The following examples exhibit reasonably consistent spacing: uint8_t foo = (((bar + baz) + 3) & 7) << 1; uint8_t foo = ((bar << 1) + baz) & 0x0e; uint8_t foo = bar ? baz : 5; The following examples exhibit extremes in either direction, although having extra spaces is less difficult to read than having too few: uint8_t foo = ( ( ( bar + baz ) + 3 ) & 7 ) << 1; uint8_t foo = ((bar<<1)+baz)&0x0e; uint8_t foo = (bar?baz:5); A space should be used between a fundamental C++ statement and its opening parenthesis, e.g.: switch (value) ... if (a != b) ... for (int i = 0; i < foo; i++) ... Scoping Variables should be scoped as narrowly as is reasonably possible. There are many instances of C89-style local variable declaration in the MAME codebase, but this is largely a hold-over from MAMEs early days, which pre-date the C99 specification. The following two snippets exhibit the legacy style of local variable declaration, followed by the more modern and preferred style: void example_device::some_function() { int i; uint8_t data; for (i = 0; i < std::size(m_buffer); i++) { data = m_buffer[i]; if (data) { some_other_function(data); } } } void example_device::some_function() { for (int i = 0; i < std::size(m_buffer); i++) { const uint8_t data = m_buffer[i]; if (data) { some_other_function(data); } } } Enumerated values, structs, and classes used only by one specific de- vice should be declared within the device's class itself. This avoids pollution of the global namespace and makes the device-specific use of them more obvious at a glance. Const Correctness Const-correctness has not historically been a strict requirement of code that goes into MAME, but theres increasing value in it as the amount of code refactoring increases and technical debt decreases. When writing new code, its worth taking the time to determine if a lo- cal variable can be declared const. Similarly, it's encouraged to con- sider which member functions of a new class can be const qualified. In a similar vein, arrays of constants should be declared constexpr and should use screaming snake case, as outlined towards the top of this document. Lastly, arrays of C-style strings should be declared as both a const array of const strings, as so: static const char *const EXAMPLE_NAMES[4] = { "1-bit", "2-bit", "4-bit", "Invalid" }; Comments While /* ANSI C comments */ are often found in the codebase, there has been a gradual shift towards // C++-style comments for single-line com- ments. This is very much a guideline, and coders are encouraged to use whichever style is most comfortable. Unless specifically quoting content from a machine or ancillary materi- als, comments should be in English so as to match the predominant lan- guage that the MAME team shares worldwide. Commented-out code should typically be removed prior to authoring a pull request, as it has a tendency to rot due to the fast-moving nature of MAMEs core API. If there is a desire known beforehand for the code to eventually be included, it should be bookended in if (0) or if (false), as code removed through a preprocessor macro will rot at the same rate. MAME-Specific Helpers When at all possible, use helper functions and macros for bit manipula- tion operations. The BIT(value, bit) helper can be used to extract the state of a bit at a given position from an integer value. The resulting value will be aligned to the least significant bit position, i.e. will be either 0 or 1. An overload of the same function, BIT(value, bit, width) can be used to extract a bit field of a specified width from an integer value, start- ing at the specified bit position. The result will also be right-jus- tified and will be of the same type as the incoming value. There are, additionally, a number of helpers for functionality such as counting leading zeroes/ones, population count, and signed/unsigned in- teger multiplication and division for both 32-bit and 64-bit results. Not all of these helpers have wide use in the MAME codebase, but using them in new code is strongly preferred when that code is performance- critical, as they utilise inline assembly or compiler intrinsics per- platform when available. count_leading_zeros_32/64(T value) Accepts an unsigned 32/64-bit value and returns an unsigned 8-bit value containing the number of consecutive zeros starting from the most significant bit. count_leading_ones_32/64(T value) Same functionality as above, but examining consecutive one-bits. population_count_32/64(T value) Accepts an unsigned 32/64-bit value and returns the number of one-bits found, i.e. the Hamming weight of the value. rotl_32/64(T value, int shift) Performs a circular/barrel left shift of an unsigned 32/64-bit value with the specified shift value. The shift value will be masked to the valid bit range for a 32-bit or 64-bit value. rotr_32/64(T value, int shift) Same functionality as above, but with a right shift. For documentation on helpers related to multiplication and division, refer to src/osd/eminline.h. Logging MAME has multiple logging function for different purposes. Two of the most frequently used logging functions are logerror and osd_printf_ver- bose: • Devices inherit a logerror member function. This automatically in- cludes the fully-qualified tag of the invoking device in log mes- sages. Output is sent to MAMEs debuggers rotating log buffer if the debugger is enabled. If the -log option is enabled, its also written to the file error.log in the working directory. If the -oslog option is enabled, its additionally sent to the OS diagnostic output (the host debugger diagnostic log on Windows if a host debugger is at- tached, or standard error otherwise). • The output of the osd_printf_verbose function is sent to standard er- ror if the -verbose option is enabled. The osd_printf_verbose function should be used for logging that is use- ful for diagnosing user issues, while logerror should be used for mes- sages more relevant to developers (either developing MAME itself, or developing software for emulated systems using MAMEs debugger). For debug logging, a channel-based logging system exists via the header logmacro.h. It can be used as a generic logging system as follows, without needing to make use of its ability to mask out specific chan- nels: // All other headers in the .cpp file should be above this line. #define VERBOSE (1) #include "logmacro.h" ... void some_device::some_reg_write(u8 data) { LOG("%s: some_reg_write: %02x\n", machine().describe_context(), data); } The above example also makes use of a helper function which is avail- able in all derivatives of device_t: machine().describe_context(). This function will return a string that describes the emulation context in which the function is being run. This includes the fully-qualified tag of the currently executing device (if any). If the relevant device implements device_state_interface, it will also include the current program-counter value reported by the device. For more fine-grained control, specific bit masks can be defined and used via the LOGMASKED macro: // All other headers in the .cpp file should be above this line. #define LOG_FOO (1 << 1U) #define LOG_BAR (1 << 2U) #define VERBOSE (LOG_FOO | LOG_BAR) #include "logmacro.h" ... void some_device::some_reg_write(u8 data) { LOGMASKED(LOG_FOO, "some_reg_write: %02x\n", data); } void some_device::another_reg_write(u8 data) { LOGMASKED(LOG_BAR, "another_reg_write: %02x\n", data); } Note that the least significant bit position for user-supplied masks is 1, as bit position 0 is reserved for LOG_GENERAL. By default, LOG and LOGMASKED will use the device-supplied logerror function. However, this can be redirected as desired. The most common use case would be to direct output to the standard output instead, which can be accomplished by explicitly defining LOG_OUTPUT_FUNC as so: #define LOG_OUTPUT_FUNC osd_printf_info A developer should always ensure that VERBOSE is set to 0 and that any definition of LOG_OUTPUT_FUNC is commented out prior to opening a pull request. Structural organization All C++ source files must begin with a two comments listing the distri- bution license and copyright holders in a standard format. Licenses are specified by their SPDX short identifier if available. Here is an example of the standard format: // license:BSD-3-Clause // copyright-holders:David Haywood, Tomasz Slanina Header includes should generally be grouped from most-dependent to least-dependent, and sorted alphabetically within said groups: • The project prefix header, emu.h, must be the first thing in a trans- lation unit • Local project headers (i.e. headers found in the same source direc- tory) • Headers in src/devices • Headers in src/emu • Headers in src/lib/formats • Headers in src/lib/util • Headers from the OSD layer • C++ standard library headers • C standard library headers • OS-specific headers • Layout headers Finally, task-specific headers such as logmacro.h - described in the previous section - should be included last. A practical example fol- lows: #include "emu.h" #include "cpu/m68000/m68000.h" #include "machine/mc68328.h" #include "machine/ram.h" #include "sound/dac.h" #include "video/mc68328lcd.h" #include "video/sed1375.h" #include "emupal.h" #include "screen.h" #include "speaker.h" #include "pilot1k.lh" #define VERBOSE (0) #include "logmacro.h" In most cases, the class declaration for a system driver should be within the corresponding source file along with the implementation. In such cases, the class declaration and all contents of the source file, excluding the GAME, COMP, or CONS macro, should be enclosed in an anonymous namespace (this produces better compiler diagnostics, allows more aggressive optimisation, reduces the chance of duplicate symbols, and reduces linking time). Within a class declaration, there should be one section for each member access level (public, protected and private) if practical. This may not be possible in cases where private constants and/or types need to be declared before public members. Members should use the least public access level necessary. Overridden virtual member functions should generally use the same access level as the corresponding member func- tion in the base class. Class member declarations should be grouped to aid understanding: • Within a member access level section, constants, types, data members, instance member functions and static member functions should be grouped. • In device classes, configuration member functions should be grouped separately from live signal member functions. • Overridden virtual member functions should be grouped according to the base classes they are inherited from. For classes with multiple overloaded constructors, constructor delega- tion should be used where possible to avoid repeated member initialiser lists. Constants which are used by a device or machine driver should be in the form of explicitly-sized enumerated values within the class declara- tion, or be relegated to #define macros within the source file. This helps avoid polluting the preprocessor. Guidelines for Software Lists • Introduction • Items and parts • Metadata Introduction MAMEs software lists describe known software media for emulated systems in a form that can be used to identify media image files for known software, verify media image file integrity, and load media image files for emulation. Software lists are implemented as XML files in the hash folder. The XML structure is described in the file hash/soft- warelist.dtd. Philosophically, software list items should represent the original me- dia, rather than a specific dump of the media. Ideally, it should be possible for anyone with the media to dump it and produce the same im- age file. Of course, this isnt always possible in practice in partic- ular its problematic for inherently analog media, like home computer software stored on audio tape cassettes. MAME strives to document the best available media images. It is not our intention to propagate corrupted, truncated, defaced, watermarked, or otherwise bad media images. Where possible, file structures match- ing the original media structure are preferred. For example we prefer individual files for separate ROM chips in cartridge media, and we use disk images rather than archives of files extracted from the original disks. Items and parts A software list is a collection of items and each item may have multi- ple parts. An item represents a piece of software, as distributed as a complete package. A part represents a single piece of media within the package. Parts can be mounted individually in emulated media devices. For example a piece of software distributed on three floppy disks will be a single item, while each floppy disk will be one part within that item. Sometimes, logically separate parts of a single physical piece of media are represented as separate parts within a software item. For example each side of an audio tape cassette is represented as a separate part. However individual ROM chips within a cartridge may be separate files, but they are not separate parts, as the cartridge is mounted as a whole. Each item is a software element. The software element may have the following attributes: name (required) The short name identifying the item. This is used for file names, command line arguments, database keys, URL fragments, and many other purposes. It should be terse but still recognisable. It must be unique within the software list. Valid characters are lowercase English letters, decimal digits and underscores. The maximum allowed length is sixteen characters. cloneof (optional) The short name of the parent item if the item is a clone. The parent must be within the same software list parent/clone rela- tionships spanning multiple software lists are not supported. supported (optional) One of the values yes (fully usable in emulation), no (not us- able in emulation), or partial (usable in emulation with limita- tions). If the attribute is not present, it is equivalent to yes. Examples of partially supported software include games that are playable with graphical glitches, and office software where some but not all functionality works. Each part is a part element within the software element. The part ele- ment must have the following attributes: name (required) The short name identifying the part. This is used for command line arguments, database keys, URL fragments, and many other purposes. It must be unique within the item. It is also used as the display name if a separate display name is not provided. Valid characters are lowercase English letters, decimal digits and underscores. The maximum allowed length is sixteen charac- ters. interface (required) This attribute is used to identify suitable emulated media de- vices for mounting the software part. Applicable values depend on the emulated system. Metadata Software lists support various kinds of metadata. All software list items require the following metadata elements to be present: description This is the primary display name for the software item. It should be the original name of the software, transliterated into English Latin script if necessary. It must be unique within the software list. If extra text besides the title itself is re- quired for disambiguation, use lowercase outside of proper nouns, initialisms and verbatim quotes. year The year of release or copyright year for the software. If un- known, use an estimate with a question mark. Items can be fil- tered by year in the software selection menu. publisher The publisher of the software. This may be the same as the de- veloper if the software was self-published. Items can be fil- tered by published in the software selection menu. Most user-visible software item metadata is provided using info ele- ments. Each info element must have a name attribute and a value at- tribute. The name attribute identifies the type of metadata, and the value attribute is the metadata value itself. Note that name attrib- utes do not need to be unique within an item. Multiple info elements with the same name may be present if appropriate. This is frequently seen for software sold using different titles in different regions. MAME displays metadata from info elements in the software selection menu. The following name attributes are recognised specifically, and can show localised names: alt_title Used for alternate titles. Examples are different tiles used in different languages, scripts or regions, or different titles used on the title screen and packaging. MAME searches alternate titles as well as the description. author Author of the software. Items can be filtered by author in the software selection menu. barcode Barcode number identifying the software package (typically an EAN). developer Developer responsible for implementing the software. Items can be filtered by developer in the software selection menu. distributor Party responsible for distributing the software to retailers (or customers in the case of direct sales). Items can be filtered by distributor in the software selection menu. install Installation instructions. isbn ISBN for software included with a commercial book. oem Original equipment manufacturer, typically used with customised versions of software distributed by a hardware vendor. original_publisher The original publisher, for items representing software re-re- leased by a different publisher. partno Distributors part number for the software. pcb Printed circuit board identifier, typically for cartridge media. programmer Programmer who wrote the code for the software. release Fine-grained release date for the software, if known. Use YYYYMMDD format with no punctuation. If only the month is known, use xx for the day digits. For example 199103xx or 19940729. serial Number identifying the software within a series of releases. usage Usage instructions. version Version number of the software. TECHNICAL SPECIFICATIONS This section covers technical specifications useful to programmers working on MAMEs source or working on scripts that run within the MAME framework. MAME Naming Conventions • Introduction • Transliteration • Titles and descriptions • C++ naming conventions Introduction To promote consistency and readability in MAME source code, we have some naming conventions for various elements. Transliteration For better or worse, the most broadly recognised script in the world is English Latin. Conveniently, its also included in almost all character encodings. To make MAME more globally accessible, we require Latin transliterations of titles and other metadata from other scripts. Do not use translations in metadata translations are inherently subjec- tive and error-prone. Translations may be included in comments if they may be helpful. If general, if an official Latin script name is known, it should be used in favour of a nave transliteration. For titles containing for- eign loanwords, the conventional Latin spelling should be used for the loanwords (the most obvious example of this is the use of Mahjong in Japanese titles rather than Maajan). Chinese Where the primary audience was Mandarin-speaking, Hanyu Pinyin should be used. In contexts where diacritics are not permitted (e.g. when limited to ASCII), tone numbers should be omitted. When tones are being indicated using diacritics, tone sandhi rules should be applied. Where the primary audience was Can- tonese-speaking (primarily Hong Kong and Guandong), Jyutping should be used with tone numbers omitted. If in doubt, use Hanyu Pinyin. Greek Use ISO 843:1997 type 2 (TR) rules. Do not use traditional Eng- lish spellings for Greek names (people or places). Japanese Modified Hepburn rules should generally be used. Use an apos- trophe between syllabic N and a following vowel (including io- tised vowels). Do not use hyphens to transliterate prolonged vowels. Korean Use Revised Romanisation of Korean (RR) rules with traditional English spelling for Korean surnames. Do not use ALA-LC rules for word division and use of hyphens. Vietnamese When diacritics cant be used, omit the tones and replace the vowels with single English vowels do not use VIQR or TELEX con- ventions (an chuot nuong rather than a(n chuo^.t nu*o*'ng or awn chuootj nuowngs). Titles and descriptions Try to reproduce the original title faithfully where possible. Try to preserve the case convention used by the manufacturer/publisher. If no official English Latin title is known, use a standard transliteration. For software list entries where a transliteration is used for the de- scription element, put the title in an info element with a name="alt_title" attribute. For software items that have multiple titles (for example different re- gional titles with the same installation media), use the most wide- spread English Latin title for the description element, and put the other titles in info elements with name="alt_title" attributes. If disambiguation is needed, try to be descriptive as possible. For example, use the manufacturers version number, regional licensees name, or terse description of hardware differences in preference to arbitrary set numbers. Surround the disambiguation text with parentheses, pre- serve original case for names and version text, but use lowercase for anything else besides proper nouns and initialisms. C++ naming conventions For C++ naming conventions, see the relevant section in the C++ Coding Guidelines: Naming conventions MAME Layout Files • Introduction • Core concepts • Numbers • Coordinates • Colours • Parameters • Pre-defined parameters • Parts of a layout • Elements • Views • Collections • Reusable groups • Repeating blocks • Interactivity • Clickable items • Element state • View item animation • Error handling • Automatically-generated views • Using complay.py • Example layout files Introduction Layout files are used to tell MAME what to display when running an emu- lated system, and how to arrange it. MAME can render emulated screens, images, text, shapes, and specialised objects for common output de- vices. Elements can be static, or dynamically update to reflect the state of inputs and outputs. Layouts may be automatically generated based on the number/type of emulated screens, built and linked into the MAME binary, or provided externally. MAME layout files are an XML ap- plication, using the .lay filename extension. Core concepts Numbers There are two kinds of numbers in MAME layouts: integers and float- ing-point numbers. Integers may be supplied in decimal or hexadecimal notation. A decimal integer consists of an optional # (hash) prefix, an optional +/- (plus or minus) sign character, and a sequence of digits 0-9. A hexadecimal number consists of one of the prefixes $ (dollar sign) or 0x (zero ex) followed by a sequence of hexadecimal digits 0-9 and A-F. Hexadecimal numbers are case-insensitive for both the prefix and digits. Floating-point numbers may be supplied in decimal fixed-point or scien- tific notation. Note that integer prefixes and hexadecimal values are not accepted where a floating-point number is expected. For a few attributes, both integers and floating-point numbers are al- lowed. In these cases, the presence of a # (hash), $ (dollar sign) or 0x (zero ex) prefix causes the value to be interpreted as an integer. If no recognised integer prefix is found and the value contains a deci- mal point or the letter E (uppercase or lowercase) introducing an expo- nent, it is interpreted as a floating-point number. If no integer pre- fix, decimal point or letter E is found, the number will be interpreted as an integer. Numbers are parsed using the "C" locale for portability. Coordinates Layout coordinates are internally represented as IEEE754 32-bit binary floating-point numbers (also known as single precision). Coordinates increase in the rightward and downward directions. The origin (0,0) has no particular significance, and you may freely use negative coordi- nates in layouts. Coordinates are supplied as floating-point numbers. MAME assumes that view coordinates have the same aspect ratio as pixels on the output device (host screen or window). Assuming square pixels and no rotation, this means equal distances in X and Y axes correspond to equal horizontal and vertical distances in the rendered output. Views, groups and elements all have their own internal coordinate sys- tems. When an element or group is referenced from a view or another group, its coordinates are scaled as necessary to fit the specified bounds. Objects are positioned and sized using bounds elements. The horizontal position and size may be specified in three ways: left edge and width using x and width attributes, horizontal centre and width using xc and width attributes, or left and right edges using left and right attrib- utes. Similarly, the vertical position and size may be specified in terms of the top edge and height using y and height attributes, verti- cal centre and height using yc and height attributes, or top and bottom edges using top and bottom attributes. These three bounds elements are equivalent: <bounds x="455" y="120" width="12" height="8" /> <bounds xc="461" yc="124" width="12" height="8" /> <bounds left="455" top="120" right="467" bottom="128" /> Its possible to use different schemes in the horizontal and vertical directions. For example, these equivalent bounds elements are also valid: <bounds x="455" top="120" width="12" bottom="128" /> <bounds left="455" yc="124" right="467" height="8" /> The width/height or right/bottom default to 1.0 if not supplied. It is an error if width or height are negative, if right is less than left, or if bottom is less than top. Colours Colours are specified in RGBA space. MAME is not aware of colour pro- files and gamuts, so colours will typically be interpreted as sRGB with your systems target gamma (usually 2.2). Channel values are specified as floating-point numbers. Red, green and blue channel values range from 0.0 (off) to 1.0 (full intensity). Alpha ranges from 0.0 (fully transparent) to 1.0 (opaque). Colour channel values are not pre-multi- plied by the alpha value. Component and view item colour is specified using color elements. Meaningful attributes are red, green, blue and alpha. This example color element specifies all channel values: <color red="0.85" green="0.4" blue="0.3" alpha="1.0" /> Any omitted channel attributes default to 1.0 (full intensity or opaque). It is an error if any channel value falls outside the range of 0.0 to 1.0 (inclusive). Parameters Parameters are named variables that can be used in most attributes. To use a parameter in an attribute, surround its name with tilde (~) char- acters. If a parameter is not defined, no substitution occurs. Here is an examples showing two instances of parameter use the values of the digitno and x parameters will be substituted for ~digitno~ and ~x~: <element name="digit~digitno~" ref="digit"> <bounds x="~x~" y="80" width="25" height="40" /> </element> A parameter name is a sequence of uppercase English letters A-Z, lower- case English letters a-z, decimal digits 0-9, and/or underscore (_) characters. Parameter names are case-sensitive. When looking for a parameter, the layout engine starts at the current, innermost scope and works outwards. The outermost scope level corresponds to the top-level mamelayout element. Each repeat, group or view element creates a new, nested scope level. Internally a parameter can hold a string, integer, or floating-point number, but this is mostly transparent. Integers are stored as 64-bit signed twos-complement values, and floating-point numbers are stored as IEEE754 64-bit binary floating-point numbers (also known as double pre- cision). Integers are substituted in decimal notation, and floating point numbers are substituted in default format, which may be decimal fixed-point or scientific notation depending on the value). There is no way to override the default formatting of integer and floating-point number parameters. There are two kinds of parameters: value parameters and generator para- meters. Value parameters keep their assigned value until reassigned. Generator parameters have a starting value and an increment and/or shift to be applied for each iteration. Value parameters are assigned using a param element with name and value attributes. Value parameters may appear inside the top-level mamelay- out element, inside repeat, and view elements, and inside group defini- tion elements (that is, group elements in the top-level mamelayout ele- ment, as opposed to group reference elements inside view elements other group definition elements). A value parameter may be reassigned at any point. Heres an example assigning the value 4 to the value parameter first- digit: <param name="firstdigit" value="4" /> Generator parameters are assigned using a param element with name and start attributes, and increment, lshift and/or rshift attributes. Gen- erator parameters may only appear inside repeat elements (see Repeating blocks for details). A generator parameter must not be reassigned in the same scope (an identically named parameter may be defined in a child scope). Here are some example generator parameters: <param name="nybble" start="3" increment="-1" /> <param name="switchpos" start="74" increment="156" /> <param name="mask" start="0x0800" rshift="4" /> • The nybble parameter generates values 3, 2, 1... • The switchpos parameter generates values 74, 230, 386... • The mask parameter generates values 2048, 128, 8... The increment attribute must be an integer or floating-point number to be added to the parameters value. The lshift and rshift attributes must be non-negative integers specifying numbers of bits to shift the parameters value to the left or right. The increment and shift are ap- plied at the end of the repeating block before the next iteration starts. The parameters value will be interpreted as an integer or floating-point number before the increment and/or shift are applied. If both an increment and shift are supplied, the increment is applied before the shift. If the increment attribute is present and is a floating-point number, the parameters value will be converted to a floating-point number if necessary before the increment is added. If the increment attribute is present and is an integer while the parameters value is a float- ing-point number, the increment will be converted to a floating-point number before the addition. If the lshift and/or rshift attributes are present and not equal, the parameters value will be converted to an integer if necessary, and shifted accordingly. Shifting to the left is defined as shifting to- wards the most significant bit. If both lshift and rshift are sup- plied, they are netted off before being applied. This means you can- not, for example, use equal lshift and rshift attributes to clear bits at one end of a parameters value after the first iteration. It is an error if a param element has neither value nor start attrib- utes, and it is an error if a param element has both a value attribute and any of the start, increment, lshift, or rshift attributes. A param element defines a parameter or reassigns its value in the cur- rent, innermost scope. It is not possible to define or reassign para- meters in a containing scope. Pre-defined parameters A number of pre-defined value parameters are available providing infor- mation about the running machine: devicetag The full tag path of the device that caused the layout to be loaded, for example : for the root driver device, or :tty:ie15 for a terminal connected to a port. This parameter is a string defined at layout (global) scope. devicebasetag The base tag of the device that caused the layout to be loaded, for example root for the root driver device, or ie15 for a ter- minal connected to a port. This parameter is a string defined at layout (global) scope. devicename The full name (description) of the device that caused the layout to be loaded, for example AIM-65/40 or IE15 Terminal. This pa- rameter is a string defined at layout (global) scope. deviceshortname The short name of the device that caused the layout to be loaded, for example aim65_40 or ie15_terminal. This parameter is a string defined at layout (global) scope. scr0physicalxaspect The horizontal part of the physical aspect ratio of the first screen (if present). The physical aspect ratio is provided as a reduced improper fraction. Note that this is the horizontal component before rotation is applied. This parameter is an in- teger defined at layout (global) scope. scr0physicalyaspect The vertical part of the physical aspect ratio of the first screen (if present). The physical aspect ratio is provided as a reduced improper fraction. Note that this is the vertical com- ponent before rotation is applied. This parameter is an integer defined at layout (global) scope. scr0nativexaspect The horizontal part of the pixel aspect ratio of the first screens visible area (if present). The pixel aspect ratio is provided as a reduced improper fraction. Note that this is the horizontal component before rotation is applied. This parameter is an integer defined at layout (global) scope. scr0nativeyaspect The vertical part of the pixel aspect ratio of the first screens visible area (if present). The pixel aspect ratio is provided as a reduced improper fraction. Note that this is the vertical component before rotation is applied. This parameter is an in- teger defined at layout (global) scope. scr0width The width of the first screens visible area (if present) in emu- lated pixels. Note that this is the width before rotation is applied. This parameter is an integer defined at layout (global) scope. scr0height The height of the first screens visible area (if present) in em- ulated pixels. Note that this is the height before rotation is applied. This parameter is an integer defined at layout (global) scope. scr1physicalxaspect The horizontal part of the physical aspect ratio of the second screen (if present). This parameter is an integer defined at layout (global) scope. scr1physicalyaspect The vertical part of the physical aspect ratio of the second screen (if present). This parameter is an integer defined at layout (global) scope. scr1nativexaspect The horizontal part of the pixel aspect ratio of the second screens visible area (if present). This parameter is an integer defined at layout (global) scope. scr1nativeyaspect The vertical part of the pixel aspect ratio of the second screens visible area (if present). This parameter is an integer defined at layout (global) scope. scr1width The width of the second screens visible area (if present) in em- ulated pixels. This parameter is an integer defined at layout (global) scope. scr1height The height of the second screens visible area (if present) in emulated pixels. This parameter is an integer defined at layout (global) scope. scrNphysicalxaspect The horizontal part of the physical aspect ratio of the (zero-based) Nth screen (if present). This parameter is an in- teger defined at layout (global) scope. scrNphysicalyaspect The vertical part of the physical aspect ratio of the (zero-based) Nth screen (if present). This parameter is an in- teger defined at layout (global) scope. scrNnativexaspect The horizontal part of the pixel aspect ratio of the (zero-based) Nth screens visible area (if present). This para- meter is an integer defined at layout (global) scope. scrNnativeyaspect The vertical part of the pixel aspect ratio of the (zero-based) Nth screens visible area (if present). This parameter is an in- teger defined at layout (global) scope. scrNwidth The width of the (zero-based) Nth screens visible area (if present) in emulated pixels. This parameter is an integer de- fined at layout (global) scope. scrNheight The height of the (zero-based) Nth screens visible area (if present) in emulated pixels. This parameter is an integer de- fined at layout (global) scope. viewname The name of the current view. This parameter is a string de- fined at view scope. It is not defined outside a view. For screen-related parameters, screens are numbered from zero in the order they appear in machine configuration, and all screens are in- cluded (not just subdevices of the device that caused the layout to be loaded). X/width and Y/height refer to the horizontal and vertical di- mensions of the screen before rotation is applied. Values based on the visible area are calculated at the end of configuration. Values are not updated and layouts are not recomputed if the system reconfigures the screen while running. Parts of a layout A view specifies an arrangement graphical object to display. A MAME layout file can contain multiple views. Views are built up from ele- ments and screens. To simplify complex layouts, reusable groups and repeating blocks are supported. The top-level element of a MAME layout file must be a mamelayout ele- ment with a version attribute. The version attribute must be an inte- ger. Currently MAME only supports version 2, and will not load any other version. This is an example opening tag for a top-level mamelay- out element: <mamelayout version="2"> In general, children of the top-level mamelayout element are processed in reading order from top to bottom. The exception is that, for his- torical reasons, views are processed last. This means views see the final values of all parameters at the end of the mamelayout element, and may refer to elements and groups that appear after them. The following elements are allowed inside the top-level mamelayout ele- ment: param Defines or reassigns a value parameter. See Parameters for de- tails. element Defines an element one of the basic objects that can be arranged in a view. See Elements for details. group Defines a reusable group of elements/screens that may be refer- enced from views or other groups. See Reusable groups for de- tails. repeat A repeating group of elements may contain param, element, group, and repeat elements. See Repeating blocks for details. view An arrangement of elements and/or screens that can be displayed on an output device (a host screen/window). See Views for de- tails. script Allows Lua script to be supplied for enhanced interactive lay- outs. See MAME Layout Scripting for details. Elements Elements are one of the basic visual objects that may be arranged, along with screens, to make up a view. Elements may be built up of one or more components, but an element is treated as a single surface when building the scene graph and rendering. An element may be used in mul- tiple views, and may be used multiple times within a view. An elements appearance depends on its state. The state is an integer which usually comes from an I/O port field or an emulated output (see Element state for information on connecting an element to an emulated I/O port or output). Any component of an element may be restricted to only drawing when the elements state is a particular value. Some com- ponents (e.g. multi-segment displays) use the state directly to deter- mine their appearance. Each element has its own internal coordinate system. The bounds of the elements coordinate system are computed as the union of the bounds of the individual components its composed of. Every element must have a name attribute specifying its name. Elements are referred to by name when instantiated in groups or views. It is an error for a layout file to contain multiple elements with identical name attributes. Elements may optionally supply a default state value with a defstate attribute, to be used if not connected to an emulated output or I/O port. If present, the defstate attribute must be a non-negative integer. Child elements of the element element instantiate components, which are drawn into the element texture in reading order from first to last us- ing alpha blending (components draw over and may obscure components that come before them). All components support a few common features: • Components may be conditionally drawn depending on the elements state by supplying state and/or statemask attributes. If present, these attributes must be non-negative integers. If only the state at- tribute is present, the component will only be drawn when the ele- ments state matches its value. If only the statemask attribute is present, the component will only be drawn when all the bits that are set in its value are set in the elements state. If both the state and statemask attributes are present, the component will only be drawn when the bits in the elements state corresponding to the bits that are set in the statemask attributes value match the value of the corresponding bits in the state attributes value. (The component will always be drawn if neither state nor statemask attributes are present, or if the statemask attributes value is zero.) • Each component may have a bounds child element specifying its posi- tion and size (see Coordinates). If no such element is present, the bounds default to a unit square (width and height of 1.0) with the top left corner at (0,0). A components position and/or size may be animated according to the elements state by supplying multiple bounds child elements with state attributes. The state attribute of each bounds child element must be a non-negative integer. The state attributes must not be equal for any two bounds elements within a component. If the elements state is lower than the state value of any bounds child element, the position/size specified by the bounds child ele- ment with the lowest state value will be used. If the elements state is higher than the state value of any bounds child element, the posi- tion/size specified by the bounds child element with the highest state value will be used. If the elements state is between the state values of two bounds child elements, the position/size will be inter- polated linearly. • Each component may have a color child element specifying an RGBA colour (see Colours for details). This can be used to control the colour of geometric, algorithmically drawn, or textual components. For image components, the colour of the image pixels is multiplied by the specified colour. If no such element is present, the colour de- faults to opaque white. A components color may be animated according to the elements state by supplying multiple color child elements with state attributes. The state attributes must not be equal for any two color elements within a component. If the elements state is lower than the state value of any color child element, the colour specified by the color child element with the lowest state value will be used. If the elements state is higher than the state value of any color child element, the colour specified by the color child element with the highest state value will be used. If the elements state is between the state values of two color child elements, the RGBA colour components will be interpolated linearly. The following components are supported: rect Draws a uniform colour rectangle filling its bounds. disk Draws a uniform colour ellipse fitted to its bounds. image Draws an image loaded from a PNG, JPEG, Windows DIB (BMP) or SVG file. The name of the file to load (including the file name ex- tension) is supplied using the file attribute. Additionally, an optional alphafile attribute may be used to specify the name of a PNG file (including the file name extension) to load into the alpha channel of the image. Alternatively, image data may be supplied in the layout file it- self using a data child element. This can be useful for supply- ing simple, human-readable SVG graphics. A file attribute or data child element must be supplied; it is an error if neither or both are supplied. If the alphafile attribute refers to a file, it must have the same dimensions (in pixels) as the file referred to by the file attribute, and must have a bit depth no greater than eight bits per channel per pixel. The intensity from this image (bright- ness) is copied to the alpha channel, with full intensity (white in a greyscale image) corresponding to fully opaque, and black corresponding to fully transparent. The alphafile attribute will be ignored if the file attribute refers to an SVG image or the data child element contains SVG data; it is only used in con- junction with bitmap images. The image file(s) should be placed in the same directory/archive as the layout file. Image file formats are detected by examin- ing the content of the files, file name extensions are ignored. text Draws text in using the UI font in the specified colour. The text to draw must be supplied using a string attribute. An align attribute may be supplied to set text alignment. If present, the align attribute must be an integer, where 0 (zero) means centred, 1 (one) means left-aligned, and 2 (two) means right-aligned. If the align attribute is absent, the text will be centred. led7seg Draws a standard seven-segment (plus decimal point) digital LED/fluorescent display in the specified colour. The low eight bits of the elements state control which segments are lit. Starting from the least significant bit, the bits correspond to the top segment, the upper right-hand segment, continuing clock- wise to the upper left segment, the middle bar, and the decimal point. Unlit segments are drawn at low intensity (0x20/0xff). led14seg Draws a standard fourteen-segment alphanumeric LED/fluorescent display in the specified colour. The low fourteen bits of the elements state control which segments are lit. Starting from the least significant bit, the bits correspond to the top seg- ment, the upper right-hand segment, continuing clockwise to the upper left segment, the left-hand and right-hand halves of the horizontal middle bar, the upper and lower halves of the verti- cal middle bar, and the diagonal bars clockwise from lower left to lower right. Unlit segments are drawn at low intensity (0x20/0xff). led14segsc Draws a standard fourteen-segment alphanumeric LED/fluorescent display with decimal point/comma in the specified colour. The low sixteen bits of the elements state control which segments are lit. The low fourteen bits correspond to the same segments as in the led14seg component. Two additional bits correspond to the decimal point and comma tail. Unlit segments are drawn at low intensity (0x20/0xff). led16seg Draws a standard sixteen-segment alphanumeric LED/fluorescent display in the specified colour. The low sixteen bits of the elements state control which segments are lit. Starting from the least significant bit, the bits correspond to the left-hand half of the top bar, the right-hand half of the top bar, contin- uing clockwise to the upper left segment, the left-hand and right-hand halves of the horizontal middle bar, the upper and lower halves of the vertical middle bar, and the diagonal bars clockwise from lower left to lower right. Unlit segments are drawn at low intensity (0x20/0xff). led16segsc Draws a standard sixteen-segment alphanumeric LED/fluorescent display with decimal point/comma in the specified colour. The low eighteen bits of the elements state control which segments are lit. The low sixteen bits correspond to the same segments as in the led16seg component. Two additional bits correspond to the decimal point and comma tail. Unlit segments are drawn at low intensity (0x20/0xff). simplecounter Displays the numeric value of the elements state using the sys- tem font in the specified colour. The value is formatted in decimal notation. A digits attribute may be supplied to specify the minimum number of digits to display. If present, the digits attribute must be a positive integer; if absent, a minimum of two digits will be displayed. A maxstate attribute may be sup- plied to specify the maximum state value to display. If present, the maxstate attribute must be a non-negative number; if absent it defaults to 999. An align attribute may be sup- plied to set text alignment. If present, the align attribute must be an integer, where 0 (zero) means centred, 1 (one) means left-aligned, and 2 (two) means right-aligned; if absent, the text will be centred. An example element that draws a static left-aligned text string: <element name="label_reset_cpu"> <text string="CPU" align="1"><color red="1.0" green="1.0" blue="1.0" /></text> </element> An example element that displays a circular LED where the intensity de- pends on the state of an active-high output: <element name="led" defstate="0"> <disk state="0"><color red="0.43" green="0.35" blue="0.39" /></disk> <disk state="1"><color red="1.0" green="0.18" blue="0.20" /></disk> </element> An example element for a button that gives visual feedback when clicked: <element name="btn_rst"> <rect state="0"><bounds x="0.0" y="0.0" width="1.0" height="1.0" /><color red="0.2" green="0.2" blue="0.2" /></rect> <rect state="1"><bounds x="0.0" y="0.0" width="1.0" height="1.0" /><color red="0.1" green="0.1" blue="0.1" /></rect> <rect state="0"><bounds x="0.1" y="0.1" width="0.9" height="0.9" /><color red="0.1" green="0.1" blue="0.1" /></rect> <rect state="1"><bounds x="0.1" y="0.1" width="0.9" height="0.9" /><color red="0.2" green="0.2" blue="0.2" /></rect> <rect><bounds x="0.1" y="0.1" width="0.8" height="0.8" /><color red="0.15" green="0.15" blue="0.15" /></rect> <text string="RESET"><bounds x="0.1" y="0.4" width="0.8" height="0.2" /><color red="1.0" green="1.0" blue="1.0" /></text> </element> An example of an element that draws a seven-segment LED display using external segment images: <element name="digit_a" defstate="0"> <image file="a_off.png" /> <image file="a_a.png" statemask="0x01" /> <image file="a_b.png" statemask="0x02" /> <image file="a_c.png" statemask="0x04" /> <image file="a_d.png" statemask="0x08" /> <image file="a_e.png" statemask="0x10" /> <image file="a_f.png" statemask="0x20" /> <image file="a_g.png" statemask="0x40" /> <image file="a_dp.png" statemask="0x80" /> </element> An example of a bar graph that grows vertically and changes colour from green, through yellow, to red as the state increases: <element name="pedal"> <rect> <bounds state="0x000" left="0.0" top="0.9" right="1.0" bottom="1.0" /> <bounds state="0x610" left="0.0" top="0.0" right="1.0" bottom="1.0" /> <color state="0x000" red="0.0" green="1.0" blue="0.0" /> <color state="0x184" red="1.0" green="1.0" blue="0.0" /> <color state="0x610" red="1.0" green="0.0" blue="0.0" /> </rect> </element> An example of a bar graph that grows horizontally to the left or right and changes colour from green, through yellow, to red as the state changes from the neutral position: <element name="wheel"> <rect> <bounds state="0x800" left="0.475" top="0.0" right="0.525" bottom="1.0" /> <bounds state="0x280" left="0.0" top="0.0" right="0.525" bottom="1.0" /> <bounds state="0xd80" left="0.475" top="0.0" right="1.0" bottom="1.0" /> <color state="0x800" red="0.0" green="1.0" blue="0.0" /> <color state="0x3e0" red="1.0" green="1.0" blue="0.0" /> <color state="0x280" red="1.0" green="0.0" blue="0.0" /> <color state="0xc20" red="1.0" green="1.0" blue="0.0" /> <color state="0xd80" red="1.0" green="0.0" blue="0.0" /> </rect> </element> Views A view defines an arrangement of elements and/or emulated screen images that can be displayed in a window or on a screen. Views also connect elements to emulated I/O ports and/or outputs. A layout file may con- tain multiple views. If a view references a non-existent screen, it will be considered unviable. MAME will print a warning message, skip over the unviable view, and continue to load views from the layout file. This is particularly useful for systems where a screen is op- tional, for example computer systems with front panel controls and an optional serial terminal. Views are identified by name in MAMEs user interface and in com- mand-line options. For layouts files associated with devices other than the root driver device, view names are prefixed with the devices tag (with the initial colon omitted) for example a view called Key- board LEDs loaded for the device :tty:ie15 will be called tty:ie15 Key- board LEDs in MAMEs user interface. Views are listed in the order they are loaded. Within a layout file, views are loaded in the order they appear, from top to bottom. Views are created with view elements inside the top-level mamelayout element. Each view element must have a name attribute, supplying its human-readable name for use in the user interface and command-line op- tions. This is an example of a valid opening tag for a view element: <view name="Control panel"> A view creates a nested parameter scope inside the parameter scope of the top-level mamelayout element. For historical reasons, view ele- ments are processed after all other child elements of the top-level mamelayout element. This means a view can reference elements and groups that appear after it in the file, and parameters from the en- closing scope will have their final values from the end of the mamelay- out element. A view element may have a showpointers attribute to set whether mouse and pen pointers should be shown for the view. If present, the value must be either yes or no. If the showpointers attribute is not present, pen and mouse pointers are shown for views that contain items bound to I/O ports. The following child elements are allowed inside a view element: bounds Sets the origin and size of the views internal coordinate system if present. See Coordinates for details. If absent, the bounds of the view are computed as the union of the bounds of all screens and elements within the view. It only makes sense to have one bounds as a direct child of a view element. Any con- tent outside the views bounds is cropped, and the view is scaled proportionally to fit the output window or screen. param Defines or reassigns a value parameter in the views scope. See Parameters for details. element Adds an element to the view (see Elements). The name of the el- ement to add is specified using the required ref attribute. It is an error if no element with this name is defined in the lay- out file. Within a view, elements are drawn in the order they appear in the layout file, from front to back. See below for more details. May optionally be connected to an emulated I/O port using input- tag and inputmask attributes, and/or an emulated output using a name attribute. See Clickable items for details. See Element state for details on supplying a state value to the instantiated element. screen Adds an emulated screen image to the view. The screen must be identified using either an index attribute or a tag attribute (it is an error for a screen element to have both index and tag attributes). If present, the index attribute must be a non-neg- ative integer. Screens are numbered by the order they appear in machine configuration, starting at zero (0). If present, the tag attribute must be the tag path to the screen relative to the device that causes the layout to be loaded. Screens are drawn in the order they appear in the layout file, from front to back. May optionally be connected to an emulated I/O port using input- tag and inputmask attributes, and/or an emulated output using a name attribute. See Clickable items for details. collection Adds screens and/or items in a collection that can be shown or hidden by the user (see Collections). The name of the collec- tion is specified using the required name attribute. There is a limit of 32 collections per view. group Adds the content of the group to the view (see Reusable groups). The name of the group to add is specified using the required ref attribute. It is an error if no group with this name is defined in the layout file. See below for more details on positioning. repeat Repeats its contents the number of times specified by the re- quired count attribute. The count attribute must be a positive integer. A repeat element in a view may contain element, screen, group, and further repeat elements, which function the same way they do when placed in a view directly. See Repeating blocks for discussion on using repeat elements. Screens (screen elements) and layout elements (element elements) may have an id attribute. If present, the id attribute must not be empty, and must be unique within a view, including screens and elements in- stantiated via reusable groups and repeating blocks. Screens and lay- out elements with id attributes can be looked up by Lua scripts (see MAME Layout Scripting). Screens (screen elements), layout elements (element elements) and groups (group elements) may have their orientation altered using an orientation child element. For screens, the orientation modifiers are applied in addition to the orientation modifiers specified on the screen device and on the machine. The orientation element supports the following attributes, all of which are optional: rotate If present, applies clockwise rotation in ninety degree incre- ments. Must be an integer equal to 0, 90, 180 or 270. swapxy Allows the screen, element or group to be mirrored along a line at forty-five degrees to vertical from upper left to lower right. Must be either yes or no if present. Mirroring applies logically after rotation. flipx Allows the screen, element or group to be mirrored around its vertical axis, from left to right. Must be either yes or no if present. Mirroring applies logically after rotation. flipy Allows the screen, element or group to be mirrored around its horizontal axis, from top to bottom. Must be either yes or no if present. Mirroring applies logically after rotation. Screens (screen elements) and layout elements (element elements) may have a blend attribute to set the blending mode. Supported values are none (no blending), alpha (alpha blending), multiply (RGB multiplica- tion), and add (additive blending). The default for screens is to al- low the driver to specify blending per layer; the default blending mode for layout elements is alpha blending. Screens (screen elements), layout elements (element elements) and groups (group elements) may be positioned and sized using a bounds child element (see Coordinates for details). In the absence of a bounds child element, screens and layout elements bounds default to a unit square (origin at 0,0 and height and width both equal to 1). In the absence of a bounds child element, groups are expanded with no translation/scaling (note that groups may position screens/elements outside their bounds). This example shows a view instantiating and po- sitioning a screen, an individual layout element, and two element groups: <view name="LED Displays, Terminal and Keypad"> <screen index="0"><bounds x="0" y="132" width="320" height="240" /></screen> <element ref="beige"><bounds x="320" y="0" width="172" height="372" /></element> <group ref="displays"><bounds x="0" y="0" width="320" height="132" /></group> <group ref="keypad"><bounds x="336" y="16" width="140" height="260" /></group> </view> Screens (screen elements), layout elements (element elements) and groups (group elements) may have a color child element (see Colours) specifying a modifier colour. The component colours of the screen or layout element(s) are multiplied by this colour. Screens (screen elements) and layout elements (element elements) may have their colour and position/size animated by supplying multiple color and/or bounds child elements with state attributes. See View item animation for details. Layout elements (element elements) may be configured to show only part of the elements width or height using xscroll and/or yscroll child ele- ments. This can be used for devices like slot machine reels. The xscroll and yscroll elements support the same attributes: size The size of the horizontal or vertical scroll window, as a pro- portion of the elements width or height, respectively. Must be in the range 0.01 to 1.0, inclusive, if present (1% of the width/height to the full width/height). By default, the entire width and height of the element is shown. wrap Whether the element should wrap horizontally or vertically. Must be either yes or no if present. By default, items do not wrap horizontally or vertically. inputtag If present, the horizontal or vertical scroll position will be taken from the value of the corresponding I/O port. Specifies the tag path of an I/O port relative to the device that caused the layout file to be loaded. The raw value from the input port is used, active-low switch values are not normalised. name If present, the horizontal or vertical scroll position will be taken from the correspondingly named output. mask If present, the horizontal or vertical scroll position will be masked with the value and shifted to the right to remove trail- ing zeroes (for example a mask of 0x05 will result in no shift, while a mask of 0x68 will result in the value being shifted three bits to the right). Note that this applies to output val- ues (specified with the name attribute) as well as input port values (specified with the inputtag attribute). Must be an in- teger value if present. If not present, it is equivalent to all 32 bits being set. min Minimum horizontal or vertical scroll position value. When the horizontal or vertical scroll position has this value, the left or top edge or the scroll window will be aligned with the left or top edge of the element. Must be an integer value if present. Defaults to zero. max Maximum horizontal or vertical scroll position value. Must be an integer value if present. Defaults to the mask value shifted to the right to remove trailing zeroes. Collections Collections of screens and/or layout elements can be shown or hidden by the user as desired. For example, a single view could include both displays and a clickable keypad, and allow the user to hide the keypad leaving only the displays visible. Collections are created using col- lection elements inside view, group and other collection elements. A collection element must have a name attribute providing the display name for the collection. Collection names must be unique within a view. The initial visibility of a collection may be specified by pro- viding a visible attribute. Set the visible attribute to yes if the collection should be initially visible, or no if it should be initially hidden. Collections are initially visible by default. Here is an example demonstrating the use of collections to allow parts of a view to be hidden by the user: <view name="LED Displays, CRT and Keypad"> <collection name="LED Displays"> <group ref="displays"><bounds x="240" y="0" width="320" height="47" /></group> </collection> <collection name="Keypad"> <group ref="keypad"><bounds x="650" y="57" width="148" height="140" /></group> </collection> <screen tag="screen"><bounds x="0" y="57" width="640" height="480" /></screen> </view> A collection creates a nested parameter scope. Any param elements in- side the collection element set parameters in the local scope for the collection. See Parameters for more detail on parameters. (Note that the collections name and default visibility are not part of its con- tent, and any parameter references in the name and visible attributes themselves will be substituted using parameter values from the collec- tions parents scope.) Reusable groups Groups allow an arrangement of screens and/or layout elements to be used multiple times in views or other groups. Groups can be beneficial even if you only use the arrangement once, as they can be used to en- capsulate part of a complex layout. Groups are defined using group el- ements inside the top-level mamelayout element, and instantiated using group elements inside view and other group elements. Each group definition element must have a name attribute providing a unique identifier. It is an error if a layout file contains multiple group definitions with identical name attributes. The value of the name attribute is used when instantiating the group from a view or an- other group. This is an example opening tag for a group definition el- ement inside the top-level mamelayout element: <group name="panel"> This group may then be instantiated in a view or another group element using a group reference element, optionally supplying destination bounds, orientation, and/or modifier colour. The ref attribute identi- fies the group to instantiate in this example, destination bounds are supplied: <group ref="panel"><bounds x="87" y="58" width="23" height="23.5" /></group> Group definition elements allow all the same child elements as views. Positioning and orienting screens, layout elements and nested groups works the same way as for views. See Views for details. A group may instantiate other groups, but recursive loops are not permitted. It is an error if a group directly or indirectly instantiates itself. Groups have their own internal coordinate systems. If a group defini- tion element has no bounds element as a direct child, its bounds are computed as the union of the bounds of all the screens, layout elements and/or nested groups it instantiates. A bounds child element may be used to explicitly specify group bounds (see Coordinates for details). Note that groups bounds are only used for the purpose of calculating the coordinate transform when instantiating a group. A group may posi- tion screens and/or elements outside its bounds, and they will not be cropped. To demonstrate how bounds calculation works, consider this example: <group name="autobounds"> <!-- bounds automatically calculated with origin at (5,10), width 30, and height 15 --> <element ref="topleft"><bounds x="5" y="10" width="10" height="10" /></element> <element ref="bottomright"><bounds x="25" y="15" width="10" height="10" /></element> </group> <view name="Test"> <!-- group bounds translated and scaled to fit - 2/3 scale horizontally and double vertically element topleft positioned at (0,0) with width 6.67 and height 20 element bottomright positioned at (13.33,10) with width 6.67 and height 20 view bounds calculated with origin at (0,0), width 20, and height 30 --> <group ref="autobounds"><bounds x="0" y="0" width="20" height="30" /></group> </view> This is relatively straightforward, as all elements inherently fall within the groups automatically computed bounds. Now consider what happens if a group positions elements outside its explicit bounds: <group name="periphery"> <!-- elements are above the top edge and to the right of the right edge of the bounds --> <bounds x="10" y="10" width="20" height="25" /> <element ref="topleft"><bounds x="10" y="0" width="10" height="10" /></element> <element ref="bottomright"><bounds x="30" y="20" width="10" height="10" /></element> </group> <view name="Test"> <!-- group bounds translated and scaled to fit - 3/2 scale horizontally and unity vertically element topleft positioned at (5,-5) with width 15 and height 10 element bottomright positioned at (35,15) with width 15 and height 10 view bounds calculated with origin at (5,-5), width 45, and height 30 --> <group ref="periphery"><bounds x="5" y="5" width="30" height="25" /></group> </view> The groups elements are translated and scaled as necessary to distort the groups internal bounds to the destination bounds in the view. The groups content is not restricted to its bounds. The view considers the bounds of the actual layout elements when computing its bounds, not the destination bounds specified for the group. When a group is instantiated, it creates a nested parameter scope. The logical parent scope is the parameter scope of the view, group or re- peating block where the group is instantiated (not its lexical parent, the top-level mamelayout element). Any param elements inside the group definition element set parameters in the local scope for the group in- stantiation. Local parameters do not persist across multiple instanti- ations. See Parameters for more detail on parameters. (Note that the groups name is not part of its content, and any parameter references in the name attribute itself will be substituted at the point where the group definition appears in the top-level mamelayout elements scope.) Repeating blocks Repeating blocks provide a concise way to generate or arrange large numbers of similar elements. Repeating blocks are generally used in conjunction with generator parameters (see Parameters). Repeating blocks may be nested for more complex arrangements. Repeating blocks are created with repeat elements. Each repeat element requires a count attribute specifying the number of iterations to gen- erate. The count attribute must be a positive integer. Repeating blocks are allowed inside the top-level mamelayout element, inside group and view elements, and insider other repeat elements. The exact child elements allowed inside a repeat element depend on where it ap- pears: • A repeating block inside the top-level mamelayout element may contain param, element, group (definition), and repeat elements. • A repeating block inside a group or view element may contain param, element (reference), screen, group (reference), and repeat elements. A repeating block effectively repeats its contents the number of times specified by its count attribute. See the relevant sections for de- tails on how the child elements are used (Parts of a layout, Reusable groups, and Views). A repeating block creates a nested parameter scope inside the parameter scope of its lexical (DOM) parent element. Generating white number labels from zero to eleven named label_0, la- bel_1, and so on (inside the top-level mamelayout element): <repeat count="12"> <param name="labelnum" start="0" increment="1" /> <element name="label_~labelnum~"> <text string="~labelnum~"><color red="1.0" green="1.0" blue="1.0" /></text> </element> </repeat> A horizontal row of forty digital displays, with five units space be- tween them, controlled by outputs digit0 to digit39 (inside a group or view element): <repeat count="40"> <param name="i" start="0" increment="1" /> <param name="x" start="5" increment="30" /> <element name="digit~i~" ref="digit"> <bounds x="~x~" y="5" width="25" height="50" /> </element> </repeat> Eight five-by-seven dot matrix displays in a row, with pixels con- trolled by outputs Dot_000 to Dot_764 (inside a group or view element): <repeat count="8"> <!-- 8 digits --> <param name="digitno" start="1" increment="1" /> <param name="digitx" start="0" increment="935" /> <!-- distance between digits ((111 * 5) + 380) --> <repeat count="7"> <!-- 7 rows in each digit --> <param name="rowno" start="1" increment="1" /> <param name="rowy" start="0" increment="114" /> <!-- vertical distance between LEDs --> <repeat count="5"> <!-- 5 columns in each digit --> <param name="colno" start="1" increment="1" /> <param name="colx" start="~digitx~" increment="111" /> <!-- horizontal distance between LEDs --> <element name="Dot_~digitno~~rowno~~colno~" ref="Pixel" state="0"> <bounds x="~colx~" y="~rowy~" width="100" height="100" /> <!-- size of each LED --> </element> </repeat> </repeat> </repeat> Two horizontally separated, clickable, four-by-four keypads (inside a group or view element): <repeat count="2"> <param name="group" start="0" increment="4" /> <param name="padx" start="10" increment="530" /> <param name="mask" start="0x01" lshift="4" /> <repeat count="4"> <param name="row" start="0" increment="1" /> <param name="y" start="100" increment="110" /> <repeat count="4"> <param name="col" start="~group~" increment="1" /> <param name="btnx" start="~padx~" increment="110" /> <param name="mask" start="~mask~" lshift="1" /> <element ref="btn~row~~col~" inputtag="row~row~" inputmask="~mask~"> <bounds x="~btnx~" y="~y~" width="80" height="80" /> </element> </repeat> </repeat> </repeat> The buttons are drawn using elements btn00 in the top left, bnt07 in the top right, btn30 in the bottom left, and btn37 in the bottom right, counting in between. The four rows are connected to I/O ports row0, row1, row2, and row3, from top to bottom. The columns are connected to consecutive I/O port bits, starting with the least significant bit on the left. Note that the mask parameter in the innermost repeat ele- ment takes its initial value from the correspondingly named parameter in the enclosing scope, but does not modify it. Generating a chequerboard pattern with alternating alpha values 0.4 and 0.2 (inside a group or view element): <repeat count="4"> <param name="pairy" start="3" increment="20" /> <param name="pairno" start="7" increment="-2" /> <repeat count="2"> <param name="rowy" start="~pairy~" increment="10" /> <param name="rowno" start="~pairno~" increment="-1" /> <param name="lalpha" start="0.4" increment="-0.2" /> <param name="ralpha" start="0.2" increment="0.2" /> <repeat count="4"> <param name="lx" start="3" increment="20" /> <param name="rx" start="13" increment="20" /> <param name="lmask" start="0x01" lshift="2" /> <param name="rmask" start="0x02" lshift="2" /> <element ref="hl" inputtag="board:IN.~rowno~" inputmask="~lmask~"> <bounds x="~lx~" y="~rowy~" width="10" height="10" /> <color alpha="~lalpha~" /> </element> <element ref="hl" inputtag="board:IN.~rowno~" inputmask="~rmask~"> <bounds x="~rx~" y="~rowy~" width="10" height="10" /> <color alpha="~ralpha~" /> </element> </repeat> </repeat> </repeat> The outermost repeat element generates a group of two rows on each it- eration; the next repeat element generates an individual row on each iteration; the innermost repeat element produces two horizontally adja- cent tiles on each iteration. Rows are connected to I/O ports board:IN.7 at the top to board.IN.0 at the bottom. Interactivity Interactive views are supported by allowing items to be bound to emu- lated outputs and I/O ports. Five kinds of interactivity are sup- ported: Clickable items If an item in a view is bound to an I/O port switch field, clicking the item will activate the emulated switch. State-dependent components Some components will be drawn differently depending on the con- taining elements state. These include the dot matrix, multi-segment LED display and simple counter elements. See Elements for details. Conditionally-drawn components Components may be conditionally drawn or hidden depending on the containing elements state by supplying state and/or statemask attributes. See Elements for details. Component parameter animation Components colour and position/size within their containing ele- ment may be animated according the elements state by providing multiple color and/or bounds elements with state attributes. See Elements for details. Item parameter animation Items colour and position/size within their containing view may be animated according to their animation state. Clickable items If a view item (element or screen element) has inputtag and inputmask attribute values that correspond to a digital switch field in the emu- lated system, clicking the element will activate the switch. The switch will remain active as long as the primary button is held down and the pointer is within the items current bounds. (Note that the bounds may change depending on the items animation state, see View item animation). The inputtag attribute specifies the tag path of an I/O port relative to the device that caused the layout file to be loaded. The inputmask attribute must be an integer specifying the bits of the I/O port field that the item should activate. This sample shows instantiation of clickable buttons: The clickthrough attribute controls whether clicks can pass through the view item to other view items drawn above it. The clickthrough at- tribute must be yes or no if present. The default is no (clicks do not pass through) for view items with inputtag and inputmask attributes, and yes (clicks pass through) for other view items. <element ref="btn_3" inputtag="X2" inputmask="0x10"> <bounds x="2.30" y="4.325" width="1.0" height="1.0" /> </element> <element ref="btn_0" inputtag="X0" inputmask="0x20"> <bounds x="0.725" y="5.375" width="1.0" height="1.0" /> </element> <element ref="btn_rst" inputtag="RESET" inputmask="0x01"> <bounds x="1.775" y="5.375" width="1.0" height="1.0" /> </element> When handling pointer input, MAME treats all layout elements as being rectangular. Element state A view item that instantiates an element (element element) may supply a state value to the element from an emulated I/O port or output. See Elements for details on how an elements state affects its appearance. If the element element has a name attribute, the element state value will be taken from the value of the correspondingly named emulated out- put. Note that output names are global, which can become an issue when a machine uses multiple instances of the same type of device. This ex- ample shows how digital displays may be connected to emulated outputs: <element name="digit6" ref="digit"><bounds x="16" y="16" width="48" height="80" /></element> <element name="digit5" ref="digit"><bounds x="64" y="16" width="48" height="80" /></element> <element name="digit4" ref="digit"><bounds x="112" y="16" width="48" height="80" /></element> <element name="digit3" ref="digit"><bounds x="160" y="16" width="48" height="80" /></element> <element name="digit2" ref="digit"><bounds x="208" y="16" width="48" height="80" /></element> <element name="digit1" ref="digit"><bounds x="256" y="16" width="48" height="80" /></element> If the element element has inputtag and inputmask attributes but lacks a name attribute, the element state value will be taken from the value of the corresponding I/O port, masked with the inputmask value. The inputtag attribute specifies the tag path of an I/O port relative to the device that caused the layout file to be loaded. The inputmask at- tribute must be an integer specifying the bits of the I/O port field to use. If the element element has no inputraw attribute, or if the value of the inputraw attribute is no, the I/O ports value is masked with the inputmask value and XORed with the I/O port default field value. If the result is non-zero, the element state is 1, otherwise its 0. This is often used or provide visual feedback for clickable buttons, as val- ues for active-high and active-low switches are normalised. If the element element has an inputraw attribute with the value yes, the element state will be taken from the I/O ports value masked with the inputmask value and shifted to the right to remove trailing zeroes (for example a mask of 0x05 will result in no shift, while a mask of 0xb0 will result in the value being shifted four bits to the right). This is useful for obtaining the value of analog or positional inputs. View item animation Items colour and position/size within their containing view may be ani- mated. This is achieved by supplying multiple color and/or bounds child elements with state attributes. The state attribute of each color or bounds child element must be a non-negative integer. Within a view item, no two color elements may have equal state state attributes, and no two bounds elements may have equal state attributes. If the items animation state is lower than the state value of any bounds child element, the position/size specified by the bounds child element with the lowest state value will be used. If the items anima- tion state is higher than the state value of any bounds child element, the position/size specified by the bounds child element with the high- est state value will be used. If the items animation state is between the state values of two bounds child elements, the position/size will be interpolated linearly. If the items animation state is lower than the state value of any color child element, the colour specified by the color child element with the lowest state value will be used. If the items animation state is higher than the state value of any color child element, the colour specified by the color child element with the highest state value will be used. If the items animation state is between the state values of two color child elements, the RGBA colour components will be interpo- lated linearly. An items animation state may be bound to an emulated output or input port by supplying an animate child element. If present, the animate element must have either an inputtag attribute or a name attribute (but not both). If the animate child element is not present, the items ani- mation state is the same as its element state (see Element state). If the animate child element is present and has an inputtag attribute, the items animation state will be taken from the value of the corre- sponding I/O port. The inputtag attribute specifies the tag path of an I/O port relative to the device that caused the layout file to be loaded. The raw value from the input port is used, active-low switch values are not normalised. If the animate child element is present and has a name attribute, the items animation state will be taken from the value of the correspond- ingly named emulated output. Note that output names are global, which can become an issue when a machine uses multiple instances of the same type of device. If the animate child element has a mask attribute, the items animation state will be masked with the mask value and shifted to the right to remove trailing zeroes (for example a mask of 0x05 will result in no shift, while a mask of 0xb0 will result in the value being shifted four bits to the right). Note that the mask attribute applies to output values (specified with the name attribute) as well as input port values (specified with the inputtag attribute). If the mask attribute is present, it must be an integer value. If the mask attribute is not present, it is equivalent to all 32 bits being set. This example shows elements with independent element state and anima- tion state, using the animation state taken from emulated outputs to control their position: <repeat count="5"> <param name="x" start="10" increment="9" /> <param name="i" start="0" increment="1" /> <param name="mask" start="0x01" lshift="1" /> <element name="cg_sol~i~" ref="cosmo"> <animate name="cg_count~i~" /> <bounds state="0" x="~x~" y="10" width="6" height="7" /> <bounds state="255" x="~x~" y="48.5" width="6" height="7" /> </element> <element ref="nothing" inputtag="FAKE1" inputmask="~mask~"> <animate name="cg_count~i~" /> <bounds state="0" x="~x~" y="10" width="6" height="7" /> <bounds state="255" x="~x~" y="48.5" width="6" height="7" /> </element> </repeat> This example shows elements with independent element state and anima- tion state, using the animation state taken from an emulated positional input to control their positions: <repeat count="4"> <param name="y" start="1" increment="3" /> <param name="n" start="0" increment="1" /> <element ref="ledr" name="~n~.7"> <animate inputtag="IN.1" mask="0x0f" /> <bounds state="0" x="0" y="~y~" width="1" height="1" /> <bounds state="11" x="16.5" y="~y~" width="1" height="1" /> </element> </repeat> Error handling • For internal (developer-supplied) layout files, errors detected by the complay.py script result in a build failure. • MAME will stop loading a layout file if a syntax error is encoun- tered. No views from the layout will be available. Examples of syn- tax errors include undefined element or group references, invalid bounds, invalid colours, recursively nested groups, and redefined generator parameters. • When loading a layout file, if a view references a non-existent screen, MAME will print a warning message and continue. Views refer- encing non-existent screens are considered unviable and not available to the user. Automatically-generated views After loading internal (developer-supplied) and external (user-sup- plied) layouts, MAME automatically generates views based on the machine configuration. The following views will be automatically generated: • If the system has no screens and no viable views were found in the internal and external layouts, MAME will load a view that shows the message No screens attached to the system. • For each emulated screen, MAME will generate a view showing the screen at its physical aspect ratio with rotation applied. • For each emulated screen where the configured pixel aspect ratio doesnt match the physical aspect ratio, MAME will generate a view showing the screen at an aspect ratio that produces square pixels, with rotation applied. • If the system has a single emulated screen, MAME will generate a view showing two copies of the screen image above each other with a small gap between them. The upper copy will be rotated by 180 degrees. This view can be used in a cocktail table cabinet for simultaneous two-player games, or alternating play games that dont automatically rotate the display for the second player. The screen will be dis- played at its physical aspect ratio, with rotation applied. • If the system has exactly two emulated screens, MAME will generate a view showing the second screen above the first screen with a small gap between them. The second screen will be rotated by 180 degrees. This view can be used to play a dual-screen two-player game on a cocktail table cabinet with a single screen. The screens will be displayed at their physical aspect ratios, with rotation applied. • If the system has exactly two emulated screens and no view in the in- ternal or external layouts shows all screens, or if the system has more than two emulated screens, MAME will generate views with the screens arranged horizontally from left to right and vertically from top to bottom, both with and without small gaps between them. The screens will be displayed at physical aspect ratio, with rotation ap- plied. • If the system has three or more emulated screens, MAME will generate views tiling the screens in grid patterns, in both row-major (left-to-right then top-to-bottom) and column-major (top-to-bottom then left-to-right) order. Views are generated with and without gaps between the screens. The screens will be displayed at physical as- pect ratio, with rotation applied. Using complay.py The MAME source contains a Python script called complay.py, found in the scripts/build subdirectory. This script is used as part of MAMEs build process to reduce the size of data for internal layouts and con- vert it to a form that can be built into the executable. However, it can also detect many common layout file format errors, and generally provides better error messages than MAME does when loading a layout file. Note that it doesnt actually run the whole layout engine, so it cant detect errors like undefined element references when parameters are used, or recursively nested groups. The complay.py script is com- patible with both Python 2.7 and Python 3 interpreters. The complay.py script takes three parameters an input file name, an output file name, and a base name for variables in the output: python scripts/build/complay.py <input> [<output> [<varname>]] The input file name is required. If no output file name is supplied, complay.py will parse and check the input, reporting any errors found, without producing output. If no base variable name is provided, com- play.py will generate one based on the input file name. This is not guaranteed to produce valid identifiers. The exit status is 0 (zero) on success, 1 on an error in the command invocation, 2 if error are found in the input file, or 3 in case of an I/O error. If an output file name is specified, the file will be created/overwritten on success or removed on failure. To check a layout file for common errors, run the script with the path to the file to check and no output file name or base variable name. For example: python scripts/build/complay.py artwork/dino/default.lay Example layout files These layout files demonstrate various artwork system features. They are all internal layouts included in MAME. sstrangr.lay A simple case of using translucent colour overlays to visually separate and highlight elements on a black and white screen. seawolf.lay This system uses lamps for key gameplay elements. Blending modes are used for the translucent colour overlay placed over the monitor, and the lamps reflected in front of the monitor. Also uses collections to allow parts of the layout to be dis- abled selectively. armora.lay This games monitor is viewed directly through a translucent colour overlay rather than being reflected from inside the cabi- net. This means the overlay reflects ambient light as well as affecting the colour of the video image. The shapes on the overlay are drawn using embedded SVG images. tranz330.lay A multi-segment alphanumeric display and keypad. The keys are clickable, and provide visual feedback when pressed. esq2by16.lay Builds up a multi-line dot matrix character display. Repeats are used to avoid repetition for the rows in a character, char- acters in a line, and lines in a page. Group colors allow a single element to be used for all four display colours. cgang.lay Animates the position of element items to simulate an electro- mechanical shooting gallery game. Also demonstrates effective use of components to build up complex graphics. minspace.lay Shows the position of a slider control with LEDs on it. md6802.lay Effectively using groups as a procedural programming language to build up an image of a trainer board. beena.lay Using event-based scripting to dynamically position elements and draw elemnt content programmatically. MAME Layout Scripting • Introduction • Practical examples • Espial: joystick split across ports • Star Wars: animation on two axes • The layout script environment • Layout events • Layout file events • Layout view events • Layout view item events • Layout element events Introduction MAME layout files can embed Lua script to provide enhanced functional- ity. Although theres a lot you can do with conditionally drawn compo- nents and parameter animation, some things can only be done with scripting. MAME uses an event-based model. Scripts can supply func- tions that will be called after certain events, or when certain data is required. Layout scripting requires the layout plugin to be enabled. For exam- ple, to run BWB Double Take with the Lua script in the layout enabled, you might use this command: mame -plugins -plugin layout v4dbltak You may want to add the settings to enable the layout plugin to an INI file to save having to enable it every time you start a system. See Plugins for more information about using plugins with MAME. Practical examples Before diving into the technical details of how it works, well start with some example layout files using Lua script for enhancement. Its assumed that youre familiar with MAMEs artwork system and have a basic understanding of Lua scripting. For details on MAMEs layout file, see MAME Layout Files; for detailed descriptions of MAMEs Lua interface, see Lua Scripting Interface. Espial: joystick split across ports Take a look at the player input definitions for Espial: PORT_START("IN1") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_START1 ) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_START2 ) PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_COCKTAIL PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_COCKTAIL PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_8WAY PORT_COCKTAIL PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_COCKTAIL PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_COCKTAIL PORT_START("IN2") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNKNOWN ) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNKNOWN ) PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_8WAY PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_COCKTAIL PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_8WAY There are two joysticks, one used for both players on an upright cabi- net or the first player on a cocktail cabinet, and one used for the second player on a cocktail cabinet. Notice that the switches for the first joystick are split across the two I/O ports. Theres no layout file syntax to build the element state using bits from multiple I/O ports. Its also inconvenient if each joystick needs to be defined as a separate element because the bits for the switches arent arranged the same way. We can overcome these limitations using a script to read the player in- puts and set the items element state: <?xml version="1.0"?> <mamelayout version="2"> <!-- element for drawing a joystick --> <!-- up = 1 (bit 0), down = 2 (bit 1), left = 4 (bit 2), right = 8 (bit 3) --> <element name="stick" defstate="0"> <image state="0x0" file="stick_c.svg" /> <image state="0x1" file="stick_u.svg" /> <image state="0x9" file="stick_ur.svg" /> <image state="0x8" file="stick_r.svg" /> <image state="0xa" file="stick_dr.svg" /> <image state="0x2" file="stick_d.svg" /> <image state="0x6" file="stick_dl.svg" /> <image state="0x4" file="stick_l.svg" /> <image state="0x5" file="stick_ul.svg" /> </element> <!-- we'll warn the user if the layout plugin isn't enabled --> <!-- draw only when state is 1, and set the default state to 1 so warning is visible initially --> <element name="warning" defstate="1"> <text state="1" string="This view requires the layout plugin." /> </element> <!-- view showing the screen and joysticks on a cocktail cabinet --> <view name="Joystick Display"> <!-- draw the screen with correct aspect ratio --> <screen index="0"> <bounds x="0" y="0" width="4" height="3" /> </screen> <!-- first joystick, id attribute allows script to find item --> <!-- no bindings, state will be set by the script --> <element id="joy_p1" ref="stick"> <!-- position below the screen --> <bounds xc="2" yc="3.35" width="0.5" height="0.5" /> </element> <!-- second joystick, id attribute allows script to find item --> <!-- no bindings, state will be set by the script --> <element id="joy_p2" ref="stick"> <!-- screen is flipped for second player, so rotate by 180 degrees --> <orientation rotate="180" /> <!-- position above the screen --> <bounds xc="2" yc="-0.35" width="0.5" height="0.5" /> </element> <!-- warning text item also has id attribute so the script can find it --> <element id="warning" ref="warning"> <!-- position over the screen near the bottom --> <bounds x="0.2" y="2.6" width="3.6" height="0.2" /> </element> </view> <!-- the content of the script element will be called as a function by the layout plugin --> <!-- use CDATA block to avoid the need to escape angle brackets and ampersands --> <script><![CDATA[ -- file is the layout file object -- set a function to call after resolving tags file:set_resolve_tags_callback( function () -- file.device is the device that caused the layout to be loaded -- in this case, it's the root machine driver for espial -- look up the two I/O ports we need to be able to read local in1 = file.device:ioport("IN1") local in2 = file.device:ioport("IN2") -- look up the view items for showing the joystick state local p1_stick = file.views["Joystick Display"].items["joy_p1"] local p2_stick = file.views["Joystick Display"].items["joy_p2"] -- set a function to call before adding the view items to the render target file.views["Joystick Display"]:set_prepare_items_callback( function () -- read the two player input I/O ports local in1_val = in1:read() local in2_val = in2:read() -- set element state for first joystick p1_stick:set_state( ((in2_val & 0x10) >> 4) | -- shift up from IN2 bit 4 to bit 0 ((in1_val & 0x20) >> 4) | -- shift down from IN1 bit 5 to bit 1 ((in2_val & 0x80) >> 5) | -- shift left from IN2 bit 7 to bit 2 (in2_val & 0x08)) -- right is in IN2 bit 3 -- set element state for second joystick p2_stick:set_state( ((in1_val & 0x10) >> 4) | -- shift up from IN1 bit 4 to bit 0 ((in1_val & 0x40) >> 5) | -- shift down from IN1 bit 6 to bit 1 (in1_val & 0x04) | -- left is in IN1 bit 2 (in1_val & 0x08)) -- right is in IN1 bit 3 end) -- hide the warning, since if we got here the script is running file.views["Joystick Display"].items["warning"]:set_state(0) end) ]]></script> </mamelayout> The layout has a script element containing the Lua script. This is called as a function by the layout plugin when the layout file is loaded. The layout views have been built at this point, but the emu- lated system has not finished starting. In particular, its not safe to access inputs and outputs at this time. The key variable in the script environment is file, which gives the script access to its layout file. We supply a function to be called after tags in the layout file have been resolved. At this point, the emulated system will have completed starting. This function does the following tasks: • Looks up the two I/O ports used for player input. I/O ports can be looked up by tag relative to the device that caused the layout file to be loaded. • Looks up the two view items used to display joystick state. Views can be looked up by name (i.e. value of the name attribute), and items within a view can be looked up by ID (i.e. the value of the id attribute). • Supplies a function to be called before view items are added to the render target when drawing a frame. • Hides the warning that reminds the user to enable the layout plugin by setting the element state for the item to 0 (the text component is only drawn when the element state is 1). The function called before view items are added to the render target reads the player inputs, and shuffles the bits into the order needed by the joystick element. Star Wars: animation on two axes Well make a layout that shows the position of the flight yoke for Atari Star Wars. The input ports are straightforward each analog axis pro- duces a value in the range from 0x00 (0) to 0xff (255), inclusive: PORT_START("STICKY") PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y ) PORT_SENSITIVITY(70) PORT_KEYDELTA(30) PORT_START("STICKX") PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X ) PORT_SENSITIVITY(50) PORT_KEYDELTA(30) Heres our layout file: <?xml version="1.0"?> <mamelayout version="2"> <!-- a square with a white outline 1% of its width --> <element name="outline"> <rect><bounds x="0.00" y="0.00" width="1.00" height="0.01" /></rect> <rect><bounds x="0.00" y="0.99" width="1.00" height="0.01" /></rect> <rect><bounds x="0.00" y="0.00" width="0.01" height="1.00" /></rect> <rect><bounds x="0.99" y="0.00" width="0.01" height="1.00" /></rect> </element> <!-- a rectangle with a vertical line 10% of its width down the middle --> <element name="line"> <!-- use a transparent rectangle to force element dimensions --> <rect> <bounds x="0" y="0" width="0.1" height="1" /> <color alpha="0" /> </rect> <!-- this is the visible white line --> <rect><bounds x="0.045" y="0" width="0.01" height="1" /></rect> </element> <!-- an outlined square inset by 20% with lines 10% of the element width/height --> <element name="box"> <!-- use a transparent rectangle to force element dimensions --> <rect> <bounds x="0" y="0" width="0.1" height="0.1" /> <color alpha="0" /> </rect> <!-- draw the outline of a square --> <rect><bounds x="0.02" y="0.02" width="0.06" height="0.01" /></rect> <rect><bounds x="0.02" y="0.07" width="0.06" height="0.01" /></rect> <rect><bounds x="0.02" y="0.02" width="0.01" height="0.06" /></rect> <rect><bounds x="0.07" y="0.02" width="0.01" height="0.06" /></rect> </element> <!-- we'll warn the user if the layout plugin isn't enabled --> <!-- draw only when state is 1, and set the default state to 1 so warning is visible initially --> <element name="warning" defstate="1"> <text state="1" string="This view requires the layout plugin." /> </element> <!-- view showing the screen and flight yoke position --> <view name="Analog Control Display"> <!-- draw the screen with correct aspect ratio --> <screen index="0"> <bounds x="0" y="0" width="4" height="3" /> </screen> <!-- draw the white outlined square to the right of the screen near the bottom --> <!-- the script uses the size of this item to determine movement ranges --> <element id="outline" ref="outline"> <bounds x="4.1" y="1.9" width="1.0" height="1.0" /> </element> <!-- vertical line for displaying X axis input --> <element id="vertical" ref="line"> <!-- element draws a vertical line, no need to rotate it --> <orientation rotate="0" /> <!-- centre it in the square horizontally, using the full height --> <bounds x="4.55" y="1.9" width="0.1" height="1" /> </element> <!-- horizontal line for displaying Y axis input --> <element id="horizontal" ref="line"> <!-- rotate the element by 90 degrees to get a horizontal line --> <orientation rotate="90" /> <!-- centre it in the square vertically, using the full width --> <bounds x="4.1" y="2.35" width="1" height="0.1" /> </element> <!-- draw a small box at the intersection of the vertical and horizontal lines --> <element id="box" ref="box"> <bounds x="4.55" y="2.35" width="0.1" height="0.1" /> </element> <!-- draw the warning text over the screen near the bottom --> <element id="warning" ref="warning"> <bounds x="0.2" y="2.6" width="3.6" height="0.2" /> </element> </view> <!-- the content of the script element will be called as a function by the layout plugin --> <!-- use CDATA block to avoid the need to escape angle brackets and ampersands --> <script><![CDATA[ -- file is the layout file object -- set a function to call after resolving tags file:set_resolve_tags_callback( function () -- file.device is the device that caused the layout to be loaded -- in this case, it's the root machine driver for starwars -- find the analog axis inputs local x_input = file.device:ioport("STICKX") local y_input = file.device:ioport("STICKY") -- find the outline item local outline_item = file.views["Analog Control Display"].items["outline"] -- variables for keeping state across callbacks local outline_bounds -- bounds of the outlined square local width, height -- width and height for animated items local x_scale, y_scale -- ratios of axis units to render coordinates local x_pos, y_pos -- display positions for the animated items -- set a function to call when view dimensions have been recalculated -- this can happen when when the window is resized or scaling options are changed file.views["Analog Control Display"]:set_recomputed_callback( function () -- get the bounds of the outlined square outline_bounds = outline_item.bounds -- animated items use 10% of the width/height of the square width = outline_bounds.width * 0.1 height = outline_bounds.height * 0.1 -- calculate ratios of axis units to render coordinates -- animated items leave 90% of the width/height for the movement range -- the end of the range of each axis is at 0xff x_scale = outline_bounds.width * 0.9 / 0xff y_scale = outline_bounds.height * 0.9 / 0xff end) -- set a function to call before adding the view items to the render target file.views["Analog Control Display"]:set_prepare_items_callback( function () -- read analog axes, reverse Y axis as zero is at the bottom local x = x_input:read() & 0xff local y = 0xff - (y_input:read() & 0xff) -- convert the input values to layout coordinates -- use the top left corner of the outlined square as the origin x_pos = outline_bounds.x0 + (x * x_scale) y_pos = outline_bounds.y0 + (y * y_scale) end) -- set a function to supply the bounds for the vertical line file.views["Analog Control Display"].items["vertical"]:set_bounds_callback( function () -- create a new render bounds object (starts as a unit square) local result = emu.render_bounds() -- set left, top, width and height result:set_wh( x_pos, -- calculated X position for animated items outline_bounds.y0, -- top of outlined square width, -- 10% of width of outlined square outline_bounds.height) -- full height of outlined square return result end) -- set a function to supply the bounds for the horizontal line file.views["Analog Control Display"].items["horizontal"]:set_bounds_callback( function () -- create a new render bounds object (starts as a unit square) local result = emu.render_bounds() -- set left, top, width and height result:set_wh( outline_bounds.x0, -- left of outlined square y_pos, -- calculated Y position for animated items outline_bounds.width, -- full width of outlined square height) -- 10% of height of outlined square return result end) -- set a function to supply the bounds for the box at the intersection of the lines file.views["Analog Control Display"].items["box"]:set_bounds_callback( function () -- create a new render bounds object (starts as a unit square) local result = emu.render_bounds() -- set left, top, width and height result:set_wh( x_pos, -- calculated X position for animated items y_pos, -- calculated Y position for animated items width, -- 10% of width of outlined square height) -- 10% of height of outlined square return result end) -- hide the warning, since if we got here the script is running file.views["Analog Control Display"].items["warning"]:set_state(0) end) ]]></script> </mamelayout> The layout has a script element containing the Lua script, to be called as a function by the layout plugin when the layout file is loaded. This happens after the layout views have been build, but before the em- ulated system has finished starting. The layout file object is sup- plied to the script in the file variable. We supply a function to be called after tags in the layout file have been resolved. This function does the following: • Looks up the analog axis inputs. • Looks up the view item that draws the outline of area where the yoke position is displayed. • Declares some variables to hold calculated values across function calls. • Supplies a function to be called when the views dimensions have been recomputed. • Supplies a function to be called before adding view items to the ren- der container when drawing a frame. • Supplies functions that will supply the bounds for the animated items. • Hides the warning that reminds the user to enable the layout plugin by setting the element state for the item to 0 (the text component is only drawn when the element state is 1). The view is looked up by name (value of its name attribute), and items within the view are looked up by ID (values of their id attributes). Layout view dimensions are recomputed in response to several events, including the window being resized, entering/leaving full screen mode, toggling visibility of item collections, and changing the zoom to screen area setting. When this happens, we need to update our size and animation scale factors. We get the bounds of the square where the yoke position is displayed, calculate the size for the animated items, and calculate the ratios of axis units to render target coordinates in each direction. Its more efficient to do these calculations only when the results may change. Before view items are added to the render target, we read the analog axis inputs and convert the values to coordinates positions for the an- imated items. The Y axis input uses larger values to aim higher, so we need to reverse the value by subtracting it from 0xff (255). We add in the coordinates of the top left corner of the square where were dis- playing the yoke position. We do this once each time the layout is drawn for efficiency, since we can use the values for all three ani- mated items. Finally, we supply bounds for the animated items when required. These functions need to return render_bounds objects giving the position and size of the items in render target coordinates. (Since the vertical and horizontal line elements each only move on a single axis, it would be possible to animate them using the layout file formats item animation features. Only the box at the intersection of the line actually requires scripting. Its done entirely using script- ing here for illustrative purposes.) The layout script environment The Lua environment is provided by the layout plugin. Its fairly mini- mal, only providing whats needed: • file giving the scripts layout file object. Has a device property for obtaining the device that caused the layout file to be loaded, and a views property for obtaining the layouts views (indexed by name). • machine giving MAMEs current running machine. • emu.device_enumerator, emu.palette_enumerator, emu.screen_enumerator, emu.cassette_enumerator, emu.image_enumerator and emu.slot_enumerator functions for obtaining specific device interfaces. • emu.attotime, emu.render_bounds and emu.render_color functions for creating attotime, bounds and colour objects. • emu.bitmap_ind8, emu.bitmap_ind16, emu.bitmap_ind32, emu.bitmap_ind64, emu.bitmap_yuy16, emu.bitmap_rgb32 and emu.bitmap_argb32 objects for creating bitmaps. • emu.print_verbose, emu.print_error, emu.print_warning, emu.print_info and emu.print_debug functions for diagnostic output. • Standard Lua tonumber, tostring, pairs and ipairs functions, and math, table and string objects for manipulating numbers, strings, ta- bles and other containers. • Standard Lua print function for text output to the console. Layout events MAME layout scripting uses an event-based model. Scripts can supply functions to be called after events occur, or when data is needed. There are three levels of events: layout file events, layout view events, and layout view item events. Layout file events Layout file events apply to the file as a whole, and not to an individ- ual view. Resolve tags file:set_resolve_tags_callback(cb) Called after the emulated system has finished starting, input and output tags in the layout have been resolved, and default item callbacks have been set up. This is a good time to look up inputs and set up view item event handlers. The callback function has no return value and takes no parame- ters. Call with nil as the argument to remove the event han- dler. Layout view events Layout view events apply to an individual view. Prepare items view:set_prepare_items_callback(cb) Called before the views items are added to the render target in preparation for drawing a video frame. The callback function has no return value and takes no parame- ters. Call with nil as the argument to remove the event han- dler. Preload view:set_preload_callback(cb) Called after pre-loading visible view elements. This can happen when the view is selected for the first time in a session, or when the user toggles visibility of an element collection on. Be aware that this can be called multiple times in a session and avoid repeating expensive tasks. The callback function has no return value and takes no parame- ters. Call with nil as the argument to remove the event han- dler. Dimensions recomputed view:set_recomputed_callback(cb) Called after view dimensions are recomputed. This happens in several situations, including the window being resized, entering or leaving full screen mode, toggling visibility of item collec- tions, and changes to the rotation and zoom to screen area set- tings. If youre animating the position of view items, this is a good time to calculate positions and scale factors. The callback function has no return value and takes no parame- ters. Call with nil as the argument to remove the event han- dler. Pointer updated view:set_pointer_updated_callback(cb) Called when a pointer enters, moves or changes button state over the view. The callback function is passed nine arguments: • The pointer type as a string. This will be mouse, pen, touch or unknown, and will not change for the lifetime of a pointer. • The pointer ID. This will be a non-negative integer that will not change for the lifetime of a pointer. Pointer ID values are recycled aggressively. • The device ID. This will be a non-negative integer that can be used to group pointers for recognising multi-touch ges- tures. • The horizontal position of the pointer in layout coordinates. • The vertical position of the pointer in layout coordinates. • A bit mask representing the currently pressed buttons. The primary button is the least significant bit. • A bit mask representing the buttons that were pressed in this update. The primary button is the least significant bit. • A bit mask representing the buttons that were released in this update. The primary button is the least significant bit. • The click count. This is positive for multi-click actions, or negative if a click is turned into a hold or drag. This only applies to the primary button. The callback function has no return value. Call with nil as the argument to remove the event handler. Pointer left view:set_pointer_left_callback(cb) Called when a pointer leaves the view normally. After receiving this event, the pointer ID may be reused for a new pointer. The callback function is passed seven arguments: • The pointer type as a string. This will be mouse, pen, touch or unknown, and will not change for the lifetime of a pointer. • The pointer ID. This will be a non-negative integer that will not change for the lifetime of a pointer. Pointer ID values are recycled aggressively. • The device ID. This will be a non-negative integer that can be used to group pointers for recognising multi-touch ges- tures. • The horizontal position of the pointer in layout coordinates. • The vertical position of the pointer in layout coordinates. • A bit mask representing the buttons that were released in this update. The primary button is the least significant bit. • The click count. This is positive for multi-click actions, or negative if a click is turned into a hold or drag. This only applies to the primary button. The callback function has no return value. Call with nil as the argument to remove the event handler. Pointer aborted view:set_pointer_aborted_callback(cb) Called when a pointer leaves the view abnormally. After receiv- ing this event, the pointer ID may be reused for a new pointer. The callback function is passed seven arguments: • The pointer type as a string. This will be mouse, pen, touch or unknown, and will not change for the lifetime of a pointer. • The pointer ID. This will be a non-negative integer that will not change for the lifetime of a pointer. Pointer ID values are recycled aggressively. • The device ID. This will be a non-negative integer that can be used to group pointers for recognising multi-touch ges- tures. • The horizontal position of the pointer in layout coordinates. • The vertical position of the pointer in layout coordinates. • A bit mask representing the buttons that were released in this update. The primary button is the least significant bit. • The click count. This is positive for multi-click actions, or negative if a click is turned into a hold or drag. This only applies to the primary button. The callback function has no return value. Call with nil as the argument to remove the event handler. Forget pointers view:set_forget_pointers_callback(cb) Called when the view should stop processing pointer input. This can happen in a number of situations, including: • The user activated a menu. • The view configuration will change. • The view will be deactivated. The callback function has no return value and takes no parame- ters. Call with nil as the argument to remove the event han- dler. Layout view item events Layout view item callbacks apply to individual items within a view. They are used to override items default element state, animation state, bounds and colour behaviour. Get element state item:set_element_state_callback(cb) Set callback for getting the items element state. This controls how the items element is drawn, for components that change ap- pearance depending on state, conditionally-drawn components, and component bounds/colour animation. Do not attempt to access the items element_state property from the callback, as it will re- sult in infinite recursion. The callback function must return an integer, and takes no para- meters. Call with nil as the argument to restore the default element state handler (based on the items XML attributes). Get animation state item:set_animation_state_callback(cb) Set callback for getting the items animation state. This is used for item bounds/colour animation. Do not attempt to access the items animation_state property from the callback, as it will result in infinite recursion. The callback function must return an integer, and takes no para- meters. Call with nil as the argument to restore the default animation state handler (based on the items XML attributes and animate child element). Get item bounds item:set_bounds_callback(cb) Set callback for getting the items bounds (position and size). Do not attempt to access the items bounds property from the callback, as it will result in infinite recursion. The callback function must return a render bounds object repre- senting the items bounds in render target coordinates (usually created by calling emu.render_bounds), and takes no parameters. Call with nil as the argument to restore the default bounds han- dler (based on the items animation state and bounds child ele- ments). Get item colour item:set_color_callback(cb) Set callback for getting the items colour (the element textures colours multiplied by this colour). Do not attempt to access the items color property from the callback, as it will result in infinite recursion. The callback function must return a render colour object repre- senting the ARGB colour (usually created by calling emu.ren- der_color), and takes no parameters. Call with nil as the argu- ment to restore the default colour handler (based on the items animation state and color child elements). Get item horizontal scroll window size item:set_scroll_size_x_callback(cb) Set callback for getting the items horizontal scroll window size. This allows the script to control how much of the element is displayed by the item. Do not attempt to access the items scroll_size_x property from the callback, as it will result in infinite recursion. The callback function must return a floating-point number repre- senting the horizontal window size as a proportion of the asso- ciated elements width, and takes no parameters. A value of 1.0 will display the entire width of the element; smaller values will display proportionally smaller parts of the element. Call with nil as the argument to restore the default horizontal scroll window size handler (based on the xscroll child element). Get item vertical scroll window size item:set_scroll_size_y_callback(cb) Set callback for getting the items vertical scroll window size. This allows the script to control how much of the element is displayed by the item. Do not attempt to access the items scroll_size_y property from the callback, as it will result in infinite recursion. The callback function must return a floating-point number repre- senting the vertical window size as a proportion of the associ- ated elements height, and takes no parameters. A value of 1.0 will display the entire height of the element; smaller values will display proportionally smaller parts of the element. Call with nil as the argument to restore the default vertical scroll window size handler (based on the xscroll child element). Get item horizontal scroll position item:set_scroll_pos_x_callback(cb) Set callback for getting the items horizontal scroll position. This allows the script to control which part of the element is displayed by the item. Do not attempt to access the items scroll_pos_x property from the callback, as this will result in infinite recursion. The callback must return a floating-point number, and takes no parameters. A value of 0.0 aligns the left edge of the element with the left edge of the item; larger values pan right. Call with nil as the argument to restore the default horizontal scroll position handler (based on bindings in the xscroll child element). Get item vertical scroll position item:set_scroll_pos_y_callback(cb) Set callback for getting the items vertical scroll position. This allows the script to control which part of the element is displayed by the item. Do not attempt to access the items scroll_pos_y property from the callback, as this will result in infinite recursion. The callback must return a floating-point number, and takes no parameters. A value of 0.0 aligns the top edge of the element with the top edge of the item; larger values pan down. Call with nil as the argument to restore the default vertical scroll position handler (based on bindings in the yscroll child ele- ment). Layout element events Layout element events apply to an individual visual element definition. Draw element:set_draw_callback(cb) Set callback for additional drawing after the elements compo- nents have been drawn. This gives the script direct control over the final texture when an element item is drawn. The callback is passed two arguments: the element state (an in- teger) and the 32-bit ARGB bitmap at the required size. The callback must not attempt to resize the bitmap. Call with nil as the argument to remove the event handler. Object Finders • Introduction • Types of object finder • Finding resources • Connections between devices • Object finder arrays • Optional object finders • Optional system components • Optional resources • Object finder types in more detail • Device finders • Memory system object finders • I/O port finders • Address space finders • Memory pointer finders • Output finders Introduction Object finders are an important part of the glue MAME provides to tie the devices that make up an emulated system together. Object finders are used to specify connections between devices, to efficiently access resources, and to check that necessary resources are available on vali- dation. Object finders search for a target object by tag relative to a base de- vice. Some types of object finder require additional parameters. Most object finders have required and optional versions. The required versions will raise an error if the target object is not found. This will prevent a device from starting or cause a validation error. The optional versions will log a verbose message if the target object is not found, and provide additional members for testing whether the tar- get object was found or not. Object finder classes are declared in the header src/emu/devfind.h and have Doxygen format API documentation. Types of object finder required_device<DeviceClass>, optional_device<DeviceClass> Finds a device. The template argument DeviceClass should be a class derived from device_t or device_interface. required_memory_region, optional_memory_region Finds a memory region, usually from ROM definitions. The target is the memory_region object. required_memory_bank, optional_memory_bank Finds a memory bank instantiated in an address map. The target is the memory_bank object. memory_bank_creator Finds a memory bank instantiated in an address map, or creates it if it doesnt exist. The target is the memory_bank object. There is no optional version, because the target object will al- ways be found or created. required_ioport, optional_ioport Finds an I/O port from a devices input port definitions. The target is the ioport_port object. required_address_space, optional_address_space Finds a devices address space. The target is the address_space object. required_region_ptr<PointerType>, optional_region_ptr<PointerType> Finds the base pointer of a memory region, usually from ROM def- initions. The template argument PointerType is the target type (usually an unsigned integer type). The target is the first el- ement in the memory region. required_shared_ptr<PointerType>, optional_shared_ptr<PointerType> Finds the base pointer of a memory share instantiated in an ad- dress map. The template argument PointerType is the target type (usually an unsigned integer type). The target is the first el- ement in the memory share. memory_share_creator<PointerType> Finds the base pointer of a memory share instantiated in an ad- dress map, or creates it if it doesnt exist. The template argu- ment PointerType is the target type (usually an unsigned integer type). The target is the first element in the memory share. There is no optional version, because the target object will al- ways be found or created. Finding resources Well start with a simple example of a device that uses object finders to access its own child devices, inputs and ROM region. The code sam- ples here are based on the Apple II Parallel Printer Interface card, but a lot of things have been removed for clarity. Object finders are declared as members of the device class: class a2bus_parprn_device : public device_t, public device_a2bus_card_interface { public: a2bus_parprn_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock); virtual void write_c0nx(u8 offset, u8 data) override; virtual u8 read_cnxx(u8 offset) override; protected: virtual tiny_rom_entry const *device_rom_region() const override; virtual void device_add_mconfig(machine_config &config) override; virtual ioport_constructor device_input_ports() const override; private: required_device<centronics_device> m_printer_conn; required_device<output_latch_device> m_printer_out; required_ioport m_input_config; required_region_ptr<u8> m_prom; }; We want to find a centronics_device, an output_latch_device, an I/O port, and an 8-bit memory region. In the constructor, we set the initial target for the object finders: a2bus_parprn_device::a2bus_parprn_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : device_t(mconfig, A2BUS_PARPRN, tag, owner, clock), device_a2bus_card_interface(mconfig, *this), m_printer_conn(*this, "prn"), m_printer_out(*this, "prn_out"), m_input_config(*this, "CFG"), m_prom(*this, "prom") { } Each object finder takes a base device and tag as constructor argu- ments. The base device supplied at construction serves two purposes. Most obviously, the tag is specified relative to this device. Possibly more importantly, the object finder registers itself with this device so that it will be called to perform validation and object resolution. Note that the object finders do not copy the tag strings. The caller must ensure the tag string remains valid until after validation and/or object resolution is complete. The memory region and I/O port come from the ROM definition and input definition, respectively: namespace { ROM_START(parprn) ROM_REGION(0x100, "prom", 0) ROM_LOAD( "prom.b4", 0x0000, 0x0100, BAD_DUMP CRC(00b742ca) SHA1(c67888354aa013f9cb882eeeed924e292734e717) ) ROM_END INPUT_PORTS_START(parprn) PORT_START("CFG") PORT_CONFNAME(0x01, 0x00, "Acknowledge latching edge") PORT_CONFSETTING( 0x00, "Falling (/Y-B)") PORT_CONFSETTING( 0x01, "Rising (Y-B)") PORT_CONFNAME(0x06, 0x02, "Printer ready") PORT_CONFSETTING( 0x00, "Always (S5-C-D)") PORT_CONFSETTING( 0x02, "Acknowledge latch (Z-C-D)") PORT_CONFSETTING( 0x04, "ACK (Y-C-D)") PORT_CONFSETTING( 0x06, "/ACK (/Y-C-D)") PORT_CONFNAME(0x08, 0x00, "Strobe polarity") PORT_CONFSETTING( 0x00, "Negative (S5-A-/X, GND-X)") PORT_CONFSETTING( 0x08, "Positive (S5-X, GND-A-/X)") PORT_CONFNAME(0x10, 0x10, "Character width") PORT_CONFSETTING( 0x00, "7-bit") PORT_CONFSETTING( 0x10, "8-bit") INPUT_PORTS_END } // anonymous namespace tiny_rom_entry const *a2bus_parprn_device::device_rom_region() const { return ROM_NAME(parprn); } ioport_constructor a2bus_parprn_device::device_input_ports() const { return INPUT_PORTS_NAME(parprn); } Note that the tags "prom" and "CFG" match the tags passed to the object finders on construction. Child devices are instantiated in the devices machine configuration member function: void a2bus_parprn_device::device_add_mconfig(machine_config &config) { CENTRONICS(config, m_printer_conn, centronics_devices, "printer"); m_printer_conn->ack_handler().set(FUNC(a2bus_parprn_device::ack_w)); OUTPUT_LATCH(config, m_printer_out); m_printer_conn->set_output_latch(*m_printer_out); } Object finders are passed to device types to provide tags when instan- tiating child devices. After instantiating a child device in this way, the object finder can be used like a pointer to the device until the end of the machine configuration member function. Note that to use an object finder like this, its base device must be the same as the device being configured (the this pointer of the machine configuration member function). After the emulated machine has been started, the object finders can be used in much the same way as pointers: void a2bus_parprn_device::write_c0nx(u8 offset, u8 data) { ioport_value const cfg(m_input_config->read()); m_printer_out->write(data & (BIT(cfg, 8) ? 0xffU : 0x7fU)); m_printer_conn->write_strobe(BIT(~cfg, 3)); } u8 a2bus_parprn_device::read_cnxx(u8 offset) { offset ^= 0x40U; return m_prom[offset]; } For convenience, object finders that target the base pointer of memory regions and shares can be indexed like arrays. Connections between devices Devices need to be connected together within a system. For example the Sun SBus device needs access to the host CPU and address space. Heres how we declare the object finders in the device class (with all dis- tractions removed): DECLARE_DEVICE_TYPE(SBUS, sbus_device) class sbus_device : public device_t, public device_memory_interface { template <typename T, typename U> sbus_device( machine_config const &mconfig, char const *tag, device_t *owner, u32 clock, T &&cpu_tag, U &&space_tag, int space_num) : sbus_device(mconfig, tag, owner, clock) { set_cpu(std::forward<T>(cpu_tag)); set_type1space(std::forward<U>(space_tag), space_num); } sbus_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : device_t(mconfig, SBUS, tag, owner, clock), device_memory_interface(mconfig, *this), m_maincpu(*this, finder_base::DUMMY_TAG), m_type1space(*this, finder_base::DUMMY_TAG, -1) { } template <typename T> void set_cpu(T &&tag) { m_maincpu.set_tag(std::forward<T>(tag)); } template <typename T> void set_type1space(T &&tag, int num) { m_type1space.set_tag(std::forward<T>(tag), num); } protected: required_device<sparc_base_device> m_maincpu; required_address_space m_type1space; }; There are several things to take note of here: • Object finder members are declared for the things the device needs to access. • The device doesnt know how it will fit into a larger system, the ob- ject finders are constructed with dummy arguments. • Configuration member functions are provided to set the tag for the host CPU, and the tag and index for the type 1 address space. • In addition to the standard device constructor, a constructor with additional parameters for setting the CPU and type 1 address space is provided. The constant finder_base::DUMMY_TAG is guaranteed to be invalid and will not resolve to an object. This makes it easy to detect incomplete configuration and report an error. Address spaces are numbered from zero, so a negative address space number is invalid. The member functions for configuring object finders take a universal reference to a tag-like object (templated type with && qualifier), as well as any other parameters needed by the specific type of object finder. An address space finder needs an address space number in addi- tion to a tag-like object. So whats a tag-like object? Three things are supported: • A C string pointer (char const *) representing a tag relative to the device being configured. Note that the object finder will not copy the string. The caller must ensure it remains valid until resolution and/or validation is complete. • Another object finder. The object finder will take on its current target. • For device finders, a reference to an instance of the target device type, setting the target to that device. Note that this will not work if the device is subsequently replaced in the machine configura- tion. Its most often used with *this. The additional constructor that sets initial configuration delegates to the standard constructor and then calls the configuration member func- tions. Its purely for convenience. When we want to instantiate this device and hook it up, we do this: SPARCV7(config, m_maincpu, 20'000'000); ADDRESS_MAP_BANK(config, m_type1space); SBUS(config, m_sbus, 20'000'000); m_sbus->set_cpu(m_maincpu); m_sbus->set_type1space(m_type1space, 0); We supply the same object finders to instantiate the CPU and address space devices, and to configure the SBus device. Note that we could also use literal C strings to configure the SBus de- vice, at the cost of needing to update the tags in multiple places if they change: SBUS(config, m_sbus, 20'000'000); m_sbus->set_cpu("maincpu"); m_sbus->set_type1space("type1", 0); If we want to use the convenience constructor, we just supply addi- tional arguments when instantiating the device: SBUS(config, m_sbus, 20'000'000, m_maincpu, m_type1space, 0); Object finder arrays Many systems have multiple similar devices, I/O ports or other re- sources that can be logically organised as an array. To simplify these use cases, object finder array types are provided. The object finder array type names have _array added to them: +------------------------+----------------------------+ | required_device | required_device_array | +------------------------+----------------------------+ | optional_device | optional_device_array | +------------------------+----------------------------+ | required_memory_region | required_memory_region_ar- | | | ray | +------------------------+----------------------------+ | optional_memory_region | optional_memory_region_ar- | | | ray | +------------------------+----------------------------+ | required_memory_bank | required_memory_bank_array | +------------------------+----------------------------+ | optional_memory_bank | optional_memory_bank_array | +------------------------+----------------------------+ | memory_bank_creator | memory_bank_array_creator | +------------------------+----------------------------+ | required_ioport | required_ioport_array | +------------------------+----------------------------+ | optional_ioport | optional_ioport_array | +------------------------+----------------------------+ | required_address_space | required_address_space_ar- | | | ray | +------------------------+----------------------------+ | optional_address_space | optional_address_space_ar- | | | ray | +------------------------+----------------------------+ | required_region_ptr | required_region_ptr_array | +------------------------+----------------------------+ | optional_region_ptr | optional_region_ptr_array | +------------------------+----------------------------+ | required_shared_ptr | required_shared_ptr_array | +------------------------+----------------------------+ | optional_shared_ptr | optional_shared_ptr_array | +------------------------+----------------------------+ | memory_share_creator | memory_share_array_creator | +------------------------+----------------------------+ A common case for an object array finder is a key matrix: class keyboard_base : public device_t, public device_mac_keyboard_interface { protected: keyboard_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) : device_t(mconfig, type, tag, owner, clock), device_mac_keyboard_interface(mconfig, *this), m_rows(*this, "ROW%u", 0U) { } u8 bus_r() { u8 result(0xffU); for (unsigned i = 0U; m_rows.size() > i; ++i) { if (!BIT(m_row_drive, i)) result &= m_rows[i]->read(); } return result; } required_ioport_array<10> m_rows; }; Constructing an object finder array is similar to constructing an ob- ject finder, except that rather than just a tag you supply a tag format string and index offset. In this case, the tags of the I/O ports in the array will be ROW0, ROW1, ROW2, ROW9. Note that the object finder array allocates dynamic storage for the tags, which remain valid until destruction. The object finder array is used in much the same way as a std::array of the underlying object finder type. It supports indexing, iterators, and range-based for loops. Because an index offset is specified, the tags dont need to use zero-based indices. Its common to use one-based indexing like this: class dooyong_state : public driver_device { protected: dooyong_state(machine_config const &mconfig, device_type type, char const *tag) : driver_device(mconfig, type, tag), m_bg(*this, "bg%u", 1U), m_fg(*this, "fg%u", 1U) { } optional_device_array<dooyong_rom_tilemap_device, 2> m_bg; optional_device_array<dooyong_rom_tilemap_device, 2> m_fg; }; This causes m_bg to find devices with tags bg1 and bg2, while m_fg finds devices with tags fg1 and fg2. Note that the indexes into the object finder arrays are still zero-based like any other C array. Its also possible to other format conversions, like hexadecimal (%x and %X) or character (%c): class eurit_state : public driver_device { public: eurit_state(machine_config const &mconfig, device_type type, char const *tag) : driver_device(mconfig, type, tag), m_keys(*this, "KEY%c", 'A') { } private: required_ioport_array<5> m_keys; }; In this case, the key matrix ports use tags KEYA, KEYB, KEYC, KEYD and KEYE. When the tags dont follow a simple ascending sequence, you can supply a brace-enclosed initialiser list of tags: class seabattl_state : public driver_device { public: seabattl_state(machine_config const &mconfig, device_type type, char const *tag) : driver_device(mconfig, type, tag), m_digits(*this, { "sc_thousand", "sc_hundred", "sc_half", "sc_unity", "tm_half", "tm_unity" }) { } private: required_device_array<dm9368_device, 6> m_digits; }; If the underlying object finders require additional constructor argu- ments, supply them after the tag format and index offset (the same val- ues will be used for all elements of the array): class dreamwld_state : public driver_device { public: dreamwld_state(machine_config const &mconfig, device_type type, char const *tag) : driver_device(mconfig, type, tag), m_vram(*this, "vram_%u", 0U, 0x2000U, ENDIANNESS_BIG) { } private: memory_share_array_creator<u16, 2> m_vram; }; This finds or creates memory shares with tags vram_0 and vram_1, each of which is 8 KiB organised as 4,096 big-Endian 16-bit words. Optional object finders Optional object finders dont raise an error if the target object isnt found. This is useful in two situations: driver_device implementations (state classes) representing a family of systems where some components arent present in all configurations, and devices that can optionally use a resource. Optional object finders provide additional member functions for testing whether the target object was found. Optional system components Often a class is used to represent a family of related systems. If a component isnt present in all configurations, it may be convenient to use an optional object finder to access it. Well use the Sega X-board device as an example: class segaxbd_state : public device_t { protected: segaxbd_state(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) : device_t(mconfig, type, tag, owner, clock), m_soundcpu(*this, "soundcpu"), m_soundcpu2(*this, "soundcpu2"), m_segaic16vid(*this, "segaic16vid"), m_pc_0(0), m_lastsurv_mux(0), m_adc_ports(*this, "ADC%u", 0), m_mux_ports(*this, "MUX%u", 0) { } optional_device<z80_device> m_soundcpu; optional_device<z80_device> m_soundcpu2; required_device<mb3773_device> m_watchdog; required_device<segaic16_video_device> m_segaic16vid; bool m_adc_reverse[8]; u8 m_pc_0; u8 m_lastsurv_mux; optional_ioport_array<8> m_adc_ports; optional_ioport_array<4> m_mux_ports; }; The optional_device and optional_ioport_array members are declared and constructed in the usual way. Before accessing the target object, we call an object finders found() member function to check whether its present in the system (the explicit cast-to-Boolean operator can be used for the same purpose): void segaxbd_state::pc_0_w(u8 data) { m_pc_0 = data; m_watchdog->write_line_ck(BIT(data, 6)); m_segaic16vid->set_display_enable(data & 0x20); if (m_soundcpu.found()) m_soundcpu->set_input_line(INPUT_LINE_RESET, (data & 0x01) ? CLEAR_LINE : ASSERT_LINE); if (m_soundcpu2.found()) m_soundcpu2->set_input_line(INPUT_LINE_RESET, (data & 0x01) ? CLEAR_LINE : ASSERT_LINE); } Optional I/O ports provide a convenience member function called read_safe that reads the port value if present, or returns the supplied default value otherwise: u8 segaxbd_state::analog_r() { int const which = (m_pc_0 >> 2) & 7; u8 value = m_adc_ports[which].read_safe(0x10); if (m_adc_reverse[which]) value = 255 - value; return value; } u8 segaxbd_state::lastsurv_port_r() { return m_mux_ports[m_lastsurv_mux].read_safe(0xff); } The ADC ports return 0x10 (16 decimal) if they are not present, while the multiplexed digital ports return 0xff (255 decimal) if they are not present. Note that read_safe is a member of the optional_ioport it- self, and not a member of the target ioport_port object (the op- tional_ioport is not dereferenced when using it). There are some disadvantages to using optional object finders: • Theres no way to distinguish between the target not being present, and the target not being found due to mismatched tags, making it more error-prone. • Checking whether the target is present may use CPU branch prediction resources, potentially hurting performance if it happens very fre- quently. Consider whether optional object finders are the best solution, or whether creating a derived class for the system with additional compo- nents is more appropriate. Optional resources Some devices can optionally use certain resources. If the host system doesnt supply them, the device will still function, although some func- tionality may not be available. For example, the Virtual Boy cartridge slot responds to three address spaces, called EXP, CHIP and ROM. If the host system will never use one or more of them, it doesnt need to supply a place for the cartridge to install the corresponding handlers. (For example a copier may only use the ROM space.) Lets look at how this is implemented. The Virtual Boy cartridge slot device declares optional_address_space members for the three address spaces, offs_t members for the base addresses in these spaces, and in- line member functions for configuring them: class vboy_cart_slot_device : public device_t, public device_image_interface, public device_single_card_slot_interface<device_vboy_cart_interface> { public: vboy_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0U); template <typename T> void set_exp(T &&tag, int no, offs_t base) { m_exp_space.set_tag(std::forward<T>(tag), no); m_exp_base = base; } template <typename T> void set_chip(T &&tag, int no, offs_t base) { m_chip_space.set_tag(std::forward<T>(tag), no); m_chip_base = base; } template <typename T> void set_rom(T &&tag, int no, offs_t base) { m_rom_space.set_tag(std::forward<T>(tag), no); m_rom_base = base; } protected: virtual void device_start() override; private: optional_address_space m_exp_space; optional_address_space m_chip_space; optional_address_space m_rom_space; offs_t m_exp_base; offs_t m_chip_base; offs_t m_rom_base; device_vboy_cart_interface *m_cart; }; DECLARE_DEVICE_TYPE(VBOY_CART_SLOT, vboy_cart_slot_device) The object finders are constructed with dummy values for the tags and space numbers (finder_base::DUMMY_TAG and -1): vboy_cart_slot_device::vboy_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : device_t(mconfig, VBOY_CART_SLOT, tag, owner, clock), device_image_interface(mconfig, *this), device_single_card_slot_interface<device_vboy_cart_interface>(mconfig, *this), m_exp_space(*this, finder_base::DUMMY_TAG, -1, 32), m_chip_space(*this, finder_base::DUMMY_TAG, -1, 32), m_rom_space(*this, finder_base::DUMMY_TAG, -1, 32), m_exp_base(0U), m_chip_base(0U), m_rom_base(0U), m_cart(nullptr) { } To help detect configuration errors, well check for cases where address spaces have been configured but arent present: void vboy_cart_slot_device::device_start() { if (!m_exp_space && ((m_exp_space.finder_tag() != finder_base::DUMMY_TAG) || (m_exp_space.spacenum() >= 0))) throw emu_fatalerror("%s: Address space %d of device %s not found (EXP)\n", tag(), m_exp_space.spacenum(), m_exp_space.finder_tag()); if (!m_chip_space && ((m_chip_space.finder_tag() != finder_base::DUMMY_TAG) || (m_chip_space.spacenum() >= 0))) throw emu_fatalerror("%s: Address space %d of device %s not found (CHIP)\n", tag(), m_chip_space.spacenum(), m_chip_space.finder_tag()); if (!m_rom_space && ((m_rom_space.finder_tag() != finder_base::DUMMY_TAG) || (m_rom_space.spacenum() >= 0))) throw emu_fatalerror("%s: Address space %d of device %s not found (ROM)\n", tag(), m_rom_space.spacenum(), m_rom_space.finder_tag()); m_cart = get_card_device(); } Object finder types in more detail All object finders provide configuration functionality: char const *finder_tag() const { return m_tag; } std::pair<device_t &, char const *> finder_target(); void set_tag(device_t &base, char const *tag); void set_tag(char const *tag); void set_tag(finder_base const &finder); The finder_tag and finder_target member function provides access to the currently configured target. Note that the tag returned by finder tag is relative to the base device. It is not sufficient on its own to identify the target. The set_tag member functions configure the target of the object finder. These members must not be called after the object finder is resolved. The first form configures the base device and relative tag. The second form sets the relative tag and also implicitly sets the base device to the device that is currently being configured. This form must only be called from machine configuration functions. The third form sets the base object and relative tag to the current target of another object finder. Note that the set_tag member functions do not copy the relative tag. It is the callers responsibility to ensure the C string remains valid until the object finder is resolved (or reconfigured with a different tag). The base device must also be valid at resolution time. This may not be the case if the device could be removed or replaced later. All object finders provide the same interface for accessing the target object: ObjectClass *target() const; operator ObjectClass *() const; ObjectClass *operator->() const; These members all provide access to the target object. The target mem- ber function and cast-to-pointer operator will return nullptr if the target has not been found. The pointer member access operator asserts that the target has been found. Optional object finders additionally provide members for testing whether the target object has been found: bool found() const; explicit operator bool() const; These members return true if the target was found, on the assumption that the target pointer will be non-null if the target was found. Device finders Device finders require one template argument for the expected device class. This should derive from either device_t or device_interface. The target device object must either be an instance of this class, an instance of a class that derives from it. A warning message is logged if a matching device is found but it is not an instance of the expected class. Device finders provide an additional set_tag overload: set_tag(DeviceClass &object); This is equivalent to calling set_tag(object, DEVICE_SELF). Note that the device object must not be removed or replaced before the object finder is resolved. Memory system object finders The memory system object finders, required_memory_region, optional_mem- ory_region, required_memory_bank, optional_memory_bank and mem- ory_bank_creator, do not have any special functionality. They are of- ten used in place of literal tags when installing memory banks in an address space. Example using memory bank finders in an address map: class qvt70_state : public driver_device { public: qvt70_state(machine_config const &mconfig, device_type type, char const *tag) : driver_device(mconfig, type, tag), m_rombank(*this, "rom"), m_rambank(*this, "ram%d", 0U), { } private: required_memory_bank m_rombank; required_memory_bank_array<2> m_rambank; void mem_map(address_map &map); void rombank_w(u8 data); }; void qvt70_state::mem_map(address_map &map) { map(0x0000, 0x7fff).bankr(m_rombank); map(0x8000, 0x8000).w(FUNC(qvt70_state::rombank_w)); map(0xa000, 0xbfff).ram(); map(0xc000, 0xdfff).bankrw(m_rambank[0]); map(0xe000, 0xffff).bankrw(m_rambank[1]); } Example using a memory bank creator to install a memory bank dynami- cally: class vegaeo_state : public eolith_state { public: vegaeo_state(machine_config const &mconfig, device_type type, char const *tag) : eolith_state(mconfig, type, tag), m_qs1000_bank(*this, "qs1000_bank") { } void init_vegaeo(); private: memory_bank_creator m_qs1000_bank; }; void vegaeo_state::init_vegaeo() { // Set up the QS1000 program ROM banking, taking care not to overlap the internal RAM m_qs1000->cpu().space(AS_IO).install_read_bank(0x0100, 0xffff, m_qs1000_bank); m_qs1000_bank->configure_entries(0, 8, memregion("qs1000:cpu")->base() + 0x100, 0x10000); init_speedup(); } I/O port finders Optional I/O port finders provide an additional convenience member function: ioport_value read_safe(ioport_value defval); This will read the ports value if the target I/O port was found, or re- turn defval otherwise. It is useful in situations where certain input devices are not always present. Address space finders Address space finders accept an additional argument for the address space number to find. A required data width can optionally be supplied to the constructor. address_space_finder(device_t &base, char const *tag, int spacenum, u8 width = 0); void set_tag(device_t &base, char const *tag, int spacenum); void set_tag(char const *tag, int spacenum); void set_tag(finder_base const &finder, int spacenum); template <bool R> void set_tag(address_space_finder<R> const &finder); The base device and tag must identify a device that implements de- vice_memory_interface. The address space number is a zero-based index to one of the devices address spaces. If the width is non-zero, it must match the target address spaces data width in bits. If the target address space exists but has a different data width, a warning message will be logged, and it will be treated as not being found. If the width is zero (the default argument value), the target address spaces data width wont be checked. Member functions are also provided to get the configured address space number and set the required data width: int spacenum() const; void set_data_width(u8 width); Memory pointer finders The memory pointer finders, required_region_ptr, optional_region_ptr, required_shared_ptr, optional_shared_ptr and memory_share_creator, all require one template argument for the element type of the memory area. This should usually be an explicitly-sized unsigned integer type (u8, u16, u32 or u64). The size of this type is compared to the width of the memory area. If it doesnt match, a warning message is logged and the region or share is treated as not being found. The memory pointer finders provide an array access operator, and mem- bers for accessing the size of the memory area: PointerType &operator[](int index) const; size_t length() const; size_t bytes() const; The array access operator returns a non-const reference to an element of the memory area. The index is in units of the element type; it must be non-negative and less than the length of the memory area. The length member returns the number of elements in the memory area. The bytes member returns the size of the memory area in bytes. These mem- bers should not be called if the target region/share has not been found. The memory_share_creator requires additional constructor arguments for the size and Endianness of the memory share: memory_share_creator(device_t &base, char const *tag, size_t bytes, endianness_t endianness); The size is specified in bytes. If an existing memory share is found, it is an error if its size does not match the specified size. If the width is wider than eight bits and an existing memory share is found, it is an error if its Endianness does not match the specified Endian- ness. The memory_share_creator provides additional members for accessing properties of the memory share: endianness_t endianness() const; u8 bitwidth() const; u8 bytewidth() const; These members return the Endianness, width in bits and width in bytes of the memory share, respectively. They must not be called if the mem- ory share has not been found. Output finders Output finders are used for exposing outputs that can be used by the artwork system, or by external programs. A common application using an external program is a control panel or cabinet lighting controller. Output finders are not really object finders, but theyre described here because theyre used in a similar way. There are a number of important differences to be aware of: • Output finders always create outputs if they do not exist. • Output finders must be manually resolved, they are not automatically resolved. • Output finders cannot have their target changed after construction. • Output finders are array-like, and support an arbitrary number of di- mensions. • Output names are global, the base device has no influence. (This will change in the future.) Output finders take a variable number of template arguments correspond- ing to the number of array dimensions you want. Lets look at an exam- ple that uses zero-, one- and two-dimensional output finders: class mmd2_state : public driver_device { public: mmd2_state(machine_config const &mconfig, device_type type, char const *tag) : driver_device(mconfig, type, tag), m_digits(*this, "digit%u", 0U), m_p(*this, "p%u_%u", 0U, 0U), m_led_halt(*this, "led_halt"), m_led_hold(*this, "led_hold") { } protected: virtual void machine_start() override; private: void round_leds_w(offs_t, u8); void digit_w(u8 data); void status_callback(u8 data); u8 m_digit; output_finder<9> m_digits; output_finder<3, 8> m_p; output_finder<> m_led_halt; output_finder<> m_led_hold; }; The m_led_halt and m_led_hold members are zero-dimensional output find- ers. They find a single output each. The m_digits member is a one-di- mensional output finder. It finds nine outputs organised as a sin- gle-dimensional array. The m_p member is a two-dimensional output finder. It finds 24 outputs organised as three rows of eight columns each. Larger numbers of dimensions are supported. The output finder constructor takes a base device reference, a format string, and an index offset for each dimension. In this case, all the offsets are zero. The one-dimensional output finder m_digits will find outputs digit0, digit1, digit2, digit8. The two-dimensional output finder m_p will find the outputs p0_0, p0_1, p0_7 for the first row, p1_0, p1_1, p1_7 for the second row, and p2_0, p2_1, p2_7 for the third row. You must call resolve on each output finder before it can be used. This should be done at start time for the output values to be included in save states: void mmd2_state::machine_start() { m_digits.resolve(); m_p.resolve(); m_led_halt.resolve(); m_led_hold.resolve(); save_item(NAME(m_digit)); } Output finders provide operators allowing them to be assigned from or cast to 32-bit signed integers. The assignment operator will send a notification if the new value is different to the outputs current value. operator s32() const; s32 operator=(s32 value); To set output values, assign through the output finders, as you would with an array of the same rank: void mmd2_state::round_leds_w(offs_t offset, u8 data) { for (u8 i = 0; i < 8; i++) m_p[offset][i] = BIT(~data, i); } void mmd2_state::digit_w(u8 data) { if (m_digit < 9) m_digits[m_digit] = data; } void mmd2_state::status_callback(u8 data) { m_led_halt = (~data & i8080_cpu_device::STATUS_HLTA) ? 1 : 0; m_led_hold = (data & i8080_cpu_device::STATUS_WO) ? 1 : 0; } Input System • Introduction • Components • Input device • Input device item • I/O port field • Input manager • I/O port manager • Structures and data types • Input code • Input sequence • Input provider modules • Player positions • Updating I/O port fields • Updating digital fields • Updating absolute analog fields • Updating relative analog fields Introduction The variety of systems MAME emulates, as well as the variation in host systems and peripherals, necessitates a flexible, configurable input system. Note that the input system is concerned with low-level user input. High-level user interaction, involving things like text input and pointing devices, is handled separately. Components From the emulated systems point of view, the input system has the fol- lowing conceptual components. Input device Input devices supply input values. An input device typically corre- sponds to a physical device in the host system, for example a keyboard, mouse or game controller. However, there isnt always a one-to-one cor- respondence between input devices and physical devices. For example the SDL keyboard provider module aggregates all keyboards into a single input device, and the Win32 lightgun provider module can present two input devices using input from a single mouse. Input devices are identified by their device class (keyboard, mouse, joystick or lightgun) and device number within the class. Input provider modules can also supply an implementation-dependent identifier to allow the user to configure stable device numbering. Note that input devices are unrelated to emulated devices (device_t im- plementations) despite the similar name. Input device item Also known as a control, and input device item corresponds to a input source that produces a single value. This usually corresponds to a physical control or sensor, for example a joystick axis, a button or an accelerometer. MAME supports three kinds of controls: switches, absolute axes and rel- ative axes: • Switches produce the value 0 when inactive (released or off) or 1 when active (pressed or on). • Absolute axes produce a value normalised to the range -65,536 to 65,536 with zero corresponding to the neutral position. • Relative axes produce a value corresponding to the movement since the previous input update. Mouse-like devices scale values to approxi- mately 512 per nominal 100 DPI pixel. Negative axis values should correspond to directions up, to the left, away from the player, or anti-clockwise. For single-ended axes (e.g. pedals or displacement-sensitive triggers and buttons), only zero and the negative portion of the range should be used. Switches are used to represent controls that naturally have two dis- tinct states, like buttons and toggle switches. Absolute axes are used to represent controls with a definite range and/or neutral position. Examples include steering wheels with limit stops, joystick axes, and displacement-sensitive triggers. Relative axes are used to represent controls with an effectively infi- nite range. Examples include mouse/trackball axes, incremental encoder dials, and gyroscopes. Accelerometers and force sensing joystick axes should be represented as absolute axes, even though the range is theoretically open-ended. In practice, there is a limit to the range the transducers can report, which is usually substantially larger than needed for normal operation. Input device items are identified by their associated devices class and device number along with an input item ID. MAME supplies item IDs for common types of controls. Additional controls or controls that do not correspond to a common type are dynamically assigned item IDs. MAME supports hundreds to items per input device. I/O port field An I/O port field represents an input source in an emulated device or system. Most types of I/O port fields can be assigned one or more com- binations of controls, allowing the user to control the input to the emulated system. Similarly to input device items, there are multiple types of I/O port fields: • Digital fields function as switches that produce one of two distinct values. They are used for keyboard keys, eight-way joystick direc- tion switches, toggle switches, photointerruptors and other emulated inputs that function as two-position switches. • Absolute analog fields have a range with defined minimum, maximum and neutral positions. They are used for analog joystick axes, displace- ment-sensitive pedals, paddle knobs, and other emulated inputs with a defined range. • Relative analog fields have a range with defined minimum, maximum and starting positions. On each update, the value accumulates and wraps when it passes either end of the range. Functionally, this is like the output of an up/down counter connected to an incremental encoder. They are used for mouse/trackball axes, steering wheels without limit stops, and other emulated inputs that have no range limits. • DIP switch, configuration and adjuster fields allow the user to set the value through MAMEs user interface. • Additional special field types are used to produce fixed or program- matically generated values. A digital field appears to the user as a single assignable input, which accepts switch values. An analog field appears to the user as three assignable inputs: an axis input, which accepts axis values; and an increment input and a decre- ment input which accept switch values. Input manager The input manager has several responsibilities: • Tracking the available input devices in the system. • Reading input values. • Converting between internal identifier values, configuration token strings and display strings. In practice, emulated devices and systems rarely interact with the in- put manager directly. The most common reason to access the input man- ager is implementing special debug controls, which should be disabled in release builds. Plugins that respond to input need to call the in- put manager to read inputs. I/O port manager The I/O port managers primary responsibilities include: • Managing assignments of controls to I/O port fields and user inter- face actions. • Reading input values via the input manager and updating I/O port field values. Like the input manager, the I/O port manager is largely transparent to emulated devices and systems. You just need to set up your I/O ports and fields, and the I/O port manager handles the rest. Structures and data types The following data types are used for dealing with input. Input code An input code specifies an input device item and how it should be in- terpreted. It is a tuple consisting of the following values: device class, device number, item class, item modifier and item ID: • The device class, device number and item ID together identify the in- put device item to read. • The item class specifies the type of output value desired: switch, absolute axis or relative axis. Axis values can be converted to switch values by specifying an appropriate modifier. • The modifier specifies how a value should be interpreted. Valid op- tions depend on the type of input device item and the specified item class. If the specified input item is a switch, it can only be read using the switch class, and no modifiers are supported. Attempting to read a switch as an absolute or relative axis always returns zero. If the specified input item is an absolute axis, it can be read as an absolute axis or as a switch: • Reading an absolute axis item as an absolute axis returns the current state of the control, potentially transformed if a modifier is speci- fied. Supported modifiers are reverse to reverse the range of the control, positive to map the positive range of the control onto the output (zero corresponding to -65,536 and 65,536 corresponding to 65,536), and negative to map the negative range of the control onto the output (zero corresponding to -65,536 and -65,536 corresponding to 65,536). • Reading an absolute axis item as a switch returns zero or 1 depending on whether the control is past a threshold in the direction specified by the modifier. Use the negative modifier to return 1 when the con- trol is beyond the threshold in the negative direction (up or left), or the positive modifier to return 1 when the control is beyond the threshold in the positive direction (down or right). There are two special pairs of modifiers, left/right and up/down that are only ap- plicable to the primary X/Y axes of joystick devices. The user can specify a joystick map to control how these modifiers interpret joy- stick movement. • Attempting to read an absolute axis item as a relative axis always returns zero. If the specified input item is a relative axis, it can be read as a relative axis or as a switch: • Reading a relative axis item as a relative axis returns the change in value since the last input update. The only supported modifier is reverse, which negates the value, reversing the direction. • Reading a relative axis as a switch returns 1 if the control moved in the direction specified by the modifier since the last input update. Use the negative/left/up modifiers to return 1 when the control has been moved in the negative direction (up or left), or the posi- tive/right/down modifiers to return 1 when the control has moved in the positive direction (down or right). • Attempting to read a relative axis item as an absolute axis always returns zero. There are also special input codes used for specifying how multiple controls are to be combined in an input sequence. The most common place youll encounter input codes in device and system driver code is when specifying initial assignments for I/O port fields that dont have default assignments supplied by the core. The PORT_CODE macro is used for this purpose. MAME provides macros and helper functions for producing commonly used input codes, including standard keyboard keys and mouse/joystick/light- gun axes and buttons. Input sequence An input sequence specifies a combination controls that can be assigned to an input. The name refers to the fact that it is implemented as a sequence container with input codes as elements. It is somewhat mis- leading, as input sequences are interpreted using instantaneous control values. Input sequences are interpreted differently for switch and axis input. Input sequences for switch input must only contain input codes with the item class set to switch along with the special or and not input codes. The input sequence is interpreted using sum-of-products logic. A not code causes the value returned by the immediately following code to be inverted. The conjunction of values returned by successive codes is evaluated until an or code is encountered. If the current value is 1 when an or code is encountered it is returned, otherwise evaluation continues. Input sequences for axis input can contain input codes with the item class set to switch, absolute axis or relative axis along with the spe- cial or and not codes. Its helpful to think of the input sequence as containing one or more groups of input codes separated by or codes: • A not code causes the value returned by an immediately following switch code to be inverted. It has no effect on absolute or relative axis codes. • Within a group, the conjunction of the values returned by switch codes is evaluated. If it is zero, the group is ignored. • Within a group, multiple axis values of the same type are summed. Values returned by absolute axis codes are summed, and values re- turned by relative axis codes are summed. • If any absolute axis code in a group returns a non-zero value, the sum of relative axes in the group is ignored. Any non-zero absolute axis value takes precedence over relative axis values. • The same logic is applied when combining group values: group values produced from the same axis type are summed, and values produced from absolute axes take precedence over values produced from relative axes. • After the group values are summed, if the value was produced from ab- solute axes it is clamped to the range -65,536 to 65,536 (values pro- duced from relative axes are not clamped). Emulation code rarely needs to deal with input sequences directly, as theyre handled internally between the I/O port manager and input man- ager. The input manager also converts input sequences to and from the token strings stored in configuration files and produces text for dis- playing input sequences to users. Plugins with controls or hotkeys need to use input sequences to allow configuration. Utility classes are provided to allow input sequences to be entered by the user in a consistent way, and the input manager can be used for conversions to and from configuration and display strings. It is very rare to need to directly manipulate input se- quences. Input provider modules Input provider modules are part of the OS-dependent layer (OSD), and are not directly exposed to emulation and user interface code. Input provider modules are responsible for detecting available host input de- vices, setting up input devices for the input manager, and providing callbacks to read the current state of input device items. Input provider modules may also provide additional default input assignments suitable for host input devices that are present. The user is given a choice of input modules to use. One input provider module is used for each of the four input device classes (keyboard, mouse, joystick and lightgun). The available modules depend on the host operating system and OSD implementation. Different modules may use different APIs, support different kinds of devices, or present de- vices in different ways. Player positions MAME uses a concept called player positions to help manage input as- signments. The number of player positions supported depends on the I/O port field type: • Ten player positions are supported for common game inputs, including joystick, pedal, paddle, dial, trackball, lightgun and mouse. • Four player positions are supported for mahjong and hanafuda inputs. • One player position is supported for gambling system inputs. • Other inputs do not use player positions. This includes coin slots, arcade start buttons, tilt switches, service switches and key- board/keypad keys. The user can configure default input assignments per player position for supported I/O port field types which are saved in the file de- fault.cfg. These assignments are used for all systems unless the de- vice/system driver supplies its own default assignments, or the user configures system-specific input assignments. In order to facilitate development of reusable emulated devices with inputs, particularly slot devices, the I/O port manager automatically renumbers player positions when setting up the emulated system: • The I/O port manager starts at player position 1 and begins iterating the emulated device tree in depth first order, starting from the root device. • If a device has I/O port fields that support player positions, they are renumbered to start from the I/O port managers current player po- sition. • Before advancing to the next device, the I/O port manager sets its current player position to the last seen player position plus one. For a simple example, consider what happens when you run a Sega Mega Drive console with two game pads connected: • The I/O port manager starts at player position 1 at the root device. • The first device encountered with I/O port fields that support player positions is the first game pad. The inputs are renumbered to start at player position 1. This has no visible effect, as the I/O port fields are initially numbered starting at player position 1. • Before moving to the next device, the I/O port manager sets its cur- rent player position to 2 (the last player position seen plus one). • The next device encountered with I/O port fields that support player positions is the second game pad. The inputs are renumbered to start at player position 2. This avoids I/O port field type conflicts with the first game pad. • Before moving to the next device, the I/O port manager sets its cur- rent player position to 3 (the last player position seen plus one). • No more devices with I/O port fields that support player positions are encountered. Updating I/O port fields The I/O port manager updates I/O port fields once for each video frame produced by the first emulated screen in the system. How a field is updated depends on whether it is a digital or analog field. Updating digital fields Updating digital I/O port fields is simple: • The I/O port manager reads the current value for the fields assigned input sequence (via the input manager). • If the value is zero, the fields default value is set. • If the value is non-zero, the binary complement of the fields default value is set. Updating absolute analog fields Updating absolute analog I/O port fields is more complex due to the need to support a variety of control setups: • The I/O port manager reads the current value for the fields assigned axis input sequence (via the input manager). • If the current value changed since the last update and the input de- vice item that produced the current value was an absolute axis, the fields value is set to the current value scaled to the correct range, and no further processing is performed. • If the current value is non-zero and the input device item that pro- duced the current value was a relative axis, the current value is added to the fields value, scaled by the fields sensitivity setting. • The I/O port manager reads the current value for the fields assigned increment input sequence (via the input manager); if this value is non-zero, the fields increment/decrement speed setting value is added to its value, scaled by its sensitivity setting. • The I/O port manager reads the current value for the fields assigned decrement input sequence (via the input manager); if this value is non-zero, the fields increment/decrement speed setting value is sub- tracted from its value, scaled by its sensitivity setting. • If the current axis input, increment input and decrement input values are all zero, but either or both of the increment input and decrement input values were non-zero the last time the fields value changed in response to user input, the fields auto-centring speed setting value is added to or subtracted from its value to move it toward its de- fault value. Note that the sensitivity setting value for absolute analog fields af- fects the response to relative axis input device items and incre- ment/decrement inputs, but it does not affect the response to absolute axis input device items or the auto-centring speed. Updating relative analog fields Relative analog I/O port fields also need special handling to cater for multiple control setups, but they are a little simpler than absolute analog fields: • The I/O port manager reads the current value for the fields assigned axis input sequence (via the input manager). • If the current value is non-zero and the input device item that pro- duced the current value was an absolute axis, the current value is added to the fields value, scaled by the fields sensitivity setting, and no further processing is performed. • If the current value is non-zero and the input device item that pro- duced the current value was a relative axis, the current value is added to the fields value, scaled by the fields sensitivity setting. • The I/O port manager reads the current value for the fields assigned increment input sequence (via the input manager); if this value is non-zero, the fields increment/decrement speed setting value is added to its value, scaled by its sensitivity setting. • The I/O port manager reads the current value for the fields assigned decrement input sequence (via the input manager); if this value is non-zero, the fields increment/decrement speed setting value is sub- tracted from its value, scaled by its sensitivity setting. Note that the sensitivity setting value for relative analog fields af- fects the response to all user input. The device_memory_interface • 1. Capabilities • 2. Setup • 3. Associating maps to spaces • 4. Accessing the spaces • 5. MMU support for disassembler 1. Capabilities The device memory interface provides devices with the capability of creating address spaces, to which address maps can be associated. Its used for any device that provides a (logical) address/data bus that other devices can be connected to. Thats mainly, but not solely, CPUs. The interface allows for an unlimited set of address spaces, numbered with small, non-negative values. The IDs index vectors, so they should stay small to keep the lookup fast. Spaces numbered 0-3 have associ- ated constant name: +----+------------+ | ID | Name | +----+------------+ | 0 | AS_PROGRAM | +----+------------+ | 1 | AS_DATA | +----+------------+ | 2 | AS_IO | +----+------------+ | 3 | AS_OPCODES | +----+------------+ Spaces 0 and 3, i.e. AS_PROGRAM and AS_OPCODES, are special for the de- bugger and some CPUs. AS_PROGRAM is use by the debugger and the CPUs as the space from which the CPU reads its instructions for the disas- sembler. When present, AS_OPCODES is used by the debugger and some CPUs to read the opcode part of the instruction. What opcode means is device-dependant, for instance for the Z80 it's the initial byte(s) which are read with the M1 signal asserted, while for the 68000 is means every instruction word plus PC-relative accesses. The main, but not only, use of AS_OPCODES is to implement hardware decryption of in- structions separately from data. 2. Setup std::vector<std::pair<int, const address_space_config *>> memory_space_config() const; The device must override that method to provide a vector of pairs com- prising of a space number and an associated address_space_config de- scribing its configuration. Some examples to look up when needed: • Standard two-space vector: v60_device • Conditional AS_OPCODES: z80_device • Inherit configuration and add a space: hd647180x_device • Inherit configuration and modify a space: tmpz84c011_device bool has_configured_map(int index = 0) const; The has_configured_map method allows to test whether an address_map has been associated with a given space in the memory_space_config method. That allows optional memory spaces to be implemented, such as AS_OP- CODES in certain CPU cores. 3. Associating maps to spaces Associating maps to spaces is done at the machine configuration level, after the device is instantiated. void set_addrmap(int spacenum, T &obj, Ret (U::*func)(Params...)); void set_addrmap(int spacenum, Ret (T::*func)(Params...)); void set_addrmap(int spacenum, address_map_constructor map); These function associate a map with a given space. Address maps asso- ciated with non-existent spaces are ignored (no warning given). The first form takes a reference to an object and a method to call on that object. The second form takes a method to call on the current device being configured. The third form takes an address_map_constructor to copy. In each case, the function must be callable with reference to an address_map object as an argument. To remove a previously configured address map, call set_addrmap with a default-constructed address_map_constructor (useful for removing a map for an optional space in a derived machine configuration). As an example, heres the address map configuration for the main CPU in the Hana Yayoi and Hana Fubuki machines, with all distractions removed: class hnayayoi_state : public driver_device { public: void hnayayoi(machine_config &config); void hnfubuki(machine_config &config); private: required_device<cpu_device> m_maincpu; void hnayayoi_map(address_map &map); void hnayayoi_io_map(address_map &map); void hnfubuki_map(address_map &map); }; void hnayayoi_state::hnayayoi(machine_config &config) { Z80(config, m_maincpu, 20000000/4); m_maincpu->set_addrmap(AS_PROGRAM, &hnayayoi_state::hnayayoi_map); m_maincpu->set_addrmap(AS_IO, &hnayayoi_state::hnayayoi_io_map); } void hnayayoi_state::hnfubuki(machine_config &config) { hnayayoi(config); m_maincpu->set_addrmap(AS_PROGRAM, &hnayayoi_state::hnfubuki_map); m_maincpu->set_addrmap(AS_IO, address_map_constructor()); } 4. Accessing the spaces address_space &space(int index = 0) const; Returns the specified address space post-initialization. The specified address space must exist. bool has_space(int index = 0) const; Indicates whether a given space actually exists. 5. MMU support for disassembler bool translate(int spacenum, int intention, offs_t &address, address_space *&target_space); Does a logical to physical address translation through the device's MMU. spacenum gives the space number, intention for the type of the future access (TR_(READ\|WRITE\|FETCH)), address is an in/out parameter holding the address to translate on entry and the translated version on return, and finally target_space is the actual space the access would end up in, which may be in a different device. Should return true if the translation went correctly, or false if the address is unmapped. The call must not change the state of the device. Note that for some historical reason, the device itself must override the virtual method memory_translate with the same signature. The device_rom_interface • 1. Capabilities • 2. Setup • 3. ROM access • 4. ROM banking • 5. Caveats 1. Capabilities This interface is designed for devices that expect to have a ROM con- nected to them on a dedicated bus. Its mostly designed for sound chips. Other devices types may be interested but other considerations may make it impractical (graphics decode caching, for instance). The interface provides the capability to connect a ROM region, connect an address map, or dynamically set up a block of memory as ROM. In the region/memory block cases, banking is handled automatically. 2. Setup device_rom_interface<AddrWidth, DataWidth=0, AddrShift=0, Endian=ENDIANNESS_LITTLE> The interface is a template that takes the address width of the dedi- cated bus as a parameter. In addition the data bus width (if not byte), address shift (if non-zero) and Endianness (if not little Endian or byte-sized bus) can be provided. Data bus width is 0 for byte, 1 for word, etc. void set_map(map); Use that method at machine configuration time to provide an address map for the bus to connect to. It has priority over a ROM region if one is also present. void set_device_rom_tag(tag); Used to specify a ROM region to use if a device address map is not given. Defaults to DEVICE_SELF, i.e. the devices tag. ROM_REGION(length, tag, flags) If a ROM region with the tag specified using set_device_rom_tag if present, or identical to the device tag otherwise, is provided in the ROM definitions for the system, it will be automatically picked up as the connected ROM. An address map has priority over the region if present in the machine configuration. void override_address_width(u8 width); This method allows the address bus width to be overridden. It must be called from within the device before config_complete time. void set_rom(const void *base, u32 size); At any time post-interface_pre_start, a memory block can be set up as the connected ROM with that method. It overrides any previous setup that may have been provided. It can be done multiple times. 3. ROM access u8 read_byte(offs_t addr); u16 read_word(offs_t addr); u32 read_dword(offs_t addr); u64 read_qword(offs_t addr); These methods provide read access to the connected ROM. Out-of-bounds access results in standard unmapped read logerror messages. 4. ROM banking If the ROM region or the memory block in set_rom is larger than the ad- dress bus can access, banking is automatically set up. void set_rom_bank(int bank); That method selects the current bank number. 5. Caveats Using that interface makes the device derive from device_memory_inter- face. If the device wants to actually use the memory interface for it- self, remember that space zero (0, or AS_PROGRAM) is used by the ROM interface, and dont forget to call the base memory_space_config method. For devices which have outputs that can be used to address ROMs but only to forward the data to another device for processing, it may be helpful to disable the interface when it is not required. This can be done by overriding memory_space_config to return an empty vector. The device_disasm_interface and the disassemblers 1. Capabilities The disassemblers are classes that provide disassembly and opcode meta-information for the cpu cores and unidasm. The device_disasm_in- terface connects a cpu core with its disassembler. 2. The disassemblers 2.1. Definition A disassembler is a class that derives from util::disasm_interface. It then has two required methods to implement, opcode_alignment and disas- semble, and 6 optional, interface_flags, page_address_bits, pc_lin- ear_to_real, pc_real_to_linear, and one with four possible variants, decrypt8/16/32/64. 2.2. opcode_alignment u32 opcode_alignment() const Returns the required alignment of opcodes by the cpu, in PC-units. In other words, the required alignment for the PC register of the cpu. Tends to be 1 (almost everything), 2 (68000...), 4 (mips, ppc...), which an exceptional 8 (tms 32082 parallel processor) and 16 (tms32010, instructions are 16-bits aligned and the PC targets bits). It must be a power-of-two or things will break. Note that processors like the tms32031 which have 32-bits instructions but where the PC targets 32-bits values have an alignment of 1. 2.3. disassemble offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) This is the method where the real work is done. This method must dis- assemble the instruction at address pc and write the result to stream. The values to decode are retrieved from the opcode buffer. A data_buffer object offers four accessor methods: u8 util::disasm_interface::data_buffer::r8 (offs_t pc) const u16 util::disasm_interface::data_buffer::r16(offs_t pc) const u32 util::disasm_interface::data_buffer::r32(offs_t pc) const u64 util::disasm_interface::data_buffer::r64(offs_t pc) const They read the data at a given address and take endianness and nonlinear PCs for larger-than-bus-width accesses. The debugger variant also caches the read data in one block, so for that reason one should not read data too far from the base pc (e.g. stay within 16K or so, careful when trying to follow indirect accesses). A number of CPUs have an external signal that splits fetches into an opcode part and a parameter part. This is for instance the M1 signal of the z80 or the SYNC signal of the 6502. Some systems present dif- ferent values to the cpu depending on whether that signal is active, usually for protection purposes. On these cpus the opcode part should be read from the opcode buffer, and the parameter part from the params buffer. They will or will not be the same buffer depending on the sys- tem itself. The method returns the size of the instruction in PC units, with a max- imum of 65535. In addition, if possible, the disassembler should give some meta-information about the opcode by OR-ing in into the result: • STEP_OVER for subroutine calls or auto-decrementing loops. If there is some delay slots, also OR with step_over_extra(n) where n is the number of instruction slots. • STEP_OUT for the return-from-subroutine instructions In addition, to indicated that these flags are supported, OR the result with SUPPORTED. An annoying number of disassemblers lies about that support (e.g. they do a or with SUPPORTED without even generating the STEP_OVER or STEP_OUT information). Don't do that, it breaks the step over/step out functionality of the debugger. 2.4. interface_flags u32 interface_flags() const That optional method indicates specifics of the disassembler. Default of zero is correct most of the time. Possible flags, which need to be OR-ed together, are: • NONLINEAR_PC: stepping to the next opcode or the next byte of the op- code is not adding one to pc. Used for old LFSR-based PCs. • PAGED: PC wraps at a page boundary • PAGED2LEVEL: not only PC wraps at some kind of page boundary, but there are two levels of paging • INTERNAL_DECRYPTION: there is some decryption tucked between reading from AS_PROGRAM and the actual disassembler • SPLIT_DECRYPTION: there is some decryption tucked between reading from AS_PROGRAM and the actual disassembler, and that decryption is different for opcodes and parameters Note that in practice non-linear pc systems are also paged, that PAGED2LEVEL implies PAGED, and that SPLIT_DECRYPTION implies DECRYP- TION. 2.5. pc_linear_to_real and pc_real_to_linear offs_t pc_linear_to_real(offs_t pc) const offs_t pc_real_to_linear(offs_t pc) const These methods should be present only when NONLINEAR_PC is set in the interface flags. They must convert pc to and from a value to a linear domain where the instruction parameters and next instruction are reached by incrementing the value. pc_real_to_linear converts to that domain, pc_linear_to_real converts back from that domain. 2.6. page_address_bits u32 page_address_bits() const Present on when PAGED or PAGED2LEVEL is set, gives the number of ad- dress bits in the lowest page. 2.7. page2_address_bits u32 page2_address_bits() const Present on when PAGED2LEVEL is set, gives the number of address bits in the upper page. 2.8. decryptnn u8 decrypt8 (u8 value, offs_t pc, bool opcode) const u16 decrypt16(u16 value, offs_t pc, bool opcode) const u32 decrypt32(u32 value, offs_t pc, bool opcode) const u64 decrypt64(u64 value, offs_t pc, bool opcode) const One of these must be defined when INTERNAL_DECRYPTION or SPLIT_DECRYP- TION is set. The chosen one is the one which takes what opcode_align- ment represents in bytes. That method decrypts a given value read from address pc (from AS_PRO- GRAM) and gives the result which will be passed to the disassembler. In the split decryption case, opcode indicates whether we're in the op- code (true) or parameter (false) part of the instruction. 3. Disassembler interface, device_disasm_interface 3.1. Definition A CPU core derives from device_disasm_interface through cpu_device. One method has to be implemented, create_disassembler. 3.2. create_disassembler util::disasm_interface *create_disassembler() That method must return a pointer to a newly allocated disassembler ob- ject. The caller takes ownership and handles the lifetime. This method will be called at most one in the lifetime of the cpu ob- ject. 4. Disassembler configuration and communication Some disassemblers need to be configured. Configuration can be un- changing (static) for the duration of the run (cpu model type for in- stance) or dynamic (state of a flag or a user preference). Static con- figuration can be done through either (a) parameter(s) to the disassem- bler constructor, or through deriving a main disassembler class. If the information is short and its semantics obvious (like a model name), feel free to use a parameter. Otherwise derive the class. Dynamic configuration must be done by first defining a nested public struct called config in the disassembler, with virtual destructor and pure virtual methods to pull the required information. A pointer to that struct should be passed to the disassembler constructor. The cpu core should then add a derivation from that config struct and implement the methods. Unidasm will have to derive a small class from the config class to give the information. 5. Missing stuff There currently is no way for the debugger GUI to add per-core configu- ration. In particular, it is needed for the s2650 and Saturn cores. It should go through the cpu core class itself, since it's pulled from the config struct. There is support missing in unidasm for per-cpu configuration. That's needed for a lot of things, see the unidasm source code for the current list ("Configuration missing" comments). Emulated system memory and address spaces management • 1. Overview • 2. Basic concepts • 2.1 Address spaces • 2.2 Address maps • 2.3 Shares, banks and regions • 2.4 Views • 3. Memory objects • 3.1 Shares - memory_share • 3.2 Banks - memory_bank • 3.3 Regions - memory_region • 3.4 Views - memory_view • 3.5 Bus contention handling • 4. Address maps API • 4.1 General API structure • 4.2 Global configurations • 4.2.1 Global masking • 4.2.2 Returned value on unmapped/nop-ed read • 4.3 Handler setting • 4.3.1 Method on the current device • 4.3.2 Method on a different device • 4.3.3 Lambda function • 4.3.4 Direct memory access • 4.3.5 Bank access • 4.3.6 Port access • 4.3.7 Dropped access • 4.3.8 Unmapped access • 4.3.9 Subdevice mapping • 4.4 Range qualifiers • 4.4.1 Mirroring • 4.4.2 Masking • 4.4.3 Selection • 4.4.4 Sub-unit selection • 4.4.5 Chip select handling on sub-unit • 4.4.6 User flags • 4.5 Contention • 4.6 View setup • 5. Address space dynamic mapping API • 5.1 General API structure • 5.2 Handler mapping • 5.3 Direct memory range mapping • 5.4 Bank mapping • 5.5 Port mapping • 5.6 Dropped accesses • 5.7 Unmapped accesses • 5.8 Device map installation • 5.9 Contention • 5.10 View installation • 5.11 Taps 1. Overview The memory subsystem (emumem and addrmap) combines multiple functions useful for system emulation: • address bus decoding and dispatching with caching • static descriptions of an address map • RAM allocation and registration for state saving • interaction with memory regions to access ROM Devices create address spaces, e.g. decodable buses, through the de- vice_memory_interface. The machine configuration sets up address maps to put in the address spaces, then the device can do read and writes through the bus. 2. Basic concepts 2.1 Address spaces An address space, implemented in the class address_space, represents an addressable bus with potentially multiple sub-devices connected requir- ing a decode. It has a number of data lines (8, 16, 32 or 64) called data width, a number of address lines (1 to 32) called address width and an Endianness. In addition an address shift allows for buses that have an atomic granularity different than a byte. Address space objects provide a series of methods for read and write access, and a second series of methods for dynamically changing the de- code. 2.2 Address maps An address map is a static description of the decode expected when us- ing a bus. It connects to memory, other devices and methods, and is installed, usually at startup, in an address space. That description is stored in an address_map structure which is filled programmatically. 2.3 Shares, banks and regions Memory shares are allocated memory zones that can be put in multiple places in the same or different address spaces, and can also be di- rectly accessed from devices. Memory banks are zones that indirect memory access, giving the possi- bility to dynamically and efficiently change where a zone actually points to. Memory regions are read-only memory zones in which ROMs are loaded. All of these have names allowing to access them. 2.4 Views Views are a way to multiplex different submaps over a memory range with fast switching. It is to be used when multiple devices map at the same addresses and are switched in externally. They must be created as an object of the device and then setup either statically in a memory map or dynamically through install_* calls. Switchable submaps, aka variants, are named through an integer. An in- ternal indirection through a map ensures that any integer value can be used. 3. Memory objects 3.1 Shares - memory_share class memory_share { const std::string &name() const; void *ptr() const; size_t bytes() const; endianness_t endianness() const; u8 bitwidth() const; u8 bytewidth() const; }; A memory share is a named allocated memory zone that is automatically saved in save states and can be mapped in address spaces. It is the standard container for memory that is shared between spaces, but also shared between an emulated CPU and a driver. As such one has easy ac- cess to its contents from the driver class. required_shared_ptr<uNN> m_share_ptr; optional_shared_ptr<uNN> m_share_ptr; required_shared_ptr_array<uNN, count> m_share_ptr_array; optional_shared_ptr_array<uNN, count> m_share_ptr_array; [device constructor] m_share_ptr(*this, "name"), [device constructor] m_share_ptr_array(*this, "name%u", 0U), At the device level, a pointer to the memory zone can easily be re- trieved by building one of these four finders. Note that like for every finder calling target() on the finder gives you the base pointer of the memory_share object. memory_share_creator<uNN> m_share; [device constructor] m_share(*this, "name", size, endianness), A memory share can be created if it doesnt exist in a memory map through that creator class. If it already exists it is just retrieved. That class behaves like a pointer but also has the target(), length(), bytes(), endianness(), bitwidth() and bytewidth() methods for share in- formation. The desired size is specified in bytes. memory_share *memshare(string tag) const; The memshare device method retrieves a memory share by name. Beware that the lookup can be expensive, prefer finders instead. 3.2 Banks - memory_bank class memory_bank { const std::string &tag() const; int entry() const; void set_entry(int entrynum); void configure_entry(int entrynum, void *base); void configure_entries(int startentry, int numentry, void *base, offs_t stride); void set_base(void *base); void *base() const; }; A memory bank is a named memory zone indirection that can be mapped in address spaces. It points to nullptr when created. configure_entry associates an entry number and a base pointer. configure_entries does the same for multiple consecutive entries spanning a memory zone. set_base sets the base address for the active entry. If there are no entries, entry 0 (zero) is automatically created and selected. Use of set_base should be avoided in favour of pre-configured entries unless there are an impractically large number of possible base addresses. set_entry dynamically and efficiently selects the active entry, entry() returns the active entry number, and base() gets the associated base pointer. required_memory_bank m_bank; optional_memory_bank m_bank; required_memory_bank_array<count> m_bank_array; optional_memory_bank_array<count> m_bank_array; [device constructor] m_bank(*this, "name"), [device constructor] m_bank_array(*this, "name%u", 0U), At the device level, a pointer to the memory bank object can easily be retrieved by building one of these four finders. memory_bank_creator m_bank; [device constructor] m_bank(*this, "name"), A memory bank can be created if it doesnt exist in a memory map through that creator class. If it already exists it is just retrieved. memory_bank *membank(string tag) const; The membank device method retrieves a memory bank by name. Beware that the lookup can be expensive, prefer finders instead. 3.3 Regions - memory_region class memory_region { u8 *base(); u8 *end(); u32 bytes() const; const std::string &name() const; endianness_t endianness() const; u8 bitwidth() const; u8 bytewidth() const; u8 &as_u8(offs_t offset = 0); u16 &as_u16(offs_t offset = 0); u32 &as_u32(offs_t offset = 0); u64 &as_u64(offs_t offset = 0); } A region is used to store read-only data like ROMs or the result of fixed decryptions. Their contents are not saved, which is why they should not being written to from the emulated system. They dont really have an intrinsic width (base() returns an u8 * always), which is his- torical and pretty much unfixable at this point. The as_* methods al- low for accessing them at a given width. required_memory_region m_region; optional_memory_region m_region; required_memory_region_array<count> m_region_array; optional_memory_region_array<count> m_region_array; [device constructor] m_region(*this, "name"), [device constructor] m_region_array(*this, "name%u", 0U), At the device level, a pointer to the memory region object can easily be retrieved by building one of these four finders. memory_region *memregion(string tag) const; The memregion device method retrieves a memory region by name. Beware that the lookup can be expensive, prefer finders instead. 3.4 Views - memory_view class memory_view { memory_view(device_t &device, std::string name); memory_view_entry &operator[](int slot); void select(int entry); void disable(); const std::string &name() const; } A view allows to switch part of a memory map between multiple possibil- ities, or even disable it entirely to see what was there before. It is created as an object of the device. memory_view m_view; [device constructor] m_view(*this, "name"), It is then setup through the address map API or dynamically. At run- time, a numbered variant can be selected using the select method, or the view can be disabled using the disable method. A disabled view can be re-enabled at any time. 3.5 Bus contention handling Some specific CPUs have been upgraded to be interruptible which allows to add bus contention and wait states capabitilites. Being interrupt- ible means, in practice, that an instruction can be interrupted at any time and the execute_run method of the core exited. Other devices can then run, then eventually controls returns to the core and the instruc- tion continues from the point it was started. Importantly, this can be triggered from a handler and even be used to interrupt just before the access that is currently done (e.g. continuation will redo the access). The CPUs supporting that declare their capability by overriding the method cpu_is_interruptible to return true. Three intermediate contention handlers can be added to accesses: • before_delay: wait a number of cycles before doing the access. • after_delay: wait a number of cycles after doing the access. • before_time: wait for a given time before doing the access. For the delay handlers, a method or lambda is called which returns the number of cycles to wait (as a u32). The before_time is special. First, the time is compared to the current value of cpu->total_cycles(). That value is the number of cycles elapsed since the last reset of the cpu. It is passed as a parameter to the method as a u64 and must return the earliest time as a u64 when the access can be done, which can be equal to the passed-in time. From there two things can happen: either the running cpu has enough cycles left to consume to reach that time. In that case, the necessary number of cycles is consumed, and the access is done. Otherwise, when there isn't enough, the remaining cycles are consumed, the access aborted, scheduling happens, and eventually the access is redone. In that case the method is called again with the new current time, and must return the (probably same) earliest time again. This will happen until enough cycles to consume are available to directly do the access. This approach allows to for instance handle consecutive DMAs. A first DMA grabs the bus for a transfer. This shows up as the method answer- ing for the earliest time for access the time of the end of the dma. If no timer happens until that time the access will then happen just after the dma finishes. But if a timer elapses before that and as a consequence another dma is queued while the first is running, the cycle will be aborted for lack of remaining time, and the method will eventu- ally be called again. It will then give the time of when the second dma will finish, and all will be well. It can also allow to reduce said earlier time when circumstances re- quire it. For instance a PIO latch that waits up to 64 cycles that data arrives can indicate that current time + 64 as a target (which will trigger a bus error for instance) but if a timer elapses and fills the latch meanwhile the method will be called again and that time can just return the current time to let the access pass though. Beware that if the timer elapsing did not fill the latch then the method must return the time it returned previously, e.g. the initial access time + 64, otherwise irrelevant timers happening or simply scheduling quantum effects will delay the timeout, possibly to infinity if the quantum is small enough. Contention handlers on the same address are taken into account in the before_time, before_delay then after_delay order. Contention handlers of the same type on the same address at last-one-wins. Installing any non-contention handler on a range where a contention handler was re- moves it. 4. Address maps API 4.1 General API structure An address map is a method of a device which fills an address_map structure, usually called map, passed by reference. The method then can set some global configuration through specific methods and then provide address range-oriented entries which indicate what should hap- pen when a specific range is accessed. The general syntax for entries uses method chaining: map(start, end).handler(...).handler_qualifier(...).range_qualifier().contention(); The values start and end define the range, the handler() block deter- mines how the access is handled, the handler_qualifier() block speci- fies some aspects of the handler (memory sharing for instance) and the range_qualifier() block refines the range (mirroring, masking, lane se- lection, etc.). The contention methods handle bus contention and wait states for cpus supporting them. The map follows a last one wins principle, where the handler specified last is selected when multiple handlers match a given address. 4.2 Global configurations 4.2.1 Global masking map.global_mask(offs_t mask); Specifies a mask to be applied to all addresses when accessing the space that map is installed in. 4.2.2 Returned value on unmapped/nop-ed read map.unmap_value_low(); map.unmap_value_high(); map.unmap_value(u8 value); Sets the value to return on reads to an unmapped or nopped-out address. Low means 0, high ~0. 4.3 Handler setting 4.3.1 Method on the current device (...).r(FUNC(my_device::read_method)) (...).w(FUNC(my_device::write_method)) (...).rw(FUNC(my_device::read_method), FUNC(my_device::write_method)) uNN my_device::read_method(address_space &space, offs_t offset, uNN mem_mask) uNN my_device::read_method(address_space &space, offs_t offset) uNN my_device::read_method(address_space &space) uNN my_device::read_method(offs_t offset, uNN mem_mask) uNN my_device::read_method(offs_t offset) uNN my_device::read_method() void my_device::write_method(address_space &space, offs_t offset, uNN data, uNN mem_mask) void my_device::write_method(address_space &space, offs_t offset, uNN data) void my_device::write_method(address_space &space, uNN data) void my_device::write_method(offs_t offset, uNN data, uNN mem_mask) void my_device::write_method(offs_t offset, uNN data) void my_device::write_method(uNN data) Sets a method of the current device or driver to read, write or both for the current entry. The prototype of the method can take multiple forms making some elements optional. uNN represents u8, u16, u32 or u64 depending on the data width of the handler. The handler can be narrower than the bus itself (for instance an 8-bit device on a 32-bit bus). The offset passed in is built from the access address. It starts at zero at the start of the range, and increments for each uNN unit. An u8 handler will get an offset in bytes, an u32 one in double words. The mem_mask has its bits set where the accessors actually drive the bit. Its usually built in byte units, but in some cases of I/O chips ports with per-bit direction registers the resolution can be at the bit level. 4.3.2 Method on a different device (...).r(m_other_device, FUNC(other_device::read_method)) (...).r("other-device-tag", FUNC(other_device::read_method)) (...).w(m_other_device, FUNC(other_device::write_method)) (...).w("other-device-tag", FUNC(other_device::write_method)) (...).rw(m_other_device, FUNC(other_device::read_method), FUNC(other_device::write_method)) (...).rw("other-device-tag", FUNC(other_device::read_method), FUNC(other_device::write_method)) Sets a method of another device, designated by an object finder (usu- ally required_device or optional_device) or its tag, to read, write or both for the current entry. 4.3.3 Lambda function (...).lr{8,16,32,64}(NAME([...](address_space &space, offs_t offset, uNN mem_mask) -> uNN { ... })) (...).lr{8,16,32,64}([...](address_space &space, offs_t offset, uNN mem_mask) -> uNN { ... }, "name") (...).lw{8,16,32,64}(NAME([...](address_space &space, offs_t offset, uNN data, uNN mem_mask) -> void { ... })) (...).lw{8,16,32,64}([...](address_space &space, offs_t offset, uNN data, uNN mem_mask) -> void { ... }, "name") (...).lrw{8,16,32,64}(NAME(read), NAME(write)) (...).lrw{8,16,32,64}(read, "name_r", write, "name_w") Sets a lambda called on read, write or both. The lambda prototype can be any of the six available for methods. One can either use NAME() over the whole lambda, or provide a name after the lambda definition. The number is the data width of the access, e.g. the NN. 4.3.4 Direct memory access (...).rom() (...).writeonly() (...).ram() Selects the range to access a memory zone as read-only, write-only or read/write respectively. Specific handler qualifiers specify the loca- tion of this memory zone. There are two cases when no qualifier is ac- ceptable: • ram() gives an anonymous RAM zone not accessible outside of the ad- dress space. • rom() when the memory map is used in an AS_PROGRAM space of a (CPU) device which names is also the name of a region. Then the memory zone points to that region at the offset corresponding to the start of the zone. (...).rom().region("name", offset) The region qualifier causes a read-only zone point to the contents of a given region at a given offset. (...).rom().share("name") (...).writeonly.share("name") (...).ram().share("name") The share qualifier causes the zone point to a shared memory region identified by its name. If the share is present in multiple spaces, the size, bus width, and, if the bus is more than byte-wide, the Endi- anness must match. 4.3.5 Bank access (...).bankr("name") (...).bankw("name") (...).bankrw("name") Sets the range to point at the contents of a memory bank in read, write or read/write mode. 4.3.6 Port access (...).portr("name") (...).portw("name") (...).portrw("name") Sets the range to point at an I/O port. 4.3.7 Dropped access (...).nopr() (...).nopw() (...).noprw() Sets the range to drop the access without logging. When reading, the unmap value is returned. 4.3.8 Unmapped access (...).unmapr() (...).unmapw() (...).unmaprw() Sets the range to drop the access with logging. When reading, the un- map value is returned. 4.3.9 Subdevice mapping (...).m(m_other_device, FUNC(other_device::map_method)) (...).m("other-device-tag", FUNC(other_device::map_method)) Includes a device-defined submap. The start of the range indicates where the address zero of the submap ends up, and the end of the range clips the submap if needed. Note that range qualifiers (defined later) apply. Currently, only handlers are allowed in submaps and not memory zones or banks. 4.4 Range qualifiers 4.4.1 Mirroring (...).mirror(mask) Duplicate the range on the addresses reachable by setting any of the 1 bits present in mask. For instance, a range 0-0x1f with mirror 0x300 will be present on 0-0x1f, 0x100-0x11f, 0x200-0x21f and 0x300-0x31f. The addresses passed in to the handler stay in the 0-0x1f range, the mirror bits are not seen by the handler. 4.4.2 Masking (...).mask(mask) Only valid with handlers, the address will be masked with the mask be- fore being passed to the handler. 4.4.3 Selection (...).select(mask) Only valid with handlers, the range will be mirrored as with mirror, but the mirror address bits are preserved in the offset passed to the handler when it is called. This is useful for devices like sound chips where the low bits of the address select a function and the high bits a voice number. 4.4.4 Sub-unit selection (...).umask16(16-bits mask) (...).umask32(32-bits mask) (...).umask64(64-bits mask) Only valid with handlers and submaps, selects which data lines of the bus are actually connected to the handler or the device. The mask value should be a multiple of a byte, e.g. the mask is a series of 00 and ff. The offset will be adjusted accordingly, so that a difference of 1 means the next handled unit in the access. If the mask is narrower than the bus width, the mask is replicated in the upper lines. 4.4.5 Chip select handling on sub-unit (...).cselect(16/32/64) When a device is connected to part of the bus, like a byte on a 16-bits bus, the target handler is only activated when that part is actually accessed. In some cases, very often byte access on a 68000 16-bits bus, the actual hardware only checks the word address and not if the correct byte is accessed. cswidth tells the memory system to trigger the handler if a wider part of the bus is accessed. The parameter is that trigger width (would be 16 in the 68000 case). 4.4.6 User flags (...).flags(16-bits mask) This parameter allows to set user-defined flags on the handler which can then be retrieved by an accessing device to change their behaviour. An example of use the i960 which marks burstable zones that way (they have a specific hardware-level support). 4.5 Contention (...).before_time(method).(...) (...).before_delay(method).(...) (...).after_delay(method).(...) These three methods allow to add the contention methods to a handler. See section 3.5. Multiple methods can be handler to one handler. 4.6 View setup map(start, end).view(m_view); m_view[0](start1, end1).[...]; A view is setup in a address map with the view method. The only quali- fier accepted is mirror. The disabled version of the view will include what was in the range prior to the view setup. The different variants are setup by indexing the view with the variant number and setting up an entry in the usual way. The entries within a variant must of course stay within the range. There are no other addi- tional constraints. The contents of a variant, by default, are what was there before, i.e. the contents of the disabled view, and setting it up allows part or all of it to be overridden. Variants can only be setup once the view itself has been setup with the view method. A view can only be put in one address map and in only one position. If multiple views have identical or similar contents, remember that set- ting up a map is nothing more than a method call, and creating a second method to setup a view is perfectly reasonable. A view is of type mem- ory_view and an indexed entry (e.g. a variant to setup) is of type mem- ory_view::memory_view_entry &. A view can be installed in another view, but dont forget that a view can be installed only once. A view can also be part of what was there before. 5. Address space dynamic mapping API 5.1 General API structure A series of methods allow the bus decoding of an address space to be changed on-the-fly. Theyre powerful but have some issues: • changing the mappings repeatedly can be slow • the address space state is not saved in the saved states, so it has to be rebuilt after state load • they can be hidden anywhere rather than be grouped in an address map, which can be less readable The methods, rather than decomposing the information in handler, han- dler qualifier and range qualifier, put them all together as method pa- rameters. To make things a little more readable, lots of them are op- tional. 5.2 Handler mapping uNN my_device::read_method(address_space &space, offs_t offset, uNN mem_mask) uNN my_device::read_method_m(address_space &space, offs_t offset) uNN my_device::read_method_mo(address_space &space) uNN my_device::read_method_s(offs_t offset, uNN mem_mask) uNN my_device::read_method_sm(offs_t offset) uNN my_device::read_method_smo() void my_device::write_method(address_space &space, offs_t offset, uNN data, uNN mem_mask) void my_device::write_method_m(address_space &space, offs_t offset, uNN data) void my_device::write_method_mo(address_space &space, uNN data) void my_device::write_method_s(offs_t offset, uNN data, uNN mem_mask) void my_device::write_method_sm(offs_t offset, uNN data) void my_device::write_method_smo(uNN data) readNN_delegate (device, FUNC(read_method)) readNNm_delegate (device, FUNC(read_method_m)) readNNmo_delegate (device, FUNC(read_method_mo)) readNNs_delegate (device, FUNC(read_method_s)) readNNsm_delegate (device, FUNC(read_method_sm)) readNNsmo_delegate(device, FUNC(read_method_smo)) writeNN_delegate (device, FUNC(write_method)) writeNNm_delegate (device, FUNC(write_method_m)) writeNNmo_delegate (device, FUNC(write_method_mo)) writeNNs_delegate (device, FUNC(write_method_s)) writeNNsm_delegate (device, FUNC(write_method_sm)) writeNNsmo_delegate(device, FUNC(write_method_smo)) To be added to a map, a method call and the device it is called onto have to be wrapped in the appropriate delegate type. There are twelve types, for read and for write and for all six possible prototypes. Note that as all delegates, they can also wrap lambdas. space.install_read_handler(addrstart, addrend, read_delegate, unitmask, cswidth, flags) space.install_read_handler(addrstart, addrend, addrmask, addrmirror, addrselect, read_delegate, unitmask, cswidth, flags) space.install_write_handler(addrstart, addrend, write_delegate, unitmask, cswidth, flags) space.install_write_handler(addrstart, addrend, addrmask, addrmirror, addrselect, write_delegate, unitmask, cswidth, flags) space.install_readwrite_handler(addrstart, addrend, read_delegate, write_delegate, unitmask, cswidth, flags) space.install_readwrite_handler(addrstart, addrend, addrmask, addrmirror, addrselect, read_delegate, write_delegate, unitmask, cswidth, flags) These six methods allow to install delegate-wrapped handlers in a live address space. Either plain or with mask, mirror and select. In the read/write case both delegates must be of the same flavor (smo stuff) to avoid a combinatorial explosion of method types. The unitmask, cswidth and flags arguments are optional. 5.3 Direct memory range mapping space.install_rom(addrstart, addrend, void *pointer) space.install_rom(addrstart, addrend, addrmirror, void *pointer) space.install_rom(addrstart, addrend, addrmirror, flags, void *pointer) space.install_writeonly(addrstart, addrend, void *pointer) space.install_writeonly(addrstart, addrend, addrmirror, void *pointer) space.install_writeonly(addrstart, addrend, addrmirror, flags, void *pointer) space.install_ram(addrstart, addrend, void *pointer) space.install_ram(addrstart, addrend, addrmirror, void *pointer) space.install_ram(addrstart, addrend, addrmirror, flags, void *pointer) Installs a memory block in an address space, with or without mirror and flags. _rom is read-only, _ram is read/write, _writeonly is write-only. The pointer must be non-null, this method will not allo- cate the memory. 5.4 Bank mapping space.install_read_bank(addrstart, addrend, memory_bank *bank) space.install_read_bank(addrstart, addrend, addrmirror, memory_bank *bank) space.install_read_bank(addrstart, addrend, addrmirror, flags, memory_bank *bank) space.install_write_bank(addrstart, addrend, memory_bank *bank) space.install_write_bank(addrstart, addrend, addrmirror, memory_bank *bank) space.install_write_bank(addrstart, addrend, addrmirror, flags, memory_bank *bank) space.install_readwrite_bank(addrstart, addrend, memory_bank *bank) space.install_readwrite_bank(addrstart, addrend, addrmirror, memory_bank *bank) space.install_readwrite_bank(addrstart, addrend, addrmirror, flags, memory_bank *bank) Install an existing memory bank for reading, writing or both in an ad- dress space. 5.5 Port mapping space.install_read_port(addrstart, addrend, const char *rtag) space.install_read_port(addrstart, addrend, addrmirror, const char *rtag) space.install_read_port(addrstart, addrend, addrmirror, flags, const char *rtag) space.install_write_port(addrstart, addrend, const char *wtag) space.install_write_port(addrstart, addrend, addrmirror, const char *wtag) space.install_write_port(addrstart, addrend, addrmirror, flags, const char *wtag) space.install_readwrite_port(addrstart, addrend, const char *rtag, const char *wtag) space.install_readwrite_port(addrstart, addrend, addrmirror, const char *rtag, const char *wtag) space.install_readwrite_port(addrstart, addrend, addrmirror, flags, const char *rtag, const char *wtag) Install ports by name for reading, writing or both. 5.6 Dropped accesses space.nop_read(addrstart, addrend, addrmirror, flags) space.nop_write(addrstart, addrend, addrmirror, flags) space.nop_readwrite(addrstart, addrend, addrmirror, flags) Drops the accesses for a given range with an optional mirror and flags; 5.7 Unmapped accesses space.unmap_read(addrstart, addrend, addrmirror, flags) space.unmap_write(addrstart, addrend, addrmirror, flags) space.unmap_readwrite(addrstart, addrend, addrmirror, flags) Unmaps the accesses (e.g. logs the access as unmapped) for a given range with an optional mirror and flags. 5.8 Device map installation space.install_device(addrstart, addrend, device, map, unitmask, cswidth, flags) Install a device address with an address map in a space. The unitmask, cswidth and flags arguments are optional. 5.9 Contention using ws_time_delegate = device_delegate<u64 (offs_t, u64)>; using ws_delay_delegate = device_delegate<u32 (offs_t)>; space.install_read_before_time(addrstart, addrend, addrmirror, ws_time_delegate) space.install_write_before_time(addrstart, addrend, addrmirror, ws_time_delegate) space.install_readwrite_before_time(addrstart, addrend, addrmirror, ws_time_delegate) space.install_read_before_delay(addrstart, addrend, addrmirror, ws_delay_delegate) space.install_write_before_delay(addrstart, addrend, addrmirror, ws_delay_delegate) space.install_readwrite_before_delay(addrstart, addrend, addrmirror, ws_delay_delegate) space.install_read_after_delay(addrstart, addrend, addrmirror, ws_delay_delegate) space.install_write_after_delay(addrstart, addrend, addrmirror, ws_delay_delegate) space.install_readwrite_after_delay(addrstart, addrend, addrmirror, ws_delay_delegate) Install a contention handler in the decode path. The addrmirror para- meter is optional. 5.10 View installation space.install_view(addrstart, addrend, view) space.install_view(addrstart, addrend, addrmirror, view) view[0].install... Installs a view in a space. This can be only done once and in only one space, and the view must not have been setup through the address map API before. Once the view is installed, variants can be selected by indexing to call a dynamic mapping method on it. A view can be installed into a variant of another view without issues, with only the usual constraint of single installation. 5.11 Taps using tap = std::function<void (offs_t offset, uNN &data, uNN mem_mask) memory_passthrough_handler mph = space.install_read_tap(addrstart, addrend, name, read_tap, &mph); memory_passthrough_handler mph = space.install_write_tap(addrstart, addrend, name, write_tap, &mph); memory_passthrough_handler mph = space.install_readwrite_tap(addrstart, addrend, name, read_tap, write_tap, &mph); mph.remove(); A tap is a method that is be called when a specific range of addresses is accessed without overriding the actual access. Taps can change the data passed around. A write tap happens before the access, and can change the value to be written. A read tap happens after the access, and can change the value returned. Taps must be of the same width and alignement than the bus. Multiple taps can act over the same addresses. The memory_passthrough_handler object collates a number of taps and al- low to remove them all in one call. The mph parameter is optional and a new one will be created if absent. Taps are lost when a new handler is installed at the same addresses (under the usual principle of last one wins). If they need to be pre- served, one should install a change notifier on the address space, and remove + reinstall the taps when notified. CPU devices • 1. Overview • 2. DRC • 3. Interruptibility • 3.1 Definition • 3.2 Implementation requirements • 3.3 Example implementation with generators • 3.4 Bus contention cpu_device interface • 3.5 Interaction with DRC 1. Overview CPU devices derivatives are used, unsurprisingly, to implement the emu- lation of CPUs, MCUs and SOCs. A CPU device is first a combination of device_execute_interface, device_memory_interface, device_state_inter- face and device_disasm_interface. Refer to the associated documenta- tions when they exist. Two more functionalities are specific to CPU devices which are the DRC and the interruptibility support. 2. DRC TODO. 3. Interruptibility 3.1 Definition An interruptible CPU is defined as a core which is able to suspend the execution of one instruction at any time, exit execute_run, then at the next call of execute_run keep going from where it was. This includes being able to abort an issued memory access, quit execute_run, then upon the next call of execute_run reissue the exact same access. 3.2 Implementation requirements Memory accesses must be done with read_interruptible or write_inter- ruptible on a memory_access_specific or a memory_access_cache. The ac- cess must be done as bus width and bus alignment. After each access the core must test whether icount <= 0. This test should be done after icount is decremented of the time taken by the ac- cess itself, to limit the number of tests. When icount reaches 0 or less it means that the instruction emulation needs to be suspended. To know whether the access needs to be re-issued, access_to_be_redone() needs to be called. If it returns true then the time taken by the ac- cess needs to be credited back, since it hasn't yet happened, and the access will need to be re-issued. The call to access_to_be_redone() clears the reissue flag. If you need to check the flag without clear- ing it use access_to_be_redone_noclear(). The core needs to do enough bookkeeping to eventually restart the in- struction execution just before the access or just after the test, de- pending on the need of reissue. Finally, to indicate to the rest of the infrastructure the support, it must override cpu_is_interruptible() to return true. 3.3 Example implementation with generators To ensure decent performance, the current implementations (h8, 6502 and 68000) use a python generator to generate two versions of each instruc- tion interpreter, one for the normal emulation, and one for restarting the instruction. The restarted version looks like that (for a 4-cycles per access cpu): void device::execute_inst_restarted() { switch(m_inst_substate) { case 0: [...] m_address = [...]; m_mask = [...]; [[fallthrough]]; case 42: m_result = specific.read_interruptible(m_address, m_mask); m_icount -= 4; if(m_icount <= 0) { if(access_to_be_redone()) { m_icount += 4; m_inst_substate = 42; } else m_inst_substate = 43; return; } [[fallthrough]]; case 43: [...] = m_result; [...] } m_inst_substate = 0; return; } The non-restarted version is the same thing with the switch and the fi- nal m_inst_substate clearing removed. void device::execute_inst_non_restarted() { [...] m_address = [...]; m_mask = [...]; m_result = specific.read_interruptible(m_address, m_mask); m_icount -= 4; if(m_icount <= 0) { if(access_to_be_redone()) { m_icount += 4; m_inst_substate = 42; } else m_inst_substate = 43; return; } [...] = m_result; [...] return; } The main loop then looks like this: void device::execute_run() { if(m_inst_substate) call appropriate restarted instruction handler while(m_icount > 0) { debugger_instruction_hook(m_pc); call appropriate non-restarted instruction handler } } The idea is thus that m_inst_substate indicates where in an instruction one is, but only when an interruption happens. It otherwise stays at 0 and is essentially never looked at. Having two versions of the inter- pretation allows to remove the overhead of the switch and the end-of-instruction substate clearing. It is not a requirement to use a generator-based that method, but a different one which does not have unacceptable performance implications has not yet been found. 3.4 Bus contention cpu_device interface The main way to setup bus contention is through the memory maps. Lower-level access can be obtained through some methods on cpu_device though. bool cpu_device::access_before_time(u64 access_time, u64 current_time) noexcept; The method access_before_time allows to try to run an access at a given time in cpu cycles. It takes the current time (total_cycles()) and the expected time for the access. If there aren't enough cycles to reach that time the remaining cycles are eaten and the method returns true to tell not to do the access and call the method again eventually. Other- wise enough cycles are eaten to reach the access time and false is re- turned to tell to do the access. bool cpu_device::access_before_delay(u32 cycles, const void *tag) noexcept; The method access_before_delay allows to try to run an access after a given delay. The tag is an opaque, non-nullptr value used to charac- terize the source of the delay, so that the delay is not applied multi- ple times. Similarly to the previous method cycles are eaten and true is returned to abort the access, false to execute it. void cpu_device::access_after_delay(u32 cycles) noexcept; The method access_after_delay allows to add a delay after an access is done. There is no abort possible, hence no return boolean. void cpu_device::defer_access() noexcept; The method defer_access tells the cpu that we need to wait for an ex- ternal event. It marks the access as to be redone, and eats all the remaining cycles of the timeslice. The idea is then that the access will be retried after time advances up to the next global system syn- chronisation event (sync, timer timeout or set_input_line). This is the method to use when for instance waiting on a magic latch for data expected from scsi transfers, which happen on timer timeouts. void cpu_device::retry_access() noexcept; The method retry_access tells the cpu that the access will need to be retried, and nothing else. This can easily reach a situation of live- lock, so be careful. It is used for instance to simulate a wait line (for the z80 for instance) which is controlled through set_input_line. The idea is that the device setting wait does the set_input_line and a retry_access. The cpu core, as long as the wait line is set just eats cycles. Then, when the line is cleared the core will retry the access. 3.5 Interaction with DRC At this point, interruptibility and DRC are entirely incompatible. We do not have a method to quit the generated code before or after an ac- cess. It's theorically possible but definitely non-trivial. The new floppy subsystem 1. Introduction The new floppy subsystem aims at emulating the behaviour of floppies and floppy controllers at a level low enough that protections work as a matter of course. It reaches its goal by following the real hardware configuration: • a floppy image class keeps in memory the magnetic state of the floppy surface and its physical characteristics • an image handler class talks with the floppy image class to simulate the floppy drive, providing all the signals you have on a floppy drive connector • floppy controller devices talk with the image handler and provide the register interfaces to the host we all know and love • format handling classes are given the task of statelessly converting to and from an on-disk image format to the in-memory magnetic state format the floppy image class manages 2. Floppy storage 101 2.1. Floppy disk A floppy disk is a disc that stores magnetic orientations on their sur- face disposed in a series on concentric circles called tracks or cylin- ders [1]. Its main characteristics are its size (goes from a diameter of around 2.8" to 8") , its number of writable sides (1 or 2) and its magnetic resistivity. The magnetic resistivity indicates how close magnetic orientation changes can happen and the information kept. That's one third of what defines the term "density" that is so often used for floppies (the other two are floppy drive head size and bit-level encoding). The magnetic orientations are always binary, e.g. they're one way or the opposite, there's no intermediate state. Their direction can ei- ther be tangentially to the track, i.e. in the direction of or opposite to the rotation, or in the case of perpendicular recording the direc- tion is perpendicular to the disc surface (hence the name). Perpendicu- lar recording allows for closer orientation changes by writing the mag- netic information more deeply, but arrived late in the technology life- time. 2.88Mb disks and the floppy children (Zip drives, etc.) used perpendicular recording. For simulation purposes the direction is not important, only the fact that only two orientations are possible is. Two more states are possible though: a portion of a track can be demag- netized (no orientation) or damaged (no orientation and can't be writ- ten to). A specific position in the disk rotation triggers an index pulse. That position can be detected through a hole in the surface (very visible in 5.25" and 3" floppies for instance) or through a specific position of the rotating center (3.5" floppies, perhaps others). This index pulse is used to designate the beginning of the track, but is not used by every system. Older 8" floppies have multiple index holes used to mark the beginning of sectors (called hard sectoring) but one of them is po- sitioned differently to be recognized as the track start, and the oth- ers are at fixed positions relative to the origin one. 2.2. Floppy drive A floppy drive is what reads and writes a floppy disk. It includes an assembly capable of rotating the disk at a fixed speed and one or two magnetic heads tied to a positioning motor to access the tracks. The head width and positioning motor step size decides how many tracks are written on the floppy. Total number of tracks goes from 32 to 84 depending on the floppy and drive, with the track 0 being the most ex- terior (longer) one of the concentric circles, and the highest numbered the smallest interior circle. As a result the tracks with the lowest numbers have the lowest physical magnetic orientation density, hence the best reliability. Which is why important and/or often changed structures like the boot block or the fat allocation table are at track 0. That is also where the terminology "stepping in" to increase the track number and "stepping out" to decrease it comes from. The number of tracks available is the second part of what is usually behind the term "density". A sensor detects when the head is on track 0 and the controller is not supposed to try to go past it. In addition physical blocks prevent the head from going out of the correct track range. Some systems (Apple II, some C64) do not take the track 0 sensor into account and just wham the head against the track 0 physical block, giving a well-known crash noise and eventually damaging the head alignment. Also, some systems (Apple II and C64 again) have direct access to the phases of the head positioning motor, allowing to trick the head into going between tracks, in middle or even quarter positions. That was not usable to write more tracks, since the head width did not change, but since reliable reading was only possible with the correct position it was used for some copy protection systems. The disk rotates at a fixed speed for a given track. The most usual speed is 300 rpm for every track, with 360 rpm found for HD 5.25" flop- pies and most 8" ones, and a number of different values like 90 rpm for the earlier floppies or 150 rpm for an HD floppy in an Amiga. Having a fixed rotational speed for the whole disk is called Constant Angular Velocity (CAV, almost everybody) or Zoned Constant Angular Velocity (ZCAV, C64) depending on whether the read/write bitrate is constant or track-dependant. Some systems (Apple II, Mac) vary the rotational speed depending on the track (something like 394 rpm up to 590 rpm) to end up with a Constant Linear Velocity (CLV). The idea behind ZCAV/CLV is to get more bits out of the media by keeping the minimal spacing be- tween magnetic orientation transitions close to the best the support can do. It seems that the complexity was not deemed worth it since al- most no system does it. Finally, after the disc rotates and the head is over the proper track reading happens. The reading is done through an inductive head, which gives it the interesting characteristic of not reading the magnetic orientation directly but instead of being sensitive to orientation in- versions, called flux transitions. This detection is weak and somewhat uncalibrated, so an amplifier with Automatic Gain Calibration (AGC) and a peak detector are put behind the head to deliver clean pulses. The AGC slowly increases the amplification level until a signal goes over the threshold, then modulates its gain so that said signal is at a fixed position over the threshold. Afterwards the increase happens again. This makes the amplifier calibrate itself to the signals read from the floppy as long as flux transitions happen often enough. Too long and the amplification level will reach a point where the random noise the head picks from the environment is amplified over the thresh- old, creating a pulse where none should be. Too long in our case hap- pens to be around 16-20us with no transitions. That means a long enough zone with a fixed magnetic orientation or no orientation at all (demag- netized or damaged) is going to be read as a series of random pulses after a brief delay. This is used by protections and is known as "weak bits", which read differently each time they're accessed. A second level of filtering happens after the peak detector. When two transitions are a little close (but still over the media threshold) a bouncing effect happens between them giving two very close pulses in the middle in addition to the two normal pulses. The floppy drive de- tects when pulses are too close and filter them out, leaving the normal ones. As a result, if one writes a train of high-frequency pulses to the floppy they will be read back as a train of too close pulses (weak because they're over the media tolerance, but picked up by the AGC any- way, only somewhat unreliably) they will be all filtered out, giving a large amount of time without any pulse in the output signal. This is used by some protections since it's not writable with a normally clocked controller. Writing is symmetrical, with a series of pulses sent which make the write head invert the magnetic field orientation each time a pulse is received. So, in conclusion, the floppy drive provides inputs to control disk ro- tation and head position (and choice when double-sided), and the data goes both way as a train of pulses representing magnetic orientation inversions. The absolute value of the orientation itself is never known. 2.3. Floppy controller The task of the floppy controller is to turn the signals to/from the floppy drive into something the main CPU can digest. The level of sup- port actually done by the controller is extremely variable from one de- vice to the other, from pretty much nothing (Apple II, C64) through minimal (Amiga) to complete (Western Digital chips, uPD765 family). Usual functions include drive selection, motor control, track seeking and of course reading and writing data. Of these only the last two need to be described, the rest is obvious. The data is structured at two levels: how individual bits (or nibbles, or bytes) are encoded on the surface, and how these are grouped in in- dividually-addressable sectors. Two standards exist for these, called FM and MFM, and in addition a number of systems use their home-grown variants. Moreover, some systems such as the Amiga use a standard bit-level encoding (MFM) but a homegrown sector-level organisation. 2.3.1. Bit-level encodings 2.3.1.1. Cell organization All floppy controllers, even the wonkiest like the Apple II one, start by dividing the track in equally-sized cells. They're angular sections in the middle of which a magnetic orientation inversion may be present. From a hardware point of view the cells are seen as durations, which combined with the floppy rotation give the section. For instance the standard MFM cell size for a 3" double-density floppy is 2us, which combined with the also standard 300 rpm rotational speed gives an angu- lar size of 1/100000th of a turn. Another way of saying it is that there are 100K cells in a 3" DD track. In every cell there may or may not be a magnetic orientation transi- tion, e.g. a pulse coming from (reading) or going to (writing) the floppy drive. A cell with a pulse is traditionally noted '1', and one without '0'. Two constraints apply to the cell contents though. First, pulses must not be too close together or they'll blur each-other and/or be filtered out. The limit is slightly better than 1/50000th of a turn for single and double density floppies, half that for HD floppys, and half that again for ED floppies with perpendicular recording. Second, they must not be too away from each other or either the AGC is going to get wonky and introduce phantom pulses or the controller is going to lose sync and get a wrong timing on the cells on reading. Conservative rule of thumb is not to have more than three consecutive '0' cells. Of course protections play with that to make formats not reproducible by the system controller, either breaking the three-zeroes rule or playing with the cells durations/sizes. Bit encoding is then the art of transforming raw data into a cell 0/1 configuration that respects the two constraints. 2.3.1.2. FM encoding The very first encoding method developed for floppies is called Fre- quency Modulation, or FM. The cell size is set at slightly over the physical limit, e.g. 4us. That means it is possible to reliably have consecutive '1' cells. Each bit is encoded on two cells: • the first cell, called the clock bit, is '1' • the second cell, called data bit, is the bit Since every other cell at least is '1' there is no risk of going over three zeroes. The name Frequency Modulation simply derives from the fact that a 0 is encoded with one period of a 125Khz pulse train while a 1 is two peri- ods of a 250Khz pulse train. 2.3.1.3. MFM encoding The FM encoding has been superseded by the Modified Frequency Modula- tion encoding, which can cram exactly twice as much data on the same surface, hence its other name of "double density". The cell size is set at slightly over half the physical limit, e.g. 2us usually. The constraint means that two '1' cells must be separated by at least one '0' cell. Each bit is once again encoded on two cells: • the first cell, called the clock bit, is '1' if both the previous and current data bits are 0, '0' otherwise • the second cell, called data bit, is the bit The minimum space rule is respected since a '1' clock bit is by defini- tion surrounded by two '0' data bits, and a '1' data bit is surrounded by two '0' clock bits. The longest '0'-cell string possible is when encoding 101 which gives x10001, respecting the maximum of three ze- roes. 2.3.1.4. GCR encodings Group Coded Recording, or GCR, encodings are a class of encodings where strings of bits at least nibble-size are encoded into a given cell stream given by a table. It has been used in particular by the Apple II, the Mac and the C64, and each system has its own table, or tables. 2.3.1.5. Other encodings Other encodings exist, like M2FM, but they're very rare and system-spe- cific. 2.3.1.6. Reading back encoded data Writing encoded data is easy: you only need a clock at the appropriate frequency and send or not a pulse on the clock edges. Reading back the data is where the fun is. Cells are a logical construct and not a physical measurable entity. Rotational speeds very around the defined one (2% is not rare), and local perturbations (air turbulence, surface distance) make the instantaneous speed very variable in general. So to extract the cell values stream, the controller must dynamically syn- chronize with the pulse train that the floppy head picks up. The prin- ciple is simple: a cell-sized duration window is built within which the presence of at least one pulse indicates the cell is a '1', and the ab- sence of any a '0'. After reaching the end of the window, the starting time is moved appropriately to try to keep the observed pulse at the exact middle of the window. This allows the phase to be corrected on every '1' cell, making the synchronization work if the rotational speed is not too off. Subsequent generations of controllers used Phase-Locked Loops (PLLs) which vary both phase and window duration to adapt better to inaccuarate rotational speeds, usually with a tolerance of 15%. Once the cell data stream is extracted, decoding depends on the encod- ing. In the FM and MFM case the only question is to recognize data bits from clock bits, while in GCR the start position of the first group should be found. That second level of synchronization is handled at a higher level using patterns not found in a normal stream. 2.3.2. Sector-level organization Floppies have been designed for read/write random access to reasonably sized blocks of data. Track selection allows for a first level of ran- dom access and sizing, but the ~6K of a double density track would be too big a block to handle. 256/512 bytes are considered a more appro- priate value. To that end data on a track is organized as a series of (sector header, sector data) pairs where the sector header indicates important information like the sector number and size, and the sector data contains the data. Sectors have to be broken in two parts because while reading is easy, read the header then read the data if you want it, writing requires reading the header to find the correct place then once that is done switching on the writing head for the data. Starting writing is not instantaneous and will not be perfectly phase-aligned with the read header, so space for synchronization is required between header and data. In addition somewhere in the sector header and in the sector data are pretty much always added some kind of checksum allowing to know whether the data was damaged or not. FM and MFM have (not always used) standard sector layout methods. 2.3.2.1. FM sector layout The standard "PC" track/sector layout for FM is as such: • A number of FM-encoded 0xff (usually 40) • 6 FM-encoded 0x00 (giving a steady 125KHz pulse train) • The 16-cell stream 1111011101111010 (f77a, clock 0xd7, data 0xfc) • A number of FM-encoded 0xff (usually 26, very variable) Then for each sector: - 6 FM-encoded 0x00 (giving a steady 125KHz pulse train) • The 16-cell stream 1111010101111110 (f57e, clock 0xc7, data 0xfe) • Sector header, e.g. FM encoded track, head, sector, size code and two bytes of crc • 11 FM-encoded 0xff • 6 FM-encoded 0x00 (giving a steady 125KHz pulse train) • The 16-cell stream 1111010101101111 (f56f, clock 0xc7, data 0xfb) • FM-encoded sector data followed by two bytes of crc • A number of FM-encoded 0xff (usually 48, very variable) The track is finished with a stream of '1' cells. The 125KHz pulse trains are used to lock the PLL to the signal cor- rectly. The specific 16-cells streams allow to distinguish between clock and data bits by providing a pattern that is not supposed to hap- pen in normal FM-encoded data. In the sector header track numbers start at 0, heads are 0/1 depending on the size, sector numbers usually start at 1 and size code is 0 for 128 bytes, 1 for 256, 2 for 512, etc. The CRC is a cyclic redundancy check of the data bits starting with the mark just after the pulse train using polynom 0x11021. The Western Digital-based controllers usually get rid of everything but some 0xff before the first sector and allow a better use of space as a result. 2.3.2.2. MFM sector layout The standard "PC" track/sector layout for MFM is as such: • A number of MFM-encoded 0x4e (usually 80) • 12 FM-encoded 0x00 (giving a steady 250KHz pulse train) • 3 times the 16-cell stream 0101001000100100 (5224, clock 0x14, data 0xc2) • The MFM-encoded value 0xfc • A number of MFM-encoded 0x4e (usually 50, very variable) Then for each sector: • 12 FM-encoded 0x00 (giving a steady 250KHz pulse train) • 3 times the 16-cell stream 0100010010001001 (4489, clock 0x0a, data 0xa1) • Sector header, e.g. MFM-encoded 0xfe, track, head, sector, size code and two bytes of crc • 22 MFM-encoded 0x4e • 12 MFM-encoded 0x00 (giving a steady 250KHz pulse train) • 3 times the 16-cell stream 0100010010001001 (4489, clock 0x0a, data 0xa1) • MFM-encoded 0xfb, sector data followed by two bytes of crc • A number of MFM-encoded 0x4e (usually 84, very variable) The track is finished with a stream of MFM-encoded 0x4e. The 250KHz pulse trains are used to lock the PLL to the signal cor- rectly. The cell pattern 4489 does not appear in normal MFM-encoded data and is used for clock/data separation. As for FM, the Western Digital-based controllers usually get rid of everything but some 0x4e before the first sector and allow a better use of space as a result. 2.3.2.3. Formatting and write splices To be usable, a floppy must have the sector headers and default sector data written on every track before using it. The controller starts writing at a given place, often the index pulse but on some systems whenever the command is sent, and writes until a complete turn is done. That's called formatting the floppy. At the point where the writing stops there is a synchronization loss since there is no chance the cell stream clock warps around perfectly. This brutal phase change is called a write splice, specifically the track write splice. It is the point where writing should start if one wants to raw copy the track to a new floppy. Similarly two write splices are created when a sector is written at the start and end of the data block part. They're not supposed to happen on a mastered disk though, even if there are some rare exceptions. 3. The new implementation 3.1. Floppy disk representation The floppy disk contents are represented by the class floppy_image. It contains information of the media type and a representation of the mag- netic state of the surface. The media type is divided in two parts. The first half indicates the physical form factor, i.e. all medias with that form factor can be physically inserted in a reader that handles it. The second half indi- cates the variants which are usually detectable by the reader, such as density and number of sides. Track data consists of a series of 32-bits lsb-first values represent- ing magnetic cells. Bits 0-27 indicate the absolute position of the start of the cell (not the size), and bits 28-31 the type. Type can be: • 0, MG_A -> Magnetic orientation A • 1, MG_B -> Magnetic orientation B • 2, MG_N -> Non-magnetized zone (neutral) • 3, MG_D -> Damaged zone, reads as neutral but cannot be changed by writing The position is in angular units of 1/200,000,000th of a turn. It cor- responds to one nanosecond when the drive rotates at 300 rpm. The last cell implicit end position is of course 200,000,000. Unformatted tracks are encoded as zero-size. The "track splice" information indicates where to start writing if you try to rewrite a physical disk with the data. Some preservation for- mats encode that information, it is guessed for others. The write track function of fdcs should set it. The representation is the angu- lar position relative to the index. 3.2. Converting to and from the internal representation 3.2.1. Class and interface We need to be able to convert on-disk formats of the floppy data to and from the internal representation. This is done through classes derived from floppy_image_format_t. The interface to be implemented includes: - name() gives the short name of the on-disk format • description() gives a short description of the format • extensions() gives a comma-separated list of file name extensions found for that format • supports_save() returns true is converting to that external format is supported • identify(file, form factor) gives a 0-100 score for the file to be of that format: • 0 = not that format • 100 = certainly that format • 50 = format identified from file size only • load(file, form factor, floppy_image) loads an image and converts it into the internal representation • save(file, floppy_image) (if implemented) converts from the internal representation and saves an image All of these methods are supposed to be stateless. 3.2.2. Conversion helper methods A number of methods are provided to simplify writing the converter classes. 3.2.2.1. Load-oriented conversion methods generate_track_from_bitstream(track number, head number, UINT8 *cell stream, int cell count, floppy image) Takes a stream of cell types (0/1), MSB-first, converts it to the internal format and stores it at the given track and head in the given image. generate_track_from_levels(track number, head number, UINT32 *cell levels, int cell count, splice position, floppy image) Takes a variant of the internal format where each value represents a cell, the position part of the values is the size of the cell and the level part is MG_0, MG_1 for normal cell types, MG_N, MG_D for unformatted/damaged cells, and MG_W for Dungeon-Master style weak bits. Converts it into the internal format. The sizes are normal- ized so that they total to a full turn. normalize_times(UINT32 *levels, int level_count) Takes an internal-format buffer where the position part represents angle until the next change and turns it into a normal positional stream, first ensuring that the total size is normalized to a full turn. 3.2.2.2. Save-oriented conversion methods generate_bitstream_from_track(track number, head number, base cell size, UINT8 *cell stream, int &cell_stream_size, floppy image) Extract a cell 0/1 stream from the internal format using a PLL setup with an initial cell size set to 'base cell size' and a +/- 25% tol- erance. struct desc_xs { int track, head, size; const UINT8 *data } extract_sectors_from_bitstream_mfm_pc(...) extract_sectors_from_bitstream_fm_pc(const UINT8 *cell stream, int cell_stream_size, desc_xs *sectors, UINT8 *sectdata, int sectdata_size) Extract standard mfm or fm sectors from a regenerated cell stream. Sectors must point to an array of 256 desc_xs. An existing sector is recognizable by having ->data non-null. Sector data is written in sectdata up to sectdata_size bytes. get_geometry_mfm_pc(...) get_geometry_fm_pc(floppy image, base cell size, int &track_count, int &head_count, int §or_count) Extract the geometry (heads, tracks, sectors) from a pc-ish floppy image by checking track 20. get_track_data_mfm_pc(...) get_track_data_fm_pc(track number, head number, floppy image, base cell size, sector size, sector count, UINT8 *sector data) Extract what you'd get by reading in order 'sector size'-sized sec- tors from number 1 to sector count and put the result in sector data. 3.3. Floppy drive The class floppy_image_interface simulates the floppy drive. That includes a number of control signals, reading, and writing. Control signal changes must be synchronized, e.g. fired off a timer to en- sure the current time is the same for all devices. 3.3.1. Control signals Due to the way they're usually connected to CPUs (e.g. directly on an I/O port), the control signals work with physical instead of log- ical values. Which means than in general 0 means active, 1 means inactive. Some signals also have a callback associated called when they change. mon_w(state) / mon_r() Motor on signal, rotates on 0. idx_r() / setup_index_pulse_cb(cb) Index signal, goes 0 at start of track for about 2ms. Callback is synchronized. Only happens when a disk is in and the motor is run- ning. ready_r() / setup_ready_cb(cb) Ready signal, goes to 1 when the disk is removed or the motor stopped. Goes to 0 after two index pulses. wpt_r() / setup_wpt_cb(cb) Write protect signal (1 = readonly). Callback is unsynchronized. dskchg_r() Disk change signal, goes to 1 when a disk is change, goes to 0 on track change. dir_w(dir) Selects track stepping direction (1 = out = decrease track number). stp_w(state) Step signal, moves by one track on 1->0 transition. trk00_r() Track 0 sensor, returns 0 when on track 0. ss_w(ss) / ss_r() Side select 3.3.2. Read/write interface The read/write interface is designed to work asynchronously, e.g. some- what independently of the current time. [1] Cylinder is a hard-drive term somewhat improperly used for flop- pies. It comes from the fact that hard-drives are similar to floppies but include a series of stacked disks with a read/write head on each. The heads are physically linked and all point to the same circle on every disk at a given time, making the accessed area look like a cylinder. Hence the name. The new SCSI subsystem Introduction The nscsi subsystem was created to allow an implementation to be closer to the physical reality, making it easier (hopefully) to implement new controller chips from the documentations. Global structure Parallel SCSI is built around a symmetric bus to which a number of de- vices are connected. The bus is composed of 9 control lines (for now, later SCSI versions may have more) and up to 32 data lines (but cur- rently implemented chips only handle 8). All the lines are open col- lector, which means that either one or multiple chip connect the line to ground and the line, of course, goes to ground, or no chip drives anything and the line stays at Vcc. Also, the bus uses inverted logic, where ground means 1. SCSI chips traditionally work in logical and not physical levels, so the nscsi subsystem also works in logical levels and does a logical-or of all the outputs of the devices. Structurally, the implementation is done around two main classes: nscsi_bus_devices represents the bus, and nscsi_device represents an individual device. A device only communicate with the bus, and the bus takes care of transparently handling the device discovery and communi- cation. In addition the nscsi_full_device class proposes a SCSI device with the SCSI protocol implemented making building generic SCSI devices like hard drives or CD-ROM readers easier. Plugging in a SCSI bus in a driver The nscsi subsystem leverages the slot interfaces and the device naming to allow for a configurable yet simple bus implementation. First you need to create a list of acceptable devices to plug on the bus. This usually comprises of cdrom, harddisk and the controller chip. For instance: static SLOT_INTERFACE_START( next_scsi_devices ) SLOT_INTERFACE("cdrom", NSCSI_CDROM) SLOT_INTERFACE("harddisk", NSCSI_HARDDISK) SLOT_INTERFACE_INTERNAL("ncr5390", NCR5390) SLOT_INTERFACE_END The _INTERNAL interface indicates a device that is not user-selectable, which is useful for the controller. Then in the machine config (or in a fragment config) you need to first add the bus, and then the (potential) devices as sub-devices of the bus with the SCSI ID as the name. For instance you can use: MCFG_NSCSI_BUS_ADD("scsibus") MCFG_NSCSI_ADD("scsibus:0", next_scsi_devices, "cdrom", 0, 0, 0, false) MCFG_NSCSI_ADD("scsibus:1", next_scsi_devices, "harddisk", 0, 0, 0, false) MCFG_NSCSI_ADD("scsibus:2", next_scsi_devices, 0, 0, 0, 0, false) MCFG_NSCSI_ADD("scsibus:3", next_scsi_devices, 0, 0, 0, 0, false) MCFG_NSCSI_ADD("scsibus:4", next_scsi_devices, 0, 0, 0, 0, false) MCFG_NSCSI_ADD("scsibus:5", next_scsi_devices, 0, 0, 0, 0, false) MCFG_NSCSI_ADD("scsibus:6", next_scsi_devices, 0, 0, 0, 0, false) MCFG_NSCSI_ADD("scsibus:7", next_scsi_devices, "ncr5390", 0, &next_ncr5390_interface, 10000000, true) That configuration puts as default a CD-ROM reader on SCSI ID 0 and a hard drive on SCSI ID 1, and forces the controller on ID 7. The para- meters of add are: • device tag, comprised of bus-tag:scsi-id • the list of acceptable devices • the device name as per the list, if one is to be there by default • the device input config, if any (and there usually isn't one) • the device configuration structure, usually for the controller only • the frequency, usually for the controller only • "false" for a user-modifiable slot, "true" for a fixed slot The full device name, for mapping purposes, will be bus-tag:scsi-id:de- vice-type, i.e. "scsibus:7:ncr5390" for our controller here. Creating a new SCSI device using nscsi_device The base class "nscsi_device" is to be used for down-to-the-metal de- vices, i.e. SCSI controller chips. The class provides three variables and one method. The first variable, scsi_bus, is a pointer to the nscsi_bus_device. The second, scsi_refid, is an opaque reference to pass to the bus on some operations. Finally, scsi_id gives the SCSI ID as per the device tag. It's written once at startup and never written or read afterwards, the device can do whatever it wants with the value or the variable. The virtual method scsi_ctrl_changed is called when watched-for control lines change. Which lines are watched is defined through the bus. The bus proposes five methods to access the lines. The read methods are ctrl_r() and data_r(). The meaning of the control bits are defined in the S_* enum of nscsi_device. The bottom three bits (INP, CTL and MSG) are setup so that masking with 7 (S_PHASE_MASK) gives the tradi- tional numbers for the phases, which are also available with the S_PHASE_* enum. Writing the data lines is done with data_w(scsi_refid, value). Writing the control lines is done with ctrl_w(scsi_refid, value, mask-of-lines-to-change). To change all control lines in one call use S_ALL as the mask. Of course, what is read is the logical-or of all of what is driven by all devices. Finally, the method ctrl_wait_w(scsi_id, value, mask-of-wait-lines-to-change) allows to select which control lines are watched. The watch mask is per-device, and the device method scsi_ctrl_changed is called whenever a control line in the mask changes due to an action of another device (not itself, to avoid an annoying and somewhat useless recursion). Implementing the controller is then just a matter of following the state machines descriptions, at least if they're available. The only part often not described is the arbitration/selection, which is docu- mented in the SCSI standard though. For an initiator (which is what the controller essentially always is), it goes like this: • wait for the bus to be idle • assert the data line which number is your scsi_id (1 << scsi_id) • assert the busy line • wait the arbitration time • check that the of the active data lines the one with the highest num- ber is yours • if no, the arbitration was lost, stop driving anything and restart at the beginning • assert the select line (at that point, the bus is yours) • wait a short while • keep your data line asserted, assert the data line which number is the SCSI ID of the target • wait a short while • assert the atn line if needed, de-assert busy • wait for busy to be asserted or timeout • timeout means nobody is answering at that id, de-assert everything and stop • wait a short while for de-skewing • de-assert the data bus and the select line • wait a short while and then you're done, you're connected with the target until the target de-asserts the busy line, either because you asked it to or just to an- noy you. The de-assert is called a disconnect. The ncr5390 is an example of how to use a two-level state machine to handle all the events. Creating a new SCSI device using nscsi_full_device The base class "nscsi_full_device" is used to create HLE-d SCSI devices intended for generic uses, like hard drives, CD-ROMs, perhaps scanners, etc. The class provides the SCSI protocol handling, leaving only the command handling and (optionally) the message handling to the implemen- tation. The class currently only support target devices. The first method to implement is scsi_command(). That method is called when a command has fully arrived. The command is available in scsi_cmd- buf[], and its length is in scsi_cmdsize (but the length is generally useless, the command first byte giving it). The 4096-bytes scsi_cmdbuf array is then freely modifiable. In scsi_command(), the device can either handle the command or pass it up with nscsi_full_device::scsi_command(). To handle the command, a number of methods are available: • get_lun(lua-set-in-command) will give you the LUN to work on (the in-command one can be overriden by a message-level one). • bad_lun() replies to the host that the specific LUN is unsupported. • scsi_data_in(buffer-id, size) sends size bytes from buffer buffer-id • scsi_data_out(buffer-id, size) receives size bytes into buffer buffer-id • scsi_status_complete(status) ends the command with a given status. • sense(deferred, key) prepares the sense buffer for a subsequent re- quest-sense command, which is useful when returning a check-condition status. The scsi_data_* and scsi_status_complete commands are queued, the com- mand handler should call them all without waiting. buffer-id identifies a buffer. 0, aka SBUF_MAIN, targets the scsi_cmd- buf buffer. Other acceptable values are 2 or more. 2+ ids are handled through the scsi_get_data method for read and scsi_put_data for write. UINT8 device::scsi_get_data(int id, int pos) must return byte pos of buffer id, upcalling in nscsi_full_device for id < 2. void device::scsi_put_data(int id, int pos, UINT8 data) must write byte pos in buffer id, upcalling in nscsi_full_device for id < 2. scsi_get_data and scsi_put_data should do the external reads/writes when needed. The device can also override scsi_message to handle SCSI messages other than the ones generically handled, and it can also override some of the timings (but a lot of them aren't used, beware). A number of enums are defined to make things easier. The SS_* enum gives status returns (with SS_GOOD for all's well). The SC_* enum gives the scsi commands. The SM_* enum gives the SCSI messages, with the exception of identify (which is 80-ff, doesn't really fit in an enum). What's missing in scsi_full_device • Initiator support We have no initiator device to HLE at that point. • Delays A scsi_delay command would help giving more realistic timings to the CD-ROM reader in particular. • Disconnected operation Would first require delays and in addition an emulated OS that can handle it. • 16-bits wide operation needs an OS and an initiator that can handle it. What's missing in the ncr5390 (and probably future other controllers) • Bus free detection Right now the bus is considered free if the con- trollers isn't using it, which is true. This may change once discon- nected operation is in. • Target commands We don't emulate (vs. HLE) any target yet. The new 6502 family implementation Introduction The new 6502 family implementation has been created to reach sub-in- struction accuracy in observable behaviour. It is designed with 3 goals in mind: • every bus cycle must happen at the exact time it would happen in a real CPU, and every access the real CPU does is done • instructions can be interrupted at any time in the middle then restarted at that point transparently • instructions can be interrupted even from within a memory handler for bus contention/wait states emulation purposes Point 1 has been ensured through bisimulation with the gate-level simu- lation perfect6502. Point 2 has been ensured structurally through a code generator which will be explained in section 8. Point 3 is not done yet due to lack of support on the memory subsystem side, but sec- tion 9 shows how it will be handled. The 6502 family The MOS 6502 family has been large and productive. A large number of variants exist, varying on bus sizes, I/O, and even opcodes. Some off- shoots (g65c816, hu6280) even exist that live elsewhere in the mame tree. The final class hierarchy is this: 6502 | +------+--------+--+--+-------+-------+ | | | | | | 6510 deco16 6504 6509 rp2a03 65c02 | | +-----+-----+ r65c02 | | | | 6510t 7501 8502 +---+---+ | | 65ce02 65sc02 | 4510 The 6510 adds an up to 8 bits I/O port, with the 6510t, 7501 and 8502 being software-identical variants with different pin count (hence I/O count), die process (NMOS, HNMOS, etc.) and clock support. The deco16 is a Deco variant with a small number of not really under- stood additional instructions and some I/O. The 6504 is a pin and address-bus reduced version. The 6509 adds internal support for paging. The rp2a03 is the NES variant with the D flag disabled and sound func- tionality integrated. The 65c02 is the very first cmos variant with some additional instruc- tions, some fixes, and most of the undocumented instructions turned into nops. The R (Rockwell, but eventually produced by WDC too among others) variant adds a number of bitwise instructions and also stp and wai. The SC variant, used by the Lynx portable console, looks identical to the R variant. The 'S' probably indicates a static-ram-cell process allowing full DC-to-max clock control. The 65ce02 is the final evolution of the ISA in this hierarchy, with additional instructions, registers, and removals of a lot of dummy ac- cesses that slowed the original 6502 down by at least 25%. The 4510 is a 65ce02 with integrated MMU and GPIO support. Usage of the classes All the CPUs are standard modern CPU devices, with all the normal in- teraction with the device infrastructure. To include one of these CPUs in your driver you need to include "CPU/m6502/<CPU>.h" and then do a MCFG_CPU_ADD("tag", <CPU>, clock). 6510 variants port I/O callbacks are setup through: MCFG_<CPU>_PORT_CALLBACKS(READ8(type, read_method), WRITE8(type, write_method)) And the pullup and floating lines mask is given through: MCFG_<CPU>_PORT_PULLS(pullups, floating) In order to see all bus accesses on the memory handlers it is possible to disable accesses through the direct map (at a CPU cost, of course) with: MCFG_M6502_DISABLE_DIRECT() In that case, transparent decryption support is also disabled, every- thing goes through normal memory-map read/write calls. The state of the sync line is given by the CPU method get_sync(), making implementing the decryption in the handler possible. Also, as for every executable device, the CPU method total_cycles() gives the current time in cycles since the start of the machine from the point of view of the CPU. Or, in other words, what is usually called the cycle number for the CPU when somebody talks about bus con- tention or wait states. The call is designed to be fast (no system-wide sync, no call to machine.time()) and is precise. Cycle number for every access is exact at the sub-instruction level. The 4510 special nomap line is accessible through get_nomap(). Other than these specifics, these are perfectly normal CPU classes. General structure of the emulations Each variant is emulated through up to 4 files: • <CPU>.h = header for the CPU class • <CPU>.c = implementation of most of the CPU class • d<CPU>.lst = dispatch table for the CPU • o<CPU>.lst = opcode implementation code for the CPU The last two are optional. They're used to generate a <CPU>.inc file in the object directory which is included by the .c file. At a minimum, the class must include a constructor and an enum picking up the correct input line ids. See m65sc02 for a minimalist example. The header can also include specific configuration macros (see m8502) and also the class can include specific memory accessors (more on these later, simple example in m6504). If the CPU has its own dispatch table, the class must also include the declaration (but not definition) of disasm_entries, do_exec_full and do_exec_partial, the declaration and definition of disasm_disassemble (identical for all classes but refers to the class-specific disasm_en- tries array) and include the .inc file (which provides the missing def- initions). Support for the generation must also be added to CPU.mak. If the CPU has in addition its own opcodes, their declaration must be done through a macro, see f.i. m65c02. The .inc file will provide the definitions. Dispatch tables Each d<CPU>.lst is the dispatch table for the CPU. Lines starting with '#' are comments. The file must include 257 entries, the first 256 be- ing opcodes and the 257th what the CPU should do on reset. In the 6502 irq and nmi actually magically call the "brk" opcode, hence the lack of specific description for them. Entries 0 to 255, i.e. the opcodes, must have one of these two struc- tures: • opcode_addressing-mode • opcode_middle_addressing-mode Opcode is traditionally a three-character value. Addressing mode must be a 3-letter value corresponding to one of the DASM_* macros in m6502.h. Opcode and addressing mode are used to generate the disassem- bly table. The full entry text is used in the opcode description file and the dispatching methods, allowing for per-CPU variants for identi- cal-looking opcodes. An entry of "." was usable for unimplemented/unknown opcodes, generat- ing "???" in the disassembly, but is not a good idea at this point since it will infloop in execute() if encountered. Opcode descriptions Each o<CPU>.lst file includes the CPU-specific opcodes descriptions. An opcode description is a series of lines starting by an opcode entry by itself and followed by a series of indented lines with code executing the opcode. For instance the asl <absolute address> opcode looks like this: asl_aba TMP = read_pc(); TMP = set_h(TMP, read_pc()); TMP2 = read(TMP); write(TMP, TMP2); TMP2 = do_asl(TMP2); write(TMP, TMP2); prefetch(); First the low part of the address is read, then the high part (read_pc is auto-incrementing). Then, now that the address is available the value to shift is read, then re-written (yes, the 6502 does that), shifted then the final result is written (do_asl takes care of the flags). The instruction finishes with a prefetch of the next instruc- tion, as all non-CPU-crashing instructions do. Available bus-accessing functions are: +------------------+----------------------------+ | read(adr) | standard read | +------------------+----------------------------+ | read_direct(adr) | read from program space | +------------------+----------------------------+ | read_pc() | read at the PC address and | | | increment it | +------------------+----------------------------+ | read_pc_noinc() | read at the PC address | +------------------+----------------------------+ | read_9() | 6509 indexed-y banked read | +------------------+----------------------------+ | write(adr, val) | standard write | +------------------+----------------------------+ | prefetch() | instruction prefetch | +------------------+----------------------------+ | prefetch_noirq() | instruction prefetch with- | | | out irq check | +------------------+----------------------------+ Cycle counting is done by the code generator which detects (through string matching) the accesses and generates the appropriate code. In addition to the bus-accessing functions a special line can be used to wait for the next event (irq or whatever). "eat-all-cycles;" on a line will do that wait then continue. It is used by wai_imp and stp_imp for the m65c02. Due to the constraints of the code generation, some rules have to be followed: • in general, stay with one instruction/expression per line • there must be no side effects in the parameters of a bus-accessing function • local variables lifetime must not go past a bus access. In general, it's better to leave them to helper methods (like do_asl) which do not do bus accesses. Note that "TMP" and "TMP2" are not local vari- ables, they're variables of the class. • single-line then or else constructs must have braces around them if they're calling a bus-accessing function The per-opcode generated code are methods of the CPU class. As such they have complete access to other methods of the class, variables of the class, everything. Memory interface For better opcode reuse with the MMU/banking variants, a memory access subclass has been created. It's called memory_interface, declared in m6502_device, and provides the following accessors: +----------------------------+----------------------------+ | UINT8 read(UINT16 adr) | normal read | +----------------------------+----------------------------+ | UINT8 read_sync(UINT16 | opcode read with sync ac- | | adr) | tive (first byte of op- | | | code) | +----------------------------+----------------------------+ | UINT8 read_arg(UINT16 adr) | opcode read with sync in- | | | active (rest of opcode) | +----------------------------+----------------------------+ | void write(UINT16 adr, | normal write | | UINT8 val) | | +----------------------------+----------------------------+ +----------------------------+----------------------------+ | UINT8 read_9(UINT16 adr) | special y-indexed 6509 | | | read, defaults to read() | +----------------------------+----------------------------+ | void write_9(UINT16 adr, | special y-indexed 6509 | | UINT8 val); | write, defaults to write() | +----------------------------+----------------------------+ Two implementations are given by default, one usual, mi_default_normal, one disabling direct access, mi_default_nd. A CPU that wants its own interface (see 6504 or 6509 for instance) must override device_start, intialize mintf there then call init(). The generated code A code generator is used to support interrupting and restarting an in- struction in the middle. This is done through a two-level state machine with updates only at the boundaries. More precisely, inst_state tells you which main state you're in. It's equal to the opcode byte when 0-255, and 0xff00 means reset. It's always valid and used by instruc- tions like rmb. inst_substate indicates at which step we are in an in- struction, but it set only when an instruction has been interrupted. Let's go back to the asl <abs> code: asl_aba TMP = read_pc(); TMP = set_h(TMP, read_pc()); TMP2 = read(TMP); write(TMP, TMP2); TMP2 = do_asl(TMP2); write(TMP, TMP2); prefetch(); The complete generated code is: void m6502_device::asl_aba_partial() { switch(inst_substate) { case 0: if(icount == 0) { inst_substate = 1; return; } case 1: TMP = read_pc(); icount--; if(icount == 0) { inst_substate = 2; return; } case 2: TMP = set_h(TMP, read_pc()); icount--; if(icount == 0) { inst_substate = 3; return; } case 3: TMP2 = read(TMP); icount--; if(icount == 0) { inst_substate = 4; return; } case 4: write(TMP, TMP2); icount--; TMP2 = do_asl(TMP2); if(icount == 0) { inst_substate = 5; return; } case 5: write(TMP, TMP2); icount--; if(icount == 0) { inst_substate = 6; return; } case 6: prefetch(); icount--; } inst_substate = 0; } One can see that the initial switch() restarts the instruction at the appropriate substate, that icount is updated after each access, and upon reaching 0 the instruction is interrupted and the substate up- dated. Since most instructions are started from the beginning a spe- cific variant is generated for when inst_substate is known to be 0: void m6502_device::asl_aba_full() { if(icount == 0) { inst_substate = 1; return; } TMP = read_pc(); icount--; if(icount == 0) { inst_substate = 2; return; } TMP = set_h(TMP, read_pc()); icount--; if(icount == 0) { inst_substate = 3; return; } TMP2 = read(TMP); icount--; if(icount == 0) { inst_substate = 4; return; } write(TMP, TMP2); icount--; TMP2 = do_asl(TMP2); if(icount == 0) { inst_substate = 5; return; } write(TMP, TMP2); icount--; if(icount == 0) { inst_substate = 6; return; } prefetch(); icount--; } That variant removes the switch, avoiding a costly computed branch and also an inst_substate write. There is in addition a fair chance that the decrement-test with zero pair is compiled into something efficient. All these opcode functions are called through two virtual methods, do_exec_full and do_exec_partial, which are generated into a 257-entry switch statement. Pointers-to-methods being expensive to call, a vir- tual function implementing a switch has a fair chance of being better. The execute main call ends up very simple: void m6502_device::execute_run() { if(inst_substate) do_exec_partial(); while(icount > 0) { if(inst_state < 0x100) { PPC = NPC; inst_state = IR; if(machine().debug_flags & DEBUG_FLAG_ENABLED) debugger_instruction_hook(this, NPC); } do_exec_full(); } } If an instruction was partially executed finish it (icount will then be zero if it still doesn't finish). Then try to run complete instruc- tions. The NPC/IR dance is due to the fact that the 6502 does instruc- tion prefetching, so the instruction PC and opcode come from the prefetch results. Future bus contention/delay slot support Supporting bus contention and delay slots in the context of the code generator only requires being able to abort a bus access when not enough cycles are available into icount, and restart it when cycles have become available again. The implementation plan is to: • Have a delay() method on the CPU that removes cycles from icount. If icount becomes zero or less, having it throw a suspend() exception. • Change the code generator to generate this: void m6502_device::asl_aba_partial() { switch(inst_substate) { case 0: if(icount == 0) { inst_substate = 1; return; } case 1: try { TMP = read_pc(); } catch(suspend) { inst_substate = 1; return; } icount--; if(icount == 0) { inst_substate = 2; return; } case 2: try { TMP = set_h(TMP, read_pc()); } catch(suspend) { inst_substate = 2; return; } icount--; if(icount == 0) { inst_substate = 3; return; } case 3: try { TMP2 = read(TMP); } catch(suspend) { inst_substate = 3; return; } icount--; if(icount == 0) { inst_substate = 4; return; } case 4: try { write(TMP, TMP2); } catch(suspend) { inst_substate = 4; return; } icount--; TMP2 = do_asl(TMP2); if(icount == 0) { inst_substate = 5; return; } case 5: try { write(TMP, TMP2); } catch(suspend) { inst_substate = 5; return; } icount--; if(icount == 0) { inst_substate = 6; return; } case 6: try { prefetch(); } catch(suspend) { inst_substate = 6; return; } icount--; } inst_substate = 0; } A modern try/catch costs nothing if an exception is not thrown. Using this the control will go back to the main loop, which will then look like this: void m6502_device::execute_run() { if(waiting_cycles) { icount -= waiting_cycles; waiting_cycles = 0; } if(icount > 0 && inst_substate) do_exec_partial(); while(icount > 0) { if(inst_state < 0x100) { PPC = NPC; inst_state = IR; if(machine().debug_flags & DEBUG_FLAG_ENABLED) debugger_instruction_hook(this, NPC); } do_exec_full(); } waiting_cycles = -icount; icount = 0; } A negative icount means that the CPU won't be able to do anything for some time in the future, because it's either waiting for the bus to be free or for a peripheral to answer. These cycles will be counted until elapsed and then normal processing will go on. It's important to note that the exception path only happens when the contention/wait state goes further than the scheduling slice of the CPU. That should not usu- ally be the case, so the cost should be minimal. Multi-dispatch variants Some variants currently in the process of being supported change in- struction set depending on an internal flag, either switching to a 16-bits mode or changing some register accesses to memory accesses. This is handled by having multiple dispatch tables for the CPU, the d<CPU>.lst not being 257 entries anymore but 256*n+1. The variable inst_state_base must select which instruction table to use at a given time. It must be a multiple of 256, and is in fact simply OR-ed to the first instruction byte to get the dispatch table index (aka inst_state). Current TO-DO: • Implement the bus contention/wait states stuff, but that requires support on the memory map side first. • Integrate the I/O subsystems in the 4510 • Possibly integrate the sound subsytem in the rp2a03 • Add decent hookups for the Apple 3 madness Software 3D Rendering in MAME • Background • Concepts • ObjectType • Primitives • Synchronization • The poly_manager class • Types & Constants • vertex_t • extent_t • render_delegate • Methods • poly_manager • wait • object_data • register_poly_array • render_tile • render_triangle • render_triangle_fan • render_triangle_strip • render_polygon • render_extents • zclip_if_less • Example Renderer • Types • Constructor • swap_buffers • clear_buffers • draw_triangle • draw_triangle_flat • draw_triangle_gouraud • Advanced Topic: the poly_array class • Methods • poly_array • count • max • itemsize • allocated • byindex • contiguous • indexof • reset • next • last Background Beginning in the late 1980s, many arcade games began incorporating hardware-rendered 3D graphics into their video. These 3D graphics are typically rendered from low-level primitives into a frame buffer (usu- ally double- or triple-buffered), then perhaps combined with tradi- tional tilemaps or sprites, before being presented to the player. When it comes to emulating 3D games, there are two general approaches. The first approach is to leverage modern 3D hardware by mapping the low-level primitives onto modern equivalents. For a cross-platform emu- lator like MAME, this requires having an API that is flexible enough to describe the primitives and all their associated behaviors with high accuracy. It also requires the emulator to be able to read back from the rendered frame buffer (since many games do this) and combine it with other elements, in a way that is properly synchronized with back- ground rendering. The alternative approach is to render the low-level primitives directly in software. This has the advantage of being able to achieve pretty much any behavior exhibited by the original hardware, but at the cost of speed. In MAME, since all emulation happens on one thread, this is particularly painful. However, just as with the 3D hardware approach, in theory a software-based approach could be spun off to other threads to handle the work, as long as mechanisms were present to synchronize when necessary, for example, when reading/writing directly to/from the frame buffer. For the time being, MAME has opted for the second approach, leveraging a templated helper class called poly_manager to handle common situa- tions. Concepts At its core, poly_manager is a mechanism to support multi-threaded ren- dering of low-level 3D primitives. Callers provide poly_manager with a set of vertices for a primitive plus a render callback. poly_manager breaks the primitive into clipped scanline extents and distributes the work among a pool of worker threads. The render callback is then called on the worker thread for each extent, where game-specific logic can do whatever needs to happen to render the data. One key responsibility that poly_manager takes care of is ensuring or- der. Given a pool of threads and a number of work items to complete, it is important thatat least within a given scanlineall work is performed serially in order. The basic approach is to assign each extent to a bucket based on the Y coordinate. poly_manager then ensures that only one worker thread at a time is responsible for processing work in a given bucket. Vertices in poly_manager consist of simple 2D X and Y coordinates, plus zero or more additional iterated parameters. These iterated parameters can be anything: intensity values for lighting; RGB(A) colors for Gouraud shading; normalized U, V coordinates for texture mapping; 1/Z values for Z buffering; etc. Iterated parameters, regardless of what they represent, are interpolated linearly across the primitive in screen space and provided as part of the extent to the render callback. ObjectType When creating a poly_manager class, you must provide it a special type that you define, known as ObjectType. Because rendering happens asynchronously on worker threads, the idea is that the ObjectType class will hold a snapshot of all the relevant data needed for rendering. This allows the main thread to proceedpoten- tially modifying some of the relevant statewhile rendering happens elsewhere. In theory, we could allocate a new ObjectType class for each primitive rendered; however, that would be rather inefficient. It is quite common to set up the rendering state and then render several primitives using the same state. For this reason, poly_manager maintains an internal array of ObjectType objects and keeps a copy of the last ObjectType used. Before submitting a new primitive, callers can see if the rendering state has changed. If it has, it can ask poly_manager to allocate a new ObjectType class and fill it in. When the primitive is submitted for rendering, the most re- cently allocated ObjectType instance is implicitly captured and pro- vided to the render callbacks. For more complex scenarios, where data might change even more infre- quently, there is a poly_array template, which can be used to manage data in a similar way. In fact, internally poly_manager uses the poly_array class to manage its ObjectType allocations. More information on the poly_array class is provided later. Primitives poly_manager supports several different types of primitives: • The most commonly-used primitive in poly_manager is the triangle, which has the nice property that iterated parameters have constant deltas across the full surface. Arbitrary-length triangle fans and triangle strips are also supported. • In addition to triangles, poly_manager also supports polygons with an arbitrary number of vertices. The list of vertices is expected to be in either clockwise or anticlockwise order. poly_manager will walk the edges to compute deltas across each extent. • As a special case, poly_manager supports a tile primitive, which is a simple quad defined by two vertices, a top-left vertex and a bot- tom-right vertex. Like triangles, tiles have constant iterated para- meter deltas across their surface. • Finally, poly_manager supports a fully custom mechanism where the caller provides a list of extents that are more or less fed directly to the worker threads. This is useful if emulating a system that has unusual primitives or requires highly specific behaviors for its edges. Synchronization One of the key requirements of providing an asynchronous rendering mechanism is synchronization. Synchronization in poly_manager is super simple: just call the wait() function. There are several common reasons for issuing a wait: • At display time, the pixel data must be copied to the screen. If any primitives were queued which touch the portion of the display that is going to be shown, you need to wait for rendering to be complete be- fore copying. Note that this wait may not be strictly necessary in some situations (for example, a triple-buffered system). • If the emulated system has a mechanism to read back from the frame- buffer after rendering, then a wait must be issued prior to the read in order to ensure that asynchronous rendering is complete. • If the emulated system modifies any state that is not cached in the ObjectType or elsewhere (for example, texture memory), then a wait must be issued to ensure that pending primitives which might consume that state have finished their work. • If the emulated system can use a previous render target as, say, the texture source for a new primitive, then submitting the second primi- tive must wait until the first completes. poly_manager provides no internal mechanism to help detect this, so it is on the caller to de- termine when or if this is necessary. Because the wait operation knows after it is done that all rendering is complete, poly_manager also takes this opportunity to reclaim all mem- ory allocated for its internal structures, as well as memory allocated for ObjectType structures. Thus it is important that you dont hang onto any ObjectType pointers after a wait is called. The poly_manager class In most applications, poly_manager is not used directly, but rather serves as the base class for a more complete rendering class. The poly_manager class itself is a template: template<typename BaseType, class ObjectType, int MaxParams, u8 Flags = 0> class poly_manager; and the template parameters are: • BaseType is the type used internally for coordinates and iterated pa- rameters, and should generally be either float or double. In theory, a fixed-point integral type could also be used, though the math logic has not been designed for that, so you may encounter problems. • ObjectType is the user-defined per-object data structure described above. Internally, poly_manager will manage a poly_array of these, and a pointer to the most-recently allocated one at the time a primi- tive is submitted will be implicitly passed to the render callback for each corresponding extent. • MaxParams is the maximum number of iterated parameters that may be specified in a vertex. Iterated parameters are generic and treated identically, so the mapping of parameter indices is completely up to the contract between the caller and the render callback. It is per- mitted for MaxParams to be 0. • Flags is zero or more of the following flags: • POLY_FLAG_NO_WORK_QUEUE specify this flag to disable asynchronous rendering; this can be useful for debugging. When this option is enabled, all primitives are queued and then processed in order on the calling thread when wait() is called on the poly_manager class. • POLY_FLAG_NO_CLIPPING specify this if you want poly_manager to skip its internal clipping. Use this if your render callbacks do their own clipping, or if the caller always handles clipping prior to submitting primitives. Types & Constants vertex_t Within the poly_manager class, youll find a vertex_t type that de- scribes a single vertex. All primitive drawing methods accept 2 or more of these vertex_t objects. The vertex_t includes the X and Y coordi- nates along with an array of iterated parameter values at that vertex: struct vertex_t { vertex_t() { } vertex_t(BaseType _x, BaseType _y) { x = _x; y = _y; } BaseType x, y; // X, Y coordinates std::array<BaseType, MaxParams> p; // iterated parameters }; Note that vertex_t itself is defined in terms of the BaseType and Max- Params template values of the owning poly_manager class. All of poly_managers primitives operate in screen space, where (0,0) represents the top-left corner of the top-left pixel, and (0.5,0.5) represents the center of that pixel. Left and top pixel values are in- clusive, while right and bottom pixel values are exclusive. Thus, a tile rendered from (2,2)-(4,3) will completely cover 2 pixels: (2,2) and (3,2). When calling a primitive drawing method, the iterated parameter array p need not be completely filled out. The number of valid iterated parame- ter values is specified as a template parameter to the primitive draw- ing methods, so only that many parameters need to actually be populated in the vertex_t structures that are passed in. extent_t poly_manager breaks primitives into extents, which are contiguous hori- zontal spans contained within a single scanline. These extents are then distributed to worker threads, who will call the render callback with information on how to render each extent. The extent_t type describes one such extent, providing the bounding X coordinates along with an ar- ray of iterated parameter start values and deltas across the span: struct extent_t { struct param_t { BaseType start; // parameter value at start BaseType dpdx; // dp/dx relative to start }; int16_t startx, stopx; // starting (inclusive)/ending (exclusive) endpoints std::array<param_t, MaxParams> param; // array of parameter start/deltas void *userdata; // custom per-span data }; For each iterated parameter, the start value contains the value at the left side of the span. The dpdx value contains the change of the para- meters value per X coordinate. There is also a userdata field in the extent_t structure, which is not normally used, except when performing custom rendering. render_delegate When rendering a primitive, in addition to the vertices, you must also provide a render_delegate callback of the form: void render(int32_t y, extent_t const &extent, ObjectType const &object, int threadid) This callback is responsible for the actual rendering. It will be called at a later time, likely on a different thread, for each extent. The parameters passed are: • y is the Y coordinate (scanline) of the current extent. • extent is a reference to a extent_t structure, described above, which specifies for this extent the start/stop X values along with the start/delta values for each iterated parameter. • object is a reference to the most recently allocated ObjectType at the time the primitive was submitted for rendering; in theory it should contain most of not all of the necessary data to perform ren- dering. • threadid is a unique ID indicating the index of the thread youre run- ning on; this value is useful if you are keeping any kind of statis- tics and dont want to add contention over shared values. In this sit- uation, you can allocate WORK_MAX_THREADS instances of your data and update the instance for the threadid you are passed. When you want to display the statistics, the main thread can accumulate and reset the data from all threads when its safe to do so (e.g., after a wait). Methods poly_manager poly_manager(running_machine &machine); The poly_manager constructor takes just one parameter, a reference to the running_machine. This grants poly_manager access to the work queues needed for multithreaded running. wait void wait(char const *debug_reason = "general"); Calling wait() stalls the calling thread until all outstanding render- ing is complete: • debug_reason is an optional parameter specifying the reason for the wait. It is useful if the compile-time constant TRACK_POLY_WAITS is enabled, as it will print a summary of wait times and reasons at the end of execution. Return value: none. object_data objectdata_array &object_data(); This method just returns a reference to the internally-maintained poly_array of the ObjectType you specified when creating poly_manager. For most applications, the only interesting thing to do with this ob- ject is call the next() method to allocate a new object to fill out. Return value: reference to a poly_array of ObjectType. register_poly_array void register_poly_array(poly_array_base &array); For advanced applications, you may choose to create your own poly_array objects to manage large chunks of infrequently-changed data, such a palettes. After each wait(), poly_manager resets all the poly_array ob- jects it knows about in order to reclaim all outstanding allocated mem- ory. By registering your poly_array objects here, you can ensure that your arrays will also be reset after an wait() call. Return value: none. render_tile template<int ParamCount> uint32_t render_tile(rectangle const &cliprect, render_delegate callback, vertex_t const &v1, vertex_t const &v2); This method enqueues a single tile primitive for rendering: • ParamCount is the number of live values in the iterated parameter ar- ray within each vertex_t provided; it must be no greater than the MaxParams value specified in the poly_manager template instantiation. • cliprect is a reference to a clipping rectangle. All pixels and para- meter values are clipped to stay within these bounds before being added to the work queues for rendering, unless POLY_FLAG_NO_CLIPPING was specified as a flag parameter to poly_manager. • callback is the render callback delegate that will be called to ren- der each extent. • v1 contains the coordinates and iterated parameters for the top-left corner of the tile. • v2 contains the coordinates and iterated parameters for the bot- tom-right corner of the tile. Return value: the total number of clipped pixels represented by the en- queued extents. render_triangle template<int ParamCount> uint32_t render_triangle(rectangle const &cliprect, render_delegate callback, vertex_t const &v1, vertex_t const &v2, vertex_t const &v3); This method enqueues a single triangle primitive for rendering: • ParamCount is the number of live values in the iterated parameter ar- ray within each vertex_t provided; it must be no greater than the MaxParams value specified in the poly_manager template instantiation. • cliprect is a reference to a clipping rectangle. All pixels and para- meter values are clipped to stay within these bounds before being added to the work queues for rendering, unless POLY_FLAG_NO_CLIPPING was specified as a flag parameter to poly_manager. • callback is the render callback delegate that will be called to ren- der each extent. • v1, v2, v3 contain the coordinates and iterated parameters for each vertex of the triangle. Return value: the total number of clipped pixels represented by the en- queued extents. render_triangle_fan template<int ParamCount> uint32_t render_triangle_fan(rectangle const &cliprect, render_delegate callback, int numverts, vertex_t const *v); This method enqueues one or more triangle primitives for rendering, specified in fan order: • ParamCount is the number of live values in the iterated parameter ar- ray within each vertex_t provided; it must be no greater than the MaxParams value specified in the poly_manager template instantiation. • cliprect is a reference to a clipping rectangle. All pixels and para- meter values are clipped to stay within these bounds before being added to the work queues for rendering, unless POLY_FLAG_NO_CLIPPING was specified as a flag parameter to poly_manager. • callback is the render callback delegate that will be called to ren- der each extent. • numverts is the total number of vertices provided; it must be at least 3. • v is a pointer to an array of vertex_t objects containing the coordi- nates and iterated parameters for all the triangles, in fan order. This means that the first vertex is fixed. So if 5 vertices are pro- vided, indicating 3 triangles, the vertices used will be: (0,1,2) (0,2,3) (0,3,4) Return value: the total number of clipped pixels represented by the en- queued extents. render_triangle_strip template<int ParamCount> uint32_t render_triangle_strip(rectangle const &cliprect, render_delegate callback, int numverts, vertex_t const *v); This method enqueues one or more triangle primitives for rendering, specified in strip order: • ParamCount is the number of live values in the iterated parameter ar- ray within each vertex_t provided; it must be no greater than the MaxParams value specified in the poly_manager template instantiation. • cliprect is a reference to a clipping rectangle. All pixels and para- meter values are clipped to stay within these bounds before being added to the work queues for rendering, unless POLY_FLAG_NO_CLIPPING was specified as a flag parameter to poly_manager. • callback is the render callback delegate that will be called to ren- der each extent. • numverts is the total number of vertices provided; it must be at least 3. • v is a pointer to an array of vertex_t objects containing the coordi- nates and iterated parameters for all the triangles, in strip order. So if 5 vertices are provided, indicating 3 triangles, the vertices used will be: (0,1,2) (1,2,3) (2,3,4) Return value: the total number of clipped pixels represented by the en- queued extents. render_polygon template<int NumVerts, int ParamCount> uint32_t render_polygon(rectangle const &cliprect, render_delegate callback, vertex_t const *v); This method enqueues a single polygon primitive for rendering: • NumVerts is the number of vertices in the polygon. • ParamCount is the number of live values in the iterated parameter ar- ray within each vertex_t provided; it must be no greater than the MaxParams value specified in the poly_manager template instantiation. • cliprect is a reference to a clipping rectangle. All pixels and para- meter values are clipped to stay within these bounds before being added to the work queues for rendering, unless POLY_FLAG_NO_CLIPPING was specified as a flag parameter to poly_manager. • callback is the render callback delegate that will be called to ren- der each extent. • v is a pointer to an array of vertex_t objects containing the coordi- nates and iterated parameters for the polygon. Vertices are assumed to be in either clockwise or anticlockwise order. Return value: the total number of clipped pixels represented by the en- queued extents. render_extents template<int ParamCount> uint32_t render_extents(rectangle const &cliprect, render_delegate callback, int startscanline, int numscanlines, extent_t const *extents); This method enqueues custom extents directly: • ParamCount is the number of live values in the iterated parameter ar- ray within each vertex_t provided; it must be no greater than the MaxParams value specified in the poly_manager template instantiation. • cliprect is a reference to a clipping rectangle. All pixels and para- meter values are clipped to stay within these bounds before being added to the work queues for rendering, unless POLY_FLAG_NO_CLIPPING was specified as a flag parameter to poly_manager. • callback is the render callback delegate that will be called to ren- der each extent. • startscanline is the Y coordinate of the first extent provided. • numscanlines is the number of extents provided. • extents is a pointer to an array of extent_t objects containing the start/stop X coordinates and iterated parameters. The userdata field of the source extents is copied to the target as well (this field is otherwise unused for all other types of rendering). Return value: the total number of clipped pixels represented by the en- queued extents. zclip_if_less template<int ParamCount> int zclip_if_less(int numverts, vertex_t const *v, vertex_t *outv, BaseType clipval); This method is a helper method to clip a polygon against a provided Z value. It assumes that the first iterated parameter in vertex_t repre- sents the Z coordinate. If any edge crosses the Z plane represented by clipval that edge is clipped. • ParamCount is the number of live values in the iterated parameter ar- ray within each vertex_t provided; it must be no greater than the MaxParams value specified in the poly_manager template instantiation. • numverts is the number of vertices in the input array. • v is a pointer to the input array of vertex_t objects. • outv is a pointer to the output array of vertex_t objects. v and outv cannot overlap or point to the same memory. • clipval is the value to compare parameter 0 against for clipping. Return value: the number of output vertices written to outv. Note that by design it is possible for this method to produce more vertices than the input array, so callers should ensure there is enough room in the output buffer to accommodate this. Example Renderer Here is a complete example of how to create a software 3D renderer us- ing poly_manager. Our example renderer will only handle flat and Gouraud-shaded triangles with depth (Z) buffering. Types The first thing we need to define is our externally-visible vertex for- mat, which is distinct from the internal vertex_t that poly_manager will define. In theory you could use vertex_t directly, but the generic nature of poly_managers iterated parameters make it awkward: struct example_vertex { float x, y, z; // X,Y,Z coordinates rgb_t color; // color at this vertex }; Next we define the ObjectType needed by poly_manager. For our simple case, we define an example_object_data struct that consists of pointers to our rendering buffers, plus a couple of fixed values that are con- sumed in some cases. More complex renderers would typically have many more object-wide parameters defined here: struct example_object_data { bitmap_rgb32 *dest; // pointer to the rendering bitmap bitmap_ind16 *depth; // pointer to the depth bitmap rgb_t color; // overall color (for clearing and flat shaded case) uint16_t depthval; // fixed depth v alue (for clearing) }; Now its time to define our renderer class, which we derive from poly_manager. As template parameters we specify float as the base type for our data, since that will be enough accuracy for this example, and we also provide our example_object_data as the ObjectType class, plus the maximum number of iterated parameters our renderer will ever need (4 in this case): class example_renderer : public poly_manager<float, example_object_data, 4> { public: example_renderer(running_machine &machine, uint32_t width, uint32_t height); bitmap_rgb32 *swap_buffers(); void clear_buffers(rgb_t color, uint16_t depthval); void draw_triangle(example_vertex const *verts); private: static uint16_t ooz_to_depthval(float ooz); void draw_triangle_flat(example_vertex const *verts); void draw_triangle_gouraud(example_vertex const *verts); void render_clear(int32_t y, extent_t const &extent, example_object_data const &object, int threadid); void render_flat(int32_t y, extent_t const &extent, example_object_data const &object, int threadid); void render_gouraud(int32_t y, extent_t const &extent, example_object_data const &object, int threadid); int m_draw_buffer; bitmap_rgb32 m_display[2]; bitmap_ind16 m_depth; }; Constructor The constructor for our example renderer just initializes poly_manager and allocates the rendering and depth buffers: example_renderer::example_renderer(running_machine &machine, uint32_t width, uint32_t height) : poly_manager(machine), m_draw_buffer(0) { // allocate two display buffers and a depth buffer m_display[0].allocate(width, height); m_display[1].allocate(width, height); m_depth.allocate(width, height); } swap_buffers The first interesting method in our renderer is swap_buffers(), which returns a pointer to the buffer weve been drawing to, and sets up the other buffer as the new drawing target. The idea is that the display update handler will call this method to get ahold of the bitmap to dis- play to the user: bitmap_rgb32 *example_renderer::swap_buffers() { // wait for any rendering to complete before returning the buffer wait("swap_buffers"); // return the current draw buffer and then switch to the other // for future drawing bitmap_rgb32 *result = &m_display[m_draw_buffer]; m_draw_buffer ^= 1; return result; } The most important thing here to note here is the call to poly_managers wait(), which will block the current thread until all rendering is com- plete. This is important because otherwise the caller may receive a bitmap that is still being drawn to, leading to torn or corrupt visu- als. clear_buffers One of the most common operations to perform when doing 3D rendering is to initialize or clear the display and depth buffers to a known value. This method below leverages the tile primitive to render a rectangle over the screen by passing in (0,0) and (width,height) for the two ver- tices. Because the color and depth values to clear the buffer to are constant, they are stored in a freshly-allocated example_object_data object, along with a pointer to the buffers in question. The render_tile() call is made with a <0> suffix indicating that there are no iterated parame- ters to worry about: void example_renderer::clear_buffers(rgb_t color, uint16_t depthval) { // allocate object data and populate it with information needed example_object_data &object = object_data().next(); object.dest = &m_display[m_draw_buffer]; object.depth = &m_depth; object.color = color; object.depthval = depthval; // top,left coordinate is always (0,0) vertex_t topleft; topleft.x = 0; topleft.y = 0; // bottom,right coordinate is (width,height) vertex_t botright; botright.x = m_display[0].width(); botright.y = m_display[0].height(); // render as a tile with 0 iterated parameters render_tile<0>(m_display[0].cliprect(), render_delegate(&example_renderer::render_clear, this), topleft, botright); } The render callback provided to render_tile() is also defined (pri- vately) in our class, and handles a single span. Note how the rendering parameters are extracted from the example_object_data struct provided: void example_renderer::render_clear(int32_t y, extent_t const &extent, example_object_data const &object, int threadid) { // get pointers to the start of the depth buffer and destination scanlines uint16_t *depth = &object.depth->pix(y); uint32_t *dest = &object.dest->pix(y); // loop over the full extent and just store the constant values from the object for (int x = extent.startx; x < extent.stopx; x++) { dest[x] = object.color; depth[x] = object.depthval; } } Another important point to make is that the X coordinates provided by extent struct are inclusive of startx but exclusive of stopx. Clipping is performed ahead of time so that the render callback can focus on laying down pixels as quickly as possible with minimal overhead. draw_triangle Next up, we have our actual triangle rendering function, which will draw a single triangle given an array of three vertices provided in the external example_vertex format: void example_renderer::draw_triangle(example_vertex const *verts) { // flat shaded case if (verts[0].color == verts[1].color && verts[0].color == verts[2].color) draw_triangle_flat(verts); else draw_triangle_gouraud(verts); } Because it is simpler and faster to render a flat shaded triangle, the code checks to see if the colors are the same on all three vertices. If they are, we call through to a special flat-shaded case, otherwise we process it as a full Gouraud-shaded triangle. This is a common technique to optimize rendering performance: identify special cases that reduce the per-pixel work, and route them to sepa- rate render callbacks that are optimized for that special case. draw_triangle_flat Heres the setup code for rendering a flat-shaded triangle: void example_renderer::draw_triangle_flat(example_vertex const *verts) { // allocate object data and populate it with information needed example_object_data &object = object_data().next(); object.dest = &m_display[m_draw_buffer]; object.depth = &m_depth; // in this case the color is constant and specified in the object data object.color = verts[0].color; // copy X, Y, and 1/Z into poly_manager vertices vertex_t v[3]; for (int vertnum = 0; vertnum < 3; vertnum++) { v[vertnum].x = verts[vertnum].x; v[vertnum].y = verts[vertnum].y; v[vertnum].p[0] = 1.0f / verts[vertnum].z; } // render the triangle with 1 iterated parameter (1/Z) render_triangle<1>(m_display[0].cliprect(), render_delegate(&example_renderer::render_flat, this), v[0], v[1], v[2]); } First, we put the fixed color into the example_object_data directly, and then fill out three vertex_t objects with the X and Y coordinates in the usual spot, and 1/Z as our one and only iterated parameter. (We use 1/Z here because iterated parameters are interpolated linearly in screen space. Z is not linear in screen space, but 1/Z is due to per- spective correction.) Our flat-shaded case then calls render_trangle specifying <1> iterated parameter to interpolate, and pointing to a special-case flat render callback: void example_renderer::render_flat(int32_t y, extent_t const &extent, example_object_data const &object, int threadid) { // get pointers to the start of the depth buffer and destination scanlines uint16_t *depth = &object.depth->pix(y); uint32_t *dest = &object.dest->pix(y); // get the starting 1/Z value and the delta per X float ooz = extent.param[0].start; float doozdx = extent.param[0].dpdx; // iterate over the extent for (int x = extent.startx; x < extent.stopx; x++) { // convert the 1/Z value into an integral depth value uint16_t depthval = ooz_to_depthval(ooz); // if closer than the current pixel, copy the color and depth value if (depthval < depth[x]) { dest[x] = object.color; depth[x] = depthval; } // regardless, update the 1/Z value for the next pixel ooz += doozdx; } } This render callback is a bit more involved than the clearing case. First, we have an iterated parameter (1/Z) to deal with, whose starting and X-delta values we extract from the extent before the start of the inner loop. Second, we perform depth buffer testing, using ooz_to_depthval() as a helper to transform the floating-point 1/Z value into a 16-bit integer. We compare this value against the current depth buffer value, and only store the pixel/depth value if its less. At the end of each iteration, we advance the 1/Z value by the X-delta in preparation for the next pixel. draw_triangle_gouraud Finally we get to the code for the full-on Gouraud-shaded case: void example_renderer::draw_triangle_gouraud(example_vertex const *verts) { // allocate object data and populate it with information needed example_object_data &object = object_data().next(); object.dest = &m_display[m_draw_buffer]; object.depth = &m_depth; // copy X, Y, 1/Z, and R,G,B into poly_manager vertices vertex_t v[3]; for (int vertnum = 0; vertnum < 3; vertnum++) { v[vertnum].x = verts[vertnum].x; v[vertnum].y = verts[vertnum].y; v[vertnum].p[0] = 1.0f / verts[vertnum].z; v[vertnum].p[1] = verts[vertnum].color.r(); v[vertnum].p[2] = verts[vertnum].color.g(); v[vertnum].p[3] = verts[vertnum].color.b(); } // render the triangle with 4 iterated parameters (1/Z, R, G, B) render_triangle<4>(m_display[0].cliprect(), render_delegate(&example_renderer::render_gouraud, this), v[0], v[1], v[2]); } Here we have 4 iterated parameters: the 1/Z depth value, plus red, green, and blue, stored as floating point values. We call render_trian- gle() with <4> as the number of iterated parameters to process, and point to the full Gouraud render callback: void example_renderer::render_gouraud(int32_t y, extent_t const &extent, example_object_data const &object, int threadid) { // get pointers to the start of the depth buffer and destination scanlines uint16_t *depth = &object.depth->pix(y); uint32_t *dest = &object.dest->pix(y); // get the starting 1/Z value and the delta per X float ooz = extent.param[0].start; float doozdx = extent.param[0].dpdx; // get the starting R,G,B values and the delta per X as 8.24 fixed-point values uint32_t r = uint32_t(extent.param[1].start * float(1 << 24)); uint32_t drdx = uint32_t(extent.param[1].dpdx * float(1 << 24)); uint32_t g = uint32_t(extent.param[2].start * float(1 << 24)); uint32_t dgdx = uint32_t(extent.param[2].dpdx * float(1 << 24)); uint32_t b = uint32_t(extent.param[3].start * float(1 << 24)); uint32_t dbdx = uint32_t(extent.param[3].dpdx * float(1 << 24)); // iterate over the extent for (int x = extent.startx; x < extent.stopx; x++) { // convert the 1/Z value into an integral depth value uint16_t depthval = ooz_to_depthval(ooz); // if closer than the current pixel, assemble the color if (depthval < depth[x]) { dest[x] = rgb_t(r >> 24, g >> 24, b >> 24); depth[x] = depthval; } // regardless, update the 1/Z and R,G,B values for the next pixel ooz += doozdx; r += drdx; g += dgdx; b += dbdx; } } This follows the same pattern as the flat-shaded callback, except we have 4 iterated parameters to step through. Note that even though the iterated parameters are of float type, we convert the color values to fixed-point integers when iterating over them. This saves us doing 3 float-to-int conversions each pixel. The original RGB values were 0-255, so interpolation can only produce val- ues in the 0-255 range. Thus we can use 24 bits of a 32-bit integer as the fraction, which is plenty accurate for this case. Advanced Topic: the poly_array class poly_array is a template class that is used to manage a dynami- cally-sized vector of objects whose lifetime starts at allocation and ends when reset() is called. The poly_manager class uses several poly_array objects internally, including one for allocated ObjectType data, one for each primitive rendered, and one for holding all allo- cated extents. poly_array has an additional property where after a reset it retains a copy of the most recently allocated object. This ensures that callers can always call last() and get a valid object, even immediately after a reset. The poly_array class requires two template parameters: template<class ArrayType, int TrackingCount> class poly_array; These parameters are: • ArrayType is the type of object you wish to allocate and manage. • TrackingCount is the number of objects you wish to preserve after a reset. Typically this value is either 0 (you dont care to track any objects) or 1 (you only need one object); however, if you are using poly_array to manage a shared collection of objects across several independent consumers, it can be higher. See below for an example where this might be handy. Note that objects allocated by poly_array are owned by poly_array and will be automatically freed upon exit. poly_array is optimized for use in high frequency multi-threaded sys- tems. Therefore, one added feature of the class is that it rounds the allocation size of ArrayType to the nearest cache line boundary, on the assumption that neighboring entries could be accessed by different cores simultaneously. Keeping each ArrayType object in its own cache line ensures no false sharing performance impacts. Currently, poly_array has no mechanism to determine cache line size at runtime, so it presumes that 64 bytes is a typical cache line size, which is true for most x64 and ARM chips as of 2021. This value can be altered by changing the CACHE_LINE_SHIFT constant defined at the top of the class. Objects allocated by poly_array are created in 64k chunks. At construc- tion time, one chunks worth of objects is allocated up front. The chunk size is controlled by the CHUNK_GRANULARITY constant defined at the top of the class. As more objects are allocated, if poly_array runs out of space, it will dynamically allocate more. This will produce discontiguous chunks of objects until the next reset() call, at which point poly_array will re- allocate all the objects into a contiguous vector once again. For the case where poly_array is used to manage a shared pool of ob- jects, it can be configured to retain multiple most recently allocated items by using a TrackingCount greater than 1. For example, if poly_ar- ray is managing objects for two texture units, then it can set Track- ingCount equal to 2, and pass the index of the texture unit in calls to next() and last(). After a reset, poly_array will remember the most re- cently allocated object for each of the units independently. Methods poly_array poly_array(); The poly_array constructor requires no parameters and simply pre-allo- cates one chunk of objects in preparation for future allocations. count u32 count() const; Return value: the number of objects currently allocated. max u32 max() const; Return value: the maximum number of objects ever allocated at one time. itemsize size_t itemsize() const; Return value: the size of an object, rounded up to the nearest cache line boundary. allocated u32 allocated() const; Return value: the number of objects that fit within whats currently been allocated. byindex ArrayType &byindex(u32 index); Returns a reference to an object in the array by index. Equivalent to [index] on a normal array: • index is the index of the item you wish to reference. Return value: a reference to the object in question. Since a reference is returned, it is your responsibility to ensure that index is less than count() as there is no mechanism to return an invalid result. contiguous ArrayType *contiguous(u32 index, u32 count, u32 &chunk); Returns a pointer to the base of a contiguous section of count items starting at index. Because poly_array dynamically resizes, it may not be possible to access all count objects contiguously, so the number of actually contiguous items is returned in chunk: • index is the index of the first item you wish to access contiguously. • count is the number of items you wish to access contiguously. • chunk is a reference to a variable that will be set to the actual number of contiguous items available starting at index. If chunk is less than count, then the caller should process the chunk items re- turned, then call countiguous() again at (index + chunk) to access the rest. Return value: a pointer to the first item in the contiguous chunk. No range checking is performed, so it is your responsibility to ensure that index + count is less than or equal to count(). indexof int indexof(ArrayType &item) const; Returns the index within the array of the given item: • item is a reference to an item in the array. Return value: the index of the item. It should always be the case that: array.indexof(array.byindex(index)) == index reset void reset(); Resets the poly_array by semantically deallocating all objects. If pre- vious allocations created a discontiguous array, a fresh vector is al- located at this time so that future allocations up to the same level will remain contiguous. Note that the ArrayType destructor is not called on objects as they are deallocated. Return value: none. next ArrayType &next(int tracking_index = 0); Allocates a new object and returns a reference to it. If there is not enough space for a new object in the current array, a new discontiguous array is created to hold it: • tracking_index is the tracking index you wish to assign the new item to. In the common case this is 0, but could be non-zero if using a TrackingCount greater than 1. Return value: a reference to the object. Note that the placement new operator is called on this object, so the default ArrayType constructor will be invoked here. last ArrayType &last(int tracking_index = 0) const; Returns a reference to the last object allocated: • tracking_index is the tracking index whose object you want. In the common case this is 0, but could be non-zero if using a TrackingCount greater than 1. poly_array remembers the most recently allocated ob- ject independently for each tracking_index. Return value: a reference to the last allocated object. MAME AND SECURITY CONCERNS MAME is not intended or designed to run in secure sites. It has not been security audited for such types of usage, and has been known in the past to have flaws that could be used for malicious intent if run as administrator or root. We do not suggest or condone the use of MAME as administrator or root and use as such is done at your own risk. Bug reports, however, are always welcome. THE MAME LICENSE The MAME project as a whole is distributed under the terms of the GNU General Public License, version 2 or later (GPL-2.0+), since it con- tains code made available under multiple GPL-compatible licenses. A great majority of files (over 90% including core files) are under the 3-Clause BSD License and we would encourage new contributors to dis- tribute files under this license. Please note that MAME is a registered trademark of Gregory Ember, and permission is required to use the MAME name, logo, or wordmark. Copyright (c) 1997-2025 MAMEDev and contributors This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MER- CHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Gen- eral Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Founda- tion, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Please see the license information for further details. CONTRIBUTE The documentation on this site is the handiwork of our many contribu- tors. AUTHOR MAMEdev Team COPYRIGHT 1997-2025, MAMEdev and contributors 0.274 Apr 13, 2025 MAME(1)
NAME | WHAT IS MAME | HEALTH WARNINGS | GETTING MAME PREPARED | BASIC MAME USAGE AND CONFIGURATION | MAME COMMAND-LINE USAGE AND OS-SPECIFIC CONFIGURATION | FOOTNOTES | FOOTNOTES | FOOTNOTES | FOOTNOTES | FOOTNOTES | FOOTNOTES | PLUGINS | ADVANCED CONFIGURATION | MAME DEBUGGER | LUA SCRIPTING INTERFACE | MAME EXTERNAL TOOLS | CONTRIBUTING TO MAME | TECHNICAL SPECIFICATIONS | MAME AND SECURITY CONCERNS | THE MAME LICENSE | CONTRIBUTE | AUTHOR | COPYRIGHT
Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=MAME&sektion=1&manpath=FreeBSD+Ports+14.3.quarterly>