diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..349c9be --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "submodules/cpu6502"] + path = submodules/cpu6502 + url = https://github.com/whscullin/cpu6502 diff --git a/README.md b/README.md index 848bd72..936ffc6 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ Things are still a little rough around the edges right now, hopefully I will hav First ```sh +git submodule init +git submodule update npm install ``` diff --git a/js/apple1.ts b/js/apple1.ts index 396a75a..663fb5b 100644 --- a/js/apple1.ts +++ b/js/apple1.ts @@ -12,7 +12,7 @@ import MicroModal from 'micromodal'; import Apple1IO from './apple1io'; -import CPU6502 from './cpu6502'; +import { CPU6502, word, byte } from '@whscullin/cpu6502'; import Prefs from './prefs'; import RAM from './ram'; import { TextPage } from './canvas1'; @@ -25,7 +25,6 @@ import Krusader from './roms/krusader'; import ACI from './cards/aci'; import { mapKeyEvent, KeyBoard } from './ui/keyboard'; -import { address, byte } from './types'; // eslint-disable-next-line prefer-const let DEBUG = false; @@ -197,7 +196,7 @@ export function setTurboTape(val: boolean) { turbotape = val; } -function run(pc?: address) { +function run(pc?: word) { if (runTimer) { clearInterval(runTimer); } @@ -364,7 +363,7 @@ export function doLoadText() { lines.forEach(function (line) { const parts = line.split(': '); if (parts.length === 2) { - let addr: address = 0; + let addr: word = 0; if (parts[0].length > 0) { addr = parseInt(parts[0], 16); } diff --git a/js/apple1io.ts b/js/apple1io.ts index 76eb10c..2261a40 100644 --- a/js/apple1io.ts +++ b/js/apple1io.ts @@ -10,7 +10,7 @@ */ import { TextPage } from './canvas1'; -import type { byte } from './types'; +import type { byte } from '@whscullin/cpu6502'; const LOC = { KBD: 0x10, diff --git a/js/base64.ts b/js/base64.ts index 827dc2b..cac518d 100644 --- a/js/base64.ts +++ b/js/base64.ts @@ -1,4 +1,4 @@ -import { memory } from './types'; +import { memory } from '@whscullin/cpu6502'; const B64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; diff --git a/js/canvas1.ts b/js/canvas1.ts index 1ab0074..1c8140b 100644 --- a/js/canvas1.ts +++ b/js/canvas1.ts @@ -10,7 +10,7 @@ */ import { charset } from './roms/apple1char'; -import type { byte } from './types'; +import type { byte } from '@whscullin/cpu6502'; /* 0: A9 9 AA 20 EF FF E8 8A 4C 2 0 diff --git a/js/cards/aci.ts b/js/cards/aci.ts index ecf6e9a..ee5ebe5 100644 --- a/js/cards/aci.ts +++ b/js/cards/aci.ts @@ -1,28 +1,40 @@ -import CPU6502 from '../cpu6502'; +import { CPU6502, byte } from '@whscullin/cpu6502'; import { debug } from '../util'; -import { byte } from '../types'; +// prettier-ignore const rom = [ - 0xa9, 0xaa, 0x20, 0xef, 0xff, 0xa9, 0x8d, 0x20, 0xef, 0xff, 0xa0, 0xff, 0xc8, - 0xad, 0x11, 0xd0, 0x10, 0xfb, 0xad, 0x10, 0xd0, 0x99, 0x00, 0x02, 0x20, 0xef, - 0xff, 0xc9, 0x9b, 0xf0, 0xe1, 0xc9, 0x8d, 0xd0, 0xe9, 0xa2, 0xff, 0xa9, 0x00, - 0x85, 0x24, 0x85, 0x25, 0x85, 0x26, 0x85, 0x27, 0xe8, 0xbd, 0x00, 0x02, 0xc9, - 0xd2, 0xf0, 0x56, 0xc9, 0xd7, 0xf0, 0x35, 0xc9, 0xae, 0xf0, 0x27, 0xc9, 0x8d, - 0xf0, 0x20, 0xc9, 0xa0, 0xf0, 0xe8, 0x49, 0xb0, 0xc9, 0x0a, 0x90, 0x06, 0x69, - 0x88, 0xc9, 0xfa, 0x90, 0xad, 0x0a, 0x0a, 0x0a, 0x0a, 0xa0, 0x04, 0x0a, 0x26, - 0x24, 0x26, 0x25, 0x88, 0xd0, 0xf8, 0xf0, 0xcc, 0x4c, 0x1a, 0xff, 0xa5, 0x24, - 0x85, 0x26, 0xa5, 0x25, 0x85, 0x27, 0xb0, 0xbf, 0xa9, 0x40, 0x20, 0xcc, 0xc1, - 0x88, 0xa2, 0x00, 0xa1, 0x26, 0xa2, 0x10, 0x0a, 0x20, 0xdb, 0xc1, 0xd0, 0xfa, - 0x20, 0xf1, 0xc1, 0xa0, 0x1e, 0x90, 0xec, 0xa6, 0x28, 0xb0, 0x98, 0x20, 0xbc, - 0xc1, 0xa9, 0x16, 0x20, 0xcc, 0xc1, 0x20, 0xbc, 0xc1, 0xa0, 0x1f, 0x20, 0xbf, - 0xc1, 0xb0, 0xf9, 0x20, 0xbf, 0xc1, 0xa0, 0x3a, 0xa2, 0x08, 0x48, 0x20, 0xbc, - 0xc1, 0x68, 0x2a, 0xa0, 0x39, 0xca, 0xd0, 0xf5, 0x81, 0x26, 0x20, 0xf1, 0xc1, - 0xa0, 0x35, 0x90, 0xea, 0xb0, 0xcd, 0x20, 0xbf, 0xc1, 0x88, 0xad, 0x81, 0xc0, - 0xc5, 0x29, 0xf0, 0xf8, 0x85, 0x29, 0xc0, 0x80, 0x60, 0x86, 0x28, 0xa0, 0x42, - 0x20, 0xe0, 0xc1, 0xd0, 0xf9, 0x69, 0xfe, 0xb0, 0xf5, 0xa0, 0x1e, 0x20, 0xe0, - 0xc1, 0xa0, 0x2c, 0x88, 0xd0, 0xfd, 0x90, 0x05, 0xa0, 0x2f, 0x88, 0xd0, 0xfd, - 0xbc, 0x00, 0xc0, 0xa0, 0x29, 0xca, 0x60, 0xa5, 0x26, 0xc5, 0x24, 0xa5, 0x27, - 0xe5, 0x25, 0xe6, 0x26, 0xd0, 0x02, 0xe6, 0x27, 0x60, + 0xA9,0xAA,0x20,0xEF,0xFF,0xA9,0x8D,0x20, + 0xEF,0xFF,0xA0,0xFF,0xC8,0xAD,0x11,0xD0, + 0x10,0xFB,0xAD,0x10,0xD0,0x99,0x00,0x02, + 0x20,0xEF,0xFF,0xC9,0x9B,0xF0,0xE1,0xC9, + 0x8D,0xD0,0xE9,0xA2,0xFF,0xA9,0x00,0x85, + 0x24,0x85,0x25,0x85,0x26,0x85,0x27,0xE8, + 0xBD,0x00,0x02,0xC9,0xD2,0xF0,0x56,0xC9, + 0xD7,0xF0,0x35,0xC9,0xAE,0xF0,0x27,0xC9, + 0x8D,0xF0,0x20,0xC9,0xA0,0xF0,0xE8,0x49, + 0xB0,0xC9,0x0A,0x90,0x06,0x69,0x88,0xC9, + 0xFA,0x90,0xAD,0x0A,0x0A,0x0A,0x0A,0xA0, + 0x04,0x0A,0x26,0x24,0x26,0x25,0x88,0xD0, + 0xF8,0xF0,0xCC,0x4C,0x1A,0xFF,0xA5,0x24, + 0x85,0x26,0xA5,0x25,0x85,0x27,0xB0,0xBF, + 0xA9,0x40,0x20,0xCC,0xC1,0x88,0xA2,0x00, + 0xA1,0x26,0xA2,0x10,0x0A,0x20,0xDB,0xC1, + 0xD0,0xFA,0x20,0xF1,0xC1,0xA0,0x1E,0x90, + 0xEC,0xA6,0x28,0xB0,0x98,0x20,0xBC,0xC1, + 0xA9,0x16,0x20,0xCC,0xC1,0x20,0xBC,0xC1, + 0xA0,0x1F,0x20,0xBF,0xC1,0xB0,0xF9,0x20, + 0xBF,0xC1,0xA0,0x3A,0xA2,0x08,0x48,0x20, + 0xBC,0xC1,0x68,0x2A,0xA0,0x39,0xCA,0xD0, + 0xF5,0x81,0x26,0x20,0xF1,0xC1,0xA0,0x35, + 0x90,0xEA,0xB0,0xCD,0x20,0xBF,0xC1,0x88, + 0xAD,0x81,0xC0,0xC5,0x29,0xF0,0xF8,0x85, + 0x29,0xC0,0x80,0x60,0x86,0x28,0xA0,0x42, + 0x20,0xE0,0xC1,0xD0,0xF9,0x69,0xFE,0xB0, + 0xF5,0xA0,0x1E,0x20,0xE0,0xC1,0xA0,0x2C, + 0x88,0xD0,0xFD,0x90,0x05,0xA0,0x2F,0x88, + 0xD0,0xFD,0xBC,0x00,0xC0,0xA0,0x29,0xCA, + 0x60,0xA5,0x26,0xC5,0x24,0xA5,0x27,0xE5, + 0x25,0xE6,0x26,0xD0,0x02,0xE6,0x27,0x60 ] as const; export interface ACICallback { diff --git a/js/cpu6502.ts b/js/cpu6502.ts deleted file mode 100644 index 11646db..0000000 --- a/js/cpu6502.ts +++ /dev/null @@ -1,3265 +0,0 @@ -/* - * Copyright 2010-2023 Will Scullin - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation. No representations are made about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - */ - -import { Memory, MemberOf, MemoryPages, byte, word } from './types'; -import { toHex } from './util'; - -export const FLAVOR_6502 = '6502'; -export const FLAVOR_ROCKWELL_65C02 = 'rockwell65c02'; -export const FLAVOR_WDC_65C02 = 'wdc65c02'; - -export const FLAVORS_65C02 = [FLAVOR_ROCKWELL_65C02, FLAVOR_WDC_65C02]; - -export const FLAVORS = [FLAVOR_6502, ...FLAVORS_65C02]; - -export type Flavor = MemberOf; - -export interface CpuOptions { - flavor?: Flavor; -} - -export interface CpuState { - /** Accumulator */ - a: byte; - /** X index */ - x: byte; - /** Y index */ - y: byte; - /** Status register */ - s: byte; - /** Program counter */ - pc: word; - /** Stack pointer */ - sp: byte; - /** Elapsed cycles */ - cycles: number; -} - -export type Mode = - | 'accumulator' // A (Accumulator) - | 'implied' // Implied - | 'immediate' // # Immediate - | 'absolute' // a Absolute - | 'zeroPage' // zp Zero Page - | 'relative' // r Relative - | 'absoluteX' // a,X Absolute, X - | 'absoluteY' // a,Y Absolute, Y - | 'zeroPageX' // zp,X Zero Page, X - | 'zeroPageY' // zp,Y Zero Page, Y - | 'absoluteIndirect' // (a) Indirect - | 'zeroPageXIndirect' // (zp,X) Zero Page Indexed Indirect - | 'zeroPageIndirectY' // (zp),Y Zero Page Indexed with Y - | 'zeroPageIndirect' // (zp), - | 'absoluteXIndirect' // (a, X), - | 'zeroPage_relative'; // zp, Relative - -export type Modes = Record; - -/** Addressing mode name to instruction size mapping. */ -export const sizes: Modes = { - accumulator: 1, - implied: 1, - immediate: 2, - absolute: 3, - zeroPage: 2, - relative: 2, - - absoluteX: 3, - absoluteY: 3, - zeroPageX: 2, - zeroPageY: 2, - - absoluteIndirect: 3, - zeroPageXIndirect: 2, - zeroPageIndirectY: 2, - - /* 65c02 */ - zeroPageIndirect: 2, - absoluteXIndirect: 3, - zeroPage_relative: 3, -}; - -/** Status register flag numbers. */ -export type flag = 0x80 | 0x40 | 0x20 | 0x10 | 0x08 | 0x04 | 0x02 | 0x01; - -/** - * - */ -export type DebugInfo = { - /** Program counter */ - pc: word; - /** Accumulator */ - ar: byte; - /** X index */ - xr: byte; - /** Y index */ - yr: byte; - /** Status register */ - sr: byte; - /** Stack pointer */ - sp: byte; - /** Current command */ - cmd: byte[]; -}; - -/** Flags to status byte mask. */ -export const flags: { [key: string]: flag } = { - N: 0x80, // Negative - V: 0x40, // oVerflow - X: 0x20, // Unused, always 1 - B: 0x10, // Break - D: 0x08, // Decimal - I: 0x04, // Interrupt - Z: 0x02, // Zero - C: 0x01, // Carry -}; - -/** CPU-referenced memory locations. */ -const loc = { - STACK: 0x100, - NMI: 0xfffa, - RESET: 0xfffc, - BRK: 0xfffe, -}; - -interface ResettablePageHandler extends MemoryPages { - reset(): void; -} - -function isResettablePageHandler( - pageHandler: MemoryPages | ResettablePageHandler, -): pageHandler is ResettablePageHandler { - return (pageHandler as ResettablePageHandler).reset !== undefined; -} - -const BLANK_PAGE: Memory = { - read: function () { - return 0; - }, - write: function () { - /* not writable */ - }, -}; - -interface Opts { - inc?: boolean; -} - -type ReadFn = () => byte; -type WriteFn = (val: byte) => void; -type ReadAddrFn = (opts?: Opts) => word; -type ImpliedFn = () => void; - -interface Instruction { - name: string; - mode: Mode; - fn: () => void; -} - -type Instructions = Record; - -type callback = (cpu: CPU6502) => boolean | void; - -export default class CPU6502 { - /** flavor */ - private readonly flavor: Flavor; - /** 65C02 emulation mode flag */ - private readonly is65C02: boolean; - - /** - * Registers - */ - - /** Program counter */ - private pc: word = 0; - /** Status register */ - private sr: byte = flags.X; - /** Accumulator */ - private ar: byte = 0; - /** X index */ - private xr: byte = 0; - /** Y index */ - private yr: byte = 0; - /** Stack pointer */ - private sp: byte = 0xff; - - /** Current instruction */ - private op: Instruction | undefined; - /** Last accessed memory address */ - private addr: word = 0; - - /** Filled array of memory handlers by address page */ - private memPages: Memory[] = new Array(0x100); - /** Callbacks invoked on reset signal */ - private resetHandlers: ResettablePageHandler[] = []; - /** Elapsed cycles */ - private cycles = 0; - /** Command being fetched signal */ - private sync = false; - - /** Processor is in WAI mode */ - private wait = false; - /** Processor is in STP mode */ - private stop = false; - - /** Filled array of CPU operations */ - private readonly opary: Instruction[]; - - constructor({ flavor }: CpuOptions = {}) { - this.flavor = flavor ?? FLAVOR_6502; - this.is65C02 = !!flavor && FLAVORS_65C02.includes(flavor); - - this.memPages.fill(BLANK_PAGE); - this.memPages.fill(BLANK_PAGE); - - // Create this CPU's instruction table - - let ops = { ...this.OPS_6502 }; - - switch (this.flavor) { - case FLAVOR_WDC_65C02: - ops = { - ...ops, - ...this.OPS_65C02, - ...this.OPS_WDC_65C02, - }; - break; - case FLAVOR_ROCKWELL_65C02: - ops = { - ...ops, - ...this.OPS_65C02, - ...this.OPS_ROCKWELL_65C02, - }; - break; - default: - ops = { - ...ops, - ...this.OPS_NMOS_6502, - }; - } - - // Certain browsers benefit from using arrays over maps - this.opary = new Array(0x100); - - for (let idx = 0; idx < 0x100; idx++) { - this.opary[idx] = ops[idx] || this.unknown(idx); - } - } - - /** - * Set or clears `f` in the status register. `f` must be a byte with a - * single bit set. - */ - private setFlag(f: flag, on: boolean) { - this.sr = on ? this.sr | f : this.sr & ~f; - } - - /** Updates the status register's zero flag and negative flag. */ - private testNZ(val: byte) { - this.sr = val === 0 ? this.sr | flags.Z : this.sr & ~flags.Z; - this.sr = val & 0x80 ? this.sr | flags.N : this.sr & ~flags.N; - - return val; - } - - /** Updates the status register's zero flag. */ - private testZ(val: byte) { - this.sr = val === 0 ? this.sr | flags.Z : this.sr & ~flags.Z; - - return val; - } - - /** - * Returns `a + b`, unless `sub` is true, in which case it performs - * `a - b`. The status register is updated according to the result. - */ - private add(a: byte, b: byte, sub: boolean): byte { - const a7 = a >> 7; - const b7 = b >> 7; - const ci = this.sr & flags.C; - let c; - let co; - let v; - let n; - let z; - - const updateFlags = (c: byte) => { - const bin = c & 0xff; - n = bin >> 7; - co = c >> 8; - z = !((a + b + ci) & 0xff); - v = a7 ^ b7 ^ n ^ co; - }; - - const updateBCDFlags = (c: byte) => { - if (this.is65C02) { - const bin = c & 0xff; - n = bin >> 7; - z = !bin; - if (this.op?.mode === 'immediate') { - if (this.flavor === FLAVOR_WDC_65C02) { - this.readByte(sub ? 0xb8 : 0x7f); - } else { - // rockwell65c02 - this.readByte(sub ? 0xb1 : 0x59); - } - } else { - this.readByte(this.addr); - } - } - if (!sub) { - co = c >> 8; - } - }; - - c = (a & 0x0f) + (b & 0x0f) + ci; - if ((this.sr & flags.D) !== 0) { - // BCD - if (sub) { - if (c < 0x10) { - c = (c - 0x06) & 0x0f; - } - c += (a & 0xf0) + (b & 0xf0); - updateFlags(c); - if (c < 0x100) { - c += 0xa0; - } - } else { - if (c > 0x9) { - c = 0x10 + ((c + 0x6) & 0xf); - } - c += (a & 0xf0) + (b & 0xf0); - updateFlags(c); - if (c >= 0xa0) { - c += 0x60; - } - } - updateBCDFlags(c); - } else { - c += (a & 0xf0) + (b & 0xf0); - updateFlags(c); - } - c = c & 0xff; - - this.setFlag(flags.N, !!n); - this.setFlag(flags.V, !!v); - this.setFlag(flags.Z, !!z); - this.setFlag(flags.C, !!co); - - return c; - } - - /** Increments `a` and returns the value, setting the status register. */ - private increment(a: byte) { - return this.testNZ((a + 0x01) & 0xff); - } - - private decrement(a: byte) { - return this.testNZ((a + 0xff) & 0xff); - } - - private readBytePC(): byte { - const result = this.readByte(this.pc); - - this.pc = (this.pc + 1) & 0xffff; - - return result; - } - - private readByte(addr: word): byte { - this.addr = addr; - const page = addr >> 8, - off = addr & 0xff; - - const result = this.memPages[page].read(page, off); - - this.cycles++; - - return result; - } - - private writeByte(addr: word, val: byte) { - this.addr = addr; - const page = addr >> 8, - off = addr & 0xff; - - this.memPages[page].write(page, off, val); - - this.cycles++; - } - - private readWord(addr: word): word { - return this.readByte(addr) | (this.readByte(addr + 1) << 8); - } - - private readWordPC(): word { - return this.readBytePC() | (this.readBytePC() << 8); - } - - private readZPWord(addr: byte): word { - const lsb = this.readByte(addr & 0xff); - const msb = this.readByte((addr + 1) & 0xff); - - return (msb << 8) | lsb; - } - - private pushByte(val: byte) { - this.writeByte(loc.STACK | this.sp, val); - this.sp = (this.sp + 0xff) & 0xff; - } - - private pushWord(val: word) { - this.pushByte(val >> 8); - this.pushByte(val & 0xff); - } - - private pullByte(): byte { - this.sp = (this.sp + 0x01) & 0xff; - return this.readByte(loc.STACK | this.sp); - } - - private pullWordRaw(): word { - const lsb = this.pullByte(); - const msb = this.pullByte(); - - return (msb << 8) | lsb; - } - - // Helpers that replicate false reads and writes during work cycles that - // vary between CPU versions - - private workCycle(addr: word, val: byte) { - if (this.is65C02) { - this.readByte(addr); - } else { - this.writeByte(addr, val); - } - } - - private workCycleIndexedWrite(pc: word, addr: word, addrIdx: word): void { - const oldPage = addr & 0xff00; - if (this.is65C02) { - this.readByte(pc); - } else { - const off = addrIdx & 0xff; - this.readByte(oldPage | off); - } - } - - private workCycleIndexedRead(pc: word, addr: word, addrIdx: word): void { - const oldPage = addr & 0xff00; - const newPage = addrIdx & 0xff00; - if (newPage !== oldPage) { - if (this.is65C02) { - this.readByte(pc); - } else { - const off = addrIdx & 0xff; - this.readByte(oldPage | off); - } - } - } - - /* - * Implied function - */ - - implied = () => { - this.readByte(this.pc); - }; - - /* - * Read functions - */ - - // #$00 - readImmediate = (): byte => { - return this.readBytePC(); - }; - - // $0000 - readAbsolute = (): byte => { - return this.readByte(this.readWordPC()); - }; - - // $00 - readZeroPage = (): byte => { - return this.readByte(this.readBytePC()); - }; - - // $0000,X - readAbsoluteX = (): byte => { - const addr = this.readWordPC(); - const pc = this.addr; - const addrIdx = (addr + this.xr) & 0xffff; - this.workCycleIndexedRead(pc, addr, addrIdx); - return this.readByte(addrIdx); - }; - - // $0000,Y - readAbsoluteY = (): byte => { - const addr = this.readWordPC(); - const pc = this.addr; - const addrIdx = (addr + this.yr) & 0xffff; - this.workCycleIndexedRead(pc, addr, addrIdx); - return this.readByte(addrIdx); - }; - - // $00,X - readZeroPageX = (): byte => { - const zpAddr = this.readBytePC(); - this.readByte(zpAddr); - return this.readByte((zpAddr + this.xr) & 0xff); - }; - - // $00,Y - readZeroPageY = (): byte => { - const zpAddr = this.readBytePC(); - this.readByte(zpAddr); - return this.readByte((zpAddr + this.yr) & 0xff); - }; - - // ($00,X) - readZeroPageXIndirect = (): byte => { - const zpAddr = this.readBytePC(); - this.readByte(zpAddr); - const addr = this.readZPWord((zpAddr + this.xr) & 0xff); - return this.readByte(addr); - }; - - // ($00),Y - readZeroPageIndirectY = (): byte => { - const zpAddr = this.readBytePC(); - const pc = this.addr; - const addr = this.readZPWord(zpAddr); - const addrIdx = (addr + this.yr) & 0xffff; - this.workCycleIndexedRead(pc, addr, addrIdx); - return this.readByte(addrIdx); - }; - - // ($00) (65C02) - readZeroPageIndirect = (): byte => { - return this.readByte(this.readZPWord(this.readBytePC())); - }; - - /* - * Write Functions - */ - - // $0000 - writeAbsolute = (val: byte) => { - this.writeByte(this.readWordPC(), val); - }; - - // $00 - writeZeroPage = (val: byte) => { - this.writeByte(this.readBytePC(), val); - }; - - // $0000,X - writeAbsoluteX = (val: byte) => { - const addr = this.readWordPC(); - const pc = this.addr; - const addrIdx = (addr + this.xr) & 0xffff; - this.workCycleIndexedWrite(pc, addr, addrIdx); - this.writeByte(addrIdx, val); - }; - - // $0000,Y - writeAbsoluteY = (val: byte) => { - const addr = this.readWordPC(); - const pc = this.addr; - const addrIdx = (addr + this.yr) & 0xffff; - this.workCycleIndexedWrite(pc, addr, addrIdx); - this.writeByte(addrIdx, val); - }; - - // $00,X - writeZeroPageX = (val: byte) => { - const zpAddr = this.readBytePC(); - this.readByte(zpAddr); - this.writeByte((zpAddr + this.xr) & 0xff, val); - }; - - // $00,Y - writeZeroPageY = (val: byte) => { - const zpAddr = this.readBytePC(); - this.readByte(zpAddr); - this.writeByte((zpAddr + this.yr) & 0xff, val); - }; - - // ($00,X) - writeZeroPageXIndirect = (val: byte) => { - const zpAddr = this.readBytePC(); - this.readByte(zpAddr); - const addr = this.readZPWord((zpAddr + this.xr) & 0xff); - this.writeByte(addr, val); - }; - - // ($00),Y - writeZeroPageIndirectY = (val: byte) => { - const zpAddr = this.readBytePC(); - const pc = this.addr; - const addr = this.readZPWord(zpAddr); - const addrIdx = (addr + this.yr) & 0xffff; - this.workCycleIndexedWrite(pc, addr, addrIdx); - this.writeByte(addrIdx, val); - }; - - // ($00) (65C02) - writeZeroPageIndirect = (val: byte) => { - this.writeByte(this.readZPWord(this.readBytePC()), val); - }; - - // $00 - readAddrZeroPage = () => { - return this.readBytePC(); - }; - - // $00,X - readAddrZeroPageX = () => { - const zpAddr = this.readBytePC(); - this.readByte(zpAddr); - return (zpAddr + this.xr) & 0xff; - }; - - // $0000 (65C02) - readAddrAbsolute = (): word => { - return this.readWordPC(); - }; - - // ($0000) (6502) - readAddrAbsoluteIndirectBug = (): word => { - const addr = this.readWordPC(); - const page = addr & 0xff00; - const off = addr & 0x00ff; - const lsb = this.readByte(addr); - const msb = this.readByte(page | ((off + 0x01) & 0xff)); - return (msb << 8) | lsb; - }; - - // ($0000) (65C02) - readAddrAbsoluteIndirect = (): word => { - const addr = this.readWord(this.readWordPC()); - this.readByte(this.addr); - return addr; - }; - - // $0000,X - readAddrAbsoluteX = (opts?: Opts): word => { - let addr = this.readWordPC(); - const page = addr & 0xff00; - addr = (addr + this.xr) & 0xffff; - if (this.is65C02) { - if (opts?.inc) { - this.readByte(this.addr); - } else { - const newPage = addr & 0xff00; - if (page !== newPage) { - this.readByte(this.addr); - } - } - } else { - const off = addr & 0x00ff; - this.readByte(page | off); - } - return addr; - }; - - // $0000,Y (NMOS 6502) - readAddrAbsoluteY = (): word => { - let addr = this.readWordPC(); - const page = addr & 0xff00; - addr = (addr + this.yr) & 0xffff; - const off = addr & 0x00ff; - this.readByte(page | off); - return addr; - }; - - // ($00,X) (NMOS 6502) - readAddrZeroPageXIndirect = () => { - const zpAddr = this.readBytePC(); - this.readByte(zpAddr); - return this.readZPWord((zpAddr + this.xr) & 0xff); - }; - - // ($00),Y (NMOS 6502) - readAddrZeroPageIndirectY = () => { - const zpAddr = this.readBytePC(); - const addr = this.readZPWord(zpAddr); - const addrIdx = (addr + this.yr) & 0xffff; - const oldPage = addr & 0xff00; - const off = addrIdx & 0xff; - this.readByte(oldPage | off); - return addrIdx; - }; - - // $(0000,X) (65C02) - readAddrAbsoluteXIndirect = (): word => { - const lsb = this.readBytePC(); - const pc = this.addr; - const msb = this.readBytePC(); - const addr = (((msb << 8) | lsb) + this.xr) & 0xffff; - this.readByte(pc); - return this.readWord(addr); - }; - - // 5C, DC, FC NOP (65C02) - readNop = (): void => { - this.readWordPC(); - this.readByte(this.addr); - }; - - // NOP (65C02) - readNopImplied = (): void => { - // Op is 1 cycle - }; - - /* Break */ - brk = (readFn: ReadFn) => { - readFn(); - this.pushWord(this.pc); - this.pushByte(this.sr | flags.B); - if (this.is65C02) { - this.setFlag(flags.D, false); - } - this.setFlag(flags.I, true); - this.pc = this.readWord(loc.BRK); - }; - - /* Stop (65C02) */ - stp = () => { - this.stop = true; - this.readByte(this.pc); - this.readByte(this.pc); - }; - - /* Wait (65C02) */ - wai = () => { - this.wait = true; - this.readByte(this.pc); - this.readByte(this.pc); - }; - - /* Load Accumulator */ - lda = (readFn: ReadFn) => { - this.ar = this.testNZ(readFn()); - }; - - /* Load X Register */ - ldx = (readFn: ReadFn) => { - this.xr = this.testNZ(readFn()); - }; - - /* Load Y Register */ - ldy = (readFn: ReadFn) => { - this.yr = this.testNZ(readFn()); - }; - - /* Store Accumulator */ - sta = (writeFn: WriteFn) => { - writeFn(this.ar); - }; - - /* Store X Register */ - stx = (writeFn: WriteFn) => { - writeFn(this.xr); - }; - - /* Store Y Register */ - sty = (writeFn: WriteFn) => { - writeFn(this.yr); - }; - - /* Store Zero */ - stz = (writeFn: WriteFn) => { - writeFn(0); - }; - - /* Add with Carry */ - adc = (readFn: ReadFn) => { - this.ar = this.add(this.ar, readFn(), /* sub= */ false); - }; - - /* Subtract with Carry */ - sbc = (readFn: ReadFn) => { - this.ar = this.add(this.ar, readFn() ^ 0xff, /* sub= */ true); - }; - - /* Increment Memory */ - incA = () => { - this.readByte(this.pc); - this.ar = this.increment(this.ar); - }; - - inc = (readAddrFn: ReadAddrFn) => { - const addr = readAddrFn({ inc: true }); - const oldVal = this.readByte(addr); - this.workCycle(addr, oldVal); - const val = this.increment(oldVal); - this.writeByte(addr, val); - }; - - /* Increment X */ - inx = () => { - this.readByte(this.pc); - this.xr = this.increment(this.xr); - }; - - /* Increment Y */ - iny = () => { - this.readByte(this.pc); - this.yr = this.increment(this.yr); - }; - - /* Decrement Memory */ - decA = () => { - this.readByte(this.pc); - this.ar = this.decrement(this.ar); - }; - - dec = (readAddrFn: ReadAddrFn) => { - const addr = readAddrFn({ inc: true }); - const oldVal = this.readByte(addr); - this.workCycle(addr, oldVal); - const val = this.decrement(oldVal); - this.writeByte(addr, val); - }; - - /* Decrement X */ - dex = () => { - this.readByte(this.pc); - this.xr = this.decrement(this.xr); - }; - - /* Decrement Y */ - dey = () => { - this.readByte(this.pc); - this.yr = this.decrement(this.yr); - }; - - shiftLeft = (val: byte) => { - this.setFlag(flags.C, !!(val & 0x80)); - return this.testNZ((val << 1) & 0xff); - }; - - /* Arithmetic Shift Left */ - aslA = () => { - this.readByte(this.pc); - this.ar = this.shiftLeft(this.ar); - }; - - asl = (readAddrFn: ReadAddrFn) => { - const addr = readAddrFn(); - const oldVal = this.readByte(addr); - this.workCycle(addr, oldVal); - const val = this.shiftLeft(oldVal); - this.writeByte(addr, val); - }; - - shiftRight = (val: byte) => { - this.setFlag(flags.C, !!(val & 0x01)); - return this.testNZ(val >> 1); - }; - - /* Logical Shift Right */ - lsrA = () => { - this.readByte(this.pc); - this.ar = this.shiftRight(this.ar); - }; - - lsr = (readAddrFn: ReadAddrFn) => { - const addr = readAddrFn(); - const oldVal = this.readByte(addr); - this.workCycle(addr, oldVal); - const val = this.shiftRight(oldVal); - this.writeByte(addr, val); - }; - - rotateLeft = (val: byte) => { - const c = this.sr & flags.C; - this.setFlag(flags.C, !!(val & 0x80)); - return this.testNZ(((val << 1) | (c ? 0x01 : 0x00)) & 0xff); - }; - - /* Rotate Left */ - rolA = () => { - this.readByte(this.pc); - this.ar = this.rotateLeft(this.ar); - }; - - rol = (readAddrFn: ReadAddrFn) => { - const addr = readAddrFn(); - const oldVal = this.readByte(addr); - this.workCycle(addr, oldVal); - const val = this.rotateLeft(oldVal); - this.writeByte(addr, val); - }; - - private rotateRight(a: byte) { - const c = this.sr & flags.C; - this.setFlag(flags.C, !!(a & 0x01)); - return this.testNZ((a >> 1) | (c ? 0x80 : 0x00)); - } - - /* Rotate Right */ - rorA = () => { - this.readByte(this.pc); - this.ar = this.rotateRight(this.ar); - }; - - ror = (readAddrFn: ReadAddrFn) => { - const addr = readAddrFn(); - const oldVal = this.readByte(addr); - this.workCycle(addr, oldVal); - const val = this.rotateRight(oldVal); - this.writeByte(addr, val); - }; - - /* Logical And Accumulator */ - and = (readFn: ReadFn) => { - this.ar = this.testNZ(this.ar & readFn()); - }; - - /* Logical Or Accumulator */ - ora = (readFn: ReadFn) => { - this.ar = this.testNZ(this.ar | readFn()); - }; - - /* Logical Exclusive Or Accumulator */ - eor = (readFn: ReadFn) => { - this.ar = this.testNZ(this.ar ^ readFn()); - }; - - /* Reset Bit */ - - rmb = (b: byte) => { - const bit = (0x1 << b) ^ 0xff; - const addr = this.readBytePC(); - let val = this.readByte(addr); - this.readByte(addr); - val &= bit; - this.writeByte(addr, val); - }; - - /* Set Bit */ - - smb = (b: byte) => { - const bit = 0x1 << b; - const addr = this.readBytePC(); - let val = this.readByte(addr); - this.readByte(addr); - val |= bit; - this.writeByte(addr, val); - }; - - /* Test and Reset Bits */ - trb = (readAddrFn: ReadAddrFn) => { - const addr = readAddrFn(); - const val = this.readByte(addr); - this.testZ(val & this.ar); - this.readByte(addr); - this.writeByte(addr, val & ~this.ar); - }; - - /* Test and Set Bits */ - tsb = (readAddrFn: ReadAddrFn) => { - const addr = readAddrFn(); - const val = this.readByte(addr); - this.testZ(val & this.ar); - this.readByte(addr); - this.writeByte(addr, val | this.ar); - }; - - /* Bit */ - bit = (readFn: ReadFn) => { - const val = readFn(); - this.setFlag(flags.Z, (val & this.ar) === 0); - this.setFlag(flags.N, !!(val & 0x80)); - this.setFlag(flags.V, !!(val & 0x40)); - }; - - /* Bit Immediate*/ - bitI = (readFn: ReadFn) => { - const val = readFn(); - this.setFlag(flags.Z, (val & this.ar) === 0); - }; - - private compare(a: byte, b: byte) { - b = b ^ 0xff; - const c = a + b + 1; - this.setFlag(flags.C, c > 0xff); - this.testNZ(c & 0xff); - } - - cmp = (readFn: ReadFn) => { - this.compare(this.ar, readFn()); - }; - - cpx = (readFn: ReadFn) => { - this.compare(this.xr, readFn()); - }; - - cpy = (readFn: ReadFn) => { - this.compare(this.yr, readFn()); - }; - - /* Branches */ - brs = (f: flag) => { - const off = this.readBytePC(); // changes pc - if ((f & this.sr) !== 0) { - this.readByte(this.pc); - const oldPage = this.pc & 0xff00; - this.pc += off > 127 ? off - 256 : off; - this.pc &= 0xffff; - const newPage = this.pc & 0xff00; - const newOff = this.pc & 0xff; - if (newPage !== oldPage) this.readByte(oldPage | newOff); - } - }; - - brc = (f: flag | 0) => { - const off = this.readBytePC(); // changes pc - if ((f & this.sr) === 0) { - this.readByte(this.pc); - const oldPage = this.pc & 0xff00; - this.pc += off > 127 ? off - 256 : off; - this.pc &= 0xffff; - const newPage = this.pc & 0xff00; - const newOff = this.pc & 0xff; - if (newPage !== oldPage) this.readByte(oldPage | newOff); - } - }; - - /* WDC 65C02 branches */ - - bbr = (b: byte) => { - const zpAddr = this.readBytePC(); - const val = this.readByte(zpAddr); - this.writeByte(zpAddr, val); - const off = this.readBytePC(); // changes pc - const oldPc = this.pc; - const oldPage = oldPc & 0xff00; - - let newPC = this.pc + (off > 127 ? off - 256 : off); - newPC &= 0xffff; - const newOff = newPC & 0xff; - this.readByte(oldPage | newOff); - if (((1 << b) & val) === 0) { - this.pc = newPC; - } - }; - - bbs = (b: byte) => { - const zpAddr = this.readBytePC(); - const val = this.readByte(zpAddr); - this.writeByte(zpAddr, val); - const off = this.readBytePC(); // changes pc - const oldPc = this.pc; - const oldPage = oldPc & 0xff00; - - let newPC = this.pc + (off > 127 ? off - 256 : off); - newPC &= 0xffff; - const newOff = newPC & 0xff; - this.readByte(oldPage | newOff); - if (((1 << b) & val) !== 0) { - this.pc = newPC; - } - }; - - /* Transfers and stack */ - tax = () => { - this.readByte(this.pc); - this.testNZ((this.xr = this.ar)); - }; - - txa = () => { - this.readByte(this.pc); - this.testNZ((this.ar = this.xr)); - }; - - tay = () => { - this.readByte(this.pc); - this.testNZ((this.yr = this.ar)); - }; - - tya = () => { - this.readByte(this.pc); - this.testNZ((this.ar = this.yr)); - }; - - tsx = () => { - this.readByte(this.pc); - this.testNZ((this.xr = this.sp)); - }; - - txs = () => { - this.readByte(this.pc); - this.sp = this.xr; - }; - - pha = () => { - this.readByte(this.pc); - this.pushByte(this.ar); - }; - - pla = () => { - this.readByte(this.pc); - this.readByte(0x0100 | this.sp); - this.testNZ((this.ar = this.pullByte())); - }; - - phx = () => { - this.readByte(this.pc); - this.pushByte(this.xr); - }; - - plx = () => { - this.readByte(this.pc); - this.readByte(0x0100 | this.sp); - this.testNZ((this.xr = this.pullByte())); - }; - - phy = () => { - this.readByte(this.pc); - this.pushByte(this.yr); - }; - - ply = () => { - this.readByte(this.pc); - this.readByte(0x0100 | this.sp); - this.testNZ((this.yr = this.pullByte())); - }; - - php = () => { - this.readByte(this.pc); - this.pushByte(this.sr | flags.B); - }; - - plp = () => { - this.readByte(this.pc); - this.readByte(0x0100 | this.sp); - this.sr = (this.pullByte() & ~flags.B) | flags.X; - }; - - /* Jump */ - jmp = (readAddrFn: ReadAddrFn) => { - this.pc = readAddrFn(); - }; - - /* Jump Subroutine */ - jsr = () => { - const lsb = this.readBytePC(); - this.readByte(0x0100 | this.sp); - this.pushWord(this.pc); - const msb = this.readBytePC(); - this.pc = ((msb << 8) | lsb) & 0xffff; - }; - - /* Return from Subroutine */ - rts = () => { - this.readByte(this.pc); - this.readByte(0x0100 | this.sp); - const addr = this.pullWordRaw(); - this.readByte(addr); - this.pc = (addr + 1) & 0xffff; - }; - - /* Return from Interrupt */ - rti = () => { - this.readByte(this.pc); - this.readByte(0x0100 | this.sp); - this.sr = (this.pullByte() & ~flags.B) | flags.X; - this.pc = this.pullWordRaw(); - }; - - /* Set and Clear */ - set = (flag: flag) => { - this.readByte(this.pc); - this.sr |= flag; - }; - - clr = (flag: flag) => { - this.readByte(this.pc); - this.sr &= ~flag; - }; - - /* No-Op */ - nop = (readFn: ImpliedFn | ReadFn) => { - readFn(); - }; - - /* NMOS 6502 Illegal opcodes */ - - /* ASO = ASL + ORA */ - aso = (readAddrFn: ReadAddrFn) => { - const addr = readAddrFn(); - const oldVal = this.readByte(addr); - this.workCycle(addr, oldVal); - const val = this.shiftLeft(oldVal); - this.writeByte(addr, val); - this.ar |= val; - this.testNZ(this.ar); - }; - - /* RLA = ROL + AND */ - rla = (readAddrFn: ReadAddrFn) => { - const addr = readAddrFn(); - const oldVal = this.readByte(addr); - this.workCycle(addr, oldVal); - const val = this.rotateLeft(oldVal); - this.writeByte(addr, val); - this.ar &= val; - this.testNZ(this.ar); - }; - - /* LSE = LSR + EOR */ - lse = (readAddrFn: ReadAddrFn) => { - const addr = readAddrFn(); - const oldVal = this.readByte(addr); - this.workCycle(addr, oldVal); - const val = this.shiftRight(oldVal); - this.writeByte(addr, val); - this.ar ^= val; - this.testNZ(this.ar); - }; - - /* RRA = ROR + ADC */ - rra = (readAddrFn: ReadAddrFn) => { - const addr = readAddrFn(); - const oldVal = this.readByte(addr); - this.workCycle(addr, oldVal); - const val = this.rotateRight(oldVal); - this.writeByte(addr, val); - this.ar = this.add(this.ar, val, false); - }; - - /* AXS = Store A & X */ - axs = (writeFn: WriteFn) => { - writeFn(this.ar & this.xr); - }; - - /* LAX = Load A & X */ - lax = (readFn: ReadFn) => { - const val = readFn(); - this.ar = val; - this.xr = val; - this.testNZ(val); - }; - - /* DCM = DEC + CMP */ - dcm = (readAddrFn: ReadAddrFn) => { - const addr = readAddrFn({ inc: true }); - const oldVal = this.readByte(addr); - this.workCycle(addr, oldVal); - const val = this.decrement(oldVal); - this.writeByte(addr, val); - this.compare(this.ar, val); - }; - - /* INS = INC + SBC */ - ins = (readAddrFn: ReadAddrFn) => { - const addr = readAddrFn({ inc: true }); - const oldVal = this.readByte(addr); - this.workCycle(addr, oldVal); - const val = this.increment(oldVal); - this.writeByte(addr, val); - this.ar = this.add(this.ar, val ^ 0xff, true); - }; - - /* ALR = AND + LSR */ - alr = (readFn: ReadFn) => { - const val = readFn() & this.ar; - this.ar = this.shiftRight(val); - }; - - /* ARR = AND + ROR */ - arr = (readFn: ReadFn) => { - const val = readFn() & this.ar; - const ah = val >> 4; - const al = val & 0xf; - const b7 = val >> 7; - const b6 = (val >> 6) & 0x1; - this.ar = this.rotateRight(val); - let c = !!b7; - const v = !!(b7 ^ b6); - if (this.sr & flags.D) { - if (al + (al & 0x1) > 0x5) { - this.ar = (this.ar & 0xf0) | ((this.ar + 0x6) & 0xf); - } - if (ah + (ah & 0x1) > 5) { - c = true; - this.ar = (this.ar + 0x60) & 0xff; - } - } - this.setFlag(flags.V, v); - this.setFlag(flags.C, c); - }; - - /* XAA = TAX + AND */ - xaa = (readFn: ReadFn) => { - const val = readFn(); - this.ar = (this.xr & 0xee) | (this.xr & this.ar & 0x11); - this.ar = this.testNZ(this.ar & val); - }; - - /** OAL = ORA + AND */ - oal = (readFn: ReadFn) => { - this.ar |= 0xee; - const val = this.testNZ(this.ar & readFn()); - this.ar = val; - this.xr = val; - }; - - /* SAX = A & X + SBC */ - sax = (readFn: ReadFn) => { - const a = this.xr & this.ar; - let b = readFn(); - b = b ^ 0xff; - const c = a + b + 1; - this.setFlag(flags.C, c > 0xff); - this.xr = this.testNZ(c & 0xff); - }; - - /* TAS = X & Y -> S */ - tas = (readAddrFn: ReadAddrFn) => { - const addr = readAddrFn(); - let val = this.xr & this.ar; - this.sp = val; - const msb = addr >> 8; - val = val & ((msb + 1) & 0xff); - this.writeByte(addr, val); - }; - - /* SAY = Y & AH + 1 */ - say = (readAddrFn: ReadAddrFn) => { - const addr = readAddrFn(); - const msb = addr >> 8; - const val = this.yr & ((msb + 1) & 0xff); - this.writeByte(addr, val); - }; - - /* XAS = X & AH + 1 */ - xas = (readAddrFn: ReadAddrFn) => { - const addr = readAddrFn(); - const msb = addr >> 8; - const val = this.xr & ((msb + 1) & 0xff); - this.writeByte(addr, val); - }; - - /* AXA = X & AH + 1 */ - axa = (readAddrFn: ReadAddrFn) => { - const addr = readAddrFn(); - let val = this.xr & this.ar; - const msb = addr >> 8; - val = val & ((msb + 1) & 0xff); - this.writeByte(addr, val); - }; - - /* ANC = AND with carry */ - anc = (readFn: ReadFn) => { - this.ar = this.testNZ(this.ar & readFn()); - const c = !!(this.ar & 0x80); - this.setFlag(flags.C, c); - }; - - /* LAS = RD & SP -> A, X, S */ - las = (readFn: ReadFn) => { - const val = this.sp & readFn(); - this.sp = val; - this.xr = val; - this.ar = this.testNZ(val); - }; - - /* SKB/SKW */ - skp = (readFn: ReadFn) => { - readFn(); - }; - - /* HLT */ - hlt = (_impliedFn: ImpliedFn) => { - this.readByte(this.pc); - this.readByte(this.pc); - // PC shouldn't have advanced - this.pc = --this.pc & 0xffff; - this.stop = true; - }; - - private unknown(b: byte): Instruction { - let unk: Instruction; - if (this.is65C02) { - // Default behavior is a 1 cycle NOP - unk = { - name: 'NOP', - fn: () => this.nop(this.readNopImplied), - mode: 'implied', - }; - } else { - // All 6502 Instructions should be defined - throw new Error(`Missing ${toHex(b)}`); - } - return unk; - } - - public step(cb?: callback) { - this.sync = true; - this.op = this.opary[this.readBytePC()]; - this.sync = false; - this.op.fn(); - - cb?.(this); - } - - public stepN(n: number, cb?: callback) { - for (let idx = 0; idx < n; idx++) { - this.sync = true; - this.op = this.opary[this.readBytePC()]; - this.sync = false; - this.op.fn(); - - if (cb?.(this)) { - return; - } - } - } - - public stepCycles(c: number) { - const end = this.cycles + c; - - while (this.cycles < end) { - this.sync = true; - this.op = this.opary[this.readBytePC()]; - this.sync = false; - this.op.fn(); - } - } - - public stepCyclesDebug(c: number, cb?: callback): void { - const end = this.cycles + c; - - while (this.cycles < end) { - this.sync = true; - this.op = this.opary[this.readBytePC()]; - this.sync = false; - this.op.fn(); - - if (cb?.(this)) { - return; - } - } - } - - public addPageHandler(pho: MemoryPages | ResettablePageHandler) { - for (let idx = pho.start(); idx <= pho.end(); idx++) { - this.memPages[idx] = pho; - } - if (isResettablePageHandler(pho)) this.resetHandlers.push(pho); - } - - public reset() { - // cycles = 0; - this.sr = flags.X; - this.sp = 0xff; - this.ar = 0; - this.yr = 0; - this.xr = 0; - this.pc = this.readWord(loc.RESET); - this.wait = false; - this.stop = false; - - for (let idx = 0; idx < this.resetHandlers.length; idx++) { - this.resetHandlers[idx].reset(); - } - } - - /* IRQ - Interrupt Request */ - public irq() { - if ((this.sr & flags.I) === 0) { - this.pushWord(this.pc); - this.pushByte(this.sr & ~flags.B); - if (this.is65C02) { - this.setFlag(flags.D, false); - } - this.setFlag(flags.I, true); - this.pc = this.readWord(loc.BRK); - this.wait = false; - } - } - - /* NMI Non-maskable Interrupt */ - public nmi() { - this.pushWord(this.pc); - this.pushByte(this.sr & ~flags.B); - if (this.is65C02) { - this.setFlag(flags.D, false); - } - this.setFlag(flags.I, true); - this.pc = this.readWord(loc.NMI); - this.wait = false; - } - - public getPC() { - return this.pc; - } - - public setPC(pc: word) { - this.pc = pc; - } - - public getDebugInfo(): DebugInfo { - const b = this.read(this.pc); - const op = this.opary[b]; - const size = sizes[op.mode]; - const cmd = new Array(size); - cmd[0] = b; - for (let idx = 1; idx < size; idx++) { - cmd[idx] = this.read(this.pc + idx); - } - - return { - pc: this.pc, - ar: this.ar, - xr: this.xr, - yr: this.yr, - sr: this.sr, - sp: this.sp, - cmd, - }; - } - public getSync() { - return this.sync; - } - - public getStop() { - return this.stop; - } - - public getWait() { - return this.wait; - } - - public getCycles() { - return this.cycles; - } - - public getOpInfo(opcode: byte) { - return this.opary[opcode]; - } - - public getState(): CpuState { - return { - a: this.ar, - x: this.xr, - y: this.yr, - s: this.sr, - pc: this.pc, - sp: this.sp, - cycles: this.cycles, - }; - } - - public setState(state: CpuState) { - this.ar = state.a; - this.xr = state.x; - this.yr = state.y; - this.sr = state.s; - this.pc = state.pc; - this.sp = state.sp; - this.cycles = state.cycles; - } - - public read(addr: word): byte; - public read(page: byte, off: byte): byte; - - public read(a: number, b?: number): byte { - let page, off; - if (b !== undefined) { - page = a & 0xff; - off = b & 0xff; - } else { - page = (a >> 8) & 0xff; - off = a & 0xff; - } - return this.memPages[page].read(page, off); - } - - public write(addr: word, val: byte): void; - public write(page: byte, off: byte, val: byte): void; - - public write(a: number, b: number, c?: byte): void { - let page, off, val; - - if (c !== undefined) { - page = a & 0xff; - off = b & 0xff; - val = c & 0xff; - } else { - page = (a >> 8) & 0xff; - off = a & 0xff; - val = b & 0xff; - } - this.memPages[page].write(page, off, val); - } - - OPS_6502: Instructions = { - // LDA - 0xa9: { - name: 'LDA', - fn: () => this.lda(this.readImmediate), - mode: 'immediate', - }, - 0xa5: { - name: 'LDA', - fn: () => this.lda(this.readZeroPage), - mode: 'zeroPage', - }, - 0xb5: { - name: 'LDA', - fn: () => this.lda(this.readZeroPageX), - mode: 'zeroPageX', - }, - 0xad: { - name: 'LDA', - fn: () => this.lda(this.readAbsolute), - mode: 'absolute', - }, - 0xbd: { - name: 'LDA', - fn: () => this.lda(this.readAbsoluteX), - mode: 'absoluteX', - }, - 0xb9: { - name: 'LDA', - fn: () => this.lda(this.readAbsoluteY), - mode: 'absoluteY', - }, - 0xa1: { - name: 'LDA', - fn: () => this.lda(this.readZeroPageXIndirect), - mode: 'zeroPageXIndirect', - }, - 0xb1: { - name: 'LDA', - fn: () => this.lda(this.readZeroPageIndirectY), - mode: 'zeroPageIndirectY', - }, - - // LDX - 0xa2: { - name: 'LDX', - fn: () => this.ldx(this.readImmediate), - mode: 'immediate', - }, - 0xa6: { - name: 'LDX', - fn: () => this.ldx(this.readZeroPage), - mode: 'zeroPage', - }, - 0xb6: { - name: 'LDX', - fn: () => this.ldx(this.readZeroPageY), - mode: 'zeroPageY', - }, - 0xae: { - name: 'LDX', - fn: () => this.ldx(this.readAbsolute), - mode: 'absolute', - }, - 0xbe: { - name: 'LDX', - fn: () => this.ldx(this.readAbsoluteY), - mode: 'absoluteY', - }, - - // LDY - 0xa0: { - name: 'LDY', - fn: () => this.ldy(this.readImmediate), - mode: 'immediate', - }, - 0xa4: { - name: 'LDY', - fn: () => this.ldy(this.readZeroPage), - mode: 'zeroPage', - }, - 0xb4: { - name: 'LDY', - fn: () => this.ldy(this.readZeroPageX), - mode: 'zeroPageX', - }, - 0xac: { - name: 'LDY', - fn: () => this.ldy(this.readAbsolute), - mode: 'absolute', - }, - 0xbc: { - name: 'LDY', - fn: () => this.ldy(this.readAbsoluteX), - mode: 'absoluteX', - }, - - // STA - 0x85: { - name: 'STA', - fn: () => this.sta(this.writeZeroPage), - mode: 'zeroPage', - }, - 0x95: { - name: 'STA', - fn: () => this.sta(this.writeZeroPageX), - mode: 'zeroPageX', - }, - 0x8d: { - name: 'STA', - fn: () => this.sta(this.writeAbsolute), - mode: 'absolute', - }, - 0x9d: { - name: 'STA', - fn: () => this.sta(this.writeAbsoluteX), - mode: 'absoluteX', - }, - 0x99: { - name: 'STA', - fn: () => this.sta(this.writeAbsoluteY), - mode: 'absoluteY', - }, - 0x81: { - name: 'STA', - fn: () => this.sta(this.writeZeroPageXIndirect), - mode: 'zeroPageXIndirect', - }, - 0x91: { - name: 'STA', - fn: () => this.sta(this.writeZeroPageIndirectY), - mode: 'zeroPageIndirectY', - }, - - // STX - 0x86: { - name: 'STX', - fn: () => this.stx(this.writeZeroPage), - mode: 'zeroPage', - }, - 0x96: { - name: 'STX', - fn: () => this.stx(this.writeZeroPageY), - mode: 'zeroPageY', - }, - 0x8e: { - name: 'STX', - fn: () => this.stx(this.writeAbsolute), - mode: 'absolute', - }, - - // STY - 0x84: { - name: 'STY', - fn: () => this.sty(this.writeZeroPage), - mode: 'zeroPage', - }, - 0x94: { - name: 'STY', - fn: () => this.sty(this.writeZeroPageX), - mode: 'zeroPageX', - }, - 0x8c: { - name: 'STY', - fn: () => this.sty(this.writeAbsolute), - mode: 'absolute', - }, - - // ADC - 0x69: { - name: 'ADC', - fn: () => this.adc(this.readImmediate), - mode: 'immediate', - }, - 0x65: { - name: 'ADC', - fn: () => this.adc(this.readZeroPage), - mode: 'zeroPage', - }, - 0x75: { - name: 'ADC', - fn: () => this.adc(this.readZeroPageX), - mode: 'zeroPageX', - }, - 0x6d: { - name: 'ADC', - fn: () => this.adc(this.readAbsolute), - mode: 'absolute', - }, - 0x7d: { - name: 'ADC', - fn: () => this.adc(this.readAbsoluteX), - mode: 'absoluteX', - }, - 0x79: { - name: 'ADC', - fn: () => this.adc(this.readAbsoluteY), - mode: 'absoluteY', - }, - 0x61: { - name: 'ADC', - fn: () => this.adc(this.readZeroPageXIndirect), - mode: 'zeroPageXIndirect', - }, - 0x71: { - name: 'ADC', - fn: () => this.adc(this.readZeroPageIndirectY), - mode: 'zeroPageIndirectY', - }, - - // SBC - 0xe9: { - name: 'SBC', - fn: () => this.sbc(this.readImmediate), - mode: 'immediate', - }, - 0xe5: { - name: 'SBC', - fn: () => this.sbc(this.readZeroPage), - mode: 'zeroPage', - }, - 0xf5: { - name: 'SBC', - fn: () => this.sbc(this.readZeroPageX), - mode: 'zeroPageX', - }, - 0xed: { - name: 'SBC', - fn: () => this.sbc(this.readAbsolute), - mode: 'absolute', - }, - 0xfd: { - name: 'SBC', - fn: () => this.sbc(this.readAbsoluteX), - mode: 'absoluteX', - }, - 0xf9: { - name: 'SBC', - fn: () => this.sbc(this.readAbsoluteY), - mode: 'absoluteY', - }, - 0xe1: { - name: 'SBC', - fn: () => this.sbc(this.readZeroPageXIndirect), - mode: 'zeroPageXIndirect', - }, - 0xf1: { - name: 'SBC', - fn: () => this.sbc(this.readZeroPageIndirectY), - mode: 'zeroPageIndirectY', - }, - - // INC - 0xe6: { - name: 'INC', - fn: () => this.inc(this.readAddrZeroPage), - mode: 'zeroPage', - }, - 0xf6: { - name: 'INC', - fn: () => this.inc(this.readAddrZeroPageX), - mode: 'zeroPageX', - }, - 0xee: { - name: 'INC', - fn: () => this.inc(this.readAddrAbsolute), - mode: 'absolute', - }, - 0xfe: { - name: 'INC', - fn: () => this.inc(this.readAddrAbsoluteX), - mode: 'absoluteX', - }, - - // INX - 0xe8: { name: 'INX', fn: () => this.inx(), mode: 'implied' }, - - // INY - 0xc8: { name: 'INY', fn: () => this.iny(), mode: 'implied' }, - - // DEC - 0xc6: { - name: 'DEC', - fn: () => this.dec(this.readAddrZeroPage), - mode: 'zeroPage', - }, - 0xd6: { - name: 'DEC', - fn: () => this.dec(this.readAddrZeroPageX), - mode: 'zeroPageX', - }, - 0xce: { - name: 'DEC', - fn: () => this.dec(this.readAddrAbsolute), - mode: 'absolute', - }, - 0xde: { - name: 'DEC', - fn: () => this.dec(this.readAddrAbsoluteX), - mode: 'absoluteX', - }, - - // DEX - 0xca: { name: 'DEX', fn: () => this.dex(), mode: 'implied' }, - - // DEY - 0x88: { name: 'DEY', fn: () => this.dey(), mode: 'implied' }, - - // ASL - 0x0a: { - name: 'ASL', - fn: () => this.aslA(), - mode: 'accumulator', - }, - 0x06: { - name: 'ASL', - fn: () => this.asl(this.readAddrZeroPage), - mode: 'zeroPage', - }, - 0x16: { - name: 'ASL', - fn: () => this.asl(this.readAddrZeroPageX), - mode: 'zeroPageX', - }, - 0x0e: { - name: 'ASL', - fn: () => this.asl(this.readAddrAbsolute), - mode: 'absolute', - }, - 0x1e: { - name: 'ASL', - fn: () => this.asl(this.readAddrAbsoluteX), - mode: 'absoluteX', - }, - - // LSR - 0x4a: { - name: 'LSR', - fn: () => this.lsrA(), - mode: 'accumulator', - }, - 0x46: { - name: 'LSR', - fn: () => this.lsr(this.readAddrZeroPage), - mode: 'zeroPage', - }, - 0x56: { - name: 'LSR', - fn: () => this.lsr(this.readAddrZeroPageX), - mode: 'zeroPageX', - }, - 0x4e: { - name: 'LSR', - fn: () => this.lsr(this.readAddrAbsolute), - mode: 'absolute', - }, - 0x5e: { - name: 'LSR', - fn: () => this.lsr(this.readAddrAbsoluteX), - mode: 'absoluteX', - }, - - // ROL - 0x2a: { - name: 'ROL', - fn: () => this.rolA(), - mode: 'accumulator', - }, - 0x26: { - name: 'ROL', - fn: () => this.rol(this.readAddrZeroPage), - mode: 'zeroPage', - }, - 0x36: { - name: 'ROL', - fn: () => this.rol(this.readAddrZeroPageX), - mode: 'zeroPageX', - }, - 0x2e: { - name: 'ROL', - fn: () => this.rol(this.readAddrAbsolute), - mode: 'absolute', - }, - 0x3e: { - name: 'ROL', - fn: () => this.rol(this.readAddrAbsoluteX), - mode: 'absoluteX', - }, - - // ROR - 0x6a: { - name: 'ROR', - fn: () => this.rorA(), - mode: 'accumulator', - }, - 0x66: { - name: 'ROR', - fn: () => this.ror(this.readAddrZeroPage), - mode: 'zeroPage', - }, - 0x76: { - name: 'ROR', - fn: () => this.ror(this.readAddrZeroPageX), - mode: 'zeroPageX', - }, - 0x6e: { - name: 'ROR', - fn: () => this.ror(this.readAddrAbsolute), - mode: 'absolute', - }, - 0x7e: { - name: 'ROR', - fn: () => this.ror(this.readAddrAbsoluteX), - mode: 'absoluteX', - }, - - // AND - 0x29: { - name: 'AND', - fn: () => this.and(this.readImmediate), - mode: 'immediate', - }, - 0x25: { - name: 'AND', - fn: () => this.and(this.readZeroPage), - mode: 'zeroPage', - }, - 0x35: { - name: 'AND', - fn: () => this.and(this.readZeroPageX), - mode: 'zeroPageX', - }, - 0x2d: { - name: 'AND', - fn: () => this.and(this.readAbsolute), - mode: 'absolute', - }, - 0x3d: { - name: 'AND', - fn: () => this.and(this.readAbsoluteX), - mode: 'absoluteX', - }, - 0x39: { - name: 'AND', - fn: () => this.and(this.readAbsoluteY), - mode: 'absoluteY', - }, - 0x21: { - name: 'AND', - fn: () => this.and(this.readZeroPageXIndirect), - mode: 'zeroPageXIndirect', - }, - 0x31: { - name: 'AND', - fn: () => this.and(this.readZeroPageIndirectY), - mode: 'zeroPageIndirectY', - }, - - // ORA - 0x09: { - name: 'ORA', - fn: () => this.ora(this.readImmediate), - mode: 'immediate', - }, - 0x05: { - name: 'ORA', - fn: () => this.ora(this.readZeroPage), - mode: 'zeroPage', - }, - 0x15: { - name: 'ORA', - fn: () => this.ora(this.readZeroPageX), - mode: 'zeroPageX', - }, - 0x0d: { - name: 'ORA', - fn: () => this.ora(this.readAbsolute), - mode: 'absolute', - }, - 0x1d: { - name: 'ORA', - fn: () => this.ora(this.readAbsoluteX), - mode: 'absoluteX', - }, - 0x19: { - name: 'ORA', - fn: () => this.ora(this.readAbsoluteY), - mode: 'absoluteY', - }, - 0x01: { - name: 'ORA', - fn: () => this.ora(this.readZeroPageXIndirect), - mode: 'zeroPageXIndirect', - }, - 0x11: { - name: 'ORA', - fn: () => this.ora(this.readZeroPageIndirectY), - mode: 'zeroPageIndirectY', - }, - - // EOR - 0x49: { - name: 'EOR', - fn: () => this.eor(this.readImmediate), - mode: 'immediate', - }, - 0x45: { - name: 'EOR', - fn: () => this.eor(this.readZeroPage), - mode: 'zeroPage', - }, - 0x55: { - name: 'EOR', - fn: () => this.eor(this.readZeroPageX), - mode: 'zeroPageX', - }, - 0x4d: { - name: 'EOR', - fn: () => this.eor(this.readAbsolute), - mode: 'absolute', - }, - 0x5d: { - name: 'EOR', - fn: () => this.eor(this.readAbsoluteX), - mode: 'absoluteX', - }, - 0x59: { - name: 'EOR', - fn: () => this.eor(this.readAbsoluteY), - mode: 'absoluteY', - }, - 0x41: { - name: 'EOR', - fn: () => this.eor(this.readZeroPageXIndirect), - mode: 'zeroPageXIndirect', - }, - 0x51: { - name: 'EOR', - fn: () => this.eor(this.readZeroPageIndirectY), - mode: 'zeroPageIndirectY', - }, - - // CMP - 0xc9: { - name: 'CMP', - fn: () => this.cmp(this.readImmediate), - mode: 'immediate', - }, - 0xc5: { - name: 'CMP', - fn: () => this.cmp(this.readZeroPage), - mode: 'zeroPage', - }, - 0xd5: { - name: 'CMP', - fn: () => this.cmp(this.readZeroPageX), - mode: 'zeroPageX', - }, - 0xcd: { - name: 'CMP', - fn: () => this.cmp(this.readAbsolute), - mode: 'absolute', - }, - 0xdd: { - name: 'CMP', - fn: () => this.cmp(this.readAbsoluteX), - mode: 'absoluteX', - }, - 0xd9: { - name: 'CMP', - fn: () => this.cmp(this.readAbsoluteY), - mode: 'absoluteY', - }, - 0xc1: { - name: 'CMP', - fn: () => this.cmp(this.readZeroPageXIndirect), - mode: 'zeroPageXIndirect', - }, - 0xd1: { - name: 'CMP', - fn: () => this.cmp(this.readZeroPageIndirectY), - mode: 'zeroPageIndirectY', - }, - - // CPX - 0xe0: { - name: 'CPX', - fn: () => this.cpx(this.readImmediate), - mode: 'immediate', - }, - 0xe4: { - name: 'CPX', - fn: () => this.cpx(this.readZeroPage), - mode: 'zeroPage', - }, - 0xec: { - name: 'CPX', - fn: () => this.cpx(this.readAbsolute), - mode: 'absolute', - }, - - // CPY - 0xc0: { - name: 'CPY', - fn: () => this.cpy(this.readImmediate), - mode: 'immediate', - }, - 0xc4: { - name: 'CPY', - fn: () => this.cpy(this.readZeroPage), - mode: 'zeroPage', - }, - 0xcc: { - name: 'CPY', - fn: () => this.cpy(this.readAbsolute), - mode: 'absolute', - }, - - // BIT - 0x24: { - name: 'BIT', - fn: () => this.bit(this.readZeroPage), - mode: 'zeroPage', - }, - 0x2c: { - name: 'BIT', - fn: () => this.bit(this.readAbsolute), - mode: 'absolute', - }, - - // BCC - 0x90: { - name: 'BCC', - fn: () => this.brc(flags.C), - mode: 'relative', - }, - - // BCS - 0xb0: { - name: 'BCS', - fn: () => this.brs(flags.C), - mode: 'relative', - }, - - // BEQ - 0xf0: { - name: 'BEQ', - fn: () => this.brs(flags.Z), - mode: 'relative', - }, - - // BMI - 0x30: { - name: 'BMI', - fn: () => this.brs(flags.N), - mode: 'relative', - }, - - // BNE - 0xd0: { - name: 'BNE', - fn: () => this.brc(flags.Z), - mode: 'relative', - }, - - // BPL - 0x10: { - name: 'BPL', - fn: () => this.brc(flags.N), - mode: 'relative', - }, - - // BVC - 0x50: { - name: 'BVC', - fn: () => this.brc(flags.V), - mode: 'relative', - }, - - // BVS - 0x70: { - name: 'BVS', - fn: () => this.brs(flags.V), - mode: 'relative', - }, - - // TAX - 0xaa: { name: 'TAX', fn: () => this.tax(), mode: 'implied' }, - - // TXA - 0x8a: { name: 'TXA', fn: () => this.txa(), mode: 'implied' }, - - // TAY - 0xa8: { name: 'TAY', fn: () => this.tay(), mode: 'implied' }, - - // TYA - 0x98: { name: 'TYA', fn: () => this.tya(), mode: 'implied' }, - - // TSX - 0xba: { name: 'TSX', fn: () => this.tsx(), mode: 'implied' }, - - // TXS - 0x9a: { name: 'TXS', fn: () => this.txs(), mode: 'implied' }, - - // PHA - 0x48: { name: 'PHA', fn: () => this.pha(), mode: 'implied' }, - - // PLA - 0x68: { name: 'PLA', fn: () => this.pla(), mode: 'implied' }, - - // PHP - 0x08: { name: 'PHP', fn: () => this.php(), mode: 'implied' }, - - // PLP - 0x28: { name: 'PLP', fn: () => this.plp(), mode: 'implied' }, - - // JMP - 0x4c: { - name: 'JMP', - fn: () => this.jmp(this.readAddrAbsolute), - mode: 'absolute', - }, - 0x6c: { - name: 'JMP', - fn: () => this.jmp(this.readAddrAbsoluteIndirectBug), - mode: 'absoluteIndirect', - }, - // JSR - 0x20: { - name: 'JSR', - fn: () => this.jsr(), - mode: 'absolute', - }, - - // RTS - 0x60: { name: 'RTS', fn: () => this.rts(), mode: 'implied' }, - - // RTI - 0x40: { name: 'RTI', fn: () => this.rti(), mode: 'implied' }, - - // SEC - 0x38: { name: 'SEC', fn: () => this.set(flags.C), mode: 'implied' }, - - // SED - 0xf8: { name: 'SED', fn: () => this.set(flags.D), mode: 'implied' }, - - // SEI - 0x78: { name: 'SEI', fn: () => this.set(flags.I), mode: 'implied' }, - - // CLC - 0x18: { name: 'CLC', fn: () => this.clr(flags.C), mode: 'implied' }, - - // CLD - 0xd8: { name: 'CLD', fn: () => this.clr(flags.D), mode: 'implied' }, - - // CLI - 0x58: { name: 'CLI', fn: () => this.clr(flags.I), mode: 'implied' }, - - // CLV - 0xb8: { name: 'CLV', fn: () => this.clr(flags.V), mode: 'implied' }, - - // NOP - 0xea: { name: 'NOP', fn: () => this.nop(this.implied), mode: 'implied' }, - - // BRK - 0x00: { - name: 'BRK', - fn: () => this.brk(this.readImmediate), - mode: 'immediate', - }, - }; - - /* 65C02 Instructions */ - - OPS_65C02: Instructions = { - // INC / DEC A - 0x1a: { - name: 'INC', - fn: () => this.incA(), - mode: 'accumulator', - }, - 0x3a: { - name: 'DEC', - fn: () => this.decA(), - mode: 'accumulator', - }, - - // Indirect Zero Page for the masses - 0x12: { - name: 'ORA', - fn: () => this.ora(this.readZeroPageIndirect), - mode: 'zeroPageIndirect', - }, - 0x32: { - name: 'AND', - fn: () => this.and(this.readZeroPageIndirect), - mode: 'zeroPageIndirect', - }, - 0x52: { - name: 'EOR', - fn: () => this.eor(this.readZeroPageIndirect), - mode: 'zeroPageIndirect', - }, - 0x72: { - name: 'ADC', - fn: () => this.adc(this.readZeroPageIndirect), - mode: 'zeroPageIndirect', - }, - 0x92: { - name: 'STA', - fn: () => this.sta(this.writeZeroPageIndirect), - mode: 'zeroPageIndirect', - }, - 0xb2: { - name: 'LDA', - fn: () => this.lda(this.readZeroPageIndirect), - mode: 'zeroPageIndirect', - }, - 0xd2: { - name: 'CMP', - fn: () => this.cmp(this.readZeroPageIndirect), - mode: 'zeroPageIndirect', - }, - 0xf2: { - name: 'SBC', - fn: () => this.sbc(this.readZeroPageIndirect), - mode: 'zeroPageIndirect', - }, - - // Better BIT - 0x34: { - name: 'BIT', - fn: () => this.bit(this.readZeroPageX), - mode: 'zeroPageX', - }, - 0x3c: { - name: 'BIT', - fn: () => this.bit(this.readAbsoluteX), - mode: 'absoluteX', - }, - 0x89: { - name: 'BIT', - fn: () => this.bitI(this.readImmediate), - mode: 'immediate', - }, - - // JMP absolute indirect indexed - 0x6c: { - name: 'JMP', - fn: () => this.jmp(this.readAddrAbsoluteIndirect), - mode: 'absoluteIndirect', - }, - 0x7c: { - name: 'JMP', - fn: () => this.jmp(this.readAddrAbsoluteXIndirect), - mode: 'absoluteXIndirect', - }, - - // BBR/BBS - 0x0f: { - name: 'BBR0', - fn: () => this.bbr(0), - mode: 'zeroPage_relative', - }, - 0x1f: { - name: 'BBR1', - fn: () => this.bbr(1), - mode: 'zeroPage_relative', - }, - 0x2f: { - name: 'BBR2', - fn: () => this.bbr(2), - mode: 'zeroPage_relative', - }, - 0x3f: { - name: 'BBR3', - fn: () => this.bbr(3), - mode: 'zeroPage_relative', - }, - 0x4f: { - name: 'BBR4', - fn: () => this.bbr(4), - mode: 'zeroPage_relative', - }, - 0x5f: { - name: 'BBR5', - fn: () => this.bbr(5), - mode: 'zeroPage_relative', - }, - 0x6f: { - name: 'BBR6', - fn: () => this.bbr(6), - mode: 'zeroPage_relative', - }, - 0x7f: { - name: 'BBR7', - fn: () => this.bbr(7), - mode: 'zeroPage_relative', - }, - - 0x8f: { - name: 'BBS0', - fn: () => this.bbs(0), - mode: 'zeroPage_relative', - }, - 0x9f: { - name: 'BBS1', - fn: () => this.bbs(1), - mode: 'zeroPage_relative', - }, - 0xaf: { - name: 'BBS2', - fn: () => this.bbs(2), - mode: 'zeroPage_relative', - }, - 0xbf: { - name: 'BBS3', - fn: () => this.bbs(3), - mode: 'zeroPage_relative', - }, - 0xcf: { - name: 'BBS4', - fn: () => this.bbs(4), - mode: 'zeroPage_relative', - }, - 0xdf: { - name: 'BBS5', - fn: () => this.bbs(5), - mode: 'zeroPage_relative', - }, - 0xef: { - name: 'BBS6', - fn: () => this.bbs(6), - mode: 'zeroPage_relative', - }, - 0xff: { - name: 'BBS7', - fn: () => this.bbs(7), - mode: 'zeroPage_relative', - }, - - // BRA - 0x80: { - name: 'BRA', - fn: () => this.brc(0), - mode: 'relative', - }, - - // NOP - 0x02: { - name: 'NOP', - fn: () => this.nop(this.readImmediate), - mode: 'immediate', - }, - 0x22: { - name: 'NOP', - fn: () => this.nop(this.readImmediate), - mode: 'immediate', - }, - 0x42: { - name: 'NOP', - fn: () => this.nop(this.readImmediate), - mode: 'immediate', - }, - 0x44: { - name: 'NOP', - fn: () => this.nop(this.readZeroPage), - mode: 'immediate', - }, - 0x54: { - name: 'NOP', - fn: () => this.nop(this.readZeroPageX), - mode: 'immediate', - }, - 0x62: { - name: 'NOP', - fn: () => this.nop(this.readImmediate), - mode: 'immediate', - }, - 0x82: { - name: 'NOP', - fn: () => this.nop(this.readImmediate), - mode: 'immediate', - }, - 0xc2: { - name: 'NOP', - fn: () => this.nop(this.readImmediate), - mode: 'immediate', - }, - 0xd4: { - name: 'NOP', - fn: () => this.nop(this.readZeroPageX), - mode: 'immediate', - }, - 0xe2: { - name: 'NOP', - fn: () => this.nop(this.readImmediate), - mode: 'immediate', - }, - 0xf4: { - name: 'NOP', - fn: () => this.nop(this.readZeroPageX), - mode: 'immediate', - }, - 0x5c: { name: 'NOP', fn: () => this.nop(this.readNop), mode: 'absolute' }, - 0xdc: { name: 'NOP', fn: () => this.nop(this.readNop), mode: 'absolute' }, - 0xfc: { name: 'NOP', fn: () => this.nop(this.readNop), mode: 'absolute' }, - - // PHX - 0xda: { name: 'PHX', fn: () => this.phx(), mode: 'implied' }, - - // PHY - 0x5a: { name: 'PHY', fn: () => this.phy(), mode: 'implied' }, - - // PLX - 0xfa: { name: 'PLX', fn: () => this.plx(), mode: 'implied' }, - - // PLY - 0x7a: { name: 'PLY', fn: () => this.ply(), mode: 'implied' }, - - // RMB/SMB - - 0x07: { name: 'RMB0', fn: () => this.rmb(0), mode: 'zeroPage' }, - 0x17: { name: 'RMB1', fn: () => this.rmb(1), mode: 'zeroPage' }, - 0x27: { name: 'RMB2', fn: () => this.rmb(2), mode: 'zeroPage' }, - 0x37: { name: 'RMB3', fn: () => this.rmb(3), mode: 'zeroPage' }, - 0x47: { name: 'RMB4', fn: () => this.rmb(4), mode: 'zeroPage' }, - 0x57: { name: 'RMB5', fn: () => this.rmb(5), mode: 'zeroPage' }, - 0x67: { name: 'RMB6', fn: () => this.rmb(6), mode: 'zeroPage' }, - 0x77: { name: 'RMB7', fn: () => this.rmb(7), mode: 'zeroPage' }, - - 0x87: { name: 'SMB0', fn: () => this.smb(0), mode: 'zeroPage' }, - 0x97: { name: 'SMB1', fn: () => this.smb(1), mode: 'zeroPage' }, - 0xa7: { name: 'SMB2', fn: () => this.smb(2), mode: 'zeroPage' }, - 0xb7: { name: 'SMB3', fn: () => this.smb(3), mode: 'zeroPage' }, - 0xc7: { name: 'SMB4', fn: () => this.smb(4), mode: 'zeroPage' }, - 0xd7: { name: 'SMB5', fn: () => this.smb(5), mode: 'zeroPage' }, - 0xe7: { name: 'SMB6', fn: () => this.smb(6), mode: 'zeroPage' }, - 0xf7: { name: 'SMB7', fn: () => this.smb(7), mode: 'zeroPage' }, - - // STZ - 0x64: { - name: 'STZ', - fn: () => this.stz(this.writeZeroPage), - mode: 'zeroPage', - }, - 0x74: { - name: 'STZ', - fn: () => this.stz(this.writeZeroPageX), - mode: 'zeroPageX', - }, - 0x9c: { - name: 'STZ', - fn: () => this.stz(this.writeAbsolute), - mode: 'absolute', - }, - 0x9e: { - name: 'STZ', - fn: () => this.stz(this.writeAbsoluteX), - mode: 'absoluteX', - }, - - // TRB - 0x14: { - name: 'TRB', - fn: () => this.trb(this.readAddrZeroPage), - mode: 'zeroPage', - }, - 0x1c: { - name: 'TRB', - fn: () => this.trb(this.readAddrAbsolute), - mode: 'absolute', - }, - - // TSB - 0x04: { - name: 'TSB', - fn: () => this.tsb(this.readAddrZeroPage), - mode: 'zeroPage', - }, - 0x0c: { - name: 'TSB', - fn: () => this.tsb(this.readAddrAbsolute), - mode: 'absolute', - }, - }; - - OPS_NMOS_6502: Instructions = { - // ASO - 0x0f: { - name: 'ASO', - fn: () => this.aso(this.readAddrAbsolute), - mode: 'absolute', - }, - 0x1f: { - name: 'ASO', - fn: () => this.aso(this.readAddrAbsoluteX), - mode: 'absoluteX', - }, - 0x1b: { - name: 'ASO', - fn: () => this.aso(this.readAddrAbsoluteY), - mode: 'absoluteY', - }, - 0x07: { - name: 'ASO', - fn: () => this.aso(this.readAddrZeroPage), - mode: 'zeroPage', - }, - 0x17: { - name: 'ASO', - fn: () => this.aso(this.readAddrZeroPageX), - mode: 'zeroPageX', - }, - 0x03: { - name: 'ASO', - fn: () => this.aso(this.readAddrZeroPageXIndirect), - mode: 'zeroPageXIndirect', - }, - 0x13: { - name: 'ASO', - fn: () => this.aso(this.readAddrZeroPageIndirectY), - mode: 'zeroPageIndirectY', - }, - - // RLA - 0x2f: { - name: 'RLA', - fn: () => this.rla(this.readAddrAbsolute), - mode: 'absolute', - }, - 0x3f: { - name: 'RLA', - fn: () => this.rla(this.readAddrAbsoluteX), - mode: 'absoluteX', - }, - 0x3b: { - name: 'RLA', - fn: () => this.rla(this.readAddrAbsoluteY), - mode: 'absoluteY', - }, - 0x27: { - name: 'RLA', - fn: () => this.rla(this.readAddrZeroPage), - mode: 'zeroPage', - }, - 0x37: { - name: 'RLA', - fn: () => this.rla(this.readAddrZeroPageX), - mode: 'zeroPageX', - }, - 0x23: { - name: 'RLA', - fn: () => this.rla(this.readAddrZeroPageXIndirect), - mode: 'zeroPageXIndirect', - }, - 0x33: { - name: 'RLA', - fn: () => this.rla(this.readAddrZeroPageIndirectY), - mode: 'zeroPageIndirectY', - }, - - // LSE - 0x4f: { - name: 'LSE', - fn: () => this.lse(this.readAddrAbsolute), - mode: 'absolute', - }, - 0x5f: { - name: 'LSE', - fn: () => this.lse(this.readAddrAbsoluteX), - mode: 'absoluteX', - }, - 0x5b: { - name: 'LSE', - fn: () => this.lse(this.readAddrAbsoluteY), - mode: 'absoluteY', - }, - 0x47: { - name: 'LSE', - fn: () => this.lse(this.readAddrZeroPage), - mode: 'zeroPage', - }, - 0x57: { - name: 'LSE', - fn: () => this.lse(this.readAddrZeroPageX), - mode: 'zeroPageX', - }, - 0x43: { - name: 'LSE', - fn: () => this.lse(this.readAddrZeroPageXIndirect), - mode: 'zeroPageXIndirect', - }, - 0x53: { - name: 'LSE', - fn: () => this.lse(this.readAddrZeroPageIndirectY), - mode: 'zeroPageIndirectY', - }, - - // RRA - 0x6f: { - name: 'RRA', - fn: () => this.rra(this.readAddrAbsolute), - mode: 'absolute', - }, - 0x7f: { - name: 'RRA', - fn: () => this.rra(this.readAddrAbsoluteX), - mode: 'absoluteX', - }, - 0x7b: { - name: 'RRA', - fn: () => this.rra(this.readAddrAbsoluteY), - mode: 'absoluteY', - }, - 0x67: { - name: 'RRA', - fn: () => this.rra(this.readAddrZeroPage), - mode: 'zeroPage', - }, - 0x77: { - name: 'RRA', - fn: () => this.rra(this.readAddrZeroPageX), - mode: 'zeroPageX', - }, - 0x63: { - name: 'RRA', - fn: () => this.rra(this.readAddrZeroPageXIndirect), - mode: 'zeroPageXIndirect', - }, - 0x73: { - name: 'RRA', - fn: () => this.rra(this.readAddrZeroPageIndirectY), - mode: 'zeroPageIndirectY', - }, - - // AXS - 0x8f: { - name: 'AXS', - fn: () => this.axs(this.writeAbsolute), - mode: 'absolute', - }, - 0x87: { - name: 'AXS', - fn: () => this.axs(this.writeZeroPage), - mode: 'zeroPage', - }, - 0x97: { - name: 'AXS', - fn: () => this.axs(this.writeZeroPageY), - mode: 'zeroPageY', - }, - 0x83: { - name: 'AXS', - fn: () => this.axs(this.writeZeroPageXIndirect), - mode: 'zeroPageXIndirect', - }, - - // LAX - 0xaf: { - name: 'LAX', - fn: () => this.lax(this.readAbsolute), - mode: 'absolute', - }, - 0xbf: { - name: 'LAX', - fn: () => this.lax(this.readAbsoluteY), - mode: 'absoluteY', - }, - 0xa7: { - name: 'LAX', - fn: () => this.lax(this.readZeroPage), - mode: 'zeroPage', - }, - 0xb7: { - name: 'LAX', - fn: () => this.lax(this.readZeroPageY), - mode: 'zeroPageY', - }, - 0xa3: { - name: 'LAX', - fn: () => this.lax(this.readZeroPageXIndirect), - mode: 'zeroPageXIndirect', - }, - 0xb3: { - name: 'LAX', - fn: () => this.lax(this.readZeroPageIndirectY), - mode: 'zeroPageIndirectY', - }, - - // DCM - 0xcf: { - name: 'DCM', - fn: () => this.dcm(this.readAddrAbsolute), - mode: 'absolute', - }, - 0xdf: { - name: 'DCM', - fn: () => this.dcm(this.readAddrAbsoluteX), - mode: 'absoluteX', - }, - 0xdb: { - name: 'DCM', - fn: () => this.dcm(this.readAddrAbsoluteY), - mode: 'absoluteY', - }, - 0xc7: { - name: 'DCM', - fn: () => this.dcm(this.readAddrZeroPage), - mode: 'zeroPage', - }, - 0xd7: { - name: 'DCM', - fn: () => this.dcm(this.readAddrZeroPageX), - mode: 'zeroPageX', - }, - 0xc3: { - name: 'DCM', - fn: () => this.dcm(this.readAddrZeroPageXIndirect), - mode: 'zeroPageXIndirect', - }, - 0xd3: { - name: 'DCM', - fn: () => this.dcm(this.readAddrZeroPageIndirectY), - mode: 'zeroPageIndirectY', - }, - - // INS - 0xef: { - name: 'INS', - fn: () => this.ins(this.readAddrAbsolute), - mode: 'absolute', - }, - 0xff: { - name: 'INS', - fn: () => this.ins(this.readAddrAbsoluteX), - mode: 'absoluteX', - }, - 0xfb: { - name: 'INS', - fn: () => this.ins(this.readAddrAbsoluteY), - mode: 'absoluteY', - }, - 0xe7: { - name: 'INS', - fn: () => this.ins(this.readAddrZeroPage), - mode: 'zeroPage', - }, - 0xf7: { - name: 'INS', - fn: () => this.ins(this.readAddrZeroPageX), - mode: 'zeroPageX', - }, - 0xe3: { - name: 'INS', - fn: () => this.ins(this.readAddrZeroPageXIndirect), - mode: 'zeroPageXIndirect', - }, - 0xf3: { - name: 'INS', - fn: () => this.ins(this.readAddrZeroPageIndirectY), - mode: 'zeroPageIndirectY', - }, - - // ALR - 0x4b: { - name: 'ALR', - fn: () => this.alr(this.readImmediate), - mode: 'immediate', - }, - - // ARR - 0x6b: { - name: 'ARR', - fn: () => this.arr(this.readImmediate), - mode: 'immediate', - }, - - // XAA - 0x8b: { - name: 'XAA', - fn: () => this.xaa(this.readImmediate), - mode: 'immediate', - }, - - // OAL - 0xab: { - name: 'OAL', - fn: () => this.oal(this.readImmediate), - mode: 'immediate', - }, - - // SAX - 0xcb: { - name: 'SAX', - fn: () => this.sax(this.readImmediate), - mode: 'immediate', - }, - - // NOP - 0x1a: { name: 'NOP', fn: () => this.nop(this.implied), mode: 'implied' }, - 0x3a: { name: 'NOP', fn: () => this.nop(this.implied), mode: 'implied' }, - 0x5a: { name: 'NOP', fn: () => this.nop(this.implied), mode: 'implied' }, - 0x7a: { name: 'NOP', fn: () => this.nop(this.implied), mode: 'implied' }, - 0xda: { name: 'NOP', fn: () => this.nop(this.implied), mode: 'implied' }, - 0xfa: { name: 'NOP', fn: () => this.nop(this.implied), mode: 'implied' }, - - // SKB - 0x80: { - name: 'SKB', - fn: () => this.skp(this.readImmediate), - mode: 'immediate', - }, - 0x82: { - name: 'SKB', - fn: () => this.skp(this.readImmediate), - mode: 'immediate', - }, - 0x89: { - name: 'SKB', - fn: () => this.skp(this.readImmediate), - mode: 'immediate', - }, - 0xc2: { - name: 'SKB', - fn: () => this.skp(this.readImmediate), - mode: 'immediate', - }, - 0xe2: { - name: 'SKB', - fn: () => this.skp(this.readImmediate), - mode: 'immediate', - }, - 0x04: { - name: 'SKB', - fn: () => this.skp(this.readZeroPage), - mode: 'zeroPage', - }, - 0x14: { - name: 'SKB', - fn: () => this.skp(this.readZeroPageX), - mode: 'zeroPageX', - }, - 0x34: { - name: 'SKB', - fn: () => this.skp(this.readZeroPageX), - mode: 'zeroPageX', - }, - 0x44: { - name: 'SKB', - fn: () => this.skp(this.readZeroPage), - mode: 'zeroPage', - }, - 0x54: { - name: 'SKB', - fn: () => this.skp(this.readZeroPageX), - mode: 'zeroPageX', - }, - 0x64: { - name: 'SKB', - fn: () => this.skp(this.readZeroPage), - mode: 'zeroPage', - }, - 0x74: { - name: 'SKB', - fn: () => this.skp(this.readZeroPageX), - mode: 'zeroPageX', - }, - 0xd4: { - name: 'SKB', - fn: () => this.skp(this.readZeroPageX), - mode: 'zeroPageX', - }, - 0xf4: { - name: 'SKB', - fn: () => this.skp(this.readZeroPageX), - mode: 'zeroPageX', - }, - - // SKW - 0x0c: { - name: 'SKW', - fn: () => this.skp(this.readAddrAbsolute), - mode: 'absolute', - }, - 0x1c: { - name: 'SKW', - fn: () => this.skp(this.readAddrAbsoluteX), - mode: 'absoluteX', - }, - 0x3c: { - name: 'SKW', - fn: () => this.skp(this.readAddrAbsoluteX), - mode: 'absoluteX', - }, - 0x5c: { - name: 'SKW', - fn: () => this.skp(this.readAddrAbsoluteX), - mode: 'absoluteX', - }, - 0x7c: { - name: 'SKW', - fn: () => this.skp(this.readAddrAbsoluteX), - mode: 'absoluteX', - }, - 0xdc: { - name: 'SKW', - fn: () => this.skp(this.readAddrAbsoluteX), - mode: 'absoluteX', - }, - 0xfc: { - name: 'SKW', - fn: () => this.skp(this.readAddrAbsoluteX), - mode: 'absoluteX', - }, - - // HLT - 0x02: { - name: 'HLT', - fn: () => this.hlt(this.readNopImplied), - mode: 'implied', - }, - 0x12: { - name: 'HLT', - fn: () => this.hlt(this.readNopImplied), - mode: 'implied', - }, - 0x22: { - name: 'HLT', - fn: () => this.hlt(this.readNopImplied), - mode: 'implied', - }, - 0x32: { - name: 'HLT', - fn: () => this.hlt(this.readNopImplied), - mode: 'implied', - }, - 0x42: { - name: 'HLT', - fn: () => this.hlt(this.readNopImplied), - mode: 'implied', - }, - 0x52: { - name: 'HLT', - fn: () => this.hlt(this.readNopImplied), - mode: 'implied', - }, - 0x62: { - name: 'HLT', - fn: () => this.hlt(this.readNopImplied), - mode: 'implied', - }, - 0x72: { - name: 'HLT', - fn: () => this.hlt(this.readNopImplied), - mode: 'implied', - }, - 0x92: { - name: 'HLT', - fn: () => this.hlt(this.readNopImplied), - mode: 'implied', - }, - 0xb2: { - name: 'HLT', - fn: () => this.hlt(this.readNopImplied), - mode: 'implied', - }, - 0xd2: { - name: 'HLT', - fn: () => this.hlt(this.readNopImplied), - mode: 'implied', - }, - 0xf2: { - name: 'HLT', - fn: () => this.hlt(this.readNopImplied), - mode: 'implied', - }, - - // TAS - 0x9b: { - name: 'TAS', - fn: () => this.tas(this.readAddrAbsoluteY), - mode: 'absoluteY', - }, - - // SAY - 0x9c: { - name: 'SAY', - fn: () => this.say(this.readAddrAbsoluteX), - mode: 'absoluteX', - }, - - // XAS - 0x9e: { - name: 'XAS', - fn: () => this.xas(this.readAddrAbsoluteY), - mode: 'absoluteY', - }, - - // AXA - 0x9f: { - name: 'AXA', - fn: () => this.axa(this.readAddrAbsoluteY), - mode: 'absoluteY', - }, - 0x93: { - name: 'AXA', - fn: () => this.axa(this.readAddrZeroPageIndirectY), - mode: 'zeroPageIndirectY', - }, - - // ANC - 0x2b: { - name: 'ANC', - fn: () => this.anc(this.readImmediate), - mode: 'immediate', - }, - 0x0b: { - name: 'ANC', - fn: () => this.anc(this.readImmediate), - mode: 'immediate', - }, - - // LAS - 0xbb: { - name: 'LAS', - fn: () => this.las(this.readAbsoluteY), - mode: 'absoluteY', - }, - - // SBC - 0xeb: { - name: 'SBC', - fn: () => this.sbc(this.readImmediate), - mode: 'immediate', - }, - }; - - OPS_ROCKWELL_65C02: Instructions = { - 0xcb: { name: 'NOP', fn: () => this.nop(this.implied), mode: 'implied' }, - 0xdb: { - name: 'NOP', - fn: () => this.nop(this.readZeroPageX), - mode: 'immediate', - }, - }; - - /* WDC 65C02 Instructions */ - - OPS_WDC_65C02: Instructions = { - 0xcb: { name: 'WAI', fn: () => this.wai(), mode: 'implied' }, - 0xdb: { name: 'STP', fn: () => this.stp(), mode: 'implied' }, - }; -} diff --git a/js/ram.ts b/js/ram.ts index 135dec2..b3ba3ac 100644 --- a/js/ram.ts +++ b/js/ram.ts @@ -11,7 +11,7 @@ import { base64_decode, base64_encode } from './base64'; import { allocMemPages } from './util'; -import type { byte } from './types'; +import type { byte, memory } from '@whscullin/cpu6502'; export interface RAMState { start: byte; @@ -20,7 +20,7 @@ export interface RAMState { } export default class RAM { - mem: Uint8Array | byte[]; + mem: memory; constructor( private start_page: byte, diff --git a/js/roms/basic.ts b/js/roms/basic.ts index b33ba68..b518943 100644 --- a/js/roms/basic.ts +++ b/js/roms/basic.ts @@ -1,4 +1,4 @@ -import { byte } from 'js/types'; +import { byte } from '@whscullin/cpu6502'; export default class Basic { ram = [ diff --git a/js/roms/bios.ts b/js/roms/bios.ts index 2b288bc..f5d41f5 100644 --- a/js/roms/bios.ts +++ b/js/roms/bios.ts @@ -1,4 +1,4 @@ -import { byte } from 'js/types'; +import { byte } from '@whscullin/cpu6502'; export default class Bios { rom = [ diff --git a/js/roms/enhanced-basic.ts b/js/roms/enhanced-basic.ts index e659777..76f4c57 100644 --- a/js/roms/enhanced-basic.ts +++ b/js/roms/enhanced-basic.ts @@ -1,4 +1,4 @@ -import { byte } from 'js/types'; +import { byte } from '@whscullin/cpu6502'; export default class EnhancedBasic { rom = [ diff --git a/js/roms/krusader.ts b/js/roms/krusader.ts index 71e980d..bfecab6 100644 --- a/js/roms/krusader.ts +++ b/js/roms/krusader.ts @@ -1,4 +1,4 @@ -import { byte } from 'js/types'; +import { byte } from '@whscullin/cpu6502'; export default class Krusader { rom = [ diff --git a/js/symbols.ts b/js/symbols.ts index 9ea4946..974731a 100644 --- a/js/symbols.ts +++ b/js/symbols.ts @@ -9,9 +9,9 @@ * implied warranty. */ -import type { address } from './types'; +import type { word } from '@whscullin/cpu6502'; -export const SYMBOLS: Record = { +export const SYMBOLS: Record = { 0xd010: 'KBD', 0xd011: 'KBDCR', 0xd012: 'DSP', diff --git a/js/types.ts b/js/types.ts deleted file mode 100644 index 33f2818..0000000 --- a/js/types.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* Copyright 2023 Will Scullin - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation. No representations are made about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - */ - -export type byte = number; - -export type word = number; - -export type address = word; - -export type memory = Uint8Array | byte[]; - -export interface Memory { - /** Read a byte. */ - read(page: byte, offset: byte): byte; - /** Write a byte. */ - write(page: byte, offset: byte, value: byte): void; -} - -/** A mapped region of memory. */ -export interface MemoryPages extends Memory { - /** Start page. */ - start(): byte; - /** End page, inclusive. */ - end(): byte; -} - -/** - * Extracts the members of a constant array as a type. Used as: - * - * @example - * const SOME_VALUES = ['a', 'b', 1, 2] as const; - * type SomeValues = MemberOf; // 'a' | 'b' | 1 | 2 - */ -export type MemberOf> = - T extends ReadonlyArray ? E : never; diff --git a/js/ui/keyboard.ts b/js/ui/keyboard.ts index bea39d8..f8f7742 100644 --- a/js/ui/keyboard.ts +++ b/js/ui/keyboard.ts @@ -9,11 +9,10 @@ * implied warranty. */ -import CPU6502 from 'js/cpu6502'; +import { CPU6502, byte } from '@whscullin/cpu6502'; import { debug, toHex } from '../util'; import Apple1IO from 'js/apple1io'; import { TextPage } from 'js/canvas1'; -import { byte } from 'js/types'; // keycode: [plain, cntl, shift] diff --git a/js/util.ts b/js/util.ts index 0d48914..82518a3 100644 --- a/js/util.ts +++ b/js/util.ts @@ -9,12 +9,12 @@ * implied warranty. */ -import { byte, word } from './types'; +import { byte, word } from '@whscullin/cpu6502'; const hex_digits = '0123456789ABCDEF'; const bin_digits = '01'; -export function allocMem(size: word) { +export function allocMem(size: word): Uint8Array | byte[] { let result; if (window.Uint8Array) { result = new Uint8Array(size); diff --git a/package-lock.json b/package-lock.json index fa3a028..00c24ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.1", "license": "MIT", "dependencies": { + "@whscullin/cpu6502": "file:submodules/cpu6502", "micromodal": "^0.4.9" }, "devDependencies": { @@ -33,6 +34,15 @@ "webpack-dev-server": "^4.6.0" } }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.16.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.0.tgz", @@ -1242,23 +1252,26 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.4.tgz", - "integrity": "sha512-h8Vx6MdxwWI2WM8/zREHMoqdgLNXEL4QX3MWSVMdyNJGvXVOs+6lp+m2hc3FnuMHDc4poxFNI20vCk0OmI4G0Q==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.0.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/@eslint/eslintrc/node_modules/argparse": { @@ -1268,9 +1281,9 @@ "dev": true }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", - "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -1306,24 +1319,46 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@eslint/js": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", + "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/@humanwhocodes/config-array": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz", - "integrity": "sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.0", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, "node_modules/@istanbuljs/load-nyc-config": { @@ -2460,21 +2495,20 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.2.1.tgz", - "integrity": "sha512-iZVM/ALid9kO0+I81pnp1xmYiFyqibAHzrqX4q5YvvVEyJqY+e6rfTXSCsc2jUxGNqJqTfFSSij/NFkZBiBzLw==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.12.0.tgz", + "integrity": "sha512-XOpZ3IyJUIV1b15M7HVOpgQxPPF7lGXgsfcEIu3yDxFPaf/xZKt7s9QO/pbk7vpWQyVulpJbu4E5LwpZiQo4kA==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.2.1", - "@typescript-eslint/type-utils": "6.2.1", - "@typescript-eslint/utils": "6.2.1", - "@typescript-eslint/visitor-keys": "6.2.1", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/type-utils": "6.12.0", + "@typescript-eslint/utils": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", "natural-compare": "^1.4.0", - "natural-compare-lite": "^1.4.0", "semver": "^7.5.4", "ts-api-utils": "^1.0.1" }, @@ -2496,13 +2530,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.2.1.tgz", - "integrity": "sha512-UCqBF9WFqv64xNsIEPfBtenbfodPXsJ3nPAr55mGPkQIkiQvgoWNo+astj9ZUfJfVKiYgAZDMnM6dIpsxUMp3Q==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", + "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.2.1", - "@typescript-eslint/visitor-keys": "6.2.1" + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2513,9 +2547,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.2.1.tgz", - "integrity": "sha512-528bGcoelrpw+sETlyM91k51Arl2ajbNT9L4JwoXE2dvRe1yd8Q64E4OL7vHYw31mlnVsf+BeeLyAZUEQtqahQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", + "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2526,13 +2560,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.2.1.tgz", - "integrity": "sha512-G+UJeQx9AKBHRQBpmvr8T/3K5bJa485eu+4tQBxFq0KoT22+jJyzo1B50JDT9QdC1DEmWQfdKsa8ybiNWYsi0Q==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", + "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.2.1", - "@typescript-eslint/visitor-keys": "6.2.1", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2553,17 +2587,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.2.1.tgz", - "integrity": "sha512-eBIXQeupYmxVB6S7x+B9SdBeB6qIdXKjgQBge2J+Ouv8h9Cxm5dHf/gfAZA6dkMaag+03HdbVInuXMmqFB/lKQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", + "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.2.1", - "@typescript-eslint/types": "6.2.1", - "@typescript-eslint/typescript-estree": "6.2.1", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", "semver": "^7.5.4" }, "engines": { @@ -2578,12 +2612,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.2.1.tgz", - "integrity": "sha512-iTN6w3k2JEZ7cyVdZJTVJx2Lv7t6zFA8DCrJEHD2mwfc16AEvvBWVhbFh34XyG2NORCd0viIgQY1+u7kPI0WpA==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", + "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.2.1", + "@typescript-eslint/types": "6.12.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -2594,15 +2628,6 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -2759,13 +2784,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.2.1.tgz", - "integrity": "sha512-fTfCgomBMIgu2Dh2Or3gMYgoNAnQm3RLtRp+jP7A8fY+LJ2+9PNpi5p6QB5C4RSP+U3cjI0vDlI3mspAkpPVbQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.12.0.tgz", + "integrity": "sha512-WWmRXxhm1X8Wlquj+MhsAG4dU/Blvf1xDgGaYCzfvStP2NwPQh6KBvCDbiOEvaE0filhranjIlK/2fSTVwtBng==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.2.1", - "@typescript-eslint/utils": "6.2.1", + "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/utils": "6.12.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -2786,13 +2811,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.2.1.tgz", - "integrity": "sha512-UCqBF9WFqv64xNsIEPfBtenbfodPXsJ3nPAr55mGPkQIkiQvgoWNo+astj9ZUfJfVKiYgAZDMnM6dIpsxUMp3Q==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", + "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.2.1", - "@typescript-eslint/visitor-keys": "6.2.1" + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2803,9 +2828,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.2.1.tgz", - "integrity": "sha512-528bGcoelrpw+sETlyM91k51Arl2ajbNT9L4JwoXE2dvRe1yd8Q64E4OL7vHYw31mlnVsf+BeeLyAZUEQtqahQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", + "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2816,13 +2841,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.2.1.tgz", - "integrity": "sha512-G+UJeQx9AKBHRQBpmvr8T/3K5bJa485eu+4tQBxFq0KoT22+jJyzo1B50JDT9QdC1DEmWQfdKsa8ybiNWYsi0Q==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", + "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.2.1", - "@typescript-eslint/visitor-keys": "6.2.1", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2843,17 +2868,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.2.1.tgz", - "integrity": "sha512-eBIXQeupYmxVB6S7x+B9SdBeB6qIdXKjgQBge2J+Ouv8h9Cxm5dHf/gfAZA6dkMaag+03HdbVInuXMmqFB/lKQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", + "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.2.1", - "@typescript-eslint/types": "6.2.1", - "@typescript-eslint/typescript-estree": "6.2.1", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", "semver": "^7.5.4" }, "engines": { @@ -2868,12 +2893,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.2.1.tgz", - "integrity": "sha512-iTN6w3k2JEZ7cyVdZJTVJx2Lv7t6zFA8DCrJEHD2mwfc16AEvvBWVhbFh34XyG2NORCd0viIgQY1+u7kPI0WpA==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", + "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.2.1", + "@typescript-eslint/types": "6.12.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -3025,6 +3050,12 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "node_modules/@webassemblyjs/ast": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", @@ -3207,6 +3238,10 @@ } } }, + "node_modules/@whscullin/cpu6502": { + "resolved": "submodules/cpu6502", + "link": true + }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -3339,15 +3374,6 @@ "ajv": "^6.9.1" } }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -3384,6 +3410,12 @@ "node": ">=8" } }, + "node_modules/ansi-sequence-parser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", + "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==", + "dev": true + }, "node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -4248,9 +4280,9 @@ } }, "node_modules/deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, "node_modules/deepmerge": { @@ -4542,18 +4574,6 @@ "node": ">=10.13.0" } }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" - } - }, "node_modules/envinfo": { "version": "7.8.1", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", @@ -4606,49 +4626,49 @@ } }, "node_modules/eslint": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.3.0.tgz", - "integrity": "sha512-aIay56Ph6RxOTC7xyr59Kt3ewX185SaGnAr8eWukoPLeriCrvGjvAubxuvaXOfsxhtwV5g0uBOsyhAom4qJdww==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", + "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.0.4", - "@humanwhocodes/config-array": "^0.6.0", - "ajv": "^6.10.0", + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.54.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", - "enquirer": "^2.3.5", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.0", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.1.0", - "espree": "^9.1.0", - "esquery": "^1.4.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.2.0", - "semver": "^7.2.1", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "text-table": "^0.2.0" }, "bin": { "eslint": "bin/eslint.js" @@ -4727,9 +4747,9 @@ } }, "node_modules/eslint-scope": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", - "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -4737,6 +4757,9 @@ }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-scope/node_modules/estraverse": { @@ -4748,37 +4771,10 @@ "node": ">=4.0" } }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/eslint-visitor-keys": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.2.tgz", - "integrity": "sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -4854,6 +4850,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eslint/node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -4867,9 +4879,9 @@ } }, "node_modules/eslint/node_modules/globals": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", - "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -4902,58 +4914,49 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/eslint/node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint/node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint/node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "p-locate": "^5.0.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint/node_modules/supports-color": { @@ -4968,18 +4971,6 @@ "node": ">=8" } }, - "node_modules/eslint/node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/eslint/node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -4993,17 +4984,20 @@ } }, "node_modules/espree": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.1.0.tgz", - "integrity": "sha512-ZgYLvCS1wxOczBYGcQT9DDWgicXwJ4dbocr9uYN+/eresBAUuBu+O4WzB21ufQ/JqQT8gyp7hJ3z8SHii32mTQ==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "dependencies": { - "acorn": "^8.6.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.1.0" + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/esprima": { @@ -5020,9 +5014,9 @@ } }, "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -5338,7 +5332,7 @@ "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, "node_modules/fastest-levenshtein": { @@ -5545,12 +5539,6 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -5668,15 +5656,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globby/node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -5850,9 +5829,9 @@ } }, "node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", "dev": true, "engines": { "node": ">= 4" @@ -8057,6 +8036,12 @@ "node": ">=6" } }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -8084,6 +8069,19 @@ "node": ">=6" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -8153,6 +8151,12 @@ "node": ">=10" } }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -8198,6 +8202,18 @@ "tmpl": "1.0.5" } }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -8379,12 +8395,6 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -8643,6 +8653,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -8857,6 +8884,15 @@ "ms": "^2.1.1" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/prettier": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.2.tgz", @@ -8926,15 +8962,6 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -9229,18 +9256,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, "node_modules/regexpu-core": { "version": "4.5.5", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.5.tgz", @@ -9723,6 +9738,18 @@ "node": ">=8" } }, + "node_modules/shiki": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.5.tgz", + "integrity": "sha512-1gCAYOcmCFONmErGTrS1fjzJLA7MGZmKzrBNX7apqSwhyITJg2O102uFzXUeBxNnEkDA9vHIKLyeKq0V083vIw==", + "dev": true, + "dependencies": { + "ansi-sequence-parser": "^1.1.0", + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" + } + }, "node_modules/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -10527,6 +10554,18 @@ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -10561,6 +10600,51 @@ "node": ">= 0.6" } }, + "node_modules/typedoc": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.3.tgz", + "integrity": "sha512-Ow8Bo7uY1Lwy7GTmphRIMEo6IOZ+yYUyrc8n5KXIZg1svpqhZSWgni2ZrDhe+wLosFS8yswowUzljTAV/3jmWw==", + "dev": true, + "dependencies": { + "lunr": "^2.3.9", + "marked": "^4.3.0", + "minimatch": "^9.0.3", + "shiki": "^0.14.1" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 16" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x" + } + }, + "node_modules/typedoc/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/typescript": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", @@ -10666,12 +10750,6 @@ "uuid": "bin/uuid" } }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, "node_modules/v8-to-istanbul": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", @@ -10695,6 +10773,18 @@ "node": ">= 0.8" } }, + "node_modules/vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true + }, + "node_modules/vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "dev": true + }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -11180,15 +11270,6 @@ "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", "dev": true }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -11311,9 +11392,33 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "submodules/cpu6502": { + "name": "@whscullin/cpu6502", + "version": "0.0.1", + "hasInstallScript": true, + "license": "MIT", + "devDependencies": { + "@types/jest": "^29.5.3", + "@typescript-eslint/eslint-plugin": "^6.4.0", + "eslint": "^8.47.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-jest": "^27.2.3", + "eslint-plugin-prettier": "^5.0.0", + "jest": "^29.6.2", + "ts-jest": "^29.1.1", + "typedoc": "^0.25.1", + "typescript": "^5.1.6" + } } }, "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, "@babel/code-frame": { "version": "7.16.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.0.tgz", @@ -12253,19 +12358,19 @@ "dev": true }, "@eslint/eslintrc": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.4.tgz", - "integrity": "sha512-h8Vx6MdxwWI2WM8/zREHMoqdgLNXEL4QX3MWSVMdyNJGvXVOs+6lp+m2hc3FnuMHDc4poxFNI20vCk0OmI4G0Q==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.0.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, "dependencies": { @@ -12276,9 +12381,9 @@ "dev": true }, "globals": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", - "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -12301,21 +12406,33 @@ } } }, + "@eslint/js": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", + "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", + "dev": true + }, "@humanwhocodes/config-array": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz", - "integrity": "sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, "requires": { - "@humanwhocodes/object-schema": "^1.2.0", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5" } }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, "@istanbuljs/load-nyc-config": { @@ -13258,49 +13375,48 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.2.1.tgz", - "integrity": "sha512-iZVM/ALid9kO0+I81pnp1xmYiFyqibAHzrqX4q5YvvVEyJqY+e6rfTXSCsc2jUxGNqJqTfFSSij/NFkZBiBzLw==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.12.0.tgz", + "integrity": "sha512-XOpZ3IyJUIV1b15M7HVOpgQxPPF7lGXgsfcEIu3yDxFPaf/xZKt7s9QO/pbk7vpWQyVulpJbu4E5LwpZiQo4kA==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.2.1", - "@typescript-eslint/type-utils": "6.2.1", - "@typescript-eslint/utils": "6.2.1", - "@typescript-eslint/visitor-keys": "6.2.1", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/type-utils": "6.12.0", + "@typescript-eslint/utils": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", "natural-compare": "^1.4.0", - "natural-compare-lite": "^1.4.0", "semver": "^7.5.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.2.1.tgz", - "integrity": "sha512-UCqBF9WFqv64xNsIEPfBtenbfodPXsJ3nPAr55mGPkQIkiQvgoWNo+astj9ZUfJfVKiYgAZDMnM6dIpsxUMp3Q==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", + "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.2.1", - "@typescript-eslint/visitor-keys": "6.2.1" + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0" } }, "@typescript-eslint/types": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.2.1.tgz", - "integrity": "sha512-528bGcoelrpw+sETlyM91k51Arl2ajbNT9L4JwoXE2dvRe1yd8Q64E4OL7vHYw31mlnVsf+BeeLyAZUEQtqahQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", + "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.2.1.tgz", - "integrity": "sha512-G+UJeQx9AKBHRQBpmvr8T/3K5bJa485eu+4tQBxFq0KoT22+jJyzo1B50JDT9QdC1DEmWQfdKsa8ybiNWYsi0Q==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", + "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.2.1", - "@typescript-eslint/visitor-keys": "6.2.1", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -13309,36 +13425,30 @@ } }, "@typescript-eslint/utils": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.2.1.tgz", - "integrity": "sha512-eBIXQeupYmxVB6S7x+B9SdBeB6qIdXKjgQBge2J+Ouv8h9Cxm5dHf/gfAZA6dkMaag+03HdbVInuXMmqFB/lKQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", + "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.2.1", - "@typescript-eslint/types": "6.2.1", - "@typescript-eslint/typescript-estree": "6.2.1", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.2.1.tgz", - "integrity": "sha512-iTN6w3k2JEZ7cyVdZJTVJx2Lv7t6zFA8DCrJEHD2mwfc16AEvvBWVhbFh34XyG2NORCd0viIgQY1+u7kPI0WpA==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", + "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.2.1", + "@typescript-eslint/types": "6.12.0", "eslint-visitor-keys": "^3.4.1" } }, - "ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true - }, "semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -13432,41 +13542,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.2.1.tgz", - "integrity": "sha512-fTfCgomBMIgu2Dh2Or3gMYgoNAnQm3RLtRp+jP7A8fY+LJ2+9PNpi5p6QB5C4RSP+U3cjI0vDlI3mspAkpPVbQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.12.0.tgz", + "integrity": "sha512-WWmRXxhm1X8Wlquj+MhsAG4dU/Blvf1xDgGaYCzfvStP2NwPQh6KBvCDbiOEvaE0filhranjIlK/2fSTVwtBng==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.2.1", - "@typescript-eslint/utils": "6.2.1", + "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/utils": "6.12.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.2.1.tgz", - "integrity": "sha512-UCqBF9WFqv64xNsIEPfBtenbfodPXsJ3nPAr55mGPkQIkiQvgoWNo+astj9ZUfJfVKiYgAZDMnM6dIpsxUMp3Q==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", + "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.2.1", - "@typescript-eslint/visitor-keys": "6.2.1" + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0" } }, "@typescript-eslint/types": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.2.1.tgz", - "integrity": "sha512-528bGcoelrpw+sETlyM91k51Arl2ajbNT9L4JwoXE2dvRe1yd8Q64E4OL7vHYw31mlnVsf+BeeLyAZUEQtqahQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", + "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.2.1.tgz", - "integrity": "sha512-G+UJeQx9AKBHRQBpmvr8T/3K5bJa485eu+4tQBxFq0KoT22+jJyzo1B50JDT9QdC1DEmWQfdKsa8ybiNWYsi0Q==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", + "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.2.1", - "@typescript-eslint/visitor-keys": "6.2.1", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -13475,27 +13585,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.2.1.tgz", - "integrity": "sha512-eBIXQeupYmxVB6S7x+B9SdBeB6qIdXKjgQBge2J+Ouv8h9Cxm5dHf/gfAZA6dkMaag+03HdbVInuXMmqFB/lKQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", + "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.2.1", - "@typescript-eslint/types": "6.2.1", - "@typescript-eslint/typescript-estree": "6.2.1", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.2.1.tgz", - "integrity": "sha512-iTN6w3k2JEZ7cyVdZJTVJx2Lv7t6zFA8DCrJEHD2mwfc16AEvvBWVhbFh34XyG2NORCd0viIgQY1+u7kPI0WpA==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", + "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.2.1", + "@typescript-eslint/types": "6.12.0", "eslint-visitor-keys": "^3.4.1" } }, @@ -13589,6 +13699,12 @@ "eslint-visitor-keys": "^3.3.0" } }, + "@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "@webassemblyjs/ast": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", @@ -13758,6 +13874,21 @@ "dev": true, "requires": {} }, + "@whscullin/cpu6502": { + "version": "file:submodules/cpu6502", + "requires": { + "@types/jest": "^29.5.3", + "@typescript-eslint/eslint-plugin": "^6.4.0", + "eslint": "^8.47.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-jest": "^27.2.3", + "eslint-plugin-prettier": "^5.0.0", + "jest": "^29.6.2", + "ts-jest": "^29.1.1", + "typedoc": "^0.25.1", + "typescript": "^5.1.6" + } + }, "@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -13858,12 +13989,6 @@ "dev": true, "requires": {} }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, "ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -13885,6 +14010,12 @@ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, + "ansi-sequence-parser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", + "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==", + "dev": true + }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -14550,9 +14681,9 @@ } }, "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, "deepmerge": { @@ -14770,15 +14901,6 @@ "tapable": "^2.2.0" } }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - } - }, "envinfo": { "version": "7.8.1", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", @@ -14819,49 +14941,49 @@ "dev": true }, "eslint": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.3.0.tgz", - "integrity": "sha512-aIay56Ph6RxOTC7xyr59Kt3ewX185SaGnAr8eWukoPLeriCrvGjvAubxuvaXOfsxhtwV5g0uBOsyhAom4qJdww==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", + "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", "dev": true, "requires": { - "@eslint/eslintrc": "^1.0.4", - "@humanwhocodes/config-array": "^0.6.0", - "ajv": "^6.10.0", + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.54.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", - "enquirer": "^2.3.5", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.0", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.1.0", - "espree": "^9.1.0", - "esquery": "^1.4.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.2.0", - "semver": "^7.2.1", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "text-table": "^0.2.0" }, "dependencies": { "ansi-styles": { @@ -14910,6 +15032,16 @@ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, "glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -14920,9 +15052,9 @@ } }, "globals": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", - "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -14943,43 +15075,31 @@ "argparse": "^2.0.1" } }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" + "p-locate": "^5.0.0" } }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "yocto-queue": "^0.1.0" } }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "p-limit": "^3.0.2" } }, "supports-color": { @@ -14991,15 +15111,6 @@ "has-flag": "^4.0.0" } }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, "type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -15035,9 +15146,9 @@ } }, "eslint-scope": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", - "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "requires": { "esrecurse": "^4.3.0", @@ -15052,38 +15163,21 @@ } } }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, "eslint-visitor-keys": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.2.tgz", - "integrity": "sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true }, "espree": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.1.0.tgz", - "integrity": "sha512-ZgYLvCS1wxOczBYGcQT9DDWgicXwJ4dbocr9uYN+/eresBAUuBu+O4WzB21ufQ/JqQT8gyp7hJ3z8SHii32mTQ==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "requires": { - "acorn": "^8.6.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.1.0" + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" } }, "esprima": { @@ -15093,9 +15187,9 @@ "dev": true }, "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "requires": { "estraverse": "^5.1.0" @@ -15336,7 +15430,7 @@ "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, "fastest-levenshtein": { @@ -15497,12 +15591,6 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -15585,14 +15673,6 @@ "ignore": "^5.2.0", "merge2": "^1.4.1", "slash": "^3.0.0" - }, - "dependencies": { - "ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true - } } }, "graceful-fs": { @@ -15737,9 +15817,9 @@ } }, "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", "dev": true }, "import-fresh": { @@ -17353,6 +17433,12 @@ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true }, + "jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -17371,6 +17457,16 @@ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, "lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -17428,6 +17524,12 @@ "yallist": "^4.0.0" } }, + "lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, "make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -17463,6 +17565,12 @@ "tmpl": "1.0.5" } }, + "marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -17602,12 +17710,6 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, - "natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, "negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -17792,6 +17894,20 @@ "is-wsl": "^2.2.0" } }, + "optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + } + }, "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -17947,6 +18063,12 @@ } } }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, "prettier": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.2.tgz", @@ -17994,12 +18116,6 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, "prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -18208,12 +18324,6 @@ } } }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, "regexpu-core": { "version": "4.5.5", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.5.tgz", @@ -18590,6 +18700,18 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "shiki": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.5.tgz", + "integrity": "sha512-1gCAYOcmCFONmErGTrS1fjzJLA7MGZmKzrBNX7apqSwhyITJg2O102uFzXUeBxNnEkDA9vHIKLyeKq0V083vIw==", + "dev": true, + "requires": { + "ansi-sequence-parser": "^1.1.0", + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" + } + }, "side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -19165,6 +19287,15 @@ "tslib": "^1.8.1" } }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -19187,6 +19318,38 @@ "mime-types": "~2.1.24" } }, + "typedoc": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.3.tgz", + "integrity": "sha512-Ow8Bo7uY1Lwy7GTmphRIMEo6IOZ+yYUyrc8n5KXIZg1svpqhZSWgni2ZrDhe+wLosFS8yswowUzljTAV/3jmWw==", + "dev": true, + "requires": { + "lunr": "^2.3.9", + "marked": "^4.3.0", + "minimatch": "^9.0.3", + "shiki": "^0.14.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "typescript": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", @@ -19260,12 +19423,6 @@ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "dev": true }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, "v8-to-istanbul": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", @@ -19283,6 +19440,18 @@ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", "dev": true }, + "vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true + }, + "vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "dev": true + }, "walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -19618,12 +19787,6 @@ "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", "dev": true }, - "word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true - }, "wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", diff --git a/package.json b/package.json index bac79ee..8d2af44 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "webpack-dev-server": "^4.6.0" }, "dependencies": { + "@whscullin/cpu6502": "file:submodules/cpu6502", "micromodal": "^0.4.9" } } diff --git a/submodules/cpu6502 b/submodules/cpu6502 new file mode 160000 index 0000000..208e761 --- /dev/null +++ b/submodules/cpu6502 @@ -0,0 +1 @@ +Subproject commit 208e761911a0088a5bafbdbc2c82de8110a92992 diff --git a/test/cpu.spec.ts b/test/cpu.spec.ts deleted file mode 100644 index c4db763..0000000 --- a/test/cpu.spec.ts +++ /dev/null @@ -1,48 +0,0 @@ -import CPU6502, { FLAVOR_ROCKWELL_65C02 } from '../js/cpu6502'; -// From https://github.com/Klaus2m5/6502_65C02_functional_tests -import Test6502 from './roms/6502test'; -import Test65C02 from './roms/65C02test'; - -import { toHex } from '../js/util'; - -describe('CPU', function () { - let cpu: CPU6502; - let lastPC = 0; - let done = false; - - function traceCB() { - const pc = cpu.getPC(); - done = lastPC === pc; - lastPC = pc; - } - - describe('6502', function () { - it('completes the test ROM', function () { - cpu = new CPU6502(); - const test = new Test6502(); - cpu.addPageHandler(test); - cpu.setPC(0x400); - - do { - cpu.stepCyclesDebug(1000, traceCB); - } while (!done); - - expect(toHex(lastPC)).toEqual(toHex(0x3469)); - }); - }); - - describe('65C02', function () { - it('completes the test ROM', function () { - cpu = new CPU6502({ flavor: FLAVOR_ROCKWELL_65C02 }); - const test = new Test65C02(); - cpu.addPageHandler(test); - cpu.setPC(0x400); - - do { - cpu.stepCyclesDebug(1000, traceCB); - } while (!done); - - expect(toHex(lastPC)).toEqual(toHex(0x24f1)); - }); - }); -}); diff --git a/test/cpu6502.spec.ts b/test/cpu6502.spec.ts deleted file mode 100644 index 5dd0046..0000000 --- a/test/cpu6502.spec.ts +++ /dev/null @@ -1,3254 +0,0 @@ -import CPU6502, { CpuState, FLAVOR_ROCKWELL_65C02, flags } from '../js/cpu6502'; -import { TestMemory } from './util/memory'; -import { bios, Program } from './util/bios'; -import { toReadableState } from './util/cpu'; - -const DEFAULT_STATE: CpuState = { - cycles: 0, - s: flags.X, - sp: 0xff, - a: 0x00, - x: 0x00, - y: 0x00, - pc: 0x0400, -}; - -let memory; -let cpu: CPU6502; -let program; - -function initState(initialState: Partial) { - const state = { ...DEFAULT_STATE, ...initialState }; - cpu.setState(state); -} - -function expectState(initialState: CpuState, expectedState: Partial) { - const state = { ...initialState, ...expectedState }; - expect(toReadableState(cpu.getState())).toEqual(toReadableState(state)); -} - -function initMemory(memAry: [page: number, off: number, data: number[]][]) { - for (let idx = 0; idx < memAry.length; idx++) { - const mem = memAry[idx]; - let page = mem[0]; - let off = mem[1]; - const data = mem[2]; - for (let jdx = 0; jdx < data.length; jdx++) { - cpu.write(page, off++, data[jdx]); - if (off > 0xff) { - page++; - off = 0; - } - } - } -} - -function expectMemory( - expectAry: [page: number, off: number, data: number[]][] -) { - const memAry = []; - for (let idx = 0; idx < expectAry.length; idx++) { - const mem = expectAry[idx]; - let page = mem[0]; - let off = mem[1]; - const expectData = mem[2]; - const data = []; - for (let jdx = 0; jdx < expectData.length; jdx++) { - data.push(cpu.read(page, off++)); - if (off > 0xff) { - page++; - off = 0; - } - } - memAry.push([mem[0], mem[1], data]); - } - expect(memAry).toEqual(expectAry); -} - -function expectStack(expectAry: number[]) { - const state = cpu.getState(); - expectMemory([[0x01, state.sp + 1, expectAry]]); -} - -function testCode( - code: number[], - steps: number, - setupState: Partial, - expectedState: Partial -) { - const initialState = { ...DEFAULT_STATE, ...setupState }; - const finalState = { pc: initialState.pc + code.length, ...expectedState }; - - program = new Program(0x04, code); - cpu.addPageHandler(program); - - cpu.setState(initialState); - cpu.stepN(steps); - expectState(initialState, finalState); -} - -describe('CPU6502', function () { - beforeEach(function () { - cpu = new CPU6502(); - memory = new TestMemory(4); - - cpu.addPageHandler(memory); - cpu.addPageHandler(bios); - }); - - describe('#step functions', function () { - const code = [0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea]; - const initialState = { ...DEFAULT_STATE }; - - it('step', function () { - cpu.setState(initialState); - program = new Program(0x04, code); - cpu.addPageHandler(program); - cpu.step(); - expect(cpu.getState()).toEqual({ - ...DEFAULT_STATE, - pc: 0x401, - cycles: 2, - }); - expect(cpu.getCycles()).toEqual(2); - }); - - it('step with callback', function () { - const callback = jest.fn(); - cpu.setState(initialState); - program = new Program(0x04, code); - cpu.addPageHandler(program); - cpu.step(callback); - expect(cpu.getState()).toEqual({ - ...DEFAULT_STATE, - pc: 0x401, - cycles: 2, - }); - expect(cpu.getCycles()).toEqual(2); - expect(callback).toHaveBeenCalledTimes(1); - }); - - it('stepN', function () { - cpu.setState(initialState); - program = new Program(0x04, code); - cpu.addPageHandler(program); - cpu.stepN(4); - expect(cpu.getState()).toEqual({ - ...DEFAULT_STATE, - pc: 0x404, - cycles: 8, - }); - expect(cpu.getCycles()).toEqual(8); - }); - - it('stepN with callback', function () { - const callback = jest.fn(); - cpu.setState(initialState); - program = new Program(0x04, code); - cpu.addPageHandler(program); - cpu.stepN(4, callback); - expect(cpu.getState()).toEqual({ - ...DEFAULT_STATE, - pc: 0x404, - cycles: 8, - }); - expect(cpu.getCycles()).toEqual(8); - expect(callback).toHaveBeenCalledTimes(4); - }); - - it('stepN with breakpoint', function () { - const callback = jest.fn().mockReturnValue(true); - cpu.setState(initialState); - program = new Program(0x04, code); - cpu.addPageHandler(program); - cpu.stepN(4, callback); - expect(cpu.getState()).toEqual({ - ...DEFAULT_STATE, - pc: 0x401, - cycles: 2, - }); - expect(cpu.getCycles()).toEqual(2); - expect(callback).toHaveBeenCalledTimes(1); - }); - - it('stepCycles', function () { - cpu.setState(initialState); - program = new Program(0x04, code); - cpu.addPageHandler(program); - cpu.stepCycles(4); - expect(cpu.getState()).toEqual({ - ...DEFAULT_STATE, - pc: 0x402, - cycles: 4, - }); - expect(cpu.getCycles()).toEqual(4); - }); - - it('stepCyclesDebug', function () { - cpu.setState(initialState); - program = new Program(0x04, code); - cpu.addPageHandler(program); - cpu.stepCyclesDebug(4); - expect(cpu.getState()).toEqual({ - ...DEFAULT_STATE, - pc: 0x402, - cycles: 4, - }); - expect(cpu.getCycles()).toEqual(4); - }); - - it('stepCyclesDebug with callback', function () { - const callback = jest.fn(); - - cpu.setState(initialState); - program = new Program(0x04, code); - cpu.addPageHandler(program); - cpu.stepCyclesDebug(4, callback); - expect(cpu.getState()).toEqual({ - ...DEFAULT_STATE, - pc: 0x402, - cycles: 4, - }); - expect(cpu.getCycles()).toEqual(4); - expect(callback).toHaveBeenCalledTimes(2); - }); - - it('stepCyclesDebug with breakpoint', function () { - const callback = jest.fn().mockReturnValue(true); - - cpu.setState(initialState); - program = new Program(0x04, code); - cpu.addPageHandler(program); - cpu.stepCyclesDebug(4, callback); - expect(cpu.getState()).toEqual({ - ...DEFAULT_STATE, - pc: 0x401, - cycles: 2, - }); - expect(cpu.getCycles()).toEqual(2); - expect(callback).toHaveBeenCalledTimes(1); - }); - }); - - describe('#signals', function () { - it('should reset', function () { - cpu.reset(); - - expectState(DEFAULT_STATE, { - cycles: 2, - }); - }); - - it('should irq', function () { - cpu.irq(); - - expectState(DEFAULT_STATE, { - cycles: 5, - s: flags.X | flags.I, - sp: 0xfc, - pc: 0xff00, - }); - }); - - it('should not irq if I set', function () { - initState({ - s: flags.X | flags.I, - }); - - cpu.irq(); - - expectState(DEFAULT_STATE, { - s: flags.X | flags.I, - pc: 0x400, - }); - }); - - it('should nmi', function () { - cpu.nmi(); - - expectState(DEFAULT_STATE, { - cycles: 5, - s: flags.X | flags.I, - sp: 0xfc, - pc: 0xff00, - }); - }); - }); - - describe('#misc', function () { - it('should NOP', function () { - testCode( - [0xea], - 1, - {}, - { - cycles: 2, - } - ); - }); - - it('should BRK', function () { - testCode( - [0x00, 0x00], - 1, - {}, - { - cycles: 7, - s: flags.X | flags.I, - sp: 0xfc, - pc: 0xff00, - } - ); - }); - - it('should RTI', function () { - initMemory([[0x01, 0xfd, [0xa0, 0x34, 0x12]]]); - testCode( - [0x40], - 1, - { - sp: 0xfc, - }, - { - cycles: 6, - s: flags.X | flags.N, - sp: 0xff, - pc: 0x1234, - } - ); - }); - }); - - describe('#registers', function () { - it('should LDA immediate', function () { - testCode( - [0xa9, 0x44], - 1, - {}, - { - cycles: 2, - a: 0x44, - } - ); - }); - - it('should TAX', function () { - testCode( - [0xaa], - 1, - { - a: 0x44, - }, - { - cycles: 2, - x: 0x44, - } - ); - }); - - it('should TAY', function () { - testCode( - [0xa8], - 1, - { - a: 0x44, - }, - { - cycles: 2, - y: 0x44, - } - ); - }); - - it('should LDX immediate', function () { - testCode( - [0xa2, 0x44], - 1, - {}, - { - cycles: 2, - x: 0x44, - } - ); - }); - - it('should TXA', function () { - testCode( - [0x8a], - 1, - { - x: 0x44, - }, - { - cycles: 2, - a: 0x44, - } - ); - }); - - it('should DEX', function () { - testCode( - [0xca], - 1, - { - x: 0x44, - }, - { - cycles: 2, - x: 0x43, - } - ); - }); - - it('should INX', function () { - testCode( - [0xe8], - 1, - { - x: 0x44, - }, - { - cycles: 2, - x: 0x45, - } - ); - }); - - it('should LDY immediate', function () { - testCode( - [0xa0, 0x44], - 1, - {}, - { - cycles: 2, - y: 0x44, - } - ); - }); - - it('should TYA', function () { - testCode( - [0x98], - 1, - { - y: 0x44, - }, - { - cycles: 2, - a: 0x44, - } - ); - }); - - it('should DEY', function () { - testCode( - [0x88], - 1, - { - y: 0x44, - }, - { - cycles: 2, - y: 0x43, - } - ); - }); - - it('should INY', function () { - testCode( - [0xc8], - 1, - { - y: 0x44, - }, - { - cycles: 2, - y: 0x45, - } - ); - }); - }); - - describe('#flags', function () { - it('should SEC', function () { - testCode( - [0x38], - 1, - {}, - { - cycles: 2, - s: flags.X | flags.C, - } - ); - }); - - it('should CLC', function () { - testCode( - [0x18], - 1, - { - s: flags.X | flags.C, - }, - { - cycles: 2, - s: flags.X, - } - ); - }); - - it('should SEI', function () { - testCode( - [0x78], - 1, - {}, - { - cycles: 2, - s: flags.X | flags.I, - } - ); - }); - - it('should CLI', function () { - testCode( - [0x58], - 1, - { - s: flags.X | flags.I, - }, - { - cycles: 2, - s: flags.X, - } - ); - }); - - it('should CLV', function () { - testCode( - [0xb8], - 1, - { - s: flags.X | flags.V, - }, - { - cycles: 2, - s: flags.X, - } - ); - }); - - it('should SED', function () { - testCode( - [0xf8], - 1, - {}, - { - cycles: 2, - s: flags.X | flags.D, - } - ); - }); - - it('should CLD', function () { - testCode( - [0xd8], - 1, - { - s: flags.X | flags.D, - }, - { - cycles: 2, - s: flags.X, - } - ); - }); - }); - - describe('#stack', function () { - it('should TXS', function () { - testCode( - [0x9a], - 1, - { - x: 0x44, - }, - { - cycles: 2, - sp: 0x44, - } - ); - }); - - it('should TSX', function () { - testCode( - [0xba], - 1, - { - sp: 0x44, - }, - { - cycles: 2, - x: 0x44, - } - ); - }); - - it('should PHA', function () { - testCode( - [0x48], - 1, - { - a: 0x44, - }, - { - cycles: 3, - sp: 0xfe, - } - ); - expectStack([0x44]); - }); - - it('should PLA', function () { - initMemory([[0x01, 0xff, [0x44]]]); - testCode( - [0x68], - 1, - { - sp: 0xfe, - }, - { - cycles: 4, - a: 0x44, - sp: 0xff, - } - ); - }); - - it('should PHP', function () { - testCode( - [0x08], - 1, - { - s: flags.X | flags.N | flags.C, - }, - { - cycles: 3, - sp: 0xfe, - } - ); - expectStack([flags.X | flags.B | flags.N | flags.C]); - }); - - it('should PLP', function () { - initMemory([[0x01, 0xff, [flags.N | flags.C]]]); - testCode( - [0x28], - 1, - { - sp: 0xfe, - }, - { - cycles: 4, - s: flags.X | flags.N | flags.C, - sp: 0xff, - } - ); - }); - }); - - describe('#jumps', function () { - it('should JMP abs', function () { - testCode( - [0x4c, 0x34, 0x12], - 1, - {}, - { - cycles: 3, - pc: 0x1234, - } - ); - }); - - it('should JMP (abs)', function () { - initMemory([[0x03, 0x33, [0x34, 0x12]]]); - testCode( - [0x6c, 0x33, 0x03], - 1, - {}, - { - cycles: 5, - pc: 0x1234, - } - ); - }); - - it('should JMP (abs) across page boundaries with bugs', function () { - initMemory([ - [0x02, 0xff, [0x34, 0x12]], - [0x02, 0x00, [0xff]], - ]); - testCode( - [0x6c, 0xff, 0x02], - 1, - {}, - { - cycles: 5, - pc: 0xff34, - } - ); - }); - - it('should JSR abs', function () { - testCode( - [0x20, 0x34, 0x12], - 1, - {}, - { - cycles: 6, - sp: 0xfd, - pc: 0x1234, - } - ); - expectStack([0x02, 0x04]); - }); - - it('should RTS', function () { - initMemory([[0x01, 0xfe, [0x34, 0x12]]]); - testCode( - [0x60], - 1, - { - sp: 0xfd, - }, - { - cycles: 6, - sp: 0xff, - pc: 0x1235, - } - ); - }); - }); - - describe('#branches', function () { - // ********** bcs - it('should BCS forward', function () { - testCode( - [0xb0, 0x7f], - 1, - { - s: flags.X | flags.C, - }, - { - cycles: 3, - pc: 0x0481, - } - ); - }); - - it('should BCS backward', function () { - testCode( - [0xb0, 0xff], - 1, - { - s: flags.X | flags.C, - }, - { - cycles: 3, - pc: 0x0401, - } - ); - }); - - it('should BCS across pages with an extra cycle', function () { - testCode( - [0xb0, 0xfd], - 1, - { - s: flags.X | flags.C, - }, - { - cycles: 4, - pc: 0x03ff, - } - ); - }); - - it('should not BCS if carry clear', function () { - testCode( - [0xb0, 0xfd], - 1, - {}, - { - cycles: 2, - pc: 0x0402, - } - ); - }); - - it('should BCC forward', function () { - testCode( - [0x90, 0x7f], - 1, - {}, - { - cycles: 3, - pc: 0x0481, - } - ); - }); - - it('should BCC backward', function () { - testCode( - [0x90, 0xff], - 1, - {}, - { - cycles: 3, - pc: 0x0401, - } - ); - }); - - it('should BCC across pages with an extra cycle', function () { - testCode( - [0x90, 0xfd], - 1, - {}, - { - cycles: 4, - pc: 0x03ff, - } - ); - }); - - it('should not BCC if carry set', function () { - testCode( - [0x90, 0xfd], - 1, - { - s: flags.X | flags.C, - }, - { - cycles: 2, - pc: 0x0402, - } - ); - }); - }); - - describe('#read memory', function () { - // ********** zp - it('should LDY zp', function () { - initMemory([[0x00, 0x33, [0x44]]]); - testCode( - [0xa4, 0x33], - 1, - {}, - { - cycles: 3, - y: 0x44, - } - ); - }); - - it('should LDA zp', function () { - initMemory([[0x00, 0x33, [0x44]]]); - testCode( - [0xa5, 0x33], - 1, - {}, - { - cycles: 3, - a: 0x44, - } - ); - }); - - it('should LDX zp', function () { - initMemory([[0x00, 0x33, [0x44]]]); - testCode( - [0xa6, 0x33], - 1, - {}, - { - cycles: 3, - x: 0x44, - } - ); - }); - - // ********** zp,x - it('should LDY zp,x', function () { - initMemory([[0x00, 0x36, [0x44]]]); - testCode( - [0xb4, 0x33], - 1, - { - x: 3, - }, - { - cycles: 4, - y: 0x44, - } - ); - }); - - it('should LDA zp,x', function () { - initMemory([[0x00, 0x36, [0x44]]]); - testCode( - [0xb5, 0x33], - 1, - { - x: 3, - }, - { - cycles: 4, - a: 0x44, - } - ); - }); - - // ********** zp,y - it('should LDX zp,y', function () { - initMemory([[0x00, 0x36, [0x44]]]); - testCode( - [0xb6, 0x33], - 1, - { - y: 3, - }, - { - cycles: 4, - x: 0x44, - } - ); - }); - - // ********** (zp,x) - it('should LDA (zp,x)', function () { - initMemory([ - [0x00, 0x36, [0x33, 0x03]], - [0x03, 0x33, [0x44]], - ]); - testCode( - [0xa1, 0x33], - 1, - { - x: 3, - }, - { - cycles: 6, - a: 0x44, - } - ); - }); - - // ********** (zp),y - it('should LDA (zp),y', function () { - initMemory([ - [0x00, 0x33, [0x33, 0x03]], - [0x03, 0x36, [0x44]], - ]); - testCode( - [0xb1, 0x33], - 1, - { - y: 3, - }, - { - cycles: 5, - a: 0x44, - } - ); - }); - - // ********** (zp),y - it('should LDA (zp),y with an extra cycle on page cross', function () { - initMemory([ - [0x00, 0x33, [0x33, 0x02]], - [0x03, 0x32, [0x44]], - ]); - testCode( - [0xb1, 0x33], - 1, - { - y: 0xff, - }, - { - cycles: 6, - a: 0x44, - } - ); - }); - - // ********** abs - it('should LDY abs', function () { - initMemory([[0x03, 0x33, [0x44]]]); - testCode( - [0xac, 0x33, 0x03], - 1, - {}, - { - cycles: 4, - y: 0x44, - } - ); - }); - - it('should LDA abs', function () { - initMemory([[0x03, 0x33, [0x44]]]); - testCode( - [0xad, 0x33, 0x03], - 1, - {}, - { - cycles: 4, - a: 0x44, - } - ); - }); - - it('should LDX abs', function () { - initMemory([[0x03, 0x33, [0x44]]]); - testCode( - [0xae, 0x33, 0x03], - 1, - {}, - { - cycles: 4, - x: 0x44, - } - ); - }); - - // ********** abs, x - it('should LDY abs,x', function () { - initMemory([[0x03, 0x36, [0x44]]]); - testCode( - [0xbc, 0x33, 0x03], - 1, - { - x: 3, - }, - { - cycles: 4, - y: 0x44, - } - ); - }); - - it('should LDA abs,x', function () { - initMemory([[0x03, 0x36, [0x44]]]); - testCode( - [0xbd, 0x33, 0x03], - 1, - { - x: 3, - }, - { - cycles: 4, - a: 0x44, - } - ); - }); - - it('should LDY abs,x with extra cycle on page cross', function () { - initMemory([[0x03, 0x32, [0x44]]]); - testCode( - [0xbc, 0x33, 0x02], - 1, - { - x: 0xff, - }, - { - cycles: 5, - y: 0x44, - } - ); - }); - - it('should LDA abs,x with extra cycle on page cross', function () { - initMemory([[0x03, 0x32, [0x44]]]); - testCode( - [0xbd, 0x33, 0x02], - 1, - { - x: 0xff, - }, - { - cycles: 5, - a: 0x44, - } - ); - }); - - // ********** abs, y - it('should LDX abs,y', function () { - initMemory([[0x03, 0x36, [0x44]]]); - testCode( - [0xbe, 0x33, 0x03], - 1, - { - y: 3, - }, - { - cycles: 4, - x: 0x44, - } - ); - }); - - it('should LDX abs,y with extra cycle on page cross', function () { - initMemory([[0x03, 0x32, [0x44]]]); - testCode( - [0xbe, 0x33, 0x02], - 1, - { - y: 0xff, - }, - { - cycles: 5, - x: 0x44, - } - ); - }); - }); - - describe('#write memory', function () { - // ********** zp - it('should STY zp', function () { - testCode( - [0x84, 0x33], - 1, - { - y: 0x44, - }, - { - cycles: 3, - } - ); - expectMemory([[0x00, 0x33, [0x44]]]); - }); - - it('should STA zp', function () { - testCode( - [0x85, 0x33], - 1, - { - a: 0x44, - }, - { - cycles: 3, - } - ); - expectMemory([[0x00, 0x33, [0x44]]]); - }); - - it('should STX zp', function () { - testCode( - [0x86, 0x33], - 1, - { - x: 0x44, - }, - { - cycles: 3, - } - ); - expectMemory([[0x00, 0x33, [0x44]]]); - }); - - // ********** zp,x - it('should STY zp,x', function () { - testCode( - [0x94, 0x33], - 1, - { - x: 3, - y: 0x44, - }, - { - cycles: 4, - } - ); - expectMemory([[0x00, 0x36, [0x44]]]); - }); - - it('should STA zp,x', function () { - testCode( - [0x95, 0x33], - 1, - { - a: 0x44, - x: 3, - }, - { - cycles: 4, - } - ); - expectMemory([[0x00, 0x36, [0x44]]]); - }); - - // ********** zp,y - it('should STX zp,y', function () { - testCode( - [0x96, 0x33], - 1, - { - x: 0x44, - y: 3, - }, - { - cycles: 4, - } - ); - expectMemory([[0x00, 0x36, [0x44]]]); - }); - - // ********** (zp,x) - it('should STA (zp,x)', function () { - initMemory([[0x00, 0x36, [0x33, 0x03]]]); - testCode( - [0x81, 0x33], - 1, - { - a: 0x44, - x: 3, - }, - { - cycles: 6, - } - ); - expectMemory([[0x03, 0x33, [0x44]]]); - }); - - // ********** (zp),y - it('should STA (zp),y', function () { - initMemory([[0x00, 0x33, [0x33, 0x03]]]); - testCode( - [0x91, 0x33], - 1, - { - a: 0x44, - y: 3, - }, - { - cycles: 6, - } - ); - expectMemory([[0x03, 0x36, [0x44]]]); - }); - - // ********** abs - it('should STY abs', function () { - testCode( - [0x8c, 0x33, 0x03], - 1, - { - y: 0x44, - }, - { - cycles: 4, - } - ); - expectMemory([[0x03, 0x33, [0x44]]]); - }); - - it('should STA abs', function () { - testCode( - [0x8d, 0x33, 0x03], - 1, - { - a: 0x44, - }, - { - cycles: 4, - } - ); - expectMemory([[0x03, 0x33, [0x44]]]); - }); - - it('should STX abs', function () { - testCode( - [0x8e, 0x33, 0x03], - 1, - { - x: 0x44, - }, - { - cycles: 4, - } - ); - expectMemory([[0x03, 0x33, [0x44]]]); - }); - - // ********** abs, x - it('should STA abs,x', function () { - testCode( - [0x9d, 0x33, 0x03], - 1, - { - a: 0x44, - x: 0x03, - }, - { - cycles: 5, - } - ); - expectMemory([[0x03, 0x36, [0x44]]]); - }); - - it('should STA abs,x with no extra cycle on page cross', function () { - testCode( - [0x9d, 0x33, 0x02], - 1, - { - a: 0x44, - x: 0xff, - }, - { - cycles: 5, - pc: 0x0403, - } - ); - expectMemory([[0x03, 0x32, [0x44]]]); - }); - - // ********** abs, y - it('should STA abs,y', function () { - testCode( - [0x99, 0x33, 0x03], - 1, - { - a: 0x44, - y: 0x03, - }, - { - cycles: 5, - } - ); - expectMemory([[0x03, 0x36, [0x44]]]); - }); - - it('should STA abs,y with no extra cycle on page cross', function () { - testCode( - [0x99, 0x33, 0x02], - 1, - { - a: 0x44, - y: 0xff, - }, - { - cycles: 5, - } - ); - expectMemory([[0x03, 0x32, [0x44]]]); - }); - }); - - describe('#bit operations', function () { - // ********** ASL - it('should ASL A', function () { - testCode( - [0x0a], - 1, - { - a: 0x55, - }, - { - cycles: 2, - a: 0xaa, - s: flags.X | flags.N, - } - ); - }); - - it('should ASL A with carry out', function () { - testCode( - [0x0a], - 1, - { - a: 0xaa, - }, - { - cycles: 2, - a: 0x54, - s: flags.X | flags.C, - } - ); - }); - - it('should ASL abs', function () { - initMemory([[0x03, 0x33, [0x55]]]); - testCode( - [0x0e, 0x33, 0x03], - 1, - {}, - { - cycles: 6, - s: flags.X | flags.N, - } - ); - expectMemory([[0x03, 0x33, [0xaa]]]); - }); - - it('should ASL abs with carry out', function () { - initMemory([[0x03, 0x33, [0xaa]]]); - testCode( - [0x0e, 0x33, 0x03], - 1, - {}, - { - cycles: 6, - s: flags.X | flags.C, - } - ); - expectMemory([[0x03, 0x33, [0x54]]]); - }); - - // ********** ROL - it('should ROL A', function () { - testCode( - [0x2a], - 1, - { - a: 0x55, - }, - { - cycles: 2, - a: 0xaa, - s: flags.X | flags.N, - } - ); - }); - - it('should ROL A with carry out', function () { - testCode( - [0x2a], - 1, - { - a: 0xaa, - }, - { - cycles: 2, - a: 0x54, - s: flags.X | flags.C, - } - ); - }); - - it('should ROL A with carry in', function () { - testCode( - [0x2a], - 1, - { - s: flags.X | flags.C, - a: 0xaa, - }, - { - cycles: 2, - a: 0x55, - s: flags.X | flags.C, - } - ); - }); - - it('should ROL abs', function () { - initMemory([[0x03, 0x33, [0x55]]]); - testCode( - [0x2e, 0x33, 0x03], - 1, - {}, - { - cycles: 6, - s: flags.X | flags.N, - } - ); - expectMemory([[0x03, 0x33, [0xaa]]]); - }); - - it('should ROL abs with carry out', function () { - initMemory([[0x03, 0x33, [0xaa]]]); - testCode( - [0x2e, 0x33, 0x03], - 1, - {}, - { - cycles: 6, - s: flags.X | flags.C, - } - ); - expectMemory([[0x03, 0x33, [0x54]]]); - }); - - it('should ROL abs with carry in', function () { - initMemory([[0x03, 0x33, [0xaa]]]); - testCode( - [0x2e, 0x33, 0x03], - 1, - { - s: flags.X | flags.C, - }, - { - cycles: 6, - s: flags.X | flags.C, - } - ); - expectMemory([[0x03, 0x33, [0x55]]]); - }); - - // ********** LSR - it('should LSR A', function () { - testCode( - [0x4a], - 1, - { - a: 0xaa, - }, - { - cycles: 2, - a: 0x55, - } - ); - }); - - it('should LSR A with carry out', function () { - testCode( - [0x4a], - 1, - { - a: 0x55, - }, - { - cycles: 2, - a: 0x2a, - s: flags.X | flags.C, - } - ); - }); - - it('should LSR abs', function () { - initMemory([[0x03, 0x33, [0xaa]]]); - testCode( - [0x4e, 0x33, 0x03], - 1, - {}, - { - cycles: 6, - } - ); - expectMemory([[0x03, 0x33, [0x55]]]); - }); - - it('should LSR abs with carry out', function () { - initMemory([[0x03, 0x33, [0x55]]]); - testCode( - [0x4e, 0x33, 0x03], - 1, - {}, - { - cycles: 6, - s: flags.X | flags.C, - } - ); - expectMemory([[0x03, 0x33, [0x2a]]]); - }); - - // ********** ROR - it('should ROR A', function () { - testCode( - [0x6a], - 1, - { - a: 0xaa, - }, - { - cycles: 2, - a: 0x55, - } - ); - }); - - it('should ROR A with carry out', function () { - testCode( - [0x6a], - 1, - { - a: 0x55, - }, - { - cycles: 2, - s: flags.X | flags.C, - a: 0x2a, - } - ); - }); - - it('should ROR A with carry in', function () { - testCode( - [0x6a], - 1, - { - s: flags.X | flags.C, - a: 0x55, - }, - { - cycles: 2, - s: flags.X | flags.C | flags.N, - a: 0xaa, - } - ); - }); - - it('should ROR abs', function () { - initMemory([[0x03, 0x33, [0xaa]]]); - testCode( - [0x6e, 0x33, 0x03], - 1, - {}, - { - cycles: 6, - } - ); - expectMemory([[0x03, 0x33, [0x55]]]); - }); - - it('should ROR abs with carry out', function () { - initMemory([[0x03, 0x33, [0x55]]]); - testCode( - [0x6e, 0x33, 0x03], - 1, - {}, - { - cycles: 6, - s: flags.X | flags.C, - } - ); - expectMemory([[0x03, 0x33, [0x2a]]]); - }); - - it('should ROR abs with carry in', function () { - initMemory([[0x03, 0x33, [0x55]]]); - testCode( - [0x6e, 0x33, 0x03], - 1, - { - s: flags.X | flags.C, - }, - { - cycles: 6, - s: flags.X | flags.C | flags.N, - } - ); - expectMemory([[0x03, 0x33, [0xaa]]]); - }); - - it('should AND', function () { - initMemory([[0x03, 0x33, [0x55]]]); - testCode( - [0x2d, 0x33, 0x03], - 1, - { - a: 0xa5, - }, - { - cycles: 4, - a: 0x05, - } - ); - }); - - it('should ORA', function () { - initMemory([[0x03, 0x33, [0x55]]]); - testCode( - [0x0d, 0x33, 0x03], - 1, - { - a: 0xa0, - }, - { - cycles: 4, - s: flags.X | flags.N, - a: 0xf5, - } - ); - }); - - it('should EOR', function () { - initMemory([[0x03, 0x33, [0x55]]]); - testCode( - [0x4d, 0x33, 0x03], - 1, - { - a: 0xa5, - }, - { - cycles: 4, - s: flags.X | flags.N, - a: 0xf0, - } - ); - }); - - it('should BIT zp', function () { - initMemory([[0x00, 0x33, [0x55]]]); - testCode( - [0x24, 0x33], - 1, - { - a: 0x55, - }, - { - cycles: 3, - s: flags.X | flags.V, - } - ); - }); - - it('should BIT abs', function () { - initMemory([[0x03, 0x33, [0xaa]]]); - testCode( - [0x2c, 0x33, 0x03], - 1, - {}, - { - cycles: 4, - s: flags.X | flags.N | flags.Z, - } - ); - }); - }); - - describe('#math', function () { - // ********** ADC - it('should ADC', function () { - testCode( - [0x69, 0x55], - 1, - { - a: 0x23, - }, - { - cycles: 2, - a: 0x78, - s: flags.X, - } - ); - }); - - it('should ADC with carry in', function () { - testCode( - [0x69, 0x55], - 1, - { - a: 0x23, - s: flags.X | flags.C, - }, - { - cycles: 2, - a: 0x79, - s: flags.X, - } - ); - }); - - it('should ADC with overflow out', function () { - testCode( - [0x69, 0x55], - 1, - { - a: 0x2b, - }, - { - cycles: 2, - a: 0x80, - s: flags.X | flags.N | flags.V, - } - ); - }); - - it('should ADC with carry out', function () { - testCode( - [0x69, 0x55], - 1, - { - a: 0xbb, - }, - { - cycles: 2, - a: 0x10, - s: flags.X | flags.C, - } - ); - }); - - // ********** ADC BCD - it('should ADC BCD', function () { - testCode( - [0x69, 0x16], - 1, - { - s: flags.X | flags.D, - a: 0x25, - }, - { - cycles: 2, - s: flags.X | flags.D, - a: 0x41, - } - ); - }); - - it('should ADC BCD with carry in', function () { - testCode( - [0x69, 0x55], - 1, - { - s: flags.X | flags.D | flags.C, - a: 0x23, - }, - { - cycles: 2, - s: flags.X | flags.D, - a: 0x79, - } - ); - }); - - it('should ADC BCD with carry out', function () { - testCode( - [0x69, 0x10], - 1, - { - s: flags.X | flags.D, - a: 0x91, - }, - { - cycles: 2, - a: 0x01, - s: flags.X | flags.N | flags.D | flags.C, - } - ); - }); - - // ********** SBC - it('should SBC', function () { - testCode( - [0xe9, 0x23], - 1, - { - s: flags.X | flags.C, - a: 0x55, - }, - { - cycles: 2, - a: 0x32, - s: flags.X | flags.C, - } - ); - }); - - it('should SBC with borrow in', function () { - testCode( - [0xe9, 0x23], - 1, - { - s: flags.X, - a: 0x55, - }, - { - cycles: 2, - a: 0x31, - s: flags.X | flags.C, - } - ); - }); - - it('should SBC with borrow out', function () { - testCode( - [0xe9, 0x55], - 1, - { - s: flags.X | flags.C, - a: 0x23, - }, - { - cycles: 2, - a: 0xce, - s: flags.X | flags.N, - } - ); - }); - - it('should SBC with overflow out', function () { - testCode( - [0xe9, 0x7f], - 1, - { - s: flags.X | flags.C, - a: 0xaf, - }, - { - cycles: 2, - a: 0x30, - s: flags.X | flags.V | flags.C, - } - ); - }); - - // ********** SBC BCD - it('should SBC BCD', function () { - testCode( - [0xe9, 0x23], - 1, - { - s: flags.X | flags.D | flags.C, - a: 0x55, - }, - { - cycles: 2, - a: 0x32, - s: flags.X | flags.D | flags.C, - } - ); - }); - - it('should SBC BCD with borrow in', function () { - testCode( - [0xe9, 0x23], - 1, - { - s: flags.X | flags.D, - a: 0x55, - }, - { - cycles: 2, - a: 0x31, - s: flags.X | flags.D | flags.C, - } - ); - }); - - it('should SBC BCD with borrow out', function () { - testCode( - [0xe9, 0x55], - 1, - { - s: flags.X | flags.D | flags.C, - a: 0x23, - }, - { - cycles: 2, - a: 0x68, - s: flags.X | flags.N | flags.D, - } - ); - }); - - // ********** INC - it('should INC zp', function () { - initMemory([[0x00, 0x33, [0x44]]]); - testCode( - [0xe6, 0x33], - 1, - {}, - { - cycles: 5, - } - ); - expectMemory([[0x00, 0x33, [0x45]]]); - }); - - it('should INC zp,x', function () { - initMemory([[0x00, 0x043, [0x44]]]); - testCode( - [0xf6, 0x33], - 1, - { - x: 0x10, - }, - { - cycles: 6, - } - ); - expectMemory([[0x00, 0x43, [0x45]]]); - }); - - it('should INC abs', function () { - initMemory([[0x03, 0x33, [0x44]]]); - testCode( - [0xee, 0x33, 0x03], - 1, - {}, - { - cycles: 6, - } - ); - expectMemory([[0x03, 0x33, [0x45]]]); - }); - - it('should INC abs,x', function () { - initMemory([[0x03, 0x043, [0x44]]]); - testCode( - [0xfe, 0x33, 0x03], - 1, - { - x: 0x10, - }, - { - cycles: 7, - } - ); - expectMemory([[0x03, 0x43, [0x45]]]); - }); - - // ********** DEC - it('should DEC zp', function () { - initMemory([[0x00, 0x33, [0x44]]]); - testCode( - [0xc6, 0x33], - 1, - {}, - { - cycles: 5, - } - ); - expectMemory([[0x00, 0x33, [0x43]]]); - }); - - it('should DEC zp,x', function () { - initMemory([[0x00, 0x043, [0x44]]]); - testCode( - [0xd6, 0x33], - 1, - { - x: 0x10, - }, - { - cycles: 6, - } - ); - expectMemory([[0x00, 0x43, [0x43]]]); - }); - - it('should DEC abs', function () { - initMemory([[0x03, 0x33, [0x44]]]); - testCode( - [0xce, 0x33, 0x03], - 1, - {}, - { - cycles: 6, - } - ); - expectMemory([[0x03, 0x33, [0x43]]]); - }); - - it('should DEC abs,x', function () { - initMemory([[0x03, 0x043, [0x44]]]); - testCode( - [0xde, 0x33, 0x03], - 1, - { - x: 0x10, - }, - { - cycles: 7, - } - ); - expectMemory([[0x03, 0x43, [0x43]]]); - }); - }); - - describe('#comparison', function () { - // ********** CMP - it('should CMP less than', function () { - testCode( - [0xc9, 0x44], - 1, - { - a: 0x33, - }, - { - cycles: 2, - s: flags.X | flags.N, - } - ); - }); - - it('should CMP equal', function () { - testCode( - [0xc9, 0x44], - 1, - { - a: 0x44, - }, - { - cycles: 2, - s: flags.X | flags.Z | flags.C, - } - ); - }); - - it('should CMP greater than', function () { - testCode( - [0xc9, 0x44], - 1, - { - a: 0x55, - }, - { - cycles: 2, - s: flags.X | flags.C, - } - ); - }); - - // ********** CPX - it('should CPX less than', function () { - testCode( - [0xe0, 0x44], - 1, - { - x: 0x33, - }, - { - cycles: 2, - s: flags.X | flags.N, - } - ); - }); - - it('should CPX equal', function () { - testCode( - [0xe0, 0x44], - 1, - { - x: 0x44, - }, - { - cycles: 2, - s: flags.X | flags.Z | flags.C, - } - ); - }); - - it('should CPX greater than', function () { - testCode( - [0xe0, 0x44], - 1, - { - x: 0x55, - }, - { - cycles: 2, - s: flags.X | flags.C, - } - ); - }); - - // ********** CPY - it('should CPY less than', function () { - testCode( - [0xe0, 0x44], - 1, - { - y: 0x33, - }, - { - cycles: 2, - s: flags.X | flags.N, - } - ); - }); - - it('should CPY equal', function () { - testCode( - [0xc0, 0x44], - 1, - { - y: 0x44, - }, - { - cycles: 2, - s: flags.X | flags.Z | flags.C, - } - ); - }); - - it('should CPY greater than', function () { - testCode( - [0xc0, 0x44], - 1, - { - y: 0x55, - }, - { - cycles: 2, - s: flags.X | flags.C, - } - ); - }); - }); -}); - -describe('65c02', function () { - beforeEach(function () { - cpu = new CPU6502({ flavor: FLAVOR_ROCKWELL_65C02 }); - memory = new TestMemory(4); - - cpu.addPageHandler(memory); - cpu.addPageHandler(bios); - }); - - describe('#signals', function () { - it('should clear D on IRQ', function () { - initState({ - s: flags.X | flags.D, - }); - - cpu.irq(); - - expectState(DEFAULT_STATE, { - cycles: 5, - s: flags.X | flags.I, - sp: 0xfc, - pc: 0xff00, - }); - }); - - it('should clear D on NMI', function () { - initState({ - s: flags.X | flags.D, - }); - - cpu.nmi(); - - expectState(DEFAULT_STATE, { - cycles: 5, - s: flags.X | flags.I, - sp: 0xfc, - pc: 0xff00, - }); - }); - - it('should clear D on BRK', function () { - testCode( - [0x00, 0x00], - 1, - { - s: flags.X | flags.D, - }, - { - cycles: 7, - s: flags.X | flags.I, - sp: 0xfc, - pc: 0xff00, - } - ); - }); - }); - - describe('#stack', function () { - it('should PHX', function () { - testCode( - [0xda], - 1, - { - x: 0x44, - }, - { - cycles: 3, - sp: 0xfe, - } - ); - expectStack([0x44]); - }); - - it('should PLX', function () { - initMemory([[0x01, 0xff, [0x44]]]); - testCode( - [0xfa], - 1, - { - sp: 0xfe, - }, - { - cycles: 4, - x: 0x44, - sp: 0xff, - } - ); - }); - - it('should PHY', function () { - testCode( - [0x5a], - 1, - { - y: 0x44, - }, - { - cycles: 3, - sp: 0xfe, - } - ); - expectStack([0x44]); - }); - - it('should PLY', function () { - initMemory([[0x01, 0xff, [0x44]]]); - testCode( - [0x7a], - 1, - { - sp: 0xfe, - }, - { - cycles: 4, - y: 0x44, - sp: 0xff, - } - ); - }); - }); - - describe('#jumps', function () { - it('should JMP (abs)', function () { - initMemory([[0x03, 0x33, [0x34, 0x12]]]); - testCode( - [0x6c, 0x33, 0x03], - 1, - {}, - { - cycles: 6, - pc: 0x1234, - } - ); - }); - - it('should JMP (abs) across page boundries without bugs', function () { - initMemory([ - [0x02, 0xff, [0x34, 0x12]], - [0x02, 0x00, [0xff]], - ]); - testCode( - [0x6c, 0xff, 0x02], - 1, - {}, - { - cycles: 6, - pc: 0x1234, - } - ); - }); - - it('should JMP (abs, x)', function () { - initMemory([[0x03, 0x43, [0x34, 0x12]]]); - testCode( - [0x7c, 0x33, 0x03], - 1, - { - x: 0x10, - }, - { - cycles: 6, - pc: 0x1234, - } - ); - }); - }); - - describe('#other addressing mode fixes', function () { - it('should INC abs,x', function () { - initMemory([[0x03, 0x043, [0x44]]]); - testCode( - [0xfe, 0x33, 0x03], - 1, - { - x: 0x10, - }, - { - cycles: 7, - } - ); - expectMemory([[0x03, 0x43, [0x45]]]); - }); - }); - - describe('#branches', function () { - it('should BRA forward', function () { - testCode( - [0x80, 0x7f], - 1, - {}, - { - cycles: 3, - pc: 0x0481, - } - ); - }); - - it('should BRA backward', function () { - testCode( - [0x80, 0xff], - 1, - {}, - { - cycles: 3, - pc: 0x0401, - } - ); - }); - }); - - describe('#read memory', function () { - // ********** (zp) - it('should LDA (zp)', function () { - initMemory([ - [0x00, 0x33, [0x33, 0x03]], - [0x03, 0x33, [0x44]], - ]); - testCode( - [0xb2, 0x33], - 1, - {}, - { - cycles: 5, - a: 0x44, - } - ); - }); - }); - - describe('#write memory', function () { - // ********** (zp) - it('should STA (zp)', function () { - initMemory([[0x00, 0x33, [0x33, 0x03]]]); - testCode( - [0x92, 0x33], - 1, - { - a: 0x44, - }, - { - cycles: 5, - } - ); - expectMemory([[0x03, 0x33, [0x44]]]); - }); - - it('should STZ abs', function () { - initMemory([[0x03, 0x33, [0x44]]]); - testCode( - [0x9c, 0x33, 0x03], - 1, - { - a: 0x44, - }, - { - cycles: 4, - } - ); - expectMemory([[0x03, 0x33, [0x00]]]); - }); - }); - - describe('#logical operators', function () { - it('should BIT imm and effect other flags', function () { - testCode( - [0x89, 0x33], - 1, - { - s: flags.X | flags.N, - a: 0x44, - }, - { - cycles: 2, - s: flags.X | flags.Z | flags.N, - } - ); - }); - - it('should BIT imm', function () { - testCode( - [0x89, 0x33], - 1, - { - a: 0x03, - }, - { - cycles: 2, - s: flags.X, - } - ); - }); - - // ******** TRB - it('should TRB zp', function () { - initMemory([[0x00, 0x33, [0x55]]]); - testCode( - [0x14, 0x33], - 1, - { - a: 0xa5, - }, - { - cycles: 5, - } - ); - expectMemory([[0x00, 0x33, [0x50]]]); - }); - - it('should TRB abs', function () { - initMemory([[0x03, 0x33, [0x55]]]); - testCode( - [0x1c, 0x33, 0x03], - 1, - { - a: 0xaa, - }, - { - cycles: 6, - s: flags.X | flags.Z, - } - ); - expectMemory([[0x00, 0x33, [0x00]]]); - }); - - // ******** TSB - it('should TSB zp', function () { - initMemory([[0x00, 0x33, [0x55]]]); - testCode( - [0x04, 0x33], - 1, - { - a: 0xa5, - }, - { - cycles: 5, - } - ); - expectMemory([[0x00, 0x33, [0xf5]]]); - }); - - it('should TSB abs', function () { - initMemory([[0x03, 0x33, [0x55]]]); - testCode( - [0x0c, 0x33, 0x03], - 1, - { - a: 0xaa, - }, - { - cycles: 6, - s: flags.X | flags.Z, - } - ); - expectMemory([[0x03, 0x33, [0xff]]]); - }); - }); - - describe('Branch bit set/reset', function () { - // ******** BBR - it('BBR0 should branch if bit 0 clear', function () { - initMemory([[0x00, 0x33, [0xfe]]]); - testCode( - [0x0f, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0482, - } - ); - }); - - it('BBR0 should branch backward', function () { - initMemory([[0x00, 0x33, [0xfe]]]); - testCode( - [0x0f, 0x33, 0xff], - 1, - {}, - { - cycles: 6, - pc: 0x0402, - } - ); - }); - - it('BBR1 should branch if bit 1 clear', function () { - initMemory([[0x00, 0x33, [0xfd]]]); - testCode( - [0x1f, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0482, - } - ); - }); - - it('BBR2 should branch if bit 2 clear', function () { - initMemory([[0x00, 0x33, [0xfb]]]); - testCode( - [0x2f, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0482, - } - ); - }); - - it('BBR3 should branch if bit 3 clear', function () { - initMemory([[0x00, 0x33, [0xf7]]]); - testCode( - [0x3f, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0482, - } - ); - }); - - it('BBR4 should branch if bit 4 clear', function () { - initMemory([[0x00, 0x33, [0xef]]]); - testCode( - [0x4f, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0482, - } - ); - }); - - it('BBR5 should branch if bit 5 clear', function () { - initMemory([[0x00, 0x33, [0xdf]]]); - testCode( - [0x5f, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0482, - } - ); - }); - - it('BBR6 should branch if bit 6 clear', function () { - initMemory([[0x00, 0x33, [0xbf]]]); - testCode( - [0x6f, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0482, - } - ); - }); - - it('BBR7 should branch if bit 7 clear', function () { - initMemory([[0x00, 0x33, [0x7f]]]); - testCode( - [0x7f, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0482, - } - ); - }); - - it('BBR0 should not branch if bit 0 set', function () { - initMemory([[0x00, 0x33, [0x01]]]); - testCode( - [0x0f, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0403, - } - ); - }); - - it('BBR1 should not branch if bit 1 set', function () { - initMemory([[0x00, 0x33, [0x02]]]); - testCode( - [0x1f, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0403, - } - ); - }); - - it('BBR2 should not branch if bit 2 set', function () { - initMemory([[0x00, 0x33, [0x04]]]); - testCode( - [0x2f, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0403, - } - ); - }); - - it('BBR3 should not branch if bit 3 set', function () { - initMemory([[0x00, 0x33, [0x08]]]); - testCode( - [0x3f, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0403, - } - ); - }); - - it('BBR4 should not branch if bit 4 set', function () { - initMemory([[0x00, 0x33, [0x10]]]); - testCode( - [0x4f, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0403, - } - ); - }); - - it('BBR5 should not branch if bit 5 set', function () { - initMemory([[0x00, 0x33, [0x20]]]); - testCode( - [0x5f, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0403, - } - ); - }); - - it('BBR6 should not branch if bit 6 set', function () { - initMemory([[0x00, 0x33, [0x40]]]); - testCode( - [0x6f, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0403, - } - ); - }); - - it('BBR7 should not branch if bit 7 set', function () { - initMemory([[0x00, 0x33, [0x80]]]); - testCode( - [0x7f, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0403, - } - ); - }); - - // ******** BBS - it('BBS0 should branch if bit 0 set', function () { - initMemory([[0x00, 0x33, [0x01]]]); - testCode( - [0x8f, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0482, - } - ); - }); - - it('BBS0 should branch backward', function () { - initMemory([[0x00, 0x33, [0x01]]]); - testCode( - [0x8f, 0x33, 0xff], - 1, - {}, - { - cycles: 6, - pc: 0x0402, - } - ); - }); - - it('BBS1 should branch if bit 1 set', function () { - initMemory([[0x00, 0x33, [0x02]]]); - testCode( - [0x9f, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0482, - } - ); - }); - - it('BBS2 should branch if bit 2 set', function () { - initMemory([[0x00, 0x33, [0x04]]]); - testCode( - [0xaf, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0482, - } - ); - }); - - it('BBS3 should branch if bit 3 set', function () { - initMemory([[0x00, 0x33, [0x08]]]); - testCode( - [0xbf, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0482, - } - ); - }); - - it('BBS4 should branch if bit 4 set', function () { - initMemory([[0x00, 0x33, [0x10]]]); - testCode( - [0xcf, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0482, - } - ); - }); - - it('BBS5 should branch if bit 5 set', function () { - initMemory([[0x00, 0x33, [0x20]]]); - testCode( - [0xdf, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0482, - } - ); - }); - - it('BBS6 should branch if bit 6 set', function () { - initMemory([[0x00, 0x33, [0x40]]]); - testCode( - [0xef, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0482, - } - ); - }); - - it('BBS7 should branch if bit 7 set', function () { - initMemory([[0x00, 0x33, [0x80]]]); - testCode( - [0xff, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0482, - } - ); - }); - - it('BBS0 should not branch if bit 0 clear', function () { - initMemory([[0x00, 0x33, [0xfe]]]); - testCode( - [0x8f, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0403, - } - ); - }); - - it('BBS1 should not branch if bit 1 clear', function () { - initMemory([[0x00, 0x33, [0xfd]]]); - testCode( - [0x9f, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0403, - } - ); - }); - - it('BBS2 should not branch if bit 2 clear', function () { - initMemory([[0x00, 0x33, [0xfb]]]); - testCode( - [0xaf, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0403, - } - ); - }); - - it('BBS3 should not branch if bit 3 clear', function () { - initMemory([[0x00, 0x33, [0xf7]]]); - testCode( - [0xbf, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0403, - } - ); - }); - - it('BBS4 should not branch if bit 4 clear', function () { - initMemory([[0x00, 0x33, [0xef]]]); - testCode( - [0xcf, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0403, - } - ); - }); - - it('BBS5 should not branch if bit 5 clear', function () { - initMemory([[0x00, 0x33, [0xdf]]]); - testCode( - [0xdf, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0403, - } - ); - }); - - it('BBS6 should not branch if bit 6 clear', function () { - initMemory([[0x00, 0x33, [0xbf]]]); - testCode( - [0xef, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0403, - } - ); - }); - - it('BBS7 should not branch if bit 7 clear', function () { - initMemory([[0x00, 0x33, [0x7b]]]); - testCode( - [0xff, 0x33, 0x7f], - 1, - {}, - { - cycles: 6, - pc: 0x0403, - } - ); - }); - }); - - describe('Bit set/reset', function () { - it('RMB0 should reset bit 0', function () { - initMemory([[0x00, 0x33, [0xff]]]); - testCode( - [0x07, 0x33], - 1, - {}, - { - cycles: 5, - pc: 0x0402, - } - ); - expectMemory([[0x00, 0x33, [0xfe]]]); - }); - - it('RMB1 should reset bit 1', function () { - initMemory([[0x00, 0x33, [0xff]]]); - testCode( - [0x17, 0x33], - 1, - {}, - { - cycles: 5, - pc: 0x0402, - } - ); - expectMemory([[0x00, 0x33, [0xfd]]]); - }); - - it('RMB2 should reset bit 2', function () { - initMemory([[0x00, 0x33, [0xff]]]); - testCode( - [0x27, 0x33], - 1, - {}, - { - cycles: 5, - pc: 0x0402, - } - ); - expectMemory([[0x00, 0x33, [0xfb]]]); - }); - - it('RMB3 should reset bit 3', function () { - initMemory([[0x00, 0x33, [0xff]]]); - testCode( - [0x37, 0x33], - 1, - {}, - { - cycles: 5, - pc: 0x0402, - } - ); - expectMemory([[0x00, 0x33, [0xf7]]]); - }); - - it('RMB4 should reset bit 4', function () { - initMemory([[0x00, 0x33, [0xff]]]); - testCode( - [0x47, 0x33], - 1, - {}, - { - cycles: 5, - pc: 0x0402, - } - ); - expectMemory([[0x00, 0x33, [0xef]]]); - }); - - it('RMB5 should reset bit 5', function () { - initMemory([[0x00, 0x33, [0xff]]]); - testCode( - [0x57, 0x33], - 1, - {}, - { - cycles: 5, - pc: 0x0402, - } - ); - expectMemory([[0x00, 0x33, [0xdf]]]); - }); - - it('RMB6 should reset bit 6', function () { - initMemory([[0x00, 0x33, [0xff]]]); - testCode( - [0x67, 0x33], - 1, - {}, - { - cycles: 5, - pc: 0x0402, - } - ); - expectMemory([[0x00, 0x33, [0xbf]]]); - }); - - it('RMB7 should reset bit 7', function () { - initMemory([[0x00, 0x33, [0xff]]]); - testCode( - [0x77, 0x33], - 1, - {}, - { - cycles: 5, - pc: 0x0402, - } - ); - expectMemory([[0x00, 0x33, [0x7f]]]); - }); - - it('SMB0 should set bit 0', function () { - initMemory([[0x00, 0x33, [0x00]]]); - testCode( - [0x87, 0x33], - 1, - {}, - { - cycles: 5, - pc: 0x0402, - } - ); - expectMemory([[0x00, 0x33, [0x01]]]); - }); - - it('SMB1 should set bit 1', function () { - initMemory([[0x00, 0x33, [0x00]]]); - testCode( - [0x97, 0x33], - 1, - {}, - { - cycles: 5, - pc: 0x0402, - } - ); - expectMemory([[0x00, 0x33, [0x02]]]); - }); - - it('SMB2 should set bit 2', function () { - initMemory([[0x00, 0x33, [0x00]]]); - testCode( - [0xa7, 0x33], - 1, - {}, - { - cycles: 5, - pc: 0x0402, - } - ); - expectMemory([[0x00, 0x33, [0x04]]]); - }); - - it('SMB3 should set bit 3', function () { - initMemory([[0x00, 0x33, [0x00]]]); - testCode( - [0xb7, 0x33], - 1, - {}, - { - cycles: 5, - pc: 0x0402, - } - ); - expectMemory([[0x00, 0x33, [0x08]]]); - }); - - it('SMB4 should set bit 4', function () { - initMemory([[0x00, 0x33, [0x00]]]); - testCode( - [0xc7, 0x33], - 1, - {}, - { - cycles: 5, - pc: 0x0402, - } - ); - expectMemory([[0x00, 0x33, [0x10]]]); - }); - - it('SMB5 should set bit 5', function () { - initMemory([[0x00, 0x33, [0x00]]]); - testCode( - [0xd7, 0x33], - 1, - {}, - { - cycles: 5, - pc: 0x0402, - } - ); - expectMemory([[0x00, 0x33, [0x20]]]); - }); - - it('SMB6 should set bit 6', function () { - initMemory([[0x00, 0x33, [0x00]]]); - testCode( - [0xe7, 0x33], - 1, - {}, - { - cycles: 5, - pc: 0x0402, - } - ); - expectMemory([[0x00, 0x33, [0x40]]]); - }); - - it('SMB7 should set bit 7', function () { - initMemory([[0x00, 0x33, [0x00]]]); - testCode( - [0xf7, 0x33], - 1, - {}, - { - cycles: 5, - pc: 0x0402, - } - ); - expectMemory([[0x00, 0x33, [0x80]]]); - }); - }); - - describe('#math', function () { - // INC A - it('should INC A', function () { - testCode( - [0x1a], - 1, - { - a: 0x44, - }, - { - cycles: 2, - a: 0x45, - } - ); - }); - - // DEC A - it('should DEC A', function () { - testCode( - [0x3a], - 1, - { - a: 0x44, - }, - { - cycles: 2, - a: 0x43, - } - ); - }); - }); -}); diff --git a/test/roms/6502_functional_test.bin b/test/roms/6502_functional_test.bin deleted file mode 100644 index 962ab40..0000000 Binary files a/test/roms/6502_functional_test.bin and /dev/null differ diff --git a/test/roms/6502test.ts b/test/roms/6502test.ts deleted file mode 100644 index 4c7a868..0000000 --- a/test/roms/6502test.ts +++ /dev/null @@ -1,29 +0,0 @@ -// From https://github.com/Klaus2m5/6502_65C02_functional_tests - -import fs from 'fs'; -import path from 'path'; -import { MemoryPages, byte } from '../../js/types'; - -export default class Test6502 implements MemoryPages { - private data: Buffer; - - constructor() { - this.data = fs.readFileSync(path.join(__dirname, '6502_functional_test.bin')); - } - - start = () => { - return 0x00; - }; - - end = () => { - return 0xff; - }; - - read = (page: byte, off: byte) => { - return this.data[page << 8 | off]; - }; - - write = (page: byte, off: byte, val: byte) => { - this.data[page << 8 | off] = val; - }; -} diff --git a/test/roms/65C02_extended_opcodes_test.bin b/test/roms/65C02_extended_opcodes_test.bin deleted file mode 100644 index b1ea946..0000000 Binary files a/test/roms/65C02_extended_opcodes_test.bin and /dev/null differ diff --git a/test/roms/65C02test.ts b/test/roms/65C02test.ts deleted file mode 100644 index 784d0fb..0000000 --- a/test/roms/65C02test.ts +++ /dev/null @@ -1,29 +0,0 @@ -// From https://github.com/Klaus2m5/6502_65C02_functional_tests - -import fs from 'fs'; -import path from 'path'; -import { MemoryPages, byte } from '../../js/types'; - -export default class Test65C02 implements MemoryPages { - private data: Buffer; - - constructor() { - this.data = fs.readFileSync(path.join(__dirname, '65C02_extended_opcodes_test.bin')); - } - - start = () => { - return 0x00; - }; - - end = () => { - return 0xff; - }; - - read = (page: byte, off: byte) => { - return this.data[page << 8 | off]; - }; - - write = (page: byte, off: byte, val: byte) => { - this.data[page << 8 | off] = val; - }; -} diff --git a/test/util/asserts.ts b/test/util/asserts.ts deleted file mode 100644 index cb1e842..0000000 --- a/test/util/asserts.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { byte } from "../../js/types"; - -export const assertByte = (b: byte) => { - expect(b <= 0xff).toEqual(true); - expect(b >= 0x00).toEqual(true); -}; diff --git a/test/util/bios.ts b/test/util/bios.ts deleted file mode 100644 index 1e10cdf..0000000 --- a/test/util/bios.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { MemoryPages, byte } from "../../js/types"; -import { assertByte } from "./asserts"; - -export class Program implements MemoryPages { - private data: Buffer; - - constructor(private page: byte, code: byte[]) { - this.data = Buffer.from(code); - } - - start() { - return this.page; - } - - end() { - return this.page; - } - - read(page: byte, off: byte) { - assertByte(page); - assertByte(off); - return this.data[off]; - } - - write(_page: byte, _off: byte, _val: byte) { - // do nothing - } -} - -export const bios = new Program( - 0xff, - [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x45, 0x4c, 0x4c, - 0x4f, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x04, 0x00, 0xff, - ] -); diff --git a/test/util/cpu.ts b/test/util/cpu.ts deleted file mode 100644 index 627b373..0000000 --- a/test/util/cpu.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { flags, CpuState } from "js/cpu6502"; -import { byte } from "js/types"; -import { toHex } from "js/util"; - -export const dumpStatusRegister = (sr: byte) => - [ - sr & flags.N ? "N" : "-", - sr & flags.V ? "V" : "-", - sr & flags.X ? "X" : "-", - sr & flags.B ? "B" : "-", - sr & flags.D ? "D" : "-", - sr & flags.I ? "I" : "-", - sr & flags.Z ? "Z" : "-", - sr & flags.C ? "C" : "-", - ].join(""); - -const detail = !!process.env.JEST_DETAIL; - -export function toReadableState(state: CpuState) { - if (detail) { - const { pc, sp, a, x, y, s } = state; - - return { - pc: toHex(pc, 4), - sp: toHex(sp), - a: toHex(a), - x: toHex(x), - y: toHex(y), - s: dumpStatusRegister(s), - }; - } else { - return state; - } -} diff --git a/test/util/memory.ts b/test/util/memory.ts deleted file mode 100644 index 6dedf1f..0000000 --- a/test/util/memory.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { MemoryPages, byte, word } from "js/types"; -import { assertByte } from "./asserts"; - -export type Log = [address: word, value: byte, types: "read" | "write"]; -export class TestMemory implements MemoryPages { - private data: Buffer; - private logging: boolean = false; - private log: Log[] = []; - - constructor(private size: number) { - this.data = Buffer.alloc(size << 8); - } - - start() { - return 0; - } - - end() { - return this.size - 1; - } - - read(page: byte, off: byte) { - assertByte(page); - assertByte(off); - - const val = this.data[(page << 8) | off]; - if (this.logging) { - this.log.push([(page << 8) | off, val, "read"]); - } - return val; - } - - write(page: byte, off: byte, val: byte) { - assertByte(page); - assertByte(off); - assertByte(val); - - if (this.logging) { - this.log.push([(page << 8) | off, val, "write"]); - } - this.data[(page << 8) | off] = val; - } - - reset() { - this.log = []; - } - - logStart() { - this.log = []; - this.logging = true; - } - - logStop() { - this.logging = false; - } - - getLog() { - return this.log; - } -}