SearchA-ZT › Time Pilot

Time Pilot

1982 Arcade Online

Time Pilot (Konami, 1982), designed by Yoshiki Okamoto, is the free-roaming aerial combat classic in which your fighter stays fixed at the centre of the screen while the whole world scrolls around it, flying through five eras of aviation -- 1910, 1940, 1970, 1982 and 2001 -- shooting down waves of enemy craft, rescuing parachuting pilots and destroying each era's giant boss aircraft. This build runs the original Konami board in the browser: a Zilog Z80 driving Konami's early tile and sprite hardware, with the authentic ROMs, booting straight into attract mode. It 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, and set execution breakpoints and write watchpoints.

Runs on: Web browser

Time Pilot Online Emulator

Play Time Pilot using JavaScript directly in your browser.

Configurations

ConfigurationEmulatorMachineOSLegal
Time PilotTime PilotTime PilotgreyOpen ⛶

Machine emulated

The Time Pilot arcade board (Konami, 1982) is an all-Z80 design: a Zilog Z80 at 3.072 MHz runs the game while a second Z80 drives two AY-3-8910 PSGs for the sound. Konami's early tile-and-sprite hardware draws a 32×32 character map and up to 24 hardware sprites over a rotated monitor, and the game's trademark trick is that your plane never moves: it sits at the centre of the screen and the world scrolls beneath it in any of eight directions.

Chips

Notes

Embedding

Time Pilot is Konami's 1982 arcade machine: a Zilog Z80 main CPU at 3.072 MHz that runs the game, and a second Zilog Z80 sound CPU driving two AY-3-8910 PSGs. This build is a from-scratch JavaScript emulation whose board is a port of MAME's konami/timeplt.cpp. The main Z80 core is Molly Howell's MIT Z80.js. The whole board runs from a host-owned loop, so the debugger can pause and single-step it.

Boot. Constructing the machine fetches the ROMs, decodes the character and sprite graphics and the four colour PROMs, resets the main Z80 and starts the loop; the board comes up in attract mode:

var m = new TimePilot({ canvas, romBase, manifest });
m.boot();                              // fetch ROMs, decode GFX + PROMs, reset the Z80, run
// each animation frame runs one 60Hz field of the main Z80, then draws the screen

The machine object. Everything the host and debugger need is a field or method on the machine:

MemberKindWhat it does
m.cpufieldThe main Z80 core. Registers are read with getReg(name) / written with setReg(name,v) for A F B C D E H L, the AF/BC/DE/HL pairs, IX IY SP PC, and I R.
m.dbgRead(a) / m.dbgWrite(a,v)methodSide-effect-free read of the main 64K bus and the CPU write path -- what the debugger's memory views read and poke.
m.setInput(id, down)methodDrive a control (up, down, left, right, fire, coin, start1, start2) into the input ports.
EMU_BOOT.transportfieldThe pause / resume / step / breakpoint / watchpoint surface the shared debugger drives.

Video. The screen is a 32×32 map of 8×8 two-bit characters (videoram holds the tile code, colorram the attribute: colour, an X/Y flip and a priority bit) plus up to 24 four-bit 16×16 sprites read from two parallel banks. Colour is fixed in four PROMs: two 32×5 PROMs give 32 master colours through a resistor DAC, and a char and a sprite 256×4 lookup PROM map each layer's pen into them. Background tiles draw first, then sprites, then the priority-bit tiles draw over the sprites. The renderer draws a 256×224 raster and rotates it (ROT90) to a 224×256 portrait, like the upright cabinet.

Debugger integration

Because the whole board is ordinary JavaScript and the host owns the run loop, the debugger's controls need no changes to the CPU core: the loop can pause, single-step and check breakpoints between any two instructions. window.EMU_BOOT.transport maps the shared debugger onto the main Z80:

  • pause / resume / isPaused -- stop or restart the requestAnimationFrame loop.
  • stepInsn(n) -- run exactly n Z80 instructions through the core's run_instruction() entry.
  • step(n) -- advance n whole 60 Hz fields of the main Z80, each honouring the one vblank NMI when the control latch has it enabled.
  • breakpoints -- a Set of PC values checked before each instruction; a match pauses before the instruction runs.
  • watchpoints -- the Z80's memory-write path flags a hit when a watched address is written, and the loop pauses on it.

The stock Z80.js keeps its registers in a closure and exposes a whole-core getState()/setState(). To make the debugger's live register window cheap, the vendored core is given get_pc() and set_pc() hooks so the run loop can read PC before every instruction (for breakpoints) without allocating a state object, plus get_iff1() and a proper NMI entry so a held vblank interrupt is honoured. The machine wraps getState/setState in focused getReg/setReg/getFlag/setFlag helpers that the plug-in binds to. Memory reads use the machine's side-effect-free bus read, which returns work RAM, the video RAMs, the two sprite banks, the program ROM and the input ports without side effects, so inspecting memory never disturbs the board. The Z80 disassembler is the shared decoder at /debugger/src/cpus/z80.js -- reused unchanged, since the Z80 is already a first-class debugger CPU.

Architecture

The Time Pilot board (Konami, 1982) is an all-Z80 design built from two Z80s and Konami's early tile/sprite hardware, run on a rotated (ROT90) monitor:

  • Main CPU -- Zilog Z80 at 3.072 MHz (18.432 MHz / 6). Program ROM at 0x0000–0x5fff, tile-attribute RAM at 0xa000, tile-code RAM at 0xa400, work RAM at 0xa800, two sprite banks at 0xb000 and 0xb400, and an I/O page at 0xc000 holding the beam-position read, the DIP banks, the three input ports and an LS259 control latch. This is the CPU the debugger targets.
  • Interrupts -- the main Z80 takes a single hardware NMI at vblank each field, gated by latch line Q0 (NMI enable); the NMI vectors to 0x0066.
  • Control latch -- an LS259 at 0xc300–0xc30f (one line per address pair, data on D0) holds NMI enable (Q0), flip screen (Q1, inverted), the sound-CPU IRQ strobe (Q2), sound mute (Q3), video enable (Q4) and the two coin counters (Q5/Q6).
  • Tilemap -- a 32×32 map of 8×8 two-bit characters. The code comes from videoram and a high bit of the colorram attribute; the attribute also holds a five-bit colour, an X and a Y flip, and a priority "category" bit that lets a tile draw in front of the sprites.
  • Sprites -- up to 24 four-bit 16×16 sprites, each described across the two 0xb000/0xb400 banks: X, Y (as 241 - y), an eight-bit code, a six-bit colour and X/Y flip. Transparent pen 0.
  • Sound CPU -- a second Z80 driving two AY-3-8910 PSGs, fed one-byte commands the main CPU writes at 0xc000 and strobed by latch line Q2. (Audio is stubbed here; the main CPU never reads back from the sound CPU, so it is not run.)
  • Palette -- there is no palette RAM. Two 32×5 PROMs, decoded through a resistor DAC, give 32 master colours; a char and a sprite 256×4 lookup PROM map each layer's pen to one of those colours (chars use the upper sixteen, sprites the lower sixteen).

The graphics ROMs are decoded to one-byte-per-pixel tiles and sprites once at boot; the visible 256×224 raster is rotated 90° to the 224×256 portrait of the upright cabinet.