urbancamo/fx870p-emulator
Casio FX-870P Emulator. Contribute to urbancamo/fx870p-emulator development by creating an account on GitHub.
4 stars · 1 forks · HLSL
README
FX-870P Emulator A browser-based emulator for the Casio FX-870P (also sold as the VX-4) pocket computer, written in TypeScript and Vue 3. The FX-870P was a 1986 programmable calculator running a Hitachi HD61700 CPU at 921 kHz with a 96×64 pixel LCD, 83-key keyboard, serial port, and optional MD-120 floppy drive. This emulator is a full port of the original Delphi reference implementation to the web platform.
Credits The original emulator is available on the PISI and credit is given to the original author of the amazing suite of emulators available on this site. This implementation is designed to purely make the code behind that emulator available to a wider audience on the internet. This version of the emulator implemented by Mark Wickens, the source code is hosted on GitHub here and it is hosted if here you want to try it. Hardware Emulated
Component Details
CPU Hitachi HD61700, 921 kHz
Memory 18-bit address space: ROM0 (6 KB, 16-bit words), ROM1 (128 KB × 2 banks), RAM (64 KB)
Display HD44352A01 LCD controller — 96×64 pixels + 5 status indicators
Keyboard 83-key matrix (9 blocks, 16 KO columns)
Serial UART with XON/XOFF flow control
Storage MD-120 floppy disk via Origin Private File System (OPFS)
Features
Responsive calculator face — scales to fit any screen size with multiple resolution faceplate images Full keyboard mapping — type directly on your PC keyboard with automatic CAPS and shifted-symbol handling Program library — built-in curated collection of sample BASIC programs loadable directly from the toolbar RS-232C serial — LOAD and SAVE BASIC programs via emulated COM0 with XON/XOFF flow control Floppy disk — MD-120 disk emulation via Origin Private File System (OPFS) Character set table — interactive 16x16 hex grid showing all 256 character bitmaps from the ROM font DEFCHR$ pixel editor — click any character to open a drag-to-paint 5x8 pixel editor that generates the BASIC DEFCHR$ command with a one-click copy button Turbo mode — run the CPU at ~50x speed for compute-heavy BASIC programs Fullscreen mode — hide toolbar and panels to use the calculator full-screen (useful on mobile) Firmware toggle — switch between FX-870P (Japanese) and VX-4 (English) ROM modes CPU debugger — live registers, flags, and disassembly view BASIC listing panel — live detokenized listing of all BASIC programs (P0–P9) stored in RAM, with tabbed navigation, syntax highlighting, and live/frozen toggle BASIC editor — in-place editing of BASIC programs with syntax highlighting, direct RAM writes, add/delete/edit lines, whole-program import/export with rich-text clipboard support Communications panel — UART register state, serial byte stream, and diagnostics
Running Prerequisites
Node.js 22 LTS ROM files placed in public/roms/ (not included)
Development server npm install ./start.sh # starts on http://localhost:3007/fx870p-emulator/ ./stop.sh # stops the server Or use npm directly: npm run dev # foreground, Ctrl-C to stop Production build npm run build # output in dist/ npm run preview # preview the built app The app is served under the /fx870p-emulator/ base path in both dev and production. Project Structure src/ emulator/ cpu.ts HD61700 CPU core — reset, fetch/decode/execute loop exec.ts Instruction handlers (~2100 lines) decoder.ts 256-entry instruction dispatch table def.ts CPU state, memory map, srcRead/dstWrite disassemble.ts Runtime disassembler (used by DebugPanel) lcd.ts HD44352A01 LCD controller → Canvas ImageData keyboard.ts 83-key matrix — keydown + mouse events port.ts I/O ports and UART state machine comm.ts RS-232C TX/RX queue, XON/XOFF, SAVE receive basic-tokens.ts Shared keyword tables (PREFIX4–7) and RAM layout constants detokenize.ts BASIC program detokenizer — reads tokenized programs from RAM tokenize.ts BASIC tokenizer — converts source text to FX-870P token bytes ram-edit.ts RAM editor — writes tokenized programs to RAM with file table management casio-ascii.ts Casio ASCII ↔ Unicode character mapping emulator.ts Main rAF loop, ROM loading, state persistence remote-log.ts Debug logging (dev only) trace.ts Per-instruction JSONL trace recorder components/ EmulatorView.vue Top-level orchestrator + panel layout LcdCanvas.vue Canvas LCD renderer KeyboardOverlay.vue Clickable key hit regions over face images CommPanel.vue Serial comms panel + toolbar buttons DebugPanel.vue CPU debugger (registers, flags, disassembly) BasicListPanel.vue BASIC program listing/editor panel (detokenized view, in-place editing, import/export) CharsetPopup.vue Character set table + DEFCHR$ pixel editor LibraryPopup.vue Program library popup (browse + load sample programs) AboutPopup.vue About dialog (renders ABOUT.md) editor/ BasicEditor.vue Reusable CodeMirror 6 editor component (single/multi-line modes) cm-basic-lang.ts CodeMirror StreamLanguage definition for FX-870P BASIC cm-basic-theme.ts CodeMirror dark theme matching the panel UI basic-highlight.ts Syntax highlighter for listing display and rich-text clipboard export public/ ABOUT.md User-facing documentation (rendered in About popup) basic/ Sample BASIC programs (.bas) images/ face.png Calculator faceplate (standard) face-large.png Calculator faceplate (large) face-huge.png Calculator faceplate (huge) keys.png Key overlay reference casio-logo.svg Casio logo (used as About popup watermark) roms/ ROM and charset binaries (not in repo) tests/ emu-harness.ts Headless emulator boot + keystroke helpers sin90.test.ts SIN(90) regression test tokenize.test.ts BASIC tokenizer tests (keywords, round-trip, edge cases) tools/ dis.ts Standalone disassembler (npm run dis) compare-traces.mjs Delphi vs TypeScript trace comparison charset-dump.ts Generate character set markdown (docs/charset.md) charset-table.ts Generate character set HTML table (docs/charset-table.html) compiler/ Casio JIS BASIC → HD61700 machine code compiler (README inside) emu-debugger/ Headless debugger library + CLI (README inside) reference/ Documentation and Delphi source docs/ Implementation notes
Developer Tools Beyond the browser emulator, this repo ships two Node.js tools for compiling and debugging HD61700 machine code: BASIC Compiler — tools/compiler/ Compiles Casio JIS Standard BASIC to HD61700 machine code. Generates an annotated 132-column assembly listing, a raw binary, a symbol table, and a self-loading BASIC program for real hardware. Generated code calls into the existing ROM for PRINT, INPUT, FP math, and string operations (the CosmicV4 pattern) rather than reimplementing the runtime. npx tsx tools/compiler/compile.ts program.bas
→ build/compiler/program.{bin,lst,sym,loader.bas}
Headless Debugger — tools/emu-debugger/ Library and CLI for driving the emulator programmatically. Breakpoints, memory watchpoints, instruction tracing, snapshot restore, single-stepping. Designed for debugging compiled binaries and automated regression testing. npm run debug -- run <binary.bin> # run + show LCD npm run debug -- trace <binary.bin> # log every instruction npm run debug -- step <binary.bin> # interactive single-step Reference DocumentsDocument Description
reference/fx870p-rom-annotations.md Annotated ROM address labels and call-flow notes
reference/fx870p-roms.md Full ROM disassembly
reference/FX-870P_VX-4 Manual.html Original user manual (HTML)
docs/CasioVX-4-Manual-Peter-Rost.pdf VX-4 manual by Peter Rost (PDF)
docs/FX-870P emulator.pdf Delphi emulator documentation (PDF)
docs/basic-detokenizer.md BASIC detokenizer reference — token tables, memory layout, line format
docs/basic-editor.md BASIC editor user guide — editing, import/export, limitations
docs/plan.md Web port implementation plan and component mapping
reference/fx870_es/ Original Delphi 5 source (reference only)
Testing The emulator has a headless test suite powered by vitest that boots the emulator in Node.js, injects keystrokes, runs the CPU, and verifies LCD output. Run all tests npm test Run a single test file npx vitest run tests/sin90.test.ts Run tests matching a name pattern npx vitest run -t "SIN" Watch mode (re-runs on file changes) npx vitest Tests require ROM files in public/roms/ (same as the dev server). Debug Logging The dev server exposes a /fx870p-emulator/log endpoint that writes to emulator-debug.log. Enable logging from the browser console: window.ioDebug(true) // enable window.ioDebug(false) // disable Tech Stack
Vue 3 + <script setup> TypeScript Vite 7 CodeMirror 6 — BASIC editor with custom syntax highlighting
