UNPKG

zx-generation

Version:

A high-fidelity ZX Spectrum emulator in JavaScript — fully generated by a large language model (LLM) to explore the boundaries of AI in systems programming.

594 lines (350 loc) 10.6 kB
# ZX Generation API Documentation This document provides detailed information about the public APIs available in the ZXGeneration emulator. ## Table of Contents - [ZXSpectrum Class](#zxspectrum-class) - [CPU Class](#cpu-class) - [Memory Class](#memory-class) - [Display Class](#display-class) - [ULA Class](#ula-class) - [Tape Class](#tape-class) - [Sound Class](#sound-class) - [Snapshot Class](#snapshot-class) - [Event System](#event-system) ## ZXSpectrum Class The main emulator class that orchestrates all components. ### Constructor ```javascript new ZXSpectrum(canvas, options = {}) ``` **Parameters:** - `canvas` (HTMLCanvasElement) - The canvas element for display output - `options` (Object) - Configuration options - `scale` (Number) - Display scale factor (default: 2) - `border` (Boolean) - Show border area (default: true) - `sound` (Boolean) - Enable sound output (default: true) - `turbo` (Boolean) - Enable turbo mode (default: false) - `touchKeyboard` (Boolean) - Enable touch keyboard (default: false) ### Methods #### `loadROM(data)` Load ROM data into the emulator. **Parameters:** - `data` (Uint8Array) - ROM data (must be 16384 bytes) **Returns:** void **Example:** ```javascript const response = await fetch('./rom/48k.rom'); const romData = await response.arrayBuffer(); spectrum.loadROM(new Uint8Array(romData)); ``` #### `start()` Start the emulation. **Returns:** void #### `stop()` Stop the emulation. **Returns:** void #### `reset()` Reset the emulator to initial state. **Returns:** void #### `loadTape(data)` Load a TAP file for tape emulation. **Parameters:** - `data` (Uint8Array) - TAP file data **Returns:** void #### `playTape()` Start tape playback. **Returns:** void #### `stopTape()` Stop tape playback. **Returns:** void #### `rewindTape()` Rewind tape to beginning. **Returns:** void #### `keyDown(key)` Simulate a key press. **Parameters:** - `key` (String|Number) - Key code or character **Returns:** void #### `keyUp(key)` Simulate a key release. **Parameters:** - `key` (String|Number) - Key code or character **Returns:** void #### `keyPress(key, duration = 50)` Simulate a key press and release. **Parameters:** - `key` (String|Number) - Key code or character - `duration` (Number) - Duration of key press in milliseconds (default: 50) **Returns:** Promise #### `typeText(text, options = {})` Type text automatically with realistic timing. **Parameters:** - `text` (String) - Text to type - `options` (Object) - Typing options - `keyDelay` (Number) - Delay between key presses in ms (default: 100) - `keyDuration` (Number) - Duration of each key press in ms (default: 50) **Returns:** Promise **Example:** ```javascript await spectrum.typeText('LOAD""'); spectrum.keyPress(13); // Press Enter ``` #### `loadSnapshot(data)` Load a Z80 snapshot file. **Parameters:** - `data` (Uint8Array) - Z80 snapshot data **Returns:** void #### `saveSnapshot()` Save current state as Z80 snapshot. **Returns:** Uint8Array - Snapshot data #### `setSpeed(speed)` Set emulation speed. **Parameters:** - `speed` (Number) - Speed multiplier (1.0 = normal, 2.0 = double speed) **Returns:** void ### Properties #### `running` **Type:** Boolean (readonly) Whether the emulator is currently running. #### `cpu` **Type:** CPU (readonly) Direct access to the CPU instance. #### `memory` **Type:** Memory (readonly) Direct access to the memory instance. #### `display` **Type:** Display (readonly) Direct access to the display instance. #### `tape` **Type:** Tape (readonly) Direct access to the tape instance. ### Events The ZXSpectrum class extends EventTarget and emits the following events: - `ready` - Emitted when ROM is loaded and emulator is ready - `frame` - Emitted after each frame is rendered - `tapeloading` - Emitted when tape starts loading - `tapeloaded` - Emitted when tape finishes loading - `tapeerror` - Emitted on tape loading error **Example:** ```javascript spectrum.addEventListener('ready', () => { console.log('Emulator ready!'); spectrum.start(); }); spectrum.addEventListener('frame', (event) => { console.log(`Frame rendered in ${event.detail.time}ms`); }); ``` ## CPU Class Z80 CPU emulation core. ### Methods #### `execute(cycles)` Execute instructions for specified cycles. **Parameters:** - `cycles` (Number) - Number of T-states to execute **Returns:** Number - Actual cycles executed #### `interrupt()` Trigger a maskable interrupt. **Returns:** void #### `nmi()` Trigger a non-maskable interrupt (Not currently implemented in this version). **Returns:** void ### Properties #### `registers` **Type:** Registers Access to CPU registers (PC, SP, A, B, C, D, E, H, L, etc.) **Note:** Use `cpu.getState()` and `cpu.setState()` for getting/setting complete CPU state. #### `halted` **Type:** Boolean Whether CPU is in HALT state. #### `cycles` **Type:** Number (readonly) Total T-states executed. ## Memory Class Memory management (16K ROM + 48K RAM). ### Methods #### `read(address)` Read a byte from memory. **Parameters:** - `address` (Number) - Memory address (0x0000-0xFFFF) **Returns:** Number - Byte value (0-255) #### `write(address, value)` Write a byte to memory. **Parameters:** - `address` (Number) - Memory address (0x0000-0xFFFF) - `value` (Number) - Byte value (0-255) **Returns:** void #### `loadROM(data)` Load ROM data. **Parameters:** - `data` (Uint8Array) - ROM data (must be 16384 bytes or less) **Returns:** void **Throws:** Error if ROM data is too large ## Display Class Screen rendering (256×192 pixels + border). ### Methods #### `renderFrame()` Render a complete frame. **Returns:** void #### `setBorderColor(color)` Set border color (Note: This method is not available in the Display class. Use `ula.borderColor` instead). **Parameters:** - `color` (Number) - Color index (0-7) **Returns:** void ### Properties #### `displayBuffer` **Type:** Uint8Array (readonly) Raw display buffer data (RGBA format). #### `totalWidth` **Type:** Number (readonly) Total display width including border (352 pixels). #### `totalHeight` **Type:** Number (readonly) Total display height including border (296 pixels). ## ULA Class ULA (Uncommitted Logic Array) chip emulation. ### Methods #### `readPort(port)` Read from I/O port. **Parameters:** - `port` (Number) - Port address **Returns:** Number - Port value #### `writePort(port, value)` Write to I/O port. **Parameters:** - `port` (Number) - Port address - `value` (Number) - Value to write **Returns:** void ## Tape Class TAP file loading support. ### Methods #### `load(buffer, filename)` Load TAP or TZX file data. **Parameters:** - `buffer` (ArrayBuffer|Uint8Array) - Tape file data - `filename` (String) - Filename to determine format (.tap or .tzx) **Returns:** void #### `play()` Start tape playback. **Returns:** void #### `stop()` Stop tape playback. **Returns:** void #### `rewind()` Rewind to beginning. **Returns:** void ### Properties #### `isPlaying` **Type:** Boolean (readonly) Whether tape is currently playing. #### `position` **Type:** Number (readonly) Current tape position in bytes. #### `length` **Type:** Number (readonly) Total tape length in bytes. ## Sound Class Beeper sound generation. ### Methods #### `beep(speakerBit)` Update beeper state (internal method for basic sound). **Parameters:** - `speakerBit` (Number) - Speaker bit value (0 or 1) **Returns:** void #### `setVolume(volume)` Set sound volume. **Parameters:** - `volume` (Number) - Volume level (0.0-1.0) **Returns:** void #### `mute()` Mute sound output. **Returns:** void #### `unmute()` Unmute sound output. **Returns:** void ## Snapshot Support The emulator provides Z80 snapshot loading through the ZXSpectrum class methods: ### Methods #### `loadZ80Snapshot(data)` Load a Z80 version 1 snapshot (48K format). **Parameters:** - `data` (ArrayBuffer|Uint8Array) - Z80 snapshot data **Returns:** void #### `loadSnapshot(data)` Load a snapshot from saved state data. **Parameters:** - `data` (Object) - Snapshot data - `ram` (Uint8Array) - RAM contents (49152 bytes) - `cpu` (Object) - CPU state - `ula` (Object) - ULA state **Returns:** void #### `saveSnapshot()` Save current state as snapshot data. **Returns:** Object - Snapshot data with ram, cpu, and ula state ## Event System The emulator uses a custom event system for communication between components. ### Global Events - `cpu:halt` - CPU entered HALT state - `cpu:unhalt` - CPU exited HALT state - `memory:write` - Memory write occurred - `io:read` - I/O port read - `io:write` - I/O port write - `display:frame` - Frame rendered - `tape:block` - Tape block loaded - `key:down` - Key pressed - `key:up` - Key released ### Subscribing to Events ```javascript spectrum.addEventListener('cpu:halt', (event) => { console.log('CPU halted at PC:', event.detail.pc); }); spectrum.addEventListener('memory:write', (event) => { const { address, value } = event.detail; console.log(`Memory write: ${address.toString(16)} = ${value}`); }); ``` ## Error Handling All methods that can fail will throw errors with descriptive messages: ```javascript try { spectrum.loadROM(invalidData); } catch (error) { console.error('Failed to load ROM:', error.message); } ``` ## Performance Considerations - The emulator aims for cycle-accurate emulation at 3.5MHz - Frame rate is locked at 50Hz (PAL standard) - Use `turbo` mode for faster execution during development - Sound generation may impact performance on slower devices ## Example: Complete Setup ```javascript // Create and configure emulator const canvas = document.getElementById('screen'); const spectrum = new ZXSpectrum(canvas, { scale: 2, border: true, sound: true, touchKeyboard: true }); // Set up event handlers spectrum.addEventListener('ready', () => { console.log('Emulator ready'); spectrum.start(); }); spectrum.addEventListener('tapeloaded', () => { console.log('Tape loaded successfully'); }); // Load ROM const romResponse = await fetch('./rom/48k.rom'); const romData = await romResponse.arrayBuffer(); spectrum.loadROM(new Uint8Array(romData)); // Load and play a game const tapResponse = await fetch('./games/manic-miner.tap'); const tapData = await tapResponse.arrayBuffer(); spectrum.loadTape(new Uint8Array(tapData)); // Type LOAD command await spectrum.typeText('LOAD""'); spectrum.keyPress(13); // Start tape spectrum.playTape(); ```