SearchA-ZT › TI-83 Emulator (Wabbitemu)

TI-83 Emulator (Wabbitemu)

1996 MIT Online

An in-browser emulator of the TI-83, the 1996 Zilog Z80 graphing calculator. It runs the portable Wabbitemu core (the reference Texas Instruments Z80 emulator, by Spencer Putt and Chris Shappell) compiled to WebAssembly, and boots straight to the TI-83 home screen. Type on the on-screen calculator keypad or your physical keyboard.

Because the core is driven through a small set of exported functions, the emulator plugs into the shared in-page debugger: single-step the Z80, read and write the registers and memory, and set breakpoints and watchpoints, all live.

Visit the official site ↗

Runs on: Web browser

TI-83 Emulator (Wabbitemu) Online Emulator

Play TI-83 Emulator (Wabbitemu) using JavaScript directly in your browser.

Configurations

ConfigurationEmulatorMachineOSLegal
TI-83 home screenTI-83 Emulator (Wabbitemu)TI-83greyOpen ⛶

Machines

Chips

Notes

Embedding

The Wabbitemu core is the reference Texas Instruments Z80 emulator. Its GUI is Windows-only, but the emulation core is portable C, so we compile just that to WebAssembly with Emscripten and drive it ourselves — Wabbitemu's own calc_run_frame loop runs free, which the debugger cannot pause or step.

Boot. Set up the original TI-83 hardware, copy the ROM image into memory, then reproduce Wabbitemu's power-on (reset, then tap the ON key):

wabbit_init();                       // memory_init_83 + CPU_init + device_init_83
wabbit_load_rom(ptr, len);            // memcpy the 256 KB image into the ROM pages
wabbit_boot();                       // CPU_reset, run 1s, press/release ON, run to HALT
(function frame(){
  wabbit_run_frame();                  // run one video frame of CPU_step()s
  blitLCD();                          // wabbit_lcd() -> ImageData -> canvas
  requestAnimationFrame(frame);
})();

The core is reached through a handful of exported C functions (all in wabbit.c), each called on demand from JavaScript — never per instruction:

ExportKindWhat it does
wabbit_step()fnRun exactly one Z80 instruction (CPU_step). The single-step primitive.
wabbit_run_frame()fnRun one video frame's worth of T-states at full speed.
wabbit_reg(i) / wabbit_set_reg(i,v)fnRead / write a register by index: AF BC DE HL IX IY SP PC, the shadows, I R, IM and the interrupt / halt flags — straight off the live CPU_t.
wabbit_read(a) / wabbit_write(a,v)fnThe banked 64K CPU bus. Reads resolve the current page mapping directly, with no I/O side effects, so an auto-polling hex view is safe.
wabbit_flash_read / wabbit_ram_readfnThe raw 256 KB ROM and 32 KB RAM chips.
wabbit_lcd(out)fnCopy the 96×64 grayscale LCD image (from the T6A04 driver) into a buffer for the canvas.
wabbit_key_down(g,b) / wabbit_key_up(g,b)fnPress / release a key in the hardware matrix by group and bit.
wabbit_reset()fnFull power-on reset: rebuild the ASIC, restore the ROM, tap ON.

Emscripten resolves ti83wabbit.wasm next to its loader script; the ROM is fetched from the same directory. Because every handle is a plain function call, the debugger reads registers and memory each refresh, single-steps with wabbit_step(), and implements breakpoints and watchpoints host-side — with no change to the emulator's hot path.

Debugger integration

The plug-in (ti83-debug.js) reads the live core from window.EMU_BOOT and calls EmuKit.defineMachine with a transport, the Z80 register set and the memory chips. It reuses the shared z80 disassembler (/debugger/src/cpus/z80.js).

Exactly what was changed in the source. The only file added to Wabbitemu is wabbit.c — a thin layer of EMSCRIPTEN_KEEPALIVE functions over the existing core API. For the TI-83 it selects memory_init_83 + device_init_83 (the original pre-flash ASIC: link port 00, keypad 01, the TI-83 standard interrupt on ports 02–04, and the T6A04 LCD on 10/11). It reads the register union CPU_t (cpu.af, cpu.pc, …), resolves the bus through mem_c.banks[addr>>14], copies the LCD via lcd->image(), and forwards keys to keypad_press/keypad_release. Nothing in the per-instruction path was touched, so with the debugger closed the emulator runs at full speed.

Single-step is CPU_step(). Breakpoints are a host-side Set of PC values: when any are set the JavaScript loop runs one instruction at a time (bounded by wabbit_tstates()) and compares the PC before each — no per-cycle hook is added to the wasm core. Watchpoints sample the watched addresses after each stepped instruction and halt on a change. Wabbitemu emulates the TI-83's memory mapping, RAM/ROM paging and standard interrupt faithfully, which is why the official TI operating system boots to its home screen here where lighter cores stall.

How to rebuild. With Emscripten on PATH, from a Wabbitemu checkout with wabbit.c beside it:

emcc core/{core,alu,control,indexcb,device,*_reverse,reverse_info}.c \
     hardware/{83hw,83phw,83psehw,lcd,colorlcd,keys,link}.c wabbit.c \
     -O2 -D_LINUX '-D__pragma(x)=' '-D_In_=' -I. -Icore -Ihardware -IInterface -Iutilities \
     -s MODULARIZE=1 -s EXPORT_NAME=WABBIT -s 'EXPORTED_FUNCTIONS=[_wabbit_init,...,_malloc,_free]' \
     -s 'EXPORTED_RUNTIME_METHODS=[ccall,cwrap,HEAPU8]' \
     -s ALLOW_MEMORY_GROWTH=1 -s ENVIRONMENT=web --no-entry -o ti83wabbit.js

-D_LINUX selects the portable branch of stdafx.h; '-D__pragma(x)=' neutralises the one MSVC pragma in lcd.c; '-D_In_=' drops the SAL annotation in 83hw.c. The full recipe and source are vendored in src/README.txt and src/wabbit.c.

Architecture

The TI-83 (1996) is a Zilog Z80 graphing calculator: a 6 MHz Z80, 256 KB of masked ROM (16 pages of 16 KB), 32 KB of RAM, and a 96×64 monochrome LCD driven by a Toshiba T6A04 controller. It is the original, pre-flash model — the TI-83 Plus that followed added flash storage and a different ASIC.

  • Z80 core — Wabbitemu's cycle-accurate interpreter (core/core.c), with the register banks held in a regpair union so cpu.af and cpu.a/cpu.f alias.
  • Memory — a banked mapping context. $0000 is a fixed page, $4000 is paged via port 04's mapping bits, and $C000 is RAM. The very first instruction of the ROM (LD A,7 · OUT ($04),A) programs that mapping — the fidelity the TI OS boot depends on.
  • Display — the T6A04 LCD driver (hardware/lcd.c); its image() composites the black-and-white frame into a 128-stride grayscale buffer whose visible 96 columns we blit.
  • Keypad — an 8×8 matrix read through port 01 (hardware/keys.c); each key is a (group, bit) pair.
  • ROM — the TI-83 operating system (v1.01, April 1996), a system image © Texas Instruments, installed into the ROM pages.

Every part is reached from JavaScript through the small wabbit.c shim, which is what makes an otherwise Windows-bound emulator a live, steppable debugging target in the browser.