MAME Debugger Watchpoints: Finding the Code Behind a Hardware Access
Use MAME debugger watchpoints and breakpoints to trace emulated memory activity, isolate address spaces, and preserve reproducible hardware evidence.
When an emulated game writes the wrong tile, toggles a register unexpectedly, or reads a value from the wrong device, the visible symptom may be several frames removed from the original cause. MAME’s integrated debugger can stop a running machine when a CPU executes an instruction or accesses a selected memory range. A breakpoint answers “when did this CPU reach this code address?” A watchpoint answers “which execution path read or wrote this emulated address?” Used with a narrow range and a reproducible action, watchpoints turn a vague visual bug into evidence about the emulated bus.
Debugger observations are not the same as observing a physical board with a logic analyzer. MAME reports accesses through the emulated machine’s address spaces and handlers. A memory-mapped register may be mirrored, banked, or accessed through a device-specific space; one host-level memory address is not necessarily one physical chip location. First understand the driver map and CPU space, then configure a point that watches the transaction of interest.
Start a controlled debugging session
Use a known MAME build and exact machine/software configuration. Enable the debugger when launching a system:
mame <system> -debug
Replace <system> with the machine short name. MAME enters the debugger at startup when enabled; the exact debugger module depends on the build and host platform. The debugger command line is available even if the selected UI module differs. If launching from a frontend, preserve the full command line and working directory so the same machine, media, BIOS, and configuration can be loaded again.
Before setting a point, record the CPU list and inspect the relevant address map. In the debugger, help, cpulist, symlist, and help watchpoints provide context. Device and driver source code are often essential: identify which CPU owns the address space, whether the space is program, data, or I/O, the byte width, and which handlers service the range. A watchpoint on the wrong CPU or address space can remain silent while the hardware is active.
Choose a watchpoint type and range
MAME debugger watchpoints can observe reads, writes, or both over a specified address range. The debugger help documents commands such as wpset, wpdset, wpiset, and wposet for address spaces. A generic form is:
wpset <address>[:<space>],<length>,<type>[,<condition>[,<action>]]
The type selects the access class supported by the command, such as read or write. Consult help wpset in the running MAME version for accepted values and exact syntax. An illustrative one-byte write watchpoint is:
wpset 0598,1,w
wplist
g
The address is only an example, not a universal device register. g resumes execution until a breakpoint, watchpoint, or manual break occurs. When a point triggers, examine the active CPU, current PC, registers, disassembly, and stack or call history where available. Then continue with a single step or remove/disable the point after collecting the transaction.
Data, I/O, and opcode spaces are distinct. A CPU can fetch instructions from one space and read a memory-mapped peripheral through another. Use the space-specific command when the driver maps I/O separately. For a multi-byte write, choose the correct length and watch the full range; for a bitfield or packed register, use a condition if the debugger expression can discriminate the value. Confirm byte-lane and endian behavior in the CPU and device map rather than assuming the address matches the host’s representation.
Reduce noise with conditions and actions
A broad watchpoint can halt hundreds of times per frame and make a game effectively unusable. Start with the smallest address and access type, then add a condition based on the value or machine state if needed. MAME expressions can reference debugger symbols and CPU state according to the current debugger documentation. Conditions should be tested on a harmless reproduction before being trusted for a final trace.
An optional action can execute debugger commands when a point triggers. This can print registers, log a message, or resume automatically for a count-based capture. Automation is useful for repetitive events, but it can hide the first unexpected access if the condition is wrong. Use a short debug script, a fixed number of triggers, and an output file in a temporary directory. Keep a manual break available so the session can be interrupted if the machine enters a rapid trigger loop.
Do not begin with a global trace over every instruction or every memory access. That can create huge logs, change timing enough to affect the reproduction, and obscure the one event that matters. Use a breakpoint at a known routine to narrow the window, or a watchpoint on a single register to locate the writer. If the memory location is dynamic, first trace the code that programs the device pointer, then watch the resolved address.
Interpret a trigger in emulated-machine context
At a watchpoint, the debugger shows a transaction observed by a particular emulated CPU. Trace backward to the instruction that formed the address and forward to the handler or device result. Check whether a bank register changed, whether the access was DMA initiated rather than CPU initiated, and whether a different CPU or device can access the same resource. A watchpoint on CPU accesses may not report activity that a separate device performs through its own emulated DMA path.
If the address appears in more than one bank, identify the bank state at the time of the trigger. A logical address may map to different physical ROM or RAM depending on a latch or bank register. Likewise, a register range may be mirrored. The driver’s address map, memory shares, bank configuration, and device callbacks provide the mapping context. A watchpoint trigger says an access occurred at the emulated interface, not necessarily which board trace or physical chip pin would toggle.
Correlate the debugger observation with the original bug: exact game revision, machine variant, DIP/input settings, reset path, and frame or event sequence. Record the MAME version, ROM audit result, device configuration, address range, point condition, PC, register state, and captured output. That evidence allows another developer to reproduce the issue without relying on an unverifiable screenshot or a broad claim that “the CPU writes the wrong value.”
Performance and common failure modes
Watchpoints can slow emulation substantially, especially on frequently accessed RAM. A measured slowdown while a watchpoint is enabled is not evidence that the emulated machine itself is slow. Keep performance measurements separate from correctness investigation. If a point does not trigger, verify the address space, CPU, bank mapping, access width, and trigger type; then confirm that the game actually reaches the operation in the selected state.
If it triggers too often, disable it and refine the range before resuming. wpdisable, wpenable, wpclear, and wplist are available in the debugger command set; confirm syntax with the running help. Avoid clearing all breakpoints/watchpoints in a session owned by someone else. A stale debugger point stored in a startup script can make a later session stop unexpectedly, so review the script and configuration files when a machine always enters the debugger.
For a regression test, prefer a concise script or a deterministic manual sequence that prints the relevant state and stops at the first unexpected transaction. Include an explicit stop condition. Do not publish ROM contents or copyrighted data in the trace; the useful artifact is generally a small log of addresses, registers, and conditions.
Acceptance criteria
A good watchpoint investigation names the machine, CPU, memory space, address range, access type, and reproduction steps. It captures the first relevant access with enough state to map it to driver code, distinguishes CPU accesses from DMA or device-side work, and documents the limits of the observation. Remove or disable temporary points before saving a normal gameplay configuration. If the bug is fixed, rerun the same sequence without a debugger and with a debugger to check both user-visible behavior and the intended hardware access.
MAME watchpoints are most useful as a focused probe of emulated transactions. Learn the address map, stop on the narrowest meaningful operation, and interpret the trigger using the machine’s banking and device model. This approach produces evidence that can guide a driver fix without confusing host behavior with the hardware being emulated.
Related:
- MAME Address Maps: Decoding Arcade Buses, Banks, Mirrors, and Handlers
- MAME Lua Scripting: Inspecting Emulated Hardware Without Editing the Driver
Sources: