From ca3f255a8758275db1ebd9324b63dfca05c541c9 Mon Sep 17 00:00:00 2001 From: Will Scullin Date: Sun, 6 Aug 2023 07:32:11 -0700 Subject: [PATCH] Lint, other build fixes --- .editorconfig | 6 +- .eslintrc.json | 211 +- js/apple1.ts | 342 +-- js/apple1io.ts | 32 +- js/base64.ts | 16 +- js/canvas1.ts | 64 +- js/cards/aci.ts | 33 +- js/cpu6502.ts | 1222 ++++----- js/entry1.js | 4 +- js/prefs.ts | 2 +- js/ram.ts | 10 +- js/roms/basic.ts | 2 +- js/roms/bios.ts | 2 +- js/roms/enhanced-basic.ts | 2 +- js/roms/krusader.ts | 2 +- js/symbols.ts | 18 +- js/ui/keyboard.ts | 144 +- js/util.ts | 22 +- package-lock.json | 1153 +++++++- package.json | 2 + test/cpu.spec.ts | 60 +- test/cpu6502.spec.ts | 5284 ++++++++++++++++++++++--------------- test/util/asserts.ts | 6 +- test/util/bios.ts | 101 +- test/util/memory.ts | 99 +- webpack.config.js | 3 - 26 files changed, 5545 insertions(+), 3297 deletions(-) diff --git a/.editorconfig b/.editorconfig index eff4970..5de5681 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,7 +8,11 @@ insert_final_newline = true trim_trailing_whitespace = true [*.js] -indent_size = 4 +indent_size = 2 + +[*.ts] +indent_size = 2 +quote_type = single [*.html] indent_size = 2 diff --git a/.eslintrc.json b/.eslintrc.json index 3f5277c..c579204 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,20 +1,60 @@ { + // Global + "root": true, + "parser": "@typescript-eslint/parser", + "extends": [ + "eslint:recommended", + "plugin:jest/recommended" + ], + "globals": { + "tapes": "writable" + }, "rules": { "indent": [ - 2, - 4 + "error", + 4, + { + "SwitchCase": 1 + } ], "quotes": [ - 2, - "single" + "error", + "single", + { "avoidEscape": true } ], "linebreak-style": [ - 2, + "error", "unix" ], - "semi": [ - 2, - "always" + "eqeqeq": [ + "error", + "smart" + ], + "prefer-const": [ + "error" + ], + "no-var": "error", + "no-use-before-define": "off", + "no-console": [ + "error", + { + "allow": [ + "info", + "warn", + "error" + ] + } + ], + // Jest configuration + "jest/expect-expect": [ + "error", + { + "assertFunctionNames": [ + "expect*", + "checkImageData", + "testCode" + ] + } ] }, "env": { @@ -22,16 +62,109 @@ "browser": true, "es6": true }, - "globals": { - "tapes": true - }, - "parserOptions": { - "sourceType": "module" - }, - "extends": "eslint:recommended", "overrides": [ + // All overrides matching a file are applied in-order, with the last + // taking precedence. + // + // TypeScript/TSX-specific configuration { - "files": [ "bin/*", "babel.config.js", "webpack.config.js" ], + "files": [ + "*.ts", + "*.tsx" + ], + "plugins": [ + "@typescript-eslint/eslint-plugin" + ], + "extends": [ + "plugin:@typescript-eslint/recommended", + "plugin:@typescript-eslint/recommended-requiring-type-checking" + ], + "rules": { + "indent": [ + "error", + 2, + { + "SwitchCase": 1 + } + ], + // recommended is just "warn" + "@typescript-eslint/no-explicit-any": "error", + // enforce semicolons at ends of statements + "semi": "off", + "@typescript-eslint/semi": [ + "error", + "always" + ], + // enforce semicolons to separate members + "@typescript-eslint/member-delimiter-style": [ + "error", + { + "multiline": { + "delimiter": "semi", + "requireLast": true + }, + "singleline": { + "delimiter": "semi", + "requireLast": false + } + } + ], + // definitions must come before uses for variables + "@typescript-eslint/no-use-before-define": [ + "error", + { + "functions": false, + "classes": false + } + ], + // no used variables + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": [ + "error", + { + "argsIgnorePattern": "^_" + } + ], + // no redeclaration of classes, members or variables + "no-redeclare": "off", + "@typescript-eslint/no-redeclare": [ + "error" + ], + // allow empty interface definitions and empty extends + "@typescript-eslint/no-empty-interface": "off", + // allow explicit type declaration + "@typescript-eslint/no-inferrable-types": "off", + // allow some non-string types in templates + "@typescript-eslint/restrict-template-expressions": [ + "error", + { + "allowNumber": true, + "allowBoolean": true + } + ] + }, + "parserOptions": { + "sourceType": "module", + "project": "./tsconfig.json" + } + }, + // UI elements + { + "files": [ + "js/ui/**.ts" + ], + "rules": { + // allow non-null assertions since these classes reference the DOM + "@typescript-eslint/no-non-null-assertion": "off" + } + }, + // JS Node configuration + { + "files": [ + "bin/*", + "babel.config.js", + "webpack.config.js" + ], "rules": { "no-console": 0 }, @@ -40,17 +173,49 @@ "jquery": false, "browser": false } - }, { - "files": [ "test/*"], + }, + // Test configuration + { + "files": [ + "test/**/*" + ], "env": { - "node": true, - "jest": true + "jest": true, + "jasmine": true, + "node": true + }, + "rules": { + "no-console": 0 } - }, { - "files": [ "js/entry1.js"], + }, + // Entry point configuration + { + "files": [ + "js/entry2.ts", + "js/entry2e.ts", + "jest.config.js" + ], "env": { "commonjs": true } + }, + // Worker configuration + { + "files": [ + "workers/*" + ], + "parserOptions": { + "project": "workers/tsconfig.json" + } } - ] + ], + "ignorePatterns": [ + "coverage/**/*" + ], + "settings": { + "react": { + "pragma": "h", + "version": "16" + } + } } diff --git a/js/apple1.ts b/js/apple1.ts index 437a270..10b1ca0 100644 --- a/js/apple1.ts +++ b/js/apple1.ts @@ -1,22 +1,35 @@ -import MicroModal from "micromodal"; +/* 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 Apple1IO from "./apple1io"; -import CPU6502 from "./cpu6502"; -import Prefs from "./prefs"; -import RAM from "./ram"; -import { TextPage } from "./canvas1"; -import { debug, hup } from "./util"; +import MicroModal from 'micromodal'; -import Basic from "./roms/basic"; -import Bios from "./roms/bios"; -import Krusader from "./roms/krusader"; +import Apple1IO from './apple1io'; +import CPU6502 from './cpu6502'; +import Prefs from './prefs'; +import RAM from './ram'; +import { TextPage } from './canvas1'; +import { debug, hup } from './util'; -import ACI from "./cards/aci"; +import Basic from './roms/basic'; +import Bios from './roms/bios'; +import Krusader from './roms/krusader'; -import { mapKeyEvent, KeyBoard } from "./ui/keyboard"; -import { address, byte } from "./types"; +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; +// eslint-disable-next-line prefer-const let TRACE = true; const skidmarks: string[] = []; @@ -32,22 +45,22 @@ const prefs = new Prefs(); let runTimer: ReturnType | null = null; const cpu = new CPU6502(); -var krusader = window.location.hash == "#krusader"; +const krusader = window.location.hash === '#krusader'; -var raml, ramh, rom, aci: ACI, io: Apple1IO, text: TextPage, keyboard: KeyBoard; +let ramh, rom; // 32K base memory. Should be 0x0f for 4K, 0x1f for 8K, 0x3f for 16K -raml = new RAM(0x00, 0x7f); -text = new TextPage(); +const raml = new RAM(0x00, 0x7f); +const text = new TextPage(); text.init(); -aci = new ACI(cpu, { +const aci = new ACI(cpu, { progress: function (val) { - document.querySelector("#tape")!.style.width = - val * 100 + "px"; + document.querySelector('#tape')!.style.width = + val * 100 + 'px'; }, }); -io = new Apple1IO(text); +const io = new Apple1IO(text); if (krusader) { ramh = null; @@ -57,7 +70,7 @@ if (krusader) { ramh = new Basic(); rom = new Bios(); } -keyboard = new KeyBoard("#keyboard", cpu, io, text); +const keyboard = new KeyBoard('#keyboard', cpu, io, text); cpu.addPageHandler(raml); if (ramh) { @@ -68,7 +81,7 @@ cpu.addPageHandler(rom); cpu.addPageHandler(aci); cpu.addPageHandler(io); -var showFPS = false; +let showFPS = false; interface Tape { script: string; @@ -86,7 +99,7 @@ declare global { //aci.setData([0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef]) //aci.setData(tapes['BASIC']); -aci.setData(window.tapes["Microchess"].tracks); +aci.setData(window.tapes['Microchess'].tracks); // Audio Buffer Source declare global { @@ -99,55 +112,61 @@ const AudioContext = window.AudioContext || window.webkitAudioContext; const context = new AudioContext(); export function doLoadLocal(files: FileList) { - context.resume(); - files = - files || document.querySelector("#local_file")!.files; - if (files.length == 1) { - var file = files[0]; - var fileReader = new FileReader(); - fileReader.onload = function (ev) { - context.decodeAudioData( - ev.target!.result as ArrayBuffer, - function (buffer) { - var buf = []; - var data = buffer.getChannelData(0); - var old = data[0] > 0.25; - var last = 0; - for (var idx = 1; idx < data.length; idx++) { - var current = data[idx] > 0.25; - if (current != old) { - var delta = idx - last; - buf.push(Math.floor((delta / buffer.sampleRate) * 1023000)); - old = current; - last = idx; - } - } - aci.buffer = buf; - MicroModal.close("local-modal"); - }, - function () { - window.alert("Unable to read tape file: " + file.name); - } - ); - }; - fileReader.readAsArrayBuffer(file); - } + context + .resume() + .then(() => { + files = + files || document.querySelector('#local_file')!.files; + if (files.length === 1) { + const file = files[0]; + const fileReader = new FileReader(); + fileReader.onload = function (ev) { + context + .decodeAudioData( + ev.target!.result as ArrayBuffer, + function (buffer) { + const buf = []; + const data = buffer.getChannelData(0); + let old = data[0] > 0.25; + let last = 0; + for (let idx = 1; idx < data.length; idx++) { + const current = data[idx] > 0.25; + if (current !== old) { + const delta = idx - last; + buf.push(Math.floor((delta / buffer.sampleRate) * 1023000)); + old = current; + last = idx; + } + } + aci.buffer = buf; + MicroModal.close('local-modal'); + }, + function () { + window.alert('Unable to read tape file: ' + file.name); + } + ) + .catch(console.error); + }; + fileReader.readAsArrayBuffer(file); + } + }) + .catch(console.error); } function updateKHz() { - let now = Date.now(); - let ms = now - startTime; - let cycles = cpu.getCycles(); + const now = Date.now(); + const ms = now - startTime; + const cycles = cpu.getCycles(); let delta: number; if (showFPS) { delta = renderedFrames - lastFrames; - var fps = Math.floor(delta / (ms / 1000)); - document.querySelector("#khz")!.innerHTML = fps + "fps"; + const fps = Math.floor(delta / (ms / 1000)); + document.querySelector('#khz')!.innerHTML = fps + 'fps'; } else { delta = cycles - lastCycles; - var khz = Math.floor(delta / ms); - document.querySelector("#khz")!.innerHTML = khz + "KHz"; + const khz = Math.floor(delta / ms); + document.querySelector('#khz')!.innerHTML = khz + 'KHz'; } startTime = now; @@ -155,9 +174,8 @@ function updateKHz() { lastFrames = renderedFrames; } -var loading = false; -var throttling = true; -var turbotape = false; +let throttling = true; +let turbotape = false; export function toggleFPS() { showFPS = !showFPS; @@ -165,7 +183,7 @@ export function toggleFPS() { export function toggleSpeed() { throttling = - document.querySelector("#speed_toggle")!.checked; + document.querySelector('#speed_toggle')!.checked; if (runTimer) { run(); } @@ -188,17 +206,17 @@ function run(pc?: address) { cpu.setPC(pc); } - var ival = 30, - step = 1023 * ival, - stepMax = step; + let ival = 30; + let step = 1023 * ival; + const stepMax = step; if (!throttling) { ival = 1; } - var now, - last = Date.now(); - var runFn = function () { + let now; + let last = Date.now(); + const runFn = function () { now = Date.now(); renderedFrames++; step = (now - last) * 1023; @@ -206,27 +224,25 @@ function run(pc?: address) { if (step > stepMax) { step = stepMax; } - if (document.location.hash != hashtag) { + if (document.location.hash !== hashtag) { hashtag = document.location.hash; } - if (!loading) { - if (DEBUG) { - cpu.stepCyclesDebug(TRACE ? 1 : step, function () { - var line = JSON.stringify(cpu.getState()); - if (TRACE) { - debug(line); - } else { - skidmarks.push(line); - if (skidmarks.length > 256) { - skidmarks.shift(); - } + if (DEBUG) { + cpu.stepCyclesDebug(TRACE ? 1 : step, function () { + const line = JSON.stringify(cpu.getState()); + if (TRACE) { + debug(line); + } else { + skidmarks.push(line); + if (skidmarks.length > 256) { + skidmarks.shift(); } - }); - } else { - cpu.stepCycles(step); - } - text.blit(); + } + }); + } else { + cpu.stepCycles(step); } + text.blit(); if (!paused) { requestAnimationFrame(runFn); } @@ -255,7 +271,7 @@ declare global { } } -var _key: byte; +let _key: byte; function _keydown(evt: KeyboardEvent) { if (evt.keyCode === 112) { cpu.reset(); @@ -263,19 +279,19 @@ function _keydown(evt: KeyboardEvent) { if (document.webkitIsFullScreen) { document.webkitCancelFullScreen(); } else { - var elem = document.getElementById("display"); + const elem = document.getElementById('display'); elem!.webkitRequestFullScreen(); } - } else if (evt.key === "Shift") { + } else if (evt.key === 'Shift') { keyboard.shiftKey(true); - } else if (evt.key == "Control") { + } else if (evt.key === 'Control') { keyboard.controlKey(true); } else if (!focused && (!evt.metaKey || evt.ctrlKey)) { evt.preventDefault(); - var key = mapKeyEvent(evt); - if (key != 0xff) { - if (_key != 0xff) io.keyUp(); + const key = mapKeyEvent(evt); + if (key !== 0xff) { + if (_key !== 0xff) io.keyUp(); io.keyDown(key); _key = key; } @@ -285,9 +301,9 @@ function _keydown(evt: KeyboardEvent) { function _keyup(evt: KeyboardEvent) { _key = 0xff; - if (evt.key === "Shift") { + if (evt.key === 'Shift') { keyboard.shiftKey(false); - } else if (evt.key === "Control") { + } else if (evt.key === 'Control') { keyboard.controlKey(false); } else { if (!focused) { @@ -300,9 +316,9 @@ let _updateScreenTimer: ReturnType | null = null; export function updateScreen() { const green = - document.querySelector("#green_screen")!.checked; + document.querySelector('#green_screen')!.checked; const scanlines = - document.querySelector("#show_scanlines")!.checked; + document.querySelector('#show_scanlines')!.checked; text.green(green); text.scanlines(scanlines); @@ -321,39 +337,39 @@ paused = false; export function pauseRun(b: HTMLButtonElement) { if (paused) { run(); - b.value = "Pause"; + b.value = 'Pause'; } else { stop(); - b.value = "Run"; + b.value = 'Run'; } paused = !paused; } export function openOptions() { - MicroModal.show("options-modal"); + MicroModal.show('options-modal'); } export function openLoadText(event?: MouseEvent) { if (event && event.altKey) { - MicroModal.show("local-modal"); + MicroModal.show('local-modal'); } else { - MicroModal.show("input-modal"); + MicroModal.show('input-modal'); } } export function doLoadText() { - var text = document.querySelector("#text_input")!.value; - if (!text.indexOf("//Binary")) { - var lines = text.split("\n"); + const text = document.querySelector('#text_input')!.value; + if (!text.indexOf('//Binary')) { + const lines = text.split('\n'); lines.forEach(function (line) { - var parts = line.split(": "); - if (parts.length == 2) { + const parts = line.split(': '); + if (parts.length === 2) { let addr: address = 0; if (parts[0].length > 0) { addr = parseInt(parts[0], 16); } - var data = parts[1].split(" "); - for (var idx = 0; idx < data.length; idx++) { + const data = parts[1].split(' '); + for (let idx = 0; idx < data.length; idx++) { cpu.write(addr >> 8, addr & 0xff, parseInt(data[idx], 16)); addr++; } @@ -362,28 +378,28 @@ export function doLoadText() { } else { io.paste(text); } - MicroModal.close("input-modal"); + MicroModal.close('input-modal'); } export function handleDragOver(event: DragEvent) { event.preventDefault(); - event.dataTransfer!.dropEffect = "copy"; + event.dataTransfer!.dropEffect = 'copy'; } export function handleDrop(event: DragEvent) { event.preventDefault(); event.stopPropagation(); - var dt = event.dataTransfer; + const dt = event.dataTransfer; if (dt?.files && dt.files.length > 0) { doLoadLocal(dt.files); } } export function handleDragEnd(event: DragEvent) { - var dt = event.dataTransfer; + const dt = event.dataTransfer; if (dt?.items) { - for (var i = 0; i < dt.items.length; i++) { + for (let i = 0; i < dt.items.length; i++) { dt.items.remove(i); } } else { @@ -393,39 +409,39 @@ export function handleDragEnd(event: DragEvent) { MicroModal.init(); -document.addEventListener("DOMContentLoaded", function () { +document.addEventListener('DOMContentLoaded', function () { hashtag = document.location.hash; /* * Input Handling */ - const canvas = document.querySelector("#text")!; - const context = canvas.getContext("2d")!; + const canvas = document.querySelector('#text')!; + const context = canvas.getContext('2d')!; text.setContext(context); - window.addEventListener("keydown", _keydown); - window.addEventListener("keyup", _keyup); + window.addEventListener('keydown', _keydown); + window.addEventListener('keyup', _keyup); - window.addEventListener("paste", (event) => { - var paste = event.clipboardData!.getData("text/plain"); + window.addEventListener('paste', (event) => { + const paste = event.clipboardData!.getData('text/plain'); setKeyBuffer(paste); event.preventDefault(); }); - window.addEventListener("copy", (event) => { - event.clipboardData?.setData("text/plain", text.getText()); + window.addEventListener('copy', (event) => { + event.clipboardData?.setData('text/plain', text.getText()); event.preventDefault(); }); - document.querySelectorAll("input,textarea").forEach(function (el) { - el.addEventListener("focus", function () { + document.querySelectorAll('input,textarea').forEach(function (el) { + el.addEventListener('focus', function () { focused = true; }); }); - document.querySelectorAll("input,textarea").forEach(function (el) { - el.addEventListener("blur", function () { + document.querySelectorAll('input,textarea').forEach(function (el) { + el.addEventListener('blur', function () { focused = false; }); }); @@ -433,58 +449,58 @@ document.addEventListener("DOMContentLoaded", function () { if (prefs.havePrefs()) { document - .querySelectorAll("input[type=checkbox]") + .querySelectorAll('input[type=checkbox]') .forEach(function (el) { - var val = prefs.readPref(el.id); - if (val != null) el.checked = JSON.parse(val); + const val = prefs.readPref(el.id); + if (val != null) el.checked = !!JSON.parse(val); }); document - .querySelectorAll("input[type=checkbox]") + .querySelectorAll('input[type=checkbox]') .forEach(function (el) { - el.addEventListener("change", function () { + el.addEventListener('change', function () { prefs.writePref(el.id, JSON.stringify(el.checked)); }); }); } - turbotape = document.querySelector("#turbo_tape")!.checked; + turbotape = document.querySelector('#turbo_tape')!.checked; Object.keys(window.tapes) .sort() .forEach(function (key) { - var option = document.createElement("option"); + const option = document.createElement('option'); option.value = key; option.text = key; - document.querySelector("#tape_select")!.append(option); + document.querySelector('#tape_select')!.append(option); }); function doTapeSelect() { - var tapeId = - document.querySelector("#tape_select")!.value; - var tape = window.tapes[tapeId]; + const tapeId = + document.querySelector('#tape_select')!.value; + const tape = window.tapes[tapeId]; if (!tape) { - document.querySelector("#text_input")!.value = ""; + document.querySelector('#text_input')!.value = ''; return; } - debug("Loading", tapeId); + debug('Loading', tapeId); window.location.hash = tapeId; reset(); if (turbotape) { - var trackIdx = 0, - script = ""; - var parts = tape.script.split("\n"); + let trackIdx = 0, + script = ''; + const parts = tape.script.split('\n'); // Ignore part 0 (C100R) // Split part 1 into ranges - var ranges = parts[1].split(" "); - var idx; + const ranges = parts[1].split(' '); + let idx; for (idx = 0; idx < ranges.length; idx++) { - var range = ranges[idx].split("."); - var start = parseInt(range[0], 16); - var end = parseInt(range[1], 16); - var track = tape.tracks[trackIdx]; - var kdx = 0; - for (var jdx = start; jdx <= end; jdx++) { + const range = ranges[idx].split('.'); + const start = parseInt(range[0], 16); + const end = parseInt(range[1], 16); + const track = tape.tracks[trackIdx]; + let kdx = 0; + for (let jdx = start; jdx <= end; jdx++) { cpu.write(jdx >> 8, jdx & 0xff, track[kdx++]); } trackIdx++; @@ -492,29 +508,29 @@ document.addEventListener("DOMContentLoaded", function () { // Execute parts 2-n for (idx = 2; idx < parts.length; idx++) { if (parts[idx]) { - script += parts[idx] + "\n"; + script += parts[idx] + '\n'; } } - document.querySelector("#text_input")!.value = script; + document.querySelector('#text_input')!.value = script; } else { aci.setData(tape.tracks); - document.querySelector("#text_input")!.value = + document.querySelector('#text_input')!.value = tape.script; } doLoadText(); } document - .querySelector("#tape_select")! - .addEventListener("change", doTapeSelect); + .querySelector('#tape_select')! + .addEventListener('change', doTapeSelect); run(); setInterval(updateKHz, 1000); updateScreen(); - var tape = hup(); + const tape = hup(); if (tape) { openLoadText(); - document.querySelector("#tape_select")!.value = tape; + document.querySelector('#tape_select')!.value = tape; doTapeSelect(); } }); diff --git a/js/apple1io.ts b/js/apple1io.ts index 8e0a359..76eb10c 100644 --- a/js/apple1io.ts +++ b/js/apple1io.ts @@ -9,8 +9,8 @@ * implied warranty. */ -import { TextPage } from "./canvas1"; -import type { byte } from "./types"; +import { TextPage } from './canvas1'; +import type { byte } from './types'; const LOC = { KBD: 0x10, @@ -36,20 +36,22 @@ export default class Apple1IO { return 0xd0; } read(_page: byte, off: byte): byte { - var result = 0; + let result = 0; off &= 0x13; switch (off) { case LOC.KBD: - // Keyboard - const key = this._buffer.shift(); - if (key != null) { - result = key.toUpperCase().charCodeAt(0) & 0x7f; - this._keyReady = this._buffer.length > 0; - } else { - result = this._key; - this._keyReady = false; + { + // Keyboard + const key = this._buffer.shift(); + if (key != null) { + result = key.toUpperCase().charCodeAt(0) & 0x7f; + this._keyReady = this._buffer.length > 0; + } else { + result = this._key; + this._keyReady = false; + } + result |= 0x80; } - result |= 0x80; break; case LOC.KBDRDY: result = this._keyReady ? 0x80 : 0x00; @@ -96,9 +98,9 @@ export default class Apple1IO { this._keyReady = true; } paste(buffer: string) { - buffer = buffer.replace(/\/\/.*\n/g, ""); - buffer = buffer.replace(/\n/g, "\r"); - this._buffer = buffer.split(""); + buffer = buffer.replace(/\/\/.*\n/g, ''); + buffer = buffer.replace(/\n/g, '\r'); + this._buffer = buffer.split(''); this._keyReady = true; } } diff --git a/js/base64.ts b/js/base64.ts index 80ef9d2..8cec772 100644 --- a/js/base64.ts +++ b/js/base64.ts @@ -1,6 +1,6 @@ -import { memory } from "./types"; +import { memory } from './types'; -const B64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; +const B64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; /** Encode an array of bytes in base64. */ export function base64_encode(data: null | undefined): undefined; @@ -37,7 +37,7 @@ export function base64_encode( bits, i = 0, ac = 0, - enc = ""; + enc = ''; const tmp_arr = []; if (!data) { @@ -62,14 +62,14 @@ export function base64_encode( B64.charAt(h1) + B64.charAt(h2) + B64.charAt(h3) + B64.charAt(h4); } while (i < data.length); - enc = tmp_arr.join(""); + enc = tmp_arr.join(''); switch (data.length % 3) { case 1: - enc = enc.slice(0, -2) + "=="; + enc = enc.slice(0, -2) + '=='; break; case 2: - enc = enc.slice(0, -1) + "="; + enc = enc.slice(0, -1) + '='; break; } @@ -147,11 +147,11 @@ export function base64_decode( return new Uint8Array(tmp_arr); } -const DATA_URL_PREFIX = "data:application/octet-stream;base64,"; +const DATA_URL_PREFIX = 'data:application/octet-stream;base64,'; export function base64_json_parse(json: string): unknown { const reviver = (_key: string, value: unknown) => { - if (typeof value === "string" && value.startsWith(DATA_URL_PREFIX)) { + if (typeof value === 'string' && value.startsWith(DATA_URL_PREFIX)) { return base64_decode(value.slice(DATA_URL_PREFIX.length)); } return value; diff --git a/js/canvas1.ts b/js/canvas1.ts index 64a2616..37d5f27 100644 --- a/js/canvas1.ts +++ b/js/canvas1.ts @@ -9,8 +9,8 @@ * implied warranty. */ -import { charset } from "./roms/apple1char"; -import type { byte } from "./types"; +import { charset } from './roms/apple1char'; +import type { byte } from './types'; /* 0: A9 9 AA 20 EF FF E8 8A 4C 2 0 @@ -40,9 +40,9 @@ export class TextPage { constructor() { this._buffer = []; - for (var row = 0; row < 24; row++) { + for (let row = 0; row < 24; row++) { this._buffer[row] = []; - for (var col = 0; col < 40; col++) { + for (let col = 0; col < 40; col++) { this._buffer[row][col] = col % 2 ? 0x00 : 0xff; } } @@ -58,12 +58,12 @@ export class TextPage { } write(val: byte): void { - var col; + let col; val &= 0x7f; if (this.transcript) { - if (val == 0xd) { - this.transcript += "\n"; + if (val === 0xd) { + this.transcript += '\n'; } else if (val >= 0x20) { if (val >= 0x60) { val &= 0x5f; @@ -72,7 +72,7 @@ export class TextPage { } } - if (val == 0x0d) { + if (val === 0x0d) { for (col = this._col; col < 40; col++) { this._buffer[this._row][col] = 0x20; } @@ -99,15 +99,13 @@ export class TextPage { } writeAt(row: byte, col: byte, val: byte): void { this._buffer[row][col] = val; - var data = this._page.data, - fore, - back, - color; - var off = (col * 14 + row * 560 * 8 * 2) * 4; + const data = this._page.data; + let color; + let off = (col * 14 + row * 560 * 8 * 2) * 4; - fore = this._greenMode ? this._green : this._white; - back = this._black; - var char = 0; + let fore = this._greenMode ? this._green : this._white; + const back = this._black; + let char = 0; if (!val) { if (this._blinking) { @@ -118,12 +116,12 @@ export class TextPage { char |= val & 0x40 ? 0 : 0x20; } - for (var jdx = 0; jdx < 8; jdx++) { - var b = charset[char * 8 + jdx]; - for (var idx = 0; idx < 7; idx += 1) { + for (let jdx = 0; jdx < 8; jdx++) { + let b = charset[char * 8 + jdx]; + for (let idx = 0; idx < 7; idx += 1) { b <<= 1; color = b & 0x80 ? fore : back; - var c0 = color[0], + const c0 = color[0], c1 = color[1], c2 = color[2]; data[off + 0] = data[off + 4] = c0; @@ -144,9 +142,9 @@ export class TextPage { } } _blink() { - for (var row = 0; row < 24; row++) { - for (var col = 0; col < 40; col++) { - var val = this._buffer[row][col]; + for (let row = 0; row < 24; row++) { + for (let col = 0; col < 40; col++) { + const val = this._buffer[row][col]; if (!val) { this.writeAt(row, col, val); } @@ -155,8 +153,8 @@ export class TextPage { this._dirty = true; } refresh() { - for (var row = 0; row < 24; row++) { - for (var col = 0; col < 40; col++) { + for (let row = 0; row < 24; row++) { + for (let col = 0; col < 40; col++) { this.writeAt(row, col, this._buffer[row][col]); } } @@ -186,7 +184,7 @@ export class TextPage { setContext(context: CanvasRenderingContext2D) { this._context = context; this._page = context.createImageData(560, 384); - for (var idx = 0; idx < 560 * 384 * 4; idx++) { + for (let idx = 0; idx < 560 * 384 * 4; idx++) { this._page.data[idx] = 0xff; } } @@ -202,24 +200,24 @@ export class TextPage { return charCode; } - var buffer = "", + let buffer = '', line, charCode; - var row, col; + let row, col; for (row = 0; row < 24; row++) { - line = ""; + line = ''; for (col = 0; col < 40; col++) { charCode = mapCharCode(this._buffer[row][col]); line += String.fromCharCode(charCode); } line = line.trimRight(); - buffer += line + "\n"; + buffer += line + '\n'; } return buffer; } clear() { - for (var row = 0; row < 24; row++) { - for (var col = 0; col < 40; col++) { + for (let row = 0; row < 24; row++) { + for (let col = 0; col < 40; col++) { this._buffer[row][col] = 0x20; } } @@ -228,5 +226,5 @@ export class TextPage { this.refresh(); } - transcript = ""; + transcript = ''; } diff --git a/js/cards/aci.ts b/js/cards/aci.ts index 75ae3a4..dc5b395 100644 --- a/js/cards/aci.ts +++ b/js/cards/aci.ts @@ -1,6 +1,6 @@ -import CPU6502 from "../cpu6502"; -import { debug } from "../util"; -import { byte } from "../types"; +import CPU6502 from '../cpu6502'; +import { debug } from '../util'; +import { byte } from '../types'; const rom = [ 0xa9, 0xaa, 0x20, 0xef, 0xff, 0xa9, 0x8d, 0x20, 0xef, 0xff, 0xa0, 0xff, 0xc8, @@ -50,19 +50,18 @@ export default class ACI { return 0xc1; } read(page: byte, off: byte) { - var now = this.cpu.getCycles(); - var result = rom[off]; - if (page == 0xc0) { + const now = this.cpu.getCycles(); + let result = rom[off]; + if (page === 0xc0) { if (this._recording) { - var delta = now - this._last; + const delta = now - this._last; this.buffer.push(delta); this._last = now; } else { - var progress; if (this._readOffset < this.buffer.length) { if (now > this._next) { - if (this._readOffset % 1000 == 0) { - debug("Read " + this._readOffset / 1000); + if (this._readOffset % 1000 === 0) { + debug('Read ' + this._readOffset / 1000); } this._flip = !this._flip; this._next = now + this.buffer[this._readOffset++]; @@ -70,9 +69,9 @@ export default class ACI { } result = this._flip ? rom[off | 0x01] : rom[off & 0xfe]; - progress = + const progress = Math.round((this._readOffset / this.buffer.length) * 100) / 100; - if (this._progress != progress) { + if (this._progress !== progress) { this._progress = progress; this.cb.progress(this._progress); } @@ -83,14 +82,14 @@ export default class ACI { case 0x00: this._recording = false; this._beKind = true; - debug("Entering ACI CLI"); + debug('Entering ACI CLI'); break; case 0x63: if (this._recording) { this.buffer.push(5000000); this._recording = false; } - debug("Exiting ACI CLI"); + debug('Exiting ACI CLI'); break; case 0x70: // WRITE this._recording = true; @@ -98,7 +97,7 @@ export default class ACI { this._beKind = false; this.buffer = []; } - debug("Start write"); + debug('Start write'); this._last = now; break; //case 0x7c: // WBITLOOP: @@ -107,7 +106,7 @@ export default class ACI { // break; case 0x8d: // READ this._recording = false; - debug("Start read"); + debug('Start read'); if (this._beKind) { this._readOffset = 0; this._next = now + 5000000; @@ -131,7 +130,7 @@ export default class ACI { setState() {} setData(data: number[][]) { - var seg, idx, jdx, d, b; + let seg, idx, jdx, d, b; this.buffer = []; for (seg = 0; seg < data.length; seg++) { for (idx = 0; idx < 16384; idx++) { diff --git a/js/cpu6502.ts b/js/cpu6502.ts index e4fc9f7..484138d 100644 --- a/js/cpu6502.ts +++ b/js/cpu6502.ts @@ -1,9 +1,9 @@ -import { Memory, MemberOf, MemoryPages, byte, word } from "./types"; -import { toHex } from "./util"; +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 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]; @@ -33,22 +33,22 @@ export interface CpuState { } 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 + | '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; @@ -303,7 +303,7 @@ export default class CPU6502 { const bin = c & 0xff; n = bin >> 7; z = !bin; - if (this.op.mode === "immediate") { + if (this.op.mode === 'immediate') { if (this.flavor === FLAVOR_WDC_65C02) { this.readByte(sub ? 0xb8 : 0x7f); } else { @@ -1396,10 +1396,10 @@ export default class CPU6502 { if (this.is65C02) { // Default behavior is a 1 cycle NOP unk = { - name: "NOP", + name: 'NOP', op: this.nop, modeFn: this.readNopImplied, - mode: "implied", + mode: 'implied', }; } else { // All 6502 Instructions should be defined @@ -1611,859 +1611,859 @@ export default class CPU6502 { OPS_6502: Instructions = { // LDA 0xa9: { - name: "LDA", + name: 'LDA', op: this.lda, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0xa5: { - name: "LDA", + name: 'LDA', op: this.lda, modeFn: this.readZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0xb5: { - name: "LDA", + name: 'LDA', op: this.lda, modeFn: this.readZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0xad: { - name: "LDA", + name: 'LDA', op: this.lda, modeFn: this.readAbsolute, - mode: "absolute", + mode: 'absolute', }, 0xbd: { - name: "LDA", + name: 'LDA', op: this.lda, modeFn: this.readAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, 0xb9: { - name: "LDA", + name: 'LDA', op: this.lda, modeFn: this.readAbsoluteY, - mode: "absoluteY", + mode: 'absoluteY', }, 0xa1: { - name: "LDA", + name: 'LDA', op: this.lda, modeFn: this.readZeroPageXIndirect, - mode: "zeroPageXIndirect", + mode: 'zeroPageXIndirect', }, 0xb1: { - name: "LDA", + name: 'LDA', op: this.lda, modeFn: this.readZeroPageIndirectY, - mode: "zeroPageIndirectY", + mode: 'zeroPageIndirectY', }, // LDX 0xa2: { - name: "LDX", + name: 'LDX', op: this.ldx, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0xa6: { - name: "LDX", + name: 'LDX', op: this.ldx, modeFn: this.readZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0xb6: { - name: "LDX", + name: 'LDX', op: this.ldx, modeFn: this.readZeroPageY, - mode: "zeroPageY", + mode: 'zeroPageY', }, 0xae: { - name: "LDX", + name: 'LDX', op: this.ldx, modeFn: this.readAbsolute, - mode: "absolute", + mode: 'absolute', }, 0xbe: { - name: "LDX", + name: 'LDX', op: this.ldx, modeFn: this.readAbsoluteY, - mode: "absoluteY", + mode: 'absoluteY', }, // LDY 0xa0: { - name: "LDY", + name: 'LDY', op: this.ldy, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0xa4: { - name: "LDY", + name: 'LDY', op: this.ldy, modeFn: this.readZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0xb4: { - name: "LDY", + name: 'LDY', op: this.ldy, modeFn: this.readZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0xac: { - name: "LDY", + name: 'LDY', op: this.ldy, modeFn: this.readAbsolute, - mode: "absolute", + mode: 'absolute', }, 0xbc: { - name: "LDY", + name: 'LDY', op: this.ldy, modeFn: this.readAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, // STA 0x85: { - name: "STA", + name: 'STA', op: this.sta, modeFn: this.writeZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0x95: { - name: "STA", + name: 'STA', op: this.sta, modeFn: this.writeZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0x8d: { - name: "STA", + name: 'STA', op: this.sta, modeFn: this.writeAbsolute, - mode: "absolute", + mode: 'absolute', }, 0x9d: { - name: "STA", + name: 'STA', op: this.sta, modeFn: this.writeAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, 0x99: { - name: "STA", + name: 'STA', op: this.sta, modeFn: this.writeAbsoluteY, - mode: "absoluteY", + mode: 'absoluteY', }, 0x81: { - name: "STA", + name: 'STA', op: this.sta, modeFn: this.writeZeroPageXIndirect, - mode: "zeroPageXIndirect", + mode: 'zeroPageXIndirect', }, 0x91: { - name: "STA", + name: 'STA', op: this.sta, modeFn: this.writeZeroPageIndirectY, - mode: "zeroPageIndirectY", + mode: 'zeroPageIndirectY', }, // STX 0x86: { - name: "STX", + name: 'STX', op: this.stx, modeFn: this.writeZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0x96: { - name: "STX", + name: 'STX', op: this.stx, modeFn: this.writeZeroPageY, - mode: "zeroPageY", + mode: 'zeroPageY', }, 0x8e: { - name: "STX", + name: 'STX', op: this.stx, modeFn: this.writeAbsolute, - mode: "absolute", + mode: 'absolute', }, // STY 0x84: { - name: "STY", + name: 'STY', op: this.sty, modeFn: this.writeZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0x94: { - name: "STY", + name: 'STY', op: this.sty, modeFn: this.writeZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0x8c: { - name: "STY", + name: 'STY', op: this.sty, modeFn: this.writeAbsolute, - mode: "absolute", + mode: 'absolute', }, // ADC 0x69: { - name: "ADC", + name: 'ADC', op: this.adc, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0x65: { - name: "ADC", + name: 'ADC', op: this.adc, modeFn: this.readZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0x75: { - name: "ADC", + name: 'ADC', op: this.adc, modeFn: this.readZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0x6d: { - name: "ADC", + name: 'ADC', op: this.adc, modeFn: this.readAbsolute, - mode: "absolute", + mode: 'absolute', }, 0x7d: { - name: "ADC", + name: 'ADC', op: this.adc, modeFn: this.readAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, 0x79: { - name: "ADC", + name: 'ADC', op: this.adc, modeFn: this.readAbsoluteY, - mode: "absoluteY", + mode: 'absoluteY', }, 0x61: { - name: "ADC", + name: 'ADC', op: this.adc, modeFn: this.readZeroPageXIndirect, - mode: "zeroPageXIndirect", + mode: 'zeroPageXIndirect', }, 0x71: { - name: "ADC", + name: 'ADC', op: this.adc, modeFn: this.readZeroPageIndirectY, - mode: "zeroPageIndirectY", + mode: 'zeroPageIndirectY', }, // SBC 0xe9: { - name: "SBC", + name: 'SBC', op: this.sbc, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0xe5: { - name: "SBC", + name: 'SBC', op: this.sbc, modeFn: this.readZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0xf5: { - name: "SBC", + name: 'SBC', op: this.sbc, modeFn: this.readZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0xed: { - name: "SBC", + name: 'SBC', op: this.sbc, modeFn: this.readAbsolute, - mode: "absolute", + mode: 'absolute', }, 0xfd: { - name: "SBC", + name: 'SBC', op: this.sbc, modeFn: this.readAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, 0xf9: { - name: "SBC", + name: 'SBC', op: this.sbc, modeFn: this.readAbsoluteY, - mode: "absoluteY", + mode: 'absoluteY', }, 0xe1: { - name: "SBC", + name: 'SBC', op: this.sbc, modeFn: this.readZeroPageXIndirect, - mode: "zeroPageXIndirect", + mode: 'zeroPageXIndirect', }, 0xf1: { - name: "SBC", + name: 'SBC', op: this.sbc, modeFn: this.readZeroPageIndirectY, - mode: "zeroPageIndirectY", + mode: 'zeroPageIndirectY', }, // INC 0xe6: { - name: "INC", + name: 'INC', op: this.inc, modeFn: this.readAddrZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0xf6: { - name: "INC", + name: 'INC', op: this.inc, modeFn: this.readAddrZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0xee: { - name: "INC", + name: 'INC', op: this.inc, modeFn: this.readAddrAbsolute, - mode: "absolute", + mode: 'absolute', }, 0xfe: { - name: "INC", + name: 'INC', op: this.inc, modeFn: this.readAddrAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, // INX - 0xe8: { name: "INX", op: this.inx, modeFn: this.implied, mode: "implied" }, + 0xe8: { name: 'INX', op: this.inx, modeFn: this.implied, mode: 'implied' }, // INY - 0xc8: { name: "INY", op: this.iny, modeFn: this.implied, mode: "implied" }, + 0xc8: { name: 'INY', op: this.iny, modeFn: this.implied, mode: 'implied' }, // DEC 0xc6: { - name: "DEC", + name: 'DEC', op: this.dec, modeFn: this.readAddrZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0xd6: { - name: "DEC", + name: 'DEC', op: this.dec, modeFn: this.readAddrZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0xce: { - name: "DEC", + name: 'DEC', op: this.dec, modeFn: this.readAddrAbsolute, - mode: "absolute", + mode: 'absolute', }, 0xde: { - name: "DEC", + name: 'DEC', op: this.dec, modeFn: this.readAddrAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, // DEX - 0xca: { name: "DEX", op: this.dex, modeFn: this.implied, mode: "implied" }, + 0xca: { name: 'DEX', op: this.dex, modeFn: this.implied, mode: 'implied' }, // DEY - 0x88: { name: "DEY", op: this.dey, modeFn: this.implied, mode: "implied" }, + 0x88: { name: 'DEY', op: this.dey, modeFn: this.implied, mode: 'implied' }, // ASL 0x0a: { - name: "ASL", + name: 'ASL', op: this.aslA, modeFn: this.implied, - mode: "accumulator", + mode: 'accumulator', }, 0x06: { - name: "ASL", + name: 'ASL', op: this.asl, modeFn: this.readAddrZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0x16: { - name: "ASL", + name: 'ASL', op: this.asl, modeFn: this.readAddrZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0x0e: { - name: "ASL", + name: 'ASL', op: this.asl, modeFn: this.readAddrAbsolute, - mode: "absolute", + mode: 'absolute', }, 0x1e: { - name: "ASL", + name: 'ASL', op: this.asl, modeFn: this.readAddrAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, // LSR 0x4a: { - name: "LSR", + name: 'LSR', op: this.lsrA, modeFn: this.implied, - mode: "accumulator", + mode: 'accumulator', }, 0x46: { - name: "LSR", + name: 'LSR', op: this.lsr, modeFn: this.readAddrZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0x56: { - name: "LSR", + name: 'LSR', op: this.lsr, modeFn: this.readAddrZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0x4e: { - name: "LSR", + name: 'LSR', op: this.lsr, modeFn: this.readAddrAbsolute, - mode: "absolute", + mode: 'absolute', }, 0x5e: { - name: "LSR", + name: 'LSR', op: this.lsr, modeFn: this.readAddrAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, // ROL 0x2a: { - name: "ROL", + name: 'ROL', op: this.rolA, modeFn: this.implied, - mode: "accumulator", + mode: 'accumulator', }, 0x26: { - name: "ROL", + name: 'ROL', op: this.rol, modeFn: this.readAddrZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0x36: { - name: "ROL", + name: 'ROL', op: this.rol, modeFn: this.readAddrZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0x2e: { - name: "ROL", + name: 'ROL', op: this.rol, modeFn: this.readAddrAbsolute, - mode: "absolute", + mode: 'absolute', }, 0x3e: { - name: "ROL", + name: 'ROL', op: this.rol, modeFn: this.readAddrAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, // ROR 0x6a: { - name: "ROR", + name: 'ROR', op: this.rorA, modeFn: this.implied, - mode: "accumulator", + mode: 'accumulator', }, 0x66: { - name: "ROR", + name: 'ROR', op: this.ror, modeFn: this.readAddrZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0x76: { - name: "ROR", + name: 'ROR', op: this.ror, modeFn: this.readAddrZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0x6e: { - name: "ROR", + name: 'ROR', op: this.ror, modeFn: this.readAddrAbsolute, - mode: "absolute", + mode: 'absolute', }, 0x7e: { - name: "ROR", + name: 'ROR', op: this.ror, modeFn: this.readAddrAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, // AND 0x29: { - name: "AND", + name: 'AND', op: this.and, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0x25: { - name: "AND", + name: 'AND', op: this.and, modeFn: this.readZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0x35: { - name: "AND", + name: 'AND', op: this.and, modeFn: this.readZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0x2d: { - name: "AND", + name: 'AND', op: this.and, modeFn: this.readAbsolute, - mode: "absolute", + mode: 'absolute', }, 0x3d: { - name: "AND", + name: 'AND', op: this.and, modeFn: this.readAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, 0x39: { - name: "AND", + name: 'AND', op: this.and, modeFn: this.readAbsoluteY, - mode: "absoluteY", + mode: 'absoluteY', }, 0x21: { - name: "AND", + name: 'AND', op: this.and, modeFn: this.readZeroPageXIndirect, - mode: "zeroPageXIndirect", + mode: 'zeroPageXIndirect', }, 0x31: { - name: "AND", + name: 'AND', op: this.and, modeFn: this.readZeroPageIndirectY, - mode: "zeroPageIndirectY", + mode: 'zeroPageIndirectY', }, // ORA 0x09: { - name: "ORA", + name: 'ORA', op: this.ora, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0x05: { - name: "ORA", + name: 'ORA', op: this.ora, modeFn: this.readZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0x15: { - name: "ORA", + name: 'ORA', op: this.ora, modeFn: this.readZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0x0d: { - name: "ORA", + name: 'ORA', op: this.ora, modeFn: this.readAbsolute, - mode: "absolute", + mode: 'absolute', }, 0x1d: { - name: "ORA", + name: 'ORA', op: this.ora, modeFn: this.readAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, 0x19: { - name: "ORA", + name: 'ORA', op: this.ora, modeFn: this.readAbsoluteY, - mode: "absoluteY", + mode: 'absoluteY', }, 0x01: { - name: "ORA", + name: 'ORA', op: this.ora, modeFn: this.readZeroPageXIndirect, - mode: "zeroPageXIndirect", + mode: 'zeroPageXIndirect', }, 0x11: { - name: "ORA", + name: 'ORA', op: this.ora, modeFn: this.readZeroPageIndirectY, - mode: "zeroPageIndirectY", + mode: 'zeroPageIndirectY', }, // EOR 0x49: { - name: "EOR", + name: 'EOR', op: this.eor, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0x45: { - name: "EOR", + name: 'EOR', op: this.eor, modeFn: this.readZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0x55: { - name: "EOR", + name: 'EOR', op: this.eor, modeFn: this.readZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0x4d: { - name: "EOR", + name: 'EOR', op: this.eor, modeFn: this.readAbsolute, - mode: "absolute", + mode: 'absolute', }, 0x5d: { - name: "EOR", + name: 'EOR', op: this.eor, modeFn: this.readAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, 0x59: { - name: "EOR", + name: 'EOR', op: this.eor, modeFn: this.readAbsoluteY, - mode: "absoluteY", + mode: 'absoluteY', }, 0x41: { - name: "EOR", + name: 'EOR', op: this.eor, modeFn: this.readZeroPageXIndirect, - mode: "zeroPageXIndirect", + mode: 'zeroPageXIndirect', }, 0x51: { - name: "EOR", + name: 'EOR', op: this.eor, modeFn: this.readZeroPageIndirectY, - mode: "zeroPageIndirectY", + mode: 'zeroPageIndirectY', }, // CMP 0xc9: { - name: "CMP", + name: 'CMP', op: this.cmp, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0xc5: { - name: "CMP", + name: 'CMP', op: this.cmp, modeFn: this.readZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0xd5: { - name: "CMP", + name: 'CMP', op: this.cmp, modeFn: this.readZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0xcd: { - name: "CMP", + name: 'CMP', op: this.cmp, modeFn: this.readAbsolute, - mode: "absolute", + mode: 'absolute', }, 0xdd: { - name: "CMP", + name: 'CMP', op: this.cmp, modeFn: this.readAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, 0xd9: { - name: "CMP", + name: 'CMP', op: this.cmp, modeFn: this.readAbsoluteY, - mode: "absoluteY", + mode: 'absoluteY', }, 0xc1: { - name: "CMP", + name: 'CMP', op: this.cmp, modeFn: this.readZeroPageXIndirect, - mode: "zeroPageXIndirect", + mode: 'zeroPageXIndirect', }, 0xd1: { - name: "CMP", + name: 'CMP', op: this.cmp, modeFn: this.readZeroPageIndirectY, - mode: "zeroPageIndirectY", + mode: 'zeroPageIndirectY', }, // CPX 0xe0: { - name: "CPX", + name: 'CPX', op: this.cpx, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0xe4: { - name: "CPX", + name: 'CPX', op: this.cpx, modeFn: this.readZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0xec: { - name: "CPX", + name: 'CPX', op: this.cpx, modeFn: this.readAbsolute, - mode: "absolute", + mode: 'absolute', }, // CPY 0xc0: { - name: "CPY", + name: 'CPY', op: this.cpy, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0xc4: { - name: "CPY", + name: 'CPY', op: this.cpy, modeFn: this.readZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0xcc: { - name: "CPY", + name: 'CPY', op: this.cpy, modeFn: this.readAbsolute, - mode: "absolute", + mode: 'absolute', }, // BIT 0x24: { - name: "BIT", + name: 'BIT', op: this.bit, modeFn: this.readZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0x2c: { - name: "BIT", + name: 'BIT', op: this.bit, modeFn: this.readAbsolute, - mode: "absolute", + mode: 'absolute', }, // BCC - 0x90: { name: "BCC", op: this.brc, modeFn: flags.C, mode: "relative" }, + 0x90: { name: 'BCC', op: this.brc, modeFn: flags.C, mode: 'relative' }, // BCS - 0xb0: { name: "BCS", op: this.brs, modeFn: flags.C, mode: "relative" }, + 0xb0: { name: 'BCS', op: this.brs, modeFn: flags.C, mode: 'relative' }, // BEQ - 0xf0: { name: "BEQ", op: this.brs, modeFn: flags.Z, mode: "relative" }, + 0xf0: { name: 'BEQ', op: this.brs, modeFn: flags.Z, mode: 'relative' }, // BMI - 0x30: { name: "BMI", op: this.brs, modeFn: flags.N, mode: "relative" }, + 0x30: { name: 'BMI', op: this.brs, modeFn: flags.N, mode: 'relative' }, // BNE - 0xd0: { name: "BNE", op: this.brc, modeFn: flags.Z, mode: "relative" }, + 0xd0: { name: 'BNE', op: this.brc, modeFn: flags.Z, mode: 'relative' }, // BPL - 0x10: { name: "BPL", op: this.brc, modeFn: flags.N, mode: "relative" }, + 0x10: { name: 'BPL', op: this.brc, modeFn: flags.N, mode: 'relative' }, // BVC - 0x50: { name: "BVC", op: this.brc, modeFn: flags.V, mode: "relative" }, + 0x50: { name: 'BVC', op: this.brc, modeFn: flags.V, mode: 'relative' }, // BVS - 0x70: { name: "BVS", op: this.brs, modeFn: flags.V, mode: "relative" }, + 0x70: { name: 'BVS', op: this.brs, modeFn: flags.V, mode: 'relative' }, // TAX - 0xaa: { name: "TAX", op: this.tax, modeFn: this.implied, mode: "implied" }, + 0xaa: { name: 'TAX', op: this.tax, modeFn: this.implied, mode: 'implied' }, // TXA - 0x8a: { name: "TXA", op: this.txa, modeFn: this.implied, mode: "implied" }, + 0x8a: { name: 'TXA', op: this.txa, modeFn: this.implied, mode: 'implied' }, // TAY - 0xa8: { name: "TAY", op: this.tay, modeFn: this.implied, mode: "implied" }, + 0xa8: { name: 'TAY', op: this.tay, modeFn: this.implied, mode: 'implied' }, // TYA - 0x98: { name: "TYA", op: this.tya, modeFn: this.implied, mode: "implied" }, + 0x98: { name: 'TYA', op: this.tya, modeFn: this.implied, mode: 'implied' }, // TSX - 0xba: { name: "TSX", op: this.tsx, modeFn: this.implied, mode: "implied" }, + 0xba: { name: 'TSX', op: this.tsx, modeFn: this.implied, mode: 'implied' }, // TXS - 0x9a: { name: "TXS", op: this.txs, modeFn: this.implied, mode: "implied" }, + 0x9a: { name: 'TXS', op: this.txs, modeFn: this.implied, mode: 'implied' }, // PHA - 0x48: { name: "PHA", op: this.pha, modeFn: this.implied, mode: "implied" }, + 0x48: { name: 'PHA', op: this.pha, modeFn: this.implied, mode: 'implied' }, // PLA - 0x68: { name: "PLA", op: this.pla, modeFn: this.implied, mode: "implied" }, + 0x68: { name: 'PLA', op: this.pla, modeFn: this.implied, mode: 'implied' }, // PHP - 0x08: { name: "PHP", op: this.php, modeFn: this.implied, mode: "implied" }, + 0x08: { name: 'PHP', op: this.php, modeFn: this.implied, mode: 'implied' }, // PLP - 0x28: { name: "PLP", op: this.plp, modeFn: this.implied, mode: "implied" }, + 0x28: { name: 'PLP', op: this.plp, modeFn: this.implied, mode: 'implied' }, // JMP 0x4c: { - name: "JMP", + name: 'JMP', op: this.jmp, modeFn: this.readAddrAbsolute, - mode: "absolute", + mode: 'absolute', }, 0x6c: { - name: "JMP", + name: 'JMP', op: this.jmp, modeFn: this.readAddrAbsoluteIndirectBug, - mode: "absoluteIndirect", + mode: 'absoluteIndirect', }, // JSR 0x20: { - name: "JSR", + name: 'JSR', op: this.jsr, modeFn: this.readAddrAbsolute, - mode: "absolute", + mode: 'absolute', }, // RTS - 0x60: { name: "RTS", op: this.rts, modeFn: this.implied, mode: "implied" }, + 0x60: { name: 'RTS', op: this.rts, modeFn: this.implied, mode: 'implied' }, // RTI - 0x40: { name: "RTI", op: this.rti, modeFn: this.implied, mode: "implied" }, + 0x40: { name: 'RTI', op: this.rti, modeFn: this.implied, mode: 'implied' }, // SEC - 0x38: { name: "SEC", op: this.set, modeFn: flags.C, mode: "implied" }, + 0x38: { name: 'SEC', op: this.set, modeFn: flags.C, mode: 'implied' }, // SED - 0xf8: { name: "SED", op: this.set, modeFn: flags.D, mode: "implied" }, + 0xf8: { name: 'SED', op: this.set, modeFn: flags.D, mode: 'implied' }, // SEI - 0x78: { name: "SEI", op: this.set, modeFn: flags.I, mode: "implied" }, + 0x78: { name: 'SEI', op: this.set, modeFn: flags.I, mode: 'implied' }, // CLC - 0x18: { name: "CLC", op: this.clr, modeFn: flags.C, mode: "implied" }, + 0x18: { name: 'CLC', op: this.clr, modeFn: flags.C, mode: 'implied' }, // CLD - 0xd8: { name: "CLD", op: this.clr, modeFn: flags.D, mode: "implied" }, + 0xd8: { name: 'CLD', op: this.clr, modeFn: flags.D, mode: 'implied' }, // CLI - 0x58: { name: "CLI", op: this.clr, modeFn: flags.I, mode: "implied" }, + 0x58: { name: 'CLI', op: this.clr, modeFn: flags.I, mode: 'implied' }, // CLV - 0xb8: { name: "CLV", op: this.clr, modeFn: flags.V, mode: "implied" }, + 0xb8: { name: 'CLV', op: this.clr, modeFn: flags.V, mode: 'implied' }, // NOP - 0xea: { name: "NOP", op: this.nop, modeFn: this.implied, mode: "implied" }, + 0xea: { name: 'NOP', op: this.nop, modeFn: this.implied, mode: 'implied' }, // BRK 0x00: { - name: "BRK", + name: 'BRK', op: this.brk, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, }; @@ -2472,946 +2472,946 @@ export default class CPU6502 { OPS_65C02: Instructions = { // INC / DEC A 0x1a: { - name: "INC", + name: 'INC', op: this.incA, modeFn: this.implied, - mode: "accumulator", + mode: 'accumulator', }, 0x3a: { - name: "DEC", + name: 'DEC', op: this.decA, modeFn: this.implied, - mode: "accumulator", + mode: 'accumulator', }, // Indirect Zero Page for the masses 0x12: { - name: "ORA", + name: 'ORA', op: this.ora, modeFn: this.readZeroPageIndirect, - mode: "zeroPageIndirect", + mode: 'zeroPageIndirect', }, 0x32: { - name: "AND", + name: 'AND', op: this.and, modeFn: this.readZeroPageIndirect, - mode: "zeroPageIndirect", + mode: 'zeroPageIndirect', }, 0x52: { - name: "EOR", + name: 'EOR', op: this.eor, modeFn: this.readZeroPageIndirect, - mode: "zeroPageIndirect", + mode: 'zeroPageIndirect', }, 0x72: { - name: "ADC", + name: 'ADC', op: this.adc, modeFn: this.readZeroPageIndirect, - mode: "zeroPageIndirect", + mode: 'zeroPageIndirect', }, 0x92: { - name: "STA", + name: 'STA', op: this.sta, modeFn: this.writeZeroPageIndirect, - mode: "zeroPageIndirect", + mode: 'zeroPageIndirect', }, 0xb2: { - name: "LDA", + name: 'LDA', op: this.lda, modeFn: this.readZeroPageIndirect, - mode: "zeroPageIndirect", + mode: 'zeroPageIndirect', }, 0xd2: { - name: "CMP", + name: 'CMP', op: this.cmp, modeFn: this.readZeroPageIndirect, - mode: "zeroPageIndirect", + mode: 'zeroPageIndirect', }, 0xf2: { - name: "SBC", + name: 'SBC', op: this.sbc, modeFn: this.readZeroPageIndirect, - mode: "zeroPageIndirect", + mode: 'zeroPageIndirect', }, // Better BIT 0x34: { - name: "BIT", + name: 'BIT', op: this.bit, modeFn: this.readZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0x3c: { - name: "BIT", + name: 'BIT', op: this.bit, modeFn: this.readAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, 0x89: { - name: "BIT", + name: 'BIT', op: this.bitI, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, // JMP absolute indirect indexed 0x6c: { - name: "JMP", + name: 'JMP', op: this.jmp, modeFn: this.readAddrAbsoluteIndirect, - mode: "absoluteIndirect", + mode: 'absoluteIndirect', }, 0x7c: { - name: "JMP", + name: 'JMP', op: this.jmp, modeFn: this.readAddrAbsoluteXIndirect, - mode: "absoluteXIndirect", + mode: 'absoluteXIndirect', }, // BBR/BBS - 0x0f: { name: "BBR0", op: this.bbr, modeFn: 0, mode: "zeroPage_relative" }, - 0x1f: { name: "BBR1", op: this.bbr, modeFn: 1, mode: "zeroPage_relative" }, - 0x2f: { name: "BBR2", op: this.bbr, modeFn: 2, mode: "zeroPage_relative" }, - 0x3f: { name: "BBR3", op: this.bbr, modeFn: 3, mode: "zeroPage_relative" }, - 0x4f: { name: "BBR4", op: this.bbr, modeFn: 4, mode: "zeroPage_relative" }, - 0x5f: { name: "BBR5", op: this.bbr, modeFn: 5, mode: "zeroPage_relative" }, - 0x6f: { name: "BBR6", op: this.bbr, modeFn: 6, mode: "zeroPage_relative" }, - 0x7f: { name: "BBR7", op: this.bbr, modeFn: 7, mode: "zeroPage_relative" }, + 0x0f: { name: 'BBR0', op: this.bbr, modeFn: 0, mode: 'zeroPage_relative' }, + 0x1f: { name: 'BBR1', op: this.bbr, modeFn: 1, mode: 'zeroPage_relative' }, + 0x2f: { name: 'BBR2', op: this.bbr, modeFn: 2, mode: 'zeroPage_relative' }, + 0x3f: { name: 'BBR3', op: this.bbr, modeFn: 3, mode: 'zeroPage_relative' }, + 0x4f: { name: 'BBR4', op: this.bbr, modeFn: 4, mode: 'zeroPage_relative' }, + 0x5f: { name: 'BBR5', op: this.bbr, modeFn: 5, mode: 'zeroPage_relative' }, + 0x6f: { name: 'BBR6', op: this.bbr, modeFn: 6, mode: 'zeroPage_relative' }, + 0x7f: { name: 'BBR7', op: this.bbr, modeFn: 7, mode: 'zeroPage_relative' }, - 0x8f: { name: "BBS0", op: this.bbs, modeFn: 0, mode: "zeroPage_relative" }, - 0x9f: { name: "BBS1", op: this.bbs, modeFn: 1, mode: "zeroPage_relative" }, - 0xaf: { name: "BBS2", op: this.bbs, modeFn: 2, mode: "zeroPage_relative" }, - 0xbf: { name: "BBS3", op: this.bbs, modeFn: 3, mode: "zeroPage_relative" }, - 0xcf: { name: "BBS4", op: this.bbs, modeFn: 4, mode: "zeroPage_relative" }, - 0xdf: { name: "BBS5", op: this.bbs, modeFn: 5, mode: "zeroPage_relative" }, - 0xef: { name: "BBS6", op: this.bbs, modeFn: 6, mode: "zeroPage_relative" }, - 0xff: { name: "BBS7", op: this.bbs, modeFn: 7, mode: "zeroPage_relative" }, + 0x8f: { name: 'BBS0', op: this.bbs, modeFn: 0, mode: 'zeroPage_relative' }, + 0x9f: { name: 'BBS1', op: this.bbs, modeFn: 1, mode: 'zeroPage_relative' }, + 0xaf: { name: 'BBS2', op: this.bbs, modeFn: 2, mode: 'zeroPage_relative' }, + 0xbf: { name: 'BBS3', op: this.bbs, modeFn: 3, mode: 'zeroPage_relative' }, + 0xcf: { name: 'BBS4', op: this.bbs, modeFn: 4, mode: 'zeroPage_relative' }, + 0xdf: { name: 'BBS5', op: this.bbs, modeFn: 5, mode: 'zeroPage_relative' }, + 0xef: { name: 'BBS6', op: this.bbs, modeFn: 6, mode: 'zeroPage_relative' }, + 0xff: { name: 'BBS7', op: this.bbs, modeFn: 7, mode: 'zeroPage_relative' }, // BRA - 0x80: { name: "BRA", op: this.brc, modeFn: 0, mode: "relative" }, + 0x80: { name: 'BRA', op: this.brc, modeFn: 0, mode: 'relative' }, // NOP 0x02: { - name: "NOP", + name: 'NOP', op: this.nop, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0x22: { - name: "NOP", + name: 'NOP', op: this.nop, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0x42: { - name: "NOP", + name: 'NOP', op: this.nop, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0x44: { - name: "NOP", + name: 'NOP', op: this.nop, modeFn: this.readZeroPage, - mode: "immediate", + mode: 'immediate', }, 0x54: { - name: "NOP", + name: 'NOP', op: this.nop, modeFn: this.readZeroPageX, - mode: "immediate", + mode: 'immediate', }, 0x62: { - name: "NOP", + name: 'NOP', op: this.nop, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0x82: { - name: "NOP", + name: 'NOP', op: this.nop, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0xc2: { - name: "NOP", + name: 'NOP', op: this.nop, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0xd4: { - name: "NOP", + name: 'NOP', op: this.nop, modeFn: this.readZeroPageX, - mode: "immediate", + mode: 'immediate', }, 0xe2: { - name: "NOP", + name: 'NOP', op: this.nop, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0xf4: { - name: "NOP", + name: 'NOP', op: this.nop, modeFn: this.readZeroPageX, - mode: "immediate", + mode: 'immediate', }, - 0x5c: { name: "NOP", op: this.nop, modeFn: this.readNop, mode: "absolute" }, - 0xdc: { name: "NOP", op: this.nop, modeFn: this.readNop, mode: "absolute" }, - 0xfc: { name: "NOP", op: this.nop, modeFn: this.readNop, mode: "absolute" }, + 0x5c: { name: 'NOP', op: this.nop, modeFn: this.readNop, mode: 'absolute' }, + 0xdc: { name: 'NOP', op: this.nop, modeFn: this.readNop, mode: 'absolute' }, + 0xfc: { name: 'NOP', op: this.nop, modeFn: this.readNop, mode: 'absolute' }, // PHX - 0xda: { name: "PHX", op: this.phx, modeFn: this.implied, mode: "implied" }, + 0xda: { name: 'PHX', op: this.phx, modeFn: this.implied, mode: 'implied' }, // PHY - 0x5a: { name: "PHY", op: this.phy, modeFn: this.implied, mode: "implied" }, + 0x5a: { name: 'PHY', op: this.phy, modeFn: this.implied, mode: 'implied' }, // PLX - 0xfa: { name: "PLX", op: this.plx, modeFn: this.implied, mode: "implied" }, + 0xfa: { name: 'PLX', op: this.plx, modeFn: this.implied, mode: 'implied' }, // PLY - 0x7a: { name: "PLY", op: this.ply, modeFn: this.implied, mode: "implied" }, + 0x7a: { name: 'PLY', op: this.ply, modeFn: this.implied, mode: 'implied' }, // RMB/SMB - 0x07: { name: "RMB0", op: this.rmb, modeFn: 0, mode: "zeroPage" }, - 0x17: { name: "RMB1", op: this.rmb, modeFn: 1, mode: "zeroPage" }, - 0x27: { name: "RMB2", op: this.rmb, modeFn: 2, mode: "zeroPage" }, - 0x37: { name: "RMB3", op: this.rmb, modeFn: 3, mode: "zeroPage" }, - 0x47: { name: "RMB4", op: this.rmb, modeFn: 4, mode: "zeroPage" }, - 0x57: { name: "RMB5", op: this.rmb, modeFn: 5, mode: "zeroPage" }, - 0x67: { name: "RMB6", op: this.rmb, modeFn: 6, mode: "zeroPage" }, - 0x77: { name: "RMB7", op: this.rmb, modeFn: 7, mode: "zeroPage" }, + 0x07: { name: 'RMB0', op: this.rmb, modeFn: 0, mode: 'zeroPage' }, + 0x17: { name: 'RMB1', op: this.rmb, modeFn: 1, mode: 'zeroPage' }, + 0x27: { name: 'RMB2', op: this.rmb, modeFn: 2, mode: 'zeroPage' }, + 0x37: { name: 'RMB3', op: this.rmb, modeFn: 3, mode: 'zeroPage' }, + 0x47: { name: 'RMB4', op: this.rmb, modeFn: 4, mode: 'zeroPage' }, + 0x57: { name: 'RMB5', op: this.rmb, modeFn: 5, mode: 'zeroPage' }, + 0x67: { name: 'RMB6', op: this.rmb, modeFn: 6, mode: 'zeroPage' }, + 0x77: { name: 'RMB7', op: this.rmb, modeFn: 7, mode: 'zeroPage' }, - 0x87: { name: "SMB0", op: this.smb, modeFn: 0, mode: "zeroPage" }, - 0x97: { name: "SMB1", op: this.smb, modeFn: 1, mode: "zeroPage" }, - 0xa7: { name: "SMB2", op: this.smb, modeFn: 2, mode: "zeroPage" }, - 0xb7: { name: "SMB3", op: this.smb, modeFn: 3, mode: "zeroPage" }, - 0xc7: { name: "SMB4", op: this.smb, modeFn: 4, mode: "zeroPage" }, - 0xd7: { name: "SMB5", op: this.smb, modeFn: 5, mode: "zeroPage" }, - 0xe7: { name: "SMB6", op: this.smb, modeFn: 6, mode: "zeroPage" }, - 0xf7: { name: "SMB7", op: this.smb, modeFn: 7, mode: "zeroPage" }, + 0x87: { name: 'SMB0', op: this.smb, modeFn: 0, mode: 'zeroPage' }, + 0x97: { name: 'SMB1', op: this.smb, modeFn: 1, mode: 'zeroPage' }, + 0xa7: { name: 'SMB2', op: this.smb, modeFn: 2, mode: 'zeroPage' }, + 0xb7: { name: 'SMB3', op: this.smb, modeFn: 3, mode: 'zeroPage' }, + 0xc7: { name: 'SMB4', op: this.smb, modeFn: 4, mode: 'zeroPage' }, + 0xd7: { name: 'SMB5', op: this.smb, modeFn: 5, mode: 'zeroPage' }, + 0xe7: { name: 'SMB6', op: this.smb, modeFn: 6, mode: 'zeroPage' }, + 0xf7: { name: 'SMB7', op: this.smb, modeFn: 7, mode: 'zeroPage' }, // STZ 0x64: { - name: "STZ", + name: 'STZ', op: this.stz, modeFn: this.writeZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0x74: { - name: "STZ", + name: 'STZ', op: this.stz, modeFn: this.writeZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0x9c: { - name: "STZ", + name: 'STZ', op: this.stz, modeFn: this.writeAbsolute, - mode: "absolute", + mode: 'absolute', }, 0x9e: { - name: "STZ", + name: 'STZ', op: this.stz, modeFn: this.writeAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, // TRB 0x14: { - name: "TRB", + name: 'TRB', op: this.trb, modeFn: this.readAddrZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0x1c: { - name: "TRB", + name: 'TRB', op: this.trb, modeFn: this.readAddrAbsolute, - mode: "absolute", + mode: 'absolute', }, // TSB 0x04: { - name: "TSB", + name: 'TSB', op: this.tsb, modeFn: this.readAddrZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0x0c: { - name: "TSB", + name: 'TSB', op: this.tsb, modeFn: this.readAddrAbsolute, - mode: "absolute", + mode: 'absolute', }, }; OPS_NMOS_6502: Instructions = { // ASO 0x0f: { - name: "ASO", + name: 'ASO', op: this.aso, modeFn: this.readAddrAbsolute, - mode: "absolute", + mode: 'absolute', }, 0x1f: { - name: "ASO", + name: 'ASO', op: this.aso, modeFn: this.readAddrAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, 0x1b: { - name: "ASO", + name: 'ASO', op: this.aso, modeFn: this.readAddrAbsoluteY, - mode: "absoluteY", + mode: 'absoluteY', }, 0x07: { - name: "ASO", + name: 'ASO', op: this.aso, modeFn: this.readAddrZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0x17: { - name: "ASO", + name: 'ASO', op: this.aso, modeFn: this.readAddrZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0x03: { - name: "ASO", + name: 'ASO', op: this.aso, modeFn: this.readAddrZeroPageXIndirect, - mode: "zeroPageXIndirect", + mode: 'zeroPageXIndirect', }, 0x13: { - name: "ASO", + name: 'ASO', op: this.aso, modeFn: this.readAddrZeroPageIndirectY, - mode: "zeroPageIndirectY", + mode: 'zeroPageIndirectY', }, // RLA 0x2f: { - name: "RLA", + name: 'RLA', op: this.rla, modeFn: this.readAddrAbsolute, - mode: "absolute", + mode: 'absolute', }, 0x3f: { - name: "RLA", + name: 'RLA', op: this.rla, modeFn: this.readAddrAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, 0x3b: { - name: "RLA", + name: 'RLA', op: this.rla, modeFn: this.readAddrAbsoluteY, - mode: "absoluteY", + mode: 'absoluteY', }, 0x27: { - name: "RLA", + name: 'RLA', op: this.rla, modeFn: this.readAddrZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0x37: { - name: "RLA", + name: 'RLA', op: this.rla, modeFn: this.readAddrZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0x23: { - name: "RLA", + name: 'RLA', op: this.rla, modeFn: this.readAddrZeroPageXIndirect, - mode: "zeroPageXIndirect", + mode: 'zeroPageXIndirect', }, 0x33: { - name: "RLA", + name: 'RLA', op: this.rla, modeFn: this.readAddrZeroPageIndirectY, - mode: "zeroPageIndirectY", + mode: 'zeroPageIndirectY', }, // LSE 0x4f: { - name: "LSE", + name: 'LSE', op: this.lse, modeFn: this.readAddrAbsolute, - mode: "absolute", + mode: 'absolute', }, 0x5f: { - name: "LSE", + name: 'LSE', op: this.lse, modeFn: this.readAddrAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, 0x5b: { - name: "LSE", + name: 'LSE', op: this.lse, modeFn: this.readAddrAbsoluteY, - mode: "absoluteY", + mode: 'absoluteY', }, 0x47: { - name: "LSE", + name: 'LSE', op: this.lse, modeFn: this.readAddrZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0x57: { - name: "LSE", + name: 'LSE', op: this.lse, modeFn: this.readAddrZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0x43: { - name: "LSE", + name: 'LSE', op: this.lse, modeFn: this.readAddrZeroPageXIndirect, - mode: "zeroPageXIndirect", + mode: 'zeroPageXIndirect', }, 0x53: { - name: "LSE", + name: 'LSE', op: this.lse, modeFn: this.readAddrZeroPageIndirectY, - mode: "zeroPageIndirectY", + mode: 'zeroPageIndirectY', }, // RRA 0x6f: { - name: "RRA", + name: 'RRA', op: this.rra, modeFn: this.readAddrAbsolute, - mode: "absolute", + mode: 'absolute', }, 0x7f: { - name: "RRA", + name: 'RRA', op: this.rra, modeFn: this.readAddrAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, 0x7b: { - name: "RRA", + name: 'RRA', op: this.rra, modeFn: this.readAddrAbsoluteY, - mode: "absoluteY", + mode: 'absoluteY', }, 0x67: { - name: "RRA", + name: 'RRA', op: this.rra, modeFn: this.readAddrZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0x77: { - name: "RRA", + name: 'RRA', op: this.rra, modeFn: this.readAddrZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0x63: { - name: "RRA", + name: 'RRA', op: this.rra, modeFn: this.readAddrZeroPageXIndirect, - mode: "zeroPageXIndirect", + mode: 'zeroPageXIndirect', }, 0x73: { - name: "RRA", + name: 'RRA', op: this.rra, modeFn: this.readAddrZeroPageIndirectY, - mode: "zeroPageIndirectY", + mode: 'zeroPageIndirectY', }, // AXS 0x8f: { - name: "AXS", + name: 'AXS', op: this.axs, modeFn: this.writeAbsolute, - mode: "absolute", + mode: 'absolute', }, 0x87: { - name: "AXS", + name: 'AXS', op: this.axs, modeFn: this.writeZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0x97: { - name: "AXS", + name: 'AXS', op: this.axs, modeFn: this.writeZeroPageY, - mode: "zeroPageY", + mode: 'zeroPageY', }, 0x83: { - name: "AXS", + name: 'AXS', op: this.axs, modeFn: this.writeZeroPageXIndirect, - mode: "zeroPageXIndirect", + mode: 'zeroPageXIndirect', }, // LAX 0xaf: { - name: "LAX", + name: 'LAX', op: this.lax, modeFn: this.readAbsolute, - mode: "absolute", + mode: 'absolute', }, 0xbf: { - name: "LAX", + name: 'LAX', op: this.lax, modeFn: this.readAbsoluteY, - mode: "absoluteY", + mode: 'absoluteY', }, 0xa7: { - name: "LAX", + name: 'LAX', op: this.lax, modeFn: this.readZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0xb7: { - name: "LAX", + name: 'LAX', op: this.lax, modeFn: this.readZeroPageY, - mode: "zeroPageY", + mode: 'zeroPageY', }, 0xa3: { - name: "LAX", + name: 'LAX', op: this.lax, modeFn: this.readZeroPageXIndirect, - mode: "zeroPageXIndirect", + mode: 'zeroPageXIndirect', }, 0xb3: { - name: "LAX", + name: 'LAX', op: this.lax, modeFn: this.readZeroPageIndirectY, - mode: "zeroPageIndirectY", + mode: 'zeroPageIndirectY', }, // DCM 0xcf: { - name: "DCM", + name: 'DCM', op: this.dcm, modeFn: this.readAddrAbsolute, - mode: "absolute", + mode: 'absolute', }, 0xdf: { - name: "DCM", + name: 'DCM', op: this.dcm, modeFn: this.readAddrAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, 0xdb: { - name: "DCM", + name: 'DCM', op: this.dcm, modeFn: this.readAddrAbsoluteY, - mode: "absoluteY", + mode: 'absoluteY', }, 0xc7: { - name: "DCM", + name: 'DCM', op: this.dcm, modeFn: this.readAddrZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0xd7: { - name: "DCM", + name: 'DCM', op: this.dcm, modeFn: this.readAddrZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0xc3: { - name: "DCM", + name: 'DCM', op: this.dcm, modeFn: this.readAddrZeroPageXIndirect, - mode: "zeroPageXIndirect", + mode: 'zeroPageXIndirect', }, 0xd3: { - name: "DCM", + name: 'DCM', op: this.dcm, modeFn: this.readAddrZeroPageIndirectY, - mode: "zeroPageIndirectY", + mode: 'zeroPageIndirectY', }, // INS 0xef: { - name: "INS", + name: 'INS', op: this.ins, modeFn: this.readAddrAbsolute, - mode: "absolute", + mode: 'absolute', }, 0xff: { - name: "INS", + name: 'INS', op: this.ins, modeFn: this.readAddrAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, 0xfb: { - name: "INS", + name: 'INS', op: this.ins, modeFn: this.readAddrAbsoluteY, - mode: "absoluteY", + mode: 'absoluteY', }, 0xe7: { - name: "INS", + name: 'INS', op: this.ins, modeFn: this.readAddrZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0xf7: { - name: "INS", + name: 'INS', op: this.ins, modeFn: this.readAddrZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0xe3: { - name: "INS", + name: 'INS', op: this.ins, modeFn: this.readAddrZeroPageXIndirect, - mode: "zeroPageXIndirect", + mode: 'zeroPageXIndirect', }, 0xf3: { - name: "INS", + name: 'INS', op: this.ins, modeFn: this.readAddrZeroPageIndirectY, - mode: "zeroPageIndirectY", + mode: 'zeroPageIndirectY', }, // ALR 0x4b: { - name: "ALR", + name: 'ALR', op: this.alr, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, // ARR 0x6b: { - name: "ARR", + name: 'ARR', op: this.arr, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, // XAA 0x8b: { - name: "XAA", + name: 'XAA', op: this.xaa, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, // OAL 0xab: { - name: "OAL", + name: 'OAL', op: this.oal, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, // SAX 0xcb: { - name: "SAX", + name: 'SAX', op: this.sax, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, // NOP - 0x1a: { name: "NOP", op: this.nop, modeFn: this.implied, mode: "implied" }, - 0x3a: { name: "NOP", op: this.nop, modeFn: this.implied, mode: "implied" }, - 0x5a: { name: "NOP", op: this.nop, modeFn: this.implied, mode: "implied" }, - 0x7a: { name: "NOP", op: this.nop, modeFn: this.implied, mode: "implied" }, - 0xda: { name: "NOP", op: this.nop, modeFn: this.implied, mode: "implied" }, - 0xfa: { name: "NOP", op: this.nop, modeFn: this.implied, mode: "implied" }, + 0x1a: { name: 'NOP', op: this.nop, modeFn: this.implied, mode: 'implied' }, + 0x3a: { name: 'NOP', op: this.nop, modeFn: this.implied, mode: 'implied' }, + 0x5a: { name: 'NOP', op: this.nop, modeFn: this.implied, mode: 'implied' }, + 0x7a: { name: 'NOP', op: this.nop, modeFn: this.implied, mode: 'implied' }, + 0xda: { name: 'NOP', op: this.nop, modeFn: this.implied, mode: 'implied' }, + 0xfa: { name: 'NOP', op: this.nop, modeFn: this.implied, mode: 'implied' }, // SKB 0x80: { - name: "SKB", + name: 'SKB', op: this.skp, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0x82: { - name: "SKB", + name: 'SKB', op: this.skp, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0x89: { - name: "SKB", + name: 'SKB', op: this.skp, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0xc2: { - name: "SKB", + name: 'SKB', op: this.skp, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0xe2: { - name: "SKB", + name: 'SKB', op: this.skp, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0x04: { - name: "SKB", + name: 'SKB', op: this.skp, modeFn: this.readZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0x14: { - name: "SKB", + name: 'SKB', op: this.skp, modeFn: this.readZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0x34: { - name: "SKB", + name: 'SKB', op: this.skp, modeFn: this.readZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0x44: { - name: "SKB", + name: 'SKB', op: this.skp, modeFn: this.readZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0x54: { - name: "SKB", + name: 'SKB', op: this.skp, modeFn: this.readZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0x64: { - name: "SKB", + name: 'SKB', op: this.skp, modeFn: this.readZeroPage, - mode: "zeroPage", + mode: 'zeroPage', }, 0x74: { - name: "SKB", + name: 'SKB', op: this.skp, modeFn: this.readZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0xd4: { - name: "SKB", + name: 'SKB', op: this.skp, modeFn: this.readZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, 0xf4: { - name: "SKB", + name: 'SKB', op: this.skp, modeFn: this.readZeroPageX, - mode: "zeroPageX", + mode: 'zeroPageX', }, // SKW 0x0c: { - name: "SKW", + name: 'SKW', op: this.skp, modeFn: this.readAddrAbsolute, - mode: "absolute", + mode: 'absolute', }, 0x1c: { - name: "SKW", + name: 'SKW', op: this.skp, modeFn: this.readAddrAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, 0x3c: { - name: "SKW", + name: 'SKW', op: this.skp, modeFn: this.readAddrAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, 0x5c: { - name: "SKW", + name: 'SKW', op: this.skp, modeFn: this.readAddrAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, 0x7c: { - name: "SKW", + name: 'SKW', op: this.skp, modeFn: this.readAddrAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, 0xdc: { - name: "SKW", + name: 'SKW', op: this.skp, modeFn: this.readAddrAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, 0xfc: { - name: "SKW", + name: 'SKW', op: this.skp, modeFn: this.readAddrAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, // HLT 0x02: { - name: "HLT", + name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, - mode: "implied", + mode: 'implied', }, 0x12: { - name: "HLT", + name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, - mode: "implied", + mode: 'implied', }, 0x22: { - name: "HLT", + name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, - mode: "implied", + mode: 'implied', }, 0x32: { - name: "HLT", + name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, - mode: "implied", + mode: 'implied', }, 0x42: { - name: "HLT", + name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, - mode: "implied", + mode: 'implied', }, 0x52: { - name: "HLT", + name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, - mode: "implied", + mode: 'implied', }, 0x62: { - name: "HLT", + name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, - mode: "implied", + mode: 'implied', }, 0x72: { - name: "HLT", + name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, - mode: "implied", + mode: 'implied', }, 0x92: { - name: "HLT", + name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, - mode: "implied", + mode: 'implied', }, 0xb2: { - name: "HLT", + name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, - mode: "implied", + mode: 'implied', }, 0xd2: { - name: "HLT", + name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, - mode: "implied", + mode: 'implied', }, 0xf2: { - name: "HLT", + name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, - mode: "implied", + mode: 'implied', }, // TAS 0x9b: { - name: "TAS", + name: 'TAS', op: this.tas, modeFn: this.readAddrAbsoluteY, - mode: "absoluteY", + mode: 'absoluteY', }, // SAY 0x9c: { - name: "SAY", + name: 'SAY', op: this.say, modeFn: this.readAddrAbsoluteX, - mode: "absoluteX", + mode: 'absoluteX', }, // XAS 0x9e: { - name: "XAS", + name: 'XAS', op: this.xas, modeFn: this.readAddrAbsoluteY, - mode: "absoluteY", + mode: 'absoluteY', }, // AXA 0x9f: { - name: "AXA", + name: 'AXA', op: this.axa, modeFn: this.readAddrAbsoluteY, - mode: "absoluteY", + mode: 'absoluteY', }, 0x93: { - name: "AXA", + name: 'AXA', op: this.axa, modeFn: this.readAddrZeroPageIndirectY, - mode: "zeroPageIndirectY", + mode: 'zeroPageIndirectY', }, // ANC 0x2b: { - name: "ANC", + name: 'ANC', op: this.anc, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, 0x0b: { - name: "ANC", + name: 'ANC', op: this.anc, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, // LAS 0xbb: { - name: "LAS", + name: 'LAS', op: this.las, modeFn: this.readAbsoluteY, - mode: "absoluteY", + mode: 'absoluteY', }, // SBC 0xeb: { - name: "SBC", + name: 'SBC', op: this.sbc, modeFn: this.readImmediate, - mode: "immediate", + mode: 'immediate', }, }; OPS_ROCKWELL_65C02: Instructions = { - 0xcb: { name: "NOP", op: this.nop, modeFn: this.implied, mode: "implied" }, + 0xcb: { name: 'NOP', op: this.nop, modeFn: this.implied, mode: 'implied' }, 0xdb: { - name: "NOP", + name: 'NOP', op: this.nop, modeFn: this.readZeroPageX, - mode: "immediate", + mode: 'immediate', }, }; /* WDC 65C02 Instructions */ OPS_WDC_65C02: Instructions = { - 0xcb: { name: "WAI", op: this.wai, modeFn: this.implied, mode: "implied" }, - 0xdb: { name: "STP", op: this.stp, modeFn: this.implied, mode: "implied" }, + 0xcb: { name: 'WAI', op: this.wai, modeFn: this.implied, mode: 'implied' }, + 0xdb: { name: 'STP', op: this.stp, modeFn: this.implied, mode: 'implied' }, }; } diff --git a/js/entry1.js b/js/entry1.js index 4015012..69799c4 100644 --- a/js/entry1.js +++ b/js/entry1.js @@ -1,3 +1,3 @@ -var Apple1 = require('./apple1'); +import * as Apple1 from './apple1'; -module.exports = { Apple1: Apple1 }; +window.Apple1 = Apple1; diff --git a/js/prefs.ts b/js/prefs.ts index b17601a..50e63f2 100644 --- a/js/prefs.ts +++ b/js/prefs.ts @@ -11,7 +11,7 @@ export default class Prefs { havePrefs() { - return typeof localStorage !== "undefined"; + return typeof localStorage !== 'undefined'; } readPref(name: string) { if (localStorage) return localStorage.getItem(name); diff --git a/js/ram.ts b/js/ram.ts index 0de775d..54df8bd 100644 --- a/js/ram.ts +++ b/js/ram.ts @@ -9,9 +9,9 @@ * implied warranty. */ -import { base64_decode, base64_encode } from "./base64"; -import { allocMemPages } from "./util"; -import type { byte } from "./types"; +import { base64_decode, base64_encode } from './base64'; +import { allocMemPages } from './util'; +import type { byte } from './types'; export interface RAMState { start: byte; @@ -25,8 +25,8 @@ export default class RAM { constructor(private start_page: byte, private end_page: byte) { this.mem = allocMemPages(end_page - start_page + 1); - for (var page = 0; page <= end_page; page++) { - for (var off = 0; off < 0x100; off++) { + for (let page = 0; page <= end_page; page++) { + for (let off = 0; off < 0x100; off++) { this.mem[page * 0x100 + off] = 0; // Math.floor(Math.random()*256); } } diff --git a/js/roms/basic.ts b/js/roms/basic.ts index 516de35..b33ba68 100644 --- a/js/roms/basic.ts +++ b/js/roms/basic.ts @@ -1,4 +1,4 @@ -import { byte } from "js/types"; +import { byte } from 'js/types'; export default class Basic { ram = [ diff --git a/js/roms/bios.ts b/js/roms/bios.ts index af1349d..2b288bc 100644 --- a/js/roms/bios.ts +++ b/js/roms/bios.ts @@ -1,4 +1,4 @@ -import { byte } from "js/types"; +import { byte } from 'js/types'; export default class Bios { rom = [ diff --git a/js/roms/enhanced-basic.ts b/js/roms/enhanced-basic.ts index bbaa0e5..e659777 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 'js/types'; export default class EnhancedBasic { rom = [ diff --git a/js/roms/krusader.ts b/js/roms/krusader.ts index 0e4c74f..71e980d 100644 --- a/js/roms/krusader.ts +++ b/js/roms/krusader.ts @@ -1,4 +1,4 @@ -import { byte } from "js/types"; +import { byte } from 'js/types'; export default class Krusader { rom = [ diff --git a/js/symbols.ts b/js/symbols.ts index bcdbe6b..9ea4946 100644 --- a/js/symbols.ts +++ b/js/symbols.ts @@ -9,16 +9,16 @@ * implied warranty. */ -import type { address } from "./types"; +import type { address } from './types'; export const SYMBOLS: Record = { - 0xd010: "KBD", - 0xd011: "KBDCR", - 0xd012: "DSP", - 0xd013: "DSPCR", + 0xd010: 'KBD', + 0xd011: 'KBDCR', + 0xd012: 'DSP', + 0xd013: 'DSPCR', - 0xff1f: "GETLINE", - 0xffef: "ECHO", - 0xffdc: "PRBYTE", - 0xffe5: "PRHEX", + 0xff1f: 'GETLINE', + 0xffef: 'ECHO', + 0xffdc: 'PRBYTE', + 0xffe5: 'PRHEX', }; diff --git a/js/ui/keyboard.ts b/js/ui/keyboard.ts index 699e0ce..d4c1985 100644 --- a/js/ui/keyboard.ts +++ b/js/ui/keyboard.ts @@ -9,11 +9,11 @@ * implied warranty. */ -import CPU6502 from "js/cpu6502"; -import { debug, toHex } from "../util"; -import Apple1IO from "js/apple1io"; -import { TextPage } from "js/canvas1"; -import { byte } from "js/types"; +import CPU6502 from 'js/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] @@ -140,29 +140,29 @@ const keymap: Record = { const keys = [ [ - ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", ":", "-", "RESET"], - ["ESC", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "FEED", "RETURN"], - ["CTRL", "A", "S", "D", "F", "G", "H", "J", "K", "L", ";", "OUT", "CLS"], - ["SHIFT", "Z", "X", "C", "V", "B", "N", "M", ",", ".", "/", "SHIFT"], - [" "], + ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', ':', '-', 'RESET'], + ['ESC', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', 'FEED', 'RETURN'], + ['CTRL', 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', 'OUT', 'CLS'], + ['SHIFT', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', ',', '.', '/', 'SHIFT'], + [' '], ], [ - ["!", '"', "#", "$", "%", "&", "'", "(", ")", "0", "*", "=", "RESET"], - ["ESC", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "@", "LINE", "RETURN"], - ["CTRL", "A", "S", "D", "F", "BELL", "H", "J", "K", "L", "+", "RUB", "CLS"], - ["SHIFT", "Z", "X", "C", "V", "B", "^", "M", "<", ">", "?", "SHIFT"], - [" "], + ['!', '"', '#', '$', '%', '&', "'", '(', ')', '0', '*', '=', 'RESET'], + ['ESC', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', '@', 'LINE', 'RETURN'], + ['CTRL', 'A', 'S', 'D', 'F', 'BELL', 'H', 'J', 'K', 'L', '+', 'RUB', 'CLS'], + ['SHIFT', 'Z', 'X', 'C', 'V', 'B', '^', 'M', '<', '>', '?', 'SHIFT'], + [' '], ], ] as const; export function mapKeyEvent(evt: KeyboardEvent) { - var code = evt.keyCode; + const code = evt.keyCode; if (code in keymap) { return keymap[code][evt.shiftKey ? 2 : evt.ctrlKey ? 1 : 0]; } - debug("Unhandled key = " + toHex(code)); + debug('Unhandled key = ' + toHex(code)); return 0xff; } @@ -182,34 +182,34 @@ export class KeyBoard { shiftKey(down: boolean) { this.shifted = down; - this.kb.querySelectorAll(".key-SHIFT").forEach(function (el) { + this.kb.querySelectorAll('.key-SHIFT').forEach(function (el) { if (down) { - el.classList.add("active"); + el.classList.add('active'); } else { - el.classList.remove("active"); + el.classList.remove('active'); } }); } controlKey(down: boolean) { this.controlled = down; - this.kb.querySelectorAll(".key-CTRL").forEach(function (el) { + this.kb.querySelectorAll('.key-CTRL').forEach(function (el) { if (down) { - el.classList.add("active"); + el.classList.add('active'); } else { - el.classList.remove("active"); + el.classList.remove('active'); } }); } create() { - var x, y, row, key, key1, key2, label, label1, label2; + let x, y, row, key, key1, key2, label, label1, label2; function buildLabel(k: string) { - var span = document.createElement("span"); + const span = document.createElement('span'); span.innerHTML = k; - if (k.length > 1 && !k.startsWith("&")) { - span.classList.add("small"); + if (k.length > 1 && !k.startsWith('&')) { + span.classList.add('small'); } return span; } @@ -219,7 +219,7 @@ export class KeyBoard { currentTarget: HTMLElement; } ) => { - event.currentTarget.classList.remove("pressed"); + event.currentTarget.classList.remove('pressed'); }; const _mousedown = ( @@ -227,31 +227,31 @@ export class KeyBoard { currentTarget: HTMLElement; } ) => { - event.currentTarget.classList.add("pressed"); - var key = event.currentTarget.dataset[this.shifted ? "key2" : "key1"]; + event.currentTarget.classList.add('pressed'); + let key = event.currentTarget.dataset[this.shifted ? 'key2' : 'key1']; if (!key) { return; } switch (key) { - case "BELL": - key = "G"; + case 'BELL': + key = 'G'; break; - case "RETURN": - key = "\r"; + case 'RETURN': + key = '\r'; break; - case "LINE": - case "FEED": - key = "\n"; + case 'LINE': + case 'FEED': + key = '\n'; break; - case "RUB": - case "OUT": - key = "_"; // 0x5f + case 'RUB': + case 'OUT': + key = '_'; // 0x5f break; - case " ": - key = " "; + case ' ': + key = ' '; break; - case "ESC": - key = "\0x1b"; + case 'ESC': + key = '\0x1b'; break; default: break; @@ -259,31 +259,31 @@ export class KeyBoard { if (key.length > 1) { switch (key) { - case "SHIFT": + case 'SHIFT': this.shifted = !this.shifted; this.kb - .querySelectorAll(".key-SHIFT") + .querySelectorAll('.key-SHIFT') .forEach(function (el: HTMLElement) { - el.classList.toggle("active"); + el.classList.toggle('active'); }); break; - case "CTRL": + case 'CTRL': this.controlled = !this.controlled; - this.kb.querySelectorAll(".key-CTRL").forEach(function (el) { - el.classList.toggle("active"); + this.kb.querySelectorAll('.key-CTRL').forEach(function (el) { + el.classList.toggle('active'); }); break; - case "RESET": + case 'RESET': this.cpu.reset(); break; - case "CLS": + case 'CLS': this.text.clear(); break; default: break; } } else { - if (this.controlled && key >= "@" && key <= "_") { + if (this.controlled && key >= '@' && key <= '_') { this.io.keyDown(key.charCodeAt(0) - 0x40); } else { this.io.keyDown(key.charCodeAt(0)); @@ -292,46 +292,46 @@ export class KeyBoard { }; for (y = 0; y < 5; y++) { - row = document.createElement("div"); - row.classList.add("row", "row" + y); + row = document.createElement('div'); + row.classList.add('row', 'row' + y); this.kb.append(row); for (x = 0; x < keys[0][y].length; x++) { key1 = keys[0][y][x]; key2 = keys[1][y][x]; - label = document.createElement("div"); + label = document.createElement('div'); label1 = buildLabel(key1); label2 = buildLabel(key2); - key = document.createElement("div"); - key.classList.add("key", "key-" + key1.replace(/[&;]/g, "")); + key = document.createElement('div'); + key.classList.add('key', 'key-' + key1.replace(/[&;]/g, '')); if (key1.length > 1) { - if (key1 != key2) { - key.classList.add("vcenter2"); + if (key1 !== key2) { + key.classList.add('vcenter2'); } else { - key.classList.add("vcenter"); + key.classList.add('vcenter'); } } - if (key1 != key2) { - key.classList.add("key-" + key2.replace(/[&;]/g, "")); + if (key1 !== key2) { + key.classList.add('key-' + key2.replace(/[&;]/g, '')); label.append(label2); - label.append(document.createElement("br")); + label.append(document.createElement('br')); } label.append(label1); key.append(label); - key.dataset["key1"] = key1; - key.dataset["key2"] = key2; + key.dataset['key1'] = key1; + key.dataset['key2'] = key2; if (window.ontouchstart === undefined) { - key.addEventListener("mousedown", _mousedown); - key.addEventListener("mouseup", _mouseup); - key.addEventListener("mouseout", _mouseup); + key.addEventListener('mousedown', _mousedown); + key.addEventListener('mouseup', _mouseup); + key.addEventListener('mouseout', _mouseup); } else { - key.addEventListener("touchstart", _mousedown); - key.addEventListener("touchend", _mouseup); - key.addEventListener("touchleave", _mouseup); + key.addEventListener('touchstart', _mousedown); + key.addEventListener('touchend', _mouseup); + key.addEventListener('touchleave', _mouseup); } row.append(key); diff --git a/js/util.ts b/js/util.ts index 01b7dbc..0d48914 100644 --- a/js/util.ts +++ b/js/util.ts @@ -9,13 +9,13 @@ * implied warranty. */ -import { byte, word } from "./types"; +import { byte, word } from './types'; -var hex_digits = "0123456789ABCDEF"; -var bin_digits = "01"; +const hex_digits = '0123456789ABCDEF'; +const bin_digits = '01'; export function allocMem(size: word) { - var result; + let result; if (window.Uint8Array) { result = new Uint8Array(size); } else { @@ -37,8 +37,8 @@ export function toHex(v: byte, n?: 2 | 4) { if (!n) { n = v < 256 ? 2 : 4; } - var result = ""; - for (var idx = 0; idx < n; idx++) { + let result = ''; + for (let idx = 0; idx < n; idx++) { result = hex_digits[v & 0x0f] + result; v >>= 4; } @@ -46,8 +46,8 @@ export function toHex(v: byte, n?: 2 | 4) { } export function toBinary(v: byte) { - var result = ""; - for (var idx = 0; idx < 8; idx++) { + let result = ''; + for (let idx = 0; idx < 8; idx++) { result = bin_digits[v & 0x01] + result; v >>= 1; } @@ -60,8 +60,8 @@ export function gup(name: string) { } export function hup() { - var regex = new RegExp("#(.*)"); - var results = regex.exec(window.location.hash); - if (!results) return ""; + const regex = new RegExp('#(.*)'); + const results = regex.exec(window.location.hash); + if (!results) return ''; else return decodeURIComponent(results[1]); } diff --git a/package-lock.json b/package-lock.json index 75dc830..68c7705 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,9 +16,11 @@ "@babel/core": "^7.4.0", "@babel/preset-env": "^7.4.2", "@types/micromodal": "^0.3.3", + "@typescript-eslint/eslint-plugin": "^6.2.1", "ajv": "^6.9.2", "babel-jest": "^29.5.0", "eslint": "^8.3.0", + "eslint-plugin-jest": "^27.2.3", "jest": "^29.5.0", "node-forge": "^1.3.0", "ts-jest": "^29.1.1", @@ -1210,6 +1212,30 @@ "node": ">=10.0.0" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", + "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, "node_modules/@eslint/eslintrc": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.4.tgz", @@ -2253,9 +2279,9 @@ } }, "node_modules/@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", "dev": true }, "node_modules/@types/micromodal": { @@ -2293,6 +2319,12 @@ "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==", "dev": true }, + "node_modules/@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, "node_modules/@types/serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", @@ -2348,6 +2380,572 @@ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" }, + "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==", + "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", + "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" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "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==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.2.1", + "@typescript-eslint/visitor-keys": "6.2.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "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==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "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==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.2.1", + "@typescript-eslint/visitor-keys": "6.2.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "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==", + "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", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.2.1", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "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", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.2.1.tgz", + "integrity": "sha512-Ld+uL1kYFU8e6btqBFpsHkwQ35rw30IWpdQxgOqOh4NfxSDH6uCkah1ks8R/RgQqI5hHPXMaLy9fbFseIe+dIg==", + "dev": true, + "peer": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.2.1", + "@typescript-eslint/types": "6.2.1", + "@typescript-eslint/typescript-estree": "6.2.1", + "@typescript-eslint/visitor-keys": "6.2.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/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==", + "dev": true, + "peer": true, + "dependencies": { + "@typescript-eslint/types": "6.2.1", + "@typescript-eslint/visitor-keys": "6.2.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/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==", + "dev": true, + "peer": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/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==", + "dev": true, + "peer": true, + "dependencies": { + "@typescript-eslint/types": "6.2.1", + "@typescript-eslint/visitor-keys": "6.2.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/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==", + "dev": true, + "peer": true, + "dependencies": { + "@typescript-eslint/types": "6.2.1", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/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, + "peer": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "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==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.2.1", + "@typescript-eslint/utils": "6.2.1", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "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==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.2.1", + "@typescript-eslint/visitor-keys": "6.2.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "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==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "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==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.2.1", + "@typescript-eslint/visitor-keys": "6.2.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "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==", + "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", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.2.1", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/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" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/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" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/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" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@webassemblyjs/ast": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", @@ -3467,9 +4065,9 @@ "dev": true }, "node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -3962,6 +4560,31 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-plugin-jest": { + "version": "27.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.3.tgz", + "integrity": "sha512-sRLlSCpICzWuje66Gl9zvdF6mwD5X86I4u55hJyFBsxYOsBCmT5+kSUjf+fkFWVMMgpzNEupjW8WzUqi83hJAQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "^5.10.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0", + "eslint": "^7.0.0 || ^8.0.0", + "jest": "*" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, "node_modules/eslint-scope": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", @@ -4012,12 +4635,15 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz", - "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==", + "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==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/ansi-styles": { @@ -4528,9 +5154,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -4540,7 +5166,7 @@ "micromatch": "^4.0.4" }, "engines": { - "node": ">=8" + "node": ">=8.6.0" } }, "node_modules/fast-json-stable-stringify": { @@ -4562,9 +5188,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -4850,16 +5476,16 @@ } }, "node_modules/globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", "slash": "^3.0.0" }, "engines": { @@ -4870,9 +5496,9 @@ } }, "node_modules/globby/node_modules/ignore": { - "version": "5.1.9", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.9.tgz", - "integrity": "sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true, "engines": { "node": ">= 4" @@ -4883,6 +5509,12 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "node_modules/handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", @@ -7566,6 +8198,12 @@ "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", @@ -9323,6 +9961,18 @@ "node": ">=0.6" } }, + "node_modules/ts-api-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", + "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", + "dev": true, + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/ts-jest": { "version": "29.1.1", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", @@ -9491,6 +10141,21 @@ "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", "dev": true }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "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-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -11245,6 +11910,21 @@ "integrity": "sha512-6nFkfkmSeV/rqSaS4oWHgmpnYw194f6hmWF5is6b0J1naJZoiD0NTc9AiUwPHvWsowkjuHErCZT1wa0jg+BLIA==", "dev": true }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", + "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "dev": true + }, "@eslint/eslintrc": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.4.tgz", @@ -12091,9 +12771,9 @@ } }, "@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", "dev": true }, "@types/micromodal": { @@ -12131,6 +12811,12 @@ "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==", "dev": true }, + "@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, "@types/serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", @@ -12186,6 +12872,338 @@ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" }, + "@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==", + "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", + "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==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.2.1", + "@typescript-eslint/visitor-keys": "6.2.1" + } + }, + "@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==", + "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==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.2.1", + "@typescript-eslint/visitor-keys": "6.2.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + } + }, + "@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==", + "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", + "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==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.2.1", + "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", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.2.1.tgz", + "integrity": "sha512-Ld+uL1kYFU8e6btqBFpsHkwQ35rw30IWpdQxgOqOh4NfxSDH6uCkah1ks8R/RgQqI5hHPXMaLy9fbFseIe+dIg==", + "dev": true, + "peer": true, + "requires": { + "@typescript-eslint/scope-manager": "6.2.1", + "@typescript-eslint/types": "6.2.1", + "@typescript-eslint/typescript-estree": "6.2.1", + "@typescript-eslint/visitor-keys": "6.2.1", + "debug": "^4.3.4" + }, + "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==", + "dev": true, + "peer": true, + "requires": { + "@typescript-eslint/types": "6.2.1", + "@typescript-eslint/visitor-keys": "6.2.1" + } + }, + "@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==", + "dev": true, + "peer": 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==", + "dev": true, + "peer": true, + "requires": { + "@typescript-eslint/types": "6.2.1", + "@typescript-eslint/visitor-keys": "6.2.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + } + }, + "@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==", + "dev": true, + "peer": true, + "requires": { + "@typescript-eslint/types": "6.2.1", + "eslint-visitor-keys": "^3.4.1" + } + }, + "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, + "peer": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + } + }, + "@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==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "6.2.1", + "@typescript-eslint/utils": "6.2.1", + "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==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.2.1", + "@typescript-eslint/visitor-keys": "6.2.1" + } + }, + "@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==", + "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==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.2.1", + "@typescript-eslint/visitor-keys": "6.2.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + } + }, + "@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==", + "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", + "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==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.2.1", + "eslint-visitor-keys": "^3.4.1" + } + }, + "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, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "dependencies": { + "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, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "dependencies": { + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "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, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + } + }, "@webassemblyjs/ast": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", @@ -13076,9 +14094,9 @@ "dev": true }, "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { "ms": "2.1.2" @@ -13628,6 +14646,15 @@ } } }, + "eslint-plugin-jest": { + "version": "27.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.3.tgz", + "integrity": "sha512-sRLlSCpICzWuje66Gl9zvdF6mwD5X86I4u55hJyFBsxYOsBCmT5+kSUjf+fkFWVMMgpzNEupjW8WzUqi83hJAQ==", + "dev": true, + "requires": { + "@typescript-eslint/utils": "^5.10.0" + } + }, "eslint-scope": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", @@ -13664,9 +14691,9 @@ } }, "eslint-visitor-keys": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz", - "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==", + "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==", "dev": true }, "espree": { @@ -13856,9 +14883,9 @@ "dev": true }, "fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -13887,9 +14914,9 @@ "dev": true }, "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -14108,23 +15135,23 @@ "dev": true }, "globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "requires": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", "slash": "^3.0.0" }, "dependencies": { "ignore": { - "version": "5.1.9", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.9.tgz", - "integrity": "sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true } } @@ -14134,6 +15161,12 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", @@ -16120,6 +17153,12 @@ "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", @@ -17426,6 +18465,13 @@ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true }, + "ts-api-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", + "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", + "dev": true, + "requires": {} + }, "ts-jest": { "version": "29.1.1", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", @@ -17531,6 +18577,15 @@ "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", "dev": true }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", diff --git a/package.json b/package.json index 641104a..ca7afbb 100644 --- a/package.json +++ b/package.json @@ -29,9 +29,11 @@ "@babel/core": "^7.4.0", "@babel/preset-env": "^7.4.2", "@types/micromodal": "^0.3.3", + "@typescript-eslint/eslint-plugin": "^6.2.1", "ajv": "^6.9.2", "babel-jest": "^29.5.0", "eslint": "^8.3.0", + "eslint-plugin-jest": "^27.2.3", "jest": "^29.5.0", "node-forge": "^1.3.0", "ts-jest": "^29.1.1", diff --git a/test/cpu.spec.ts b/test/cpu.spec.ts index 1001830..c4db763 100644 --- a/test/cpu.spec.ts +++ b/test/cpu.spec.ts @@ -6,43 +6,43 @@ import Test65C02 from './roms/65C02test'; import { toHex } from '../js/util'; describe('CPU', function () { - let cpu: CPU6502; - let lastPC = 0; - let done = false; + let cpu: CPU6502; + let lastPC = 0; + let done = false; - function traceCB() { - const pc = cpu.getPC(); - done = lastPC === pc; - lastPC = pc; - } + 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); + 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); + do { + cpu.stepCyclesDebug(1000, traceCB); + } while (!done); - expect(toHex(lastPC)).toEqual(toHex(0x3469)); - }); + 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); + 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); + do { + cpu.stepCyclesDebug(1000, traceCB); + } while (!done); - expect(toHex(lastPC)).toEqual(toHex(0x24f1)); - }); + expect(toHex(lastPC)).toEqual(toHex(0x24f1)); }); + }); }); diff --git a/test/cpu6502.spec.ts b/test/cpu6502.spec.ts index d274265..5dd0046 100644 --- a/test/cpu6502.spec.ts +++ b/test/cpu6502.spec.ts @@ -1,20 +1,16 @@ -import CPU6502, { - CpuState, - FLAVOR_ROCKWELL_65C02, - flags -} from '../js/cpu6502'; +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 + cycles: 0, + s: flags.X, + sp: 0xff, + a: 0x00, + x: 0x00, + y: 0x00, + pc: 0x0400, }; let memory; @@ -22,2215 +18,3237 @@ let cpu: CPU6502; let program; function initState(initialState: Partial) { - const state = {...DEFAULT_STATE, ...initialState}; - cpu.setState(state); + 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)); + 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; - } - } + 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]); +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; + } } - expect(memAry).toEqual(expectAry); + 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]]); + 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 }; +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); + program = new Program(0x04, code); + cpu.addPageHandler(program); - cpu.setState(initialState); - cpu.stepN(steps); - expectState(initialState, finalState); + cpu.setState(initialState); + cpu.stepN(steps); + expectState(initialState, finalState); } -describe('CPU6502', function() { - beforeEach(function() { - cpu = new CPU6502(); - memory = new TestMemory(4); +describe('CPU6502', function () { + beforeEach(function () { + cpu = new CPU6502(); + memory = new TestMemory(4); - cpu.addPageHandler(memory); - cpu.addPageHandler(bios); + 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); }); - 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); - }); + 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); }); - 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 - }); - }); + 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); }); - 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 - }); - }); + 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); }); - 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 - }); - }); + 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); }); - 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 - }); - }); + 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); }); - 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 - }); - }); + 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); }); - describe('#jumps', function() { - it('should JMP abs', function () { - testCode([0x4C, 0x34, 0x12], 1, {}, { - cycles: 3, - pc: 0x1234 - }); - }); + it('stepCyclesDebug with callback', function () { + const callback = jest.fn(); - 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 - }); - }); + 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); }); - describe('#branches', function() { - // ********** bcs - it('should BCS forward', function () { - testCode([0xB0, 0x7F], 1, { - s: flags.X | flags.C - }, { - cycles: 3, - pc: 0x0481 - }); - }); + it('stepCyclesDebug with breakpoint', function () { + const callback = jest.fn().mockReturnValue(true); - it('should BCS backward', function () { - testCode([0xB0, 0xff], 1, { - s: flags.X | flags.C - }, { - cycles: 3, - pc: 0x0401 - }); - }); + 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); + }); + }); - it('should BCS across pages with an extra cycle', function () { - testCode([0xB0, 0xfd], 1, { - s: flags.X | flags.C - }, { - cycles: 4, - pc: 0x03FF - }); - }); + describe('#signals', function () { + it('should reset', function () { + cpu.reset(); - 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 - }); - }); + expectState(DEFAULT_STATE, { + cycles: 2, + }); }); - describe('#read memory', function() { - // ********** zp - it('should LDY zp', function () { - initMemory([[0x00, 0x33, [0x44]]]); - testCode([0xA4, 0x33], 1, {}, { - cycles: 3, - y: 0x44 - }); - }); + it('should irq', function () { + cpu.irq(); - 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 - }); - }); + expectState(DEFAULT_STATE, { + cycles: 5, + s: flags.X | flags.I, + sp: 0xfc, + pc: 0xff00, + }); }); - describe('#write memory', function() { - // ********** zp - it('should STY zp', function () { - testCode([0x84, 0x33], 1, { - y: 0x44 - }, { - cycles: 3 - }); - expectMemory([[0x00, 0x33, [0x44]]]); - }); + it('should not irq if I set', function () { + initState({ + s: flags.X | flags.I, + }); - it('should STA zp', function () { - testCode([0x85, 0x33], 1, { - a: 0x44 - }, { - cycles: 3 - }); - expectMemory([[0x00, 0x33, [0x44]]]); - }); + cpu.irq(); - 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]]]); - }); + expectState(DEFAULT_STATE, { + s: flags.X | flags.I, + pc: 0x400, + }); }); - 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 nmi', function () { + cpu.nmi(); - it('should ASL A with carry out', function () { - testCode([0x0A], 1, { - a: 0xAA - }, { - cycles: 2, - a: 0x54, - s: flags.X | flags.C - }); - }); + expectState(DEFAULT_STATE, { + cycles: 5, + s: flags.X | flags.I, + sp: 0xfc, + pc: 0xff00, + }); + }); + }); - 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('#misc', function () { + it('should NOP', function () { + testCode( + [0xea], + 1, + {}, + { + cycles: 2, + } + ); }); - 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]]]); - }); + it('should BRK', function () { + testCode( + [0x00, 0x00], + 1, + {}, + { + cycles: 7, + s: flags.X | flags.I, + sp: 0xfc, + pc: 0xff00, + } + ); }); - 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 - }); - }); + 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); +describe('65c02', function () { + beforeEach(function () { + cpu = new CPU6502({ flavor: FLAVOR_ROCKWELL_65C02 }); + memory = new TestMemory(4); - cpu.addPageHandler(memory); - cpu.addPageHandler(bios); + 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, + }); }); - describe('#signals', function() { - it('should clear D on IRQ', function() { - initState({ - s: flags.X | flags.D - }); + it('should clear D on NMI', function () { + initState({ + s: flags.X | flags.D, + }); - cpu.irq(); + cpu.nmi(); - 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 - }); - }); + expectState(DEFAULT_STATE, { + cycles: 5, + 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 - }); - }); + 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]); }); - 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 - }); - }); + it('should PLX', function () { + initMemory([[0x01, 0xff, [0x44]]]); + testCode( + [0xfa], + 1, + { + sp: 0xfe, + }, + { + cycles: 4, + x: 0x44, + sp: 0xff, + } + ); }); - 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]]]); - }); + it('should PHY', function () { + testCode( + [0x5a], + 1, + { + y: 0x44, + }, + { + cycles: 3, + sp: 0xfe, + } + ); + expectStack([0x44]); }); - describe('#branches', function() { - it('should BRA forward', function () { - testCode([0x80, 0x7F], 1, {}, { - cycles: 3, - pc: 0x0481 - }); - }); + it('should PLY', function () { + initMemory([[0x01, 0xff, [0x44]]]); + testCode( + [0x7a], + 1, + { + sp: 0xfe, + }, + { + cycles: 4, + y: 0x44, + sp: 0xff, + } + ); + }); + }); - it('should BRA backward', function () { - testCode([0x80, 0xFF], 1, {}, { - cycles: 3, - pc: 0x0401 - }); - }); + describe('#jumps', function () { + it('should JMP (abs)', function () { + initMemory([[0x03, 0x33, [0x34, 0x12]]]); + testCode( + [0x6c, 0x33, 0x03], + 1, + {}, + { + cycles: 6, + pc: 0x1234, + } + ); }); - 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 - }); - }); + 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, + } + ); }); - 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 JMP (abs, x)', function () { + initMemory([[0x03, 0x43, [0x34, 0x12]]]); + testCode( + [0x7c, 0x33, 0x03], + 1, + { + x: 0x10, + }, + { + cycles: 6, + pc: 0x1234, + } + ); + }); + }); - it('should STZ abs', function () { - initMemory([[0x03, 0x33, [0x44]]]); - testCode([0x9C, 0x33, 0x03], 1, { - a: 0x44 - }, { - cycles: 4 - }); - expectMemory([[0x03, 0x33, [0x00]]]); - }); + 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, + } + ); }); - 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 BRA backward', function () { + testCode( + [0x80, 0xff], + 1, + {}, + { + cycles: 3, + pc: 0x0401, + } + ); + }); + }); - it('should BIT imm', function() { - testCode([0x89, 0x33], 1, { - a: 0x03 - }, { - cycles: 2, - s: flags.X - }); - }); + 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, + } + ); + }); + }); - // ******** 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('#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]]]); }); - 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('should STZ abs', function () { + initMemory([[0x03, 0x33, [0x44]]]); + testCode( + [0x9c, 0x33, 0x03], + 1, + { + a: 0x44, + }, + { + cycles: 4, + } + ); + expectMemory([[0x03, 0x33, [0x00]]]); + }); + }); - 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('#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, + } + ); }); - 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]]]); - }); + it('should BIT imm', function () { + testCode( + [0x89, 0x33], + 1, + { + a: 0x03, + }, + { + cycles: 2, + s: flags.X, + } + ); }); - 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 - }); - }); + // ******** 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/util/asserts.ts b/test/util/asserts.ts index 46023cb..cb1e842 100644 --- a/test/util/asserts.ts +++ b/test/util/asserts.ts @@ -1,6 +1,6 @@ -import { byte } from '../../js/types'; +import { byte } from "../../js/types"; export const assertByte = (b: byte) => { - expect(b <= 0xFF).toEqual(true); - expect(b >= 0x00).toEqual(true); + expect(b <= 0xff).toEqual(true); + expect(b >= 0x00).toEqual(true); }; diff --git a/test/util/bios.ts b/test/util/bios.ts index 786017a..1e10cdf 100644 --- a/test/util/bios.ts +++ b/test/util/bios.ts @@ -1,63 +1,56 @@ -import { MemoryPages, byte } from '../../js/types'; -import { assertByte } from './asserts'; +import { MemoryPages, byte } from "../../js/types"; +import { assertByte } from "./asserts"; export class Program implements MemoryPages { - private data: Buffer; + private data: Buffer; - constructor(private page: byte, code: byte[]) { - this.data = Buffer.from(code); - } + constructor(private page: byte, code: byte[]) { + this.data = Buffer.from(code); + } - start() { - return this.page; - } + start() { + return this.page; + } - end() { - return this.page; - } + end() { + return this.page; + } - read(page: byte, off: byte) { - assertByte(page); - assertByte(off); - return this.data[off]; - } + read(page: byte, off: byte) { + assertByte(page); + assertByte(off); + return this.data[off]; + } - write(_page: byte, _off: byte, _val: byte) { - // do nothing - } + 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 -]); +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/memory.ts b/test/util/memory.ts index 040ea81..6dedf1f 100644 --- a/test/util/memory.ts +++ b/test/util/memory.ts @@ -1,61 +1,60 @@ -import { MemoryPages, byte, word } from 'js/types'; -import { assertByte } from './asserts'; +import { MemoryPages, byte, word } from "js/types"; +import { assertByte } from "./asserts"; -export type Log = [address: word, value: byte, types: 'read'|'write']; +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[] = []; + private data: Buffer; + private logging: boolean = false; + private log: Log[] = []; - constructor(private size: number) { - this.data = Buffer.alloc(size << 8); + 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; + } - start() { - return 0; + 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; + } - end() { - return this.size - 1; - } + reset() { + this.log = []; + } - read(page: byte, off: byte) { - assertByte(page); - assertByte(off); + logStart() { + this.log = []; + this.logging = true; + } - const val = this.data[(page << 8) | off]; - if (this.logging) { - this.log.push([page << 8 | off, val, 'read']); - } - return val; - } + logStop() { + this.logging = false; + } - 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; - } + getLog() { + return this.log; + } } - diff --git a/webpack.config.js b/webpack.config.js index bfe140d..dce35a0 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -9,9 +9,6 @@ module.exports = }, output: { path: path.resolve('dist/'), - library: 'Apple1', - libraryExport: 'Apple1', - libraryTarget: 'var' }, module: { rules: [