SearchA-ZG › Game Gear (jsSMS)

Game Gear (jsSMS)

2026 Open source · GPL-3.0 Online

The Sega Game Gear (1990) is a handheld Master System: the same Zilog Z80 CPU, the same Mode-4 VDP and the same SN76489 sound chip, in a portable shell with a smaller 160×144 screen and a richer 12-bit colour palette.

This entry runs Guillaume Marty's pure-JavaScript jsSMS core in Game Gear mode, using its plain Z80 interpreter so the whole CPU can be single-stepped, register-edited and breakpointed in the shared in-page debugger.

Visit the project ↗

Visit the official site ↗

Runs on: Web browser

Game Gear (jsSMS) Online Emulator

Play Game Gear (jsSMS) using JavaScript directly in your browser.

Configurations

ConfigurationEmulatorMachineOSLegal
Colour Pad demoGame Gear (jsSMS)Sega Game GearopenOpen ⛶

Machines emulated

Chips

Notes

Embedding

jsSMS is a set of plain-global JavaScript modules (no bundler) that emulates the Sega Master System and the Game Gear - the Game Gear is essentially a Master System in a handheld shell (same Z80, same Mode-4 VDP, same SN76489), with a smaller 160×144 visible window and a 12-bit colour palette instead of the SMS's 6-bit one. jsSMS picks the mode from the cartridge file name: a .gg name makes readRomDirectly() call setGG(). We vendor the core files, load them in dependency order, and construct the machine with ENABLE_COMPILER:false so it runs the plain interpreter (the dynamic recompiler cannot be paused mid-block or stepped one instruction at a time, which the debugger needs).

var sms = new JSSMS({ ui: EmuUI, ENABLE_COMPILER: false });
var buf = await (await fetch(romUrl)).arrayBuffer();
var bin = ''; new Uint8Array(buf).forEach(b => bin += String.fromCharCode(b));
sms.readRomDirectly(bin, 'game.gg');   // ".gg" -> setGG(): Game Gear mode
sms.reset();
(function loop(){ sms.cpu.frame(); requestAnimationFrame(loop); })();

The machine is plain objects. With the interpreter the whole Z80 state is live JavaScript:

MemberKindWhat it does
sms.cpu.frame()methodInterpret one whole video frame (a scanline at a time, driving the VDP and interrupts). The fast-run primitive.
sms.cpu.interpret()methodFetch and execute exactly one Z80 instruction at pc. The single-step primitive.
sms.setGG() / sms.is_ggmethod / fieldSwitch the machine into Game Gear mode (160×144 window at offset 48,24; 12-bit CRAM). Selected automatically from the ".gg" ROM name.
sms.cpu.pc / .sp / .a / .f / .b .c .d .e .h .lfieldLive Z80 registers (8-bit halves, plus the shadow set and ixL ixH iyL iyH i r).
sms.cpu.getUint8(a) / setUint8(a,v)methodRead/write the banked Z80 bus (ROM banks, 8 KB work RAM at 0xC000, cart SRAM).
sms.vdp.VRAM / .CRAMfield16 KB video RAM and the Game Gear 12-bit colour RAM (two bytes per colour).
sms.keyboard.controller1fieldPlayer-1 pad latch (active-low: clear a bit to press). What the on-screen gamepad drives.

Because the interpreter keeps every register and the whole bus as ordinary JavaScript, the debugger single-steps with interpret(), reads and writes registers straight off sms.cpu, and implements execution breakpoints and write watchpoints as host-side checks around those calls, no changes to the emulator core.

Debugger integration

The debugger plug-in (gamegear-debug.js) reads the live machine from window.EMU_BOOT and calls EmuKit.defineMachine. The Z80 is disassembled by the shared z80 decoder (/debugger/src/cpus/z80.js), so this file only exposes a program counter, the register set and a byte reader.

Owning the loop. We do not call sms.start() (its internal requestAnimationFrame loop can't be paused or stepped). Instead we re-implement cpu.frame() so we can check the program counter against a breakpoint set before every instruction: with no breakpoints we run the native cpu.frame() at full speed; with any set we loop interpret() a scanline at a time, halting the moment pc hits a breakpoint. Write watchpoints wrap cpu.setUint8/setUint16.

Registers. Z80 registers live as 8-bit halves on sms.cpu; the plug-in presents the 16-bit pairs AF BC DE HL IX IY SP PC and decodes the flag byte (S Z H P/V N C) into individual, writable flag chips.

Architecture

jsSMS in Game Gear mode is an interpreted Sega 8-bit handheld. Each chip is its own object hanging off the top-level JSSMS:

  • Z80 - the Zilog Z80 CPU. interpret() is a giant opcode switch (base page plus the CB, ED, DD/FD and DDCB/FDCB prefixes); frame() drives it a scanline at a time.
  • Vdp - the Sega VDP (a superset of the TMS9918) in Mode 4. In Game Gear mode it crops to the central 160×144 window and reads its colours from a 12-bit palette (two CRAM bytes per colour: GGGGRRRR then ----BBBB).
  • SN76489 - the PSG sound chip; silent here, audio disabled for headless use.
  • Ports - the Z80 I/O port map. In GG mode the low ports (0x00-0x06) add the Game Gear's Start button and EXT/link registers on top of the shared SMS controller ports.
  • Sega mapper - the cartridge is paged in 16 KB banks through registers at 0xFFFC-0xFFFF.

Because the interpreter keeps the machine as ordinary objects, the entire state is inspectable and pokeable at runtime, which is what makes it a good debugging target.