Search › A-Z › P › Punch-Out!!
Punch-Out!!
Punch-Out!! (Nintendo, 1984) is the famous two-monitor boxing arcade game in which the player, as Little Mac, weaves and dodges past a roster of larger-than-life opponents. The upper monitor frames the opponent while the lower monitor shows Mac from behind with the health bars and round clock. This build runs the original Nintendo board in the browser, a pure-JavaScript Zilog Z80 core plus a hand-written model of the tile-and-big-sprite video hardware ported from MAME, and boots straight into the game’s attract mode. It renders the bottom (main game) monitor and is wired to the emulators.org in-frame debugger so you can single-step the Z80, read and write the registers and the full 64K memory, set execution breakpoints and set write watchpoints.
Runs on: Web browser
Punch-Out!! Online Emulator
Play Punch-Out!! using JavaScript directly in your browser.
Controls
Configurations
| Configuration | Emulator | Machine | OS | Legal | |
|---|---|---|---|---|---|
| Punch-Out!! | Punch-Out!! | Punch-Out!! | grey | Open ⛶ |
Machine emulated
The Punch-Out!! arcade board (Nintendo, 1984) - a Zilog Z80 at 4 MHz (an 8 MHz crystal divided by two) with 48 KB of program ROM driving Nintendo’s tile-and-big-sprite video across two stacked monitors: two 8×8 tile background layers plus two "big sprites" (the boxers) that the hardware scales and positions with a zoom/roz unit, coloured through six PROMs. A second RP2A03 CPU and a VLM5030 speech synth handle sound on the real cabinet. This build models the main (bottom) monitor.
Chips
Notes
Embedding
Punch-Out!! is Nintendo's 1984 arcade boxing machine, famous for its two stacked monitors: the top screen shows the opponent up close, the bottom screen shows Little Mac from behind together with the health bars and round clock. Both are driven by a single Zilog Z80 at 4 MHz. This build runs the original program ROMs on DrGoldfire/Z80.js (MIT), an instruction-at-a-time Z80 interpreter, wrapped in a hand-written model of the Punch-Out!! board (memory map, tile + big-sprite video and input latches) ported from MAME's punchout.cpp. It renders the bottom (main game) monitor.
Boot. The program ROMs are loaded into 0x0000–0xBFFF and the Z80 starts at 0x0000, dropping straight into the attract-mode demo:
var po = new PunchOut(); // decodes gfx ROMs + PROMs, wires the Z80
po.reset(); // PC = 0x0000 -> attract mode
The machine object. PunchOut exposes the cabinet as ordinary methods, so the host page can render, step and inject input:
| Member | Kind | What it does |
|---|---|---|
stepInsn() | method | Fetch, decode and run one Z80 instruction; returns its T-cycle count. |
frameInterrupt() | method | Pulse the vertical-blank NMI (gated by the mainlatch Q0 mask the game writes to I/O port 0x08) once per field. |
render(buf32) | method | Paint the 256×224 bottom monitor: the scrolling background tilemap plus the two zoomable big sprites (the boxers). |
peek(a) / poke(a,v) | method | Side-effect-free access to the address space - what the debugger's memory views read and poke. |
setInput(id,down) | method | Drive the joystick / punch / coin latches read on I/O ports 0x00 (IN0) and 0x01 (IN1). |
reset() | method | Clear RAM and reset the Z80 - the cabinet's power-cycle. |
Video. Each animation frame the loop runs one field's worth of Z80 cycles, pulses the NMI, then re-renders. The bottom monitor is a 64×32 tilemap of 8×8 characters (video RAM at 0xF000, with per-row horizontal scroll RAM in the same window), over which two "big sprites" are drawn: sprite #1 (the 3bpp boxer, video RAM 0xE000) is scaled through a zoom/roz blit, and sprite #2 (the 2bpp boxer, video RAM 0xE800) is drawn 1:1. Colours come from the bottom-monitor colour PROMs (white-labelled set), banked by 0xDFFD.
Debugger integration
The debugger drives a host-owned run loop: because the Z80 interpreter runs one instruction at a time in JavaScript, the loop can pause, single-step and check breakpoints between any two instructions - no changes to the CPU core are needed.
window.EMU_BOOT.transport exposes the controls the shared debugger calls:
- pause / resume / isPaused - stop or restart the
requestAnimationFrameloop. - stepInsn(n) - call the core's
stepInsn()exactly n times and redraw, so a single step advances the PC by one Z80 instruction. - step(n) - advance n whole 60 Hz fields (each with its NMI).
- breakpoints - a
Setof PC values. When it is non-empty the loop reads the Z80's PC (viagetState()) before each instruction and pauses before executing an address in the set; when empty it runs a full field at speed, so an idle debugger costs nothing. - watchpoints - the Z80 core's memory-write callback is wrapped, so a write to a watched RAM address sets a flag that pauses the loop after that instruction.
The plug-in (punchout-debug.js) reads these hooks and calls EmuKit.defineMachine with the full Z80 register file (AF/BC/DE/HL and their bytes, IX/IY, SP, PC, I, R and the S Z H P/V N C flags), each read live from getState() and written back through setState(). It reuses the shared z80 disassembler (/debugger/src/cpus/z80.js) for the hex/disasm views over the 64 KB bus, the 48 KB program ROM, the background tile RAM and the two big-sprite RAMs.
Architecture
The Punch-Out!! board is a single Zilog Z80 at 4 MHz (an 8 MHz crystal divided by two) with 48 KB of program ROM and Nintendo's tile-and-big-sprite video across two monitors, all modelled here as plain JavaScript hanging off PunchOut:
- CPU - a Z80 interpreter.
0x0000–0xBFFFis program ROM;0xC000–0xFFFFis work RAM plus video RAM: the top-monitor tilemap at0xD800, the big-sprite control latches at0xDFF0, big-sprite #1 RAM at0xE000, big-sprite #2 RAM at0xE800and the bottom-monitor tilemap at0xF000. - Video - two 8×8 tile background layers (2bpp), plus two "big sprites" made of 16×32 arrangements of 8×8 tiles that the hardware scales and positions with a zoom/roz unit - this is how the boxers grow and shrink. Sprite #1 is 3bpp, sprite #2 is 2bpp. Six 256-nibble colour PROMs give the two monitors' palettes; the
0xDFFDlatch selects the colour bank per monitor. - Input - read on Z80 I/O ports: the two punch buttons on port
0x00(IN0), the 4-way joystick plus coin and service on port0x01(IN1); the DIP switches on ports0x02/0x03. - Interrupt - a single NMI per field at vertical blank, gated by the mainlatch
Q0mask (I/O port0x08), is the only timing the game depends on. - Sound - the real cabinet uses an RP2A03 (2A03) sound CPU plus a VLM5030 speech synth for the referee and crowd; this build has no audio, so those latch writes are ignored.