jsbeeb 1.23.0 → 1.24.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/README.md +2 -2
  2. package/package.json +14 -10
  3. package/src/6502.js +39 -42
  4. package/src/6502.opcodes.js +7 -13
  5. package/src/6847.js +4 -5
  6. package/src/6847_fontdata.js +0 -2
  7. package/src/acia.js +2 -3
  8. package/src/app/app.js +0 -1
  9. package/src/app/args.js +0 -2
  10. package/src/app/electron.js +4 -6
  11. package/src/app-bench.js +1 -3
  12. package/src/archive.js +243 -0
  13. package/src/basic-loader.js +0 -7
  14. package/src/basic-tokenise.js +19 -6
  15. package/src/bbc-palette.js +0 -2
  16. package/src/bbcdiscs.js +0 -2
  17. package/src/bem-snapshot.js +1 -3
  18. package/src/binary.js +175 -0
  19. package/src/cmos.js +0 -2
  20. package/src/ddnoise.js +0 -1
  21. package/src/debounce.js +7 -0
  22. package/src/disc-surface.js +0 -2
  23. package/src/disc.js +10 -9
  24. package/src/fake6502.js +11 -24
  25. package/src/fdc.js +9 -51
  26. package/src/filestore.js +10 -17
  27. package/src/hex.js +38 -0
  28. package/src/index.js +11 -0
  29. package/src/intel-fdc.js +18 -20
  30. package/src/{utils_atom.js → keymap-atom.js} +2 -18
  31. package/src/{utils.js → keymap.js} +47 -610
  32. package/src/loader.js +63 -0
  33. package/src/machine-session.js +37 -177
  34. package/src/machine-spec.js +59 -0
  35. package/src/main.js +66 -180
  36. package/src/media-resolver.js +68 -0
  37. package/src/mmc.js +3 -2
  38. package/src/models.js +18 -3
  39. package/src/music5000.js +0 -2
  40. package/src/ppia.js +3 -4
  41. package/src/printer.js +7 -14
  42. package/src/relaynoise.js +0 -1
  43. package/src/rewind.js +0 -2
  44. package/src/sample-player.js +2 -3
  45. package/src/serial.js +0 -2
  46. package/src/snapshot-helpers.js +0 -2
  47. package/src/snapshot.js +0 -2
  48. package/src/soundchip.js +1 -1
  49. package/src/state-utils.js +0 -2
  50. package/src/sth.js +2 -4
  51. package/src/tapes.js +10 -4
  52. package/src/teletext.js +2 -3
  53. package/src/teletext_adaptor.js +2 -4
  54. package/src/teletext_data.js +0 -2
  55. package/src/test-machine.js +281 -0
  56. package/src/touchscreen.js +2 -4
  57. package/src/tube.js +5 -6
  58. package/src/typist.js +103 -0
  59. package/src/uef-snapshot.js +0 -2
  60. package/src/url-params.js +4 -5
  61. package/src/vdu-capture.js +113 -0
  62. package/src/via.js +3 -4
  63. package/src/video-filters/pal-composite.js +0 -2
  64. package/src/video-filters/passthrough-filter.js +0 -2
  65. package/src/video-filters/pixel-grid.js +0 -2
  66. package/src/video-filters/shader-program.js +0 -2
  67. package/src/video-filters/xbr-filter.js +0 -2
  68. package/src/video.js +38 -11
  69. package/src/wd-fdc.js +20 -20
  70. package/src/web/analogue-inputs.js +6 -8
  71. package/src/web/analytics.js +13 -0
  72. package/src/web/audio-handler.js +2 -2
  73. package/src/{audio-utils.js → web/audio-utils.js} +0 -2
  74. package/src/web/autoboot.js +10 -13
  75. package/src/{canvas.js → web/canvas.js} +4 -5
  76. package/src/web/config.js +41 -74
  77. package/src/web/console-surface.js +25 -0
  78. package/src/web/debug.js +6 -5
  79. package/src/web/disc-visualiser.js +0 -2
  80. package/src/web/display.js +21 -4
  81. package/src/{dom-utils.js → web/dom-utils.js} +1 -11
  82. package/src/web/drives.js +1 -1
  83. package/src/web/emulation-loop.js +54 -33
  84. package/src/web/front-panel.js +13 -12
  85. package/src/{gamepads.js → web/gamepads.js} +2 -6
  86. package/src/web/google-drive-picker.js +14 -9
  87. package/src/{google-drive.js → web/google-drive.js} +9 -10
  88. package/src/web/hfe-picker.js +5 -4
  89. package/src/web/keyboard-setup.js +18 -38
  90. package/src/{keyboard.js → web/keyboard.js} +18 -119
  91. package/src/web/layout.js +4 -0
  92. package/src/web/local-disc.js +44 -0
  93. package/src/web/machine.js +27 -20
  94. package/src/web/media-loader.js +38 -147
  95. package/src/{microphone-input.js → web/microphone-input.js} +1 -1
  96. package/src/web/modals.js +6 -9
  97. package/src/web/page-actions.js +88 -0
  98. package/src/web/quick-settings.js +16 -15
  99. package/src/web/reporting.js +0 -7
  100. package/src/{rewind-thumbnail.js → web/rewind-thumbnail.js} +0 -2
  101. package/src/web/rewind-ui.js +29 -29
  102. package/src/web/run-controls.js +39 -0
  103. package/src/web/settings.js +64 -135
  104. package/src/web/snapshot-ui.js +10 -16
  105. package/src/{speech-output.js → web/speech-output.js} +0 -2
  106. package/src/web/sth-picker.js +9 -7
  107. package/src/web/url-state.js +20 -6
  108. package/src/econet/L3FS.dat +0 -0
  109. package/src/econet/scsi.dat +0 -0
  110. package/tests/test-machine.js +0 -609
package/README.md CHANGED
@@ -96,8 +96,8 @@ Some things to know:
96
96
  was at fault.
97
97
  - On the Atom, use the Atom's own key names (`LOCK`, `UP_DOWN`, `LEFT_RIGHT` and so on) rather than the BBC's.
98
98
 
99
- The definitive lists are `keyCodes` (host) and `BBC` (BBC micro) in [`src/utils.js`](src/utils.js), and `ATOM` in
100
- [`src/utils_atom.js`](src/utils_atom.js).
99
+ The definitive lists are `keyCodes` (host) and `BBC` (BBC micro) in [`src/keymap.js`](src/keymap.js), and `ATOM` in
100
+ [`src/keymap-atom.js`](src/keymap-atom.js).
101
101
 
102
102
  ### Emulator Shortcuts
103
103
 
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "name": "jsbeeb",
8
8
  "description": "Emulate a BBC Micro",
9
9
  "repository": "git@github.com:mattgodbolt/jsbeeb.git",
10
- "version": "1.23.0",
10
+ "version": "1.24.1",
11
11
  "//engines": "If you change the version of Node, it must also be updated at the top of the Dockerfile.",
12
12
  "engines": {
13
13
  "node": ">=24.15.0"
@@ -15,14 +15,12 @@
15
15
  "type": "module",
16
16
  "main": "./src/app/app.js",
17
17
  "exports": {
18
- ".": "./src/app/app.js",
18
+ ".": "./src/index.js",
19
19
  "./machine-session": "./src/machine-session.js",
20
- "./src/*": "./src/*",
21
- "./tests/test-machine.js": "./tests/test-machine.js"
20
+ "./src/*": "./src/*"
22
21
  },
23
22
  "files": [
24
23
  "src/",
25
- "tests/test-machine.js",
26
24
  "public/roms/"
27
25
  ],
28
26
  "dependencies": {
@@ -32,11 +30,11 @@
32
30
  "bootstrap-icons": "^1.13.1",
33
31
  "bootswatch": "^5.3.8",
34
32
  "pako": "^3.0.1",
35
- "sharp": "^0.35.3",
36
33
  "smoothie": "^1.36.1"
37
34
  },
38
35
  "devDependencies": {
39
36
  "@eslint/js": "^10.0.1",
37
+ "@playwright/test": "^1.62.1",
40
38
  "@vitest/coverage-v8": "^4.0.18",
41
39
  "eslint": "^10.7.0",
42
40
  "eslint-config-prettier": "^10.1.8",
@@ -54,6 +52,7 @@
54
52
  },
55
53
  "optionalDependencies": {
56
54
  "electron": "^44.0.0",
55
+ "sharp": "^0.35.3",
57
56
  "electron-builder": "^26.15.3",
58
57
  "electron-store": "^11.0.2"
59
58
  },
@@ -90,9 +89,12 @@
90
89
  "start": "vite",
91
90
  "build": "vite build",
92
91
  "preview": "vite preview",
93
- "ci-checks": "eslint .",
94
- "lint": "eslint . --fix",
92
+ "ci-checks": "npm-run-all lint format:check check-workflow-suites",
93
+ "check-workflow-suites": "node tools/check-workflow-suites.js",
94
+ "lint": "eslint .",
95
+ "lint-fix": "eslint . --fix",
95
96
  "format": "prettier --write .",
97
+ "format:check": "prettier --check .",
96
98
  "pre-commit": "lint-staged",
97
99
  "test": "npm-run-all test:*",
98
100
  "test:unit": "vitest run --silent=true tests/unit",
@@ -100,6 +102,7 @@
100
102
  "test:cpu": "node tests/test-suite.js",
101
103
  "test:shader": "vitest run --silent=true tests/shader",
102
104
  "coverage:unit": "vitest run tests/unit --coverage",
105
+ "dom-unit-tests": "vitest run --silent=true --project unit $(grep -rl domFromIndexHtml tests/unit)",
103
106
  "coverage:all-tests": "vitest run --coverage",
104
107
  "benchmark": "node src/app-bench.js",
105
108
  "mirror-sth": "node tools/mirror-sth.js --out .sth-mirror",
@@ -116,14 +119,15 @@
116
119
  "mirror-bbcdiscs:upload:index": "aws s3 cp .bbcdiscs-mirror/hfe/manifest.json s3://bbc.xania.org/archive/bbcdiscs/hfe/manifest.json --cache-control 'public, max-age=300' && aws s3 cp .bbcdiscs-mirror/manifest.json s3://bbc.xania.org/archive/bbcdiscs/manifest.json --cache-control 'public, max-age=300'",
117
120
  "electron": "npm run build && ELECTRON_DISABLE_SANDBOX=1 electron .",
118
121
  "electron:build": "electron-builder",
119
- "test:smoke": "npm run build && node tests/browser/smoke.js"
122
+ "test:e2e": "npm run build && playwright test --project chrome"
120
123
  },
121
124
  "lint-staged": {
122
125
  "*.js": [
123
- "vitest related --run --exclude tests/integration --exclude tests/shader --no-file-parallelism",
126
+ "vitest related --run --project unit --no-file-parallelism",
124
127
  "eslint --cache --fix",
125
128
  "prettier --write"
126
129
  ],
130
+ "index.html": "npm run dom-unit-tests --",
127
131
  "*.{md,json,yml,yaml,css,html}": "prettier --write"
128
132
  },
129
133
  "allowScripts": {
package/src/6502.js CHANGED
@@ -1,5 +1,3 @@
1
- "use strict";
2
- import * as utils from "./utils.js";
3
1
  import * as via from "./via.js";
4
2
  import { Acia } from "./acia.js";
5
3
  import { Serial } from "./serial.js";
@@ -12,8 +10,10 @@ import { Filestore } from "./filestore.js";
12
10
  import { FakeRelayNoise } from "./relaynoise.js";
13
11
  import { AtomPPIA } from "./ppia.js";
14
12
  import { AtomMMC2 } from "./mmc.js";
15
-
16
- const signExtend = utils.signExtend;
13
+ import { unzipRomImage } from "./archive.js";
14
+ import { signExtend } from "./binary.js";
15
+ import { hexbyte, hexword } from "./hex.js";
16
+ import { loadData } from "./loader.js";
17
17
 
18
18
  function _set(byte, mask, set) {
19
19
  return (byte & ~mask) | (set ? mask : 0);
@@ -255,7 +255,7 @@ class Base6502 {
255
255
  this.polltime(3);
256
256
  } else {
257
257
  this.polltime(2);
258
- // TODO: check 65c12 BRK interrupt poll timing.
258
+ // TODO(#1063) check 65c12 BRK interrupt poll timing.
259
259
  this.checkInt();
260
260
  this.polltime(1);
261
261
  }
@@ -540,7 +540,7 @@ class Tube6502 extends Base6502 {
540
540
  async loadOs() {
541
541
  console.log("Loading tube rom from roms/" + this.model.os);
542
542
  const tubeRom = this.rom;
543
- const data = await utils.loadData("roms/" + this.model.os);
543
+ const data = await loadData("roms/" + this.model.os);
544
544
  const len = data.length;
545
545
  if (len !== 2048) throw new Error("Broken ROM file (length=" + len + ")");
546
546
  for (let i = 0; i < len; ++i) {
@@ -561,25 +561,6 @@ class FakeTube {
561
561
  reset() {}
562
562
  }
563
563
 
564
- class FakeUserPort {
565
- write() {}
566
-
567
- read() {
568
- return 0xff;
569
- }
570
- }
571
-
572
- function fixUpConfig(config) {
573
- if (config === undefined) config = {};
574
- if (!config.keyLayout) config.keyLayout = "physical";
575
- if (!config.cpuMultiplier) config.cpuMultiplier = 1;
576
- if (!config.userPort) config.userPort = new FakeUserPort();
577
- if (config.printerPort === undefined) config.printerPort = null;
578
- config.extraRoms = config.extraRoms || [];
579
- config.debugFlags = config.debugFlags || {};
580
- return config;
581
- }
582
-
583
564
  class DebugHook {
584
565
  constructor(cpu, functionName) {
585
566
  this.cpu = cpu;
@@ -645,7 +626,8 @@ export class Cpu6502 extends Base6502 {
645
626
  } = {},
646
627
  ) {
647
628
  super(model, { cycleAccurate });
648
- this.config = fixUpConfig(config);
629
+ this.config = config;
630
+ this.keyLayout = config.keyLayout;
649
631
  this.debugFlags = this.config.debugFlags;
650
632
  this.cmos = cmos;
651
633
  this.debugger = dbgr;
@@ -702,12 +684,14 @@ export class Cpu6502 extends Base6502 {
702
684
  soundChip: this.soundChip,
703
685
  cmos: this.cmos,
704
686
  isMaster: this.model.isMaster,
705
- initialLayout: this.config.keyLayout,
687
+ initialLayout: this.keyLayout,
706
688
  getGamepads: this.config.getGamepads,
707
689
  });
708
690
  this.uservia = new via.UserVia(this, this.scheduler, this.model.isMaster, this.config.userPort);
709
691
  this.acia = new Acia(this, this.soundChip.toneGenerator, this.scheduler, this.relayNoise);
710
692
  this.serial = new Serial(this.acia);
693
+ this.keyboardInterface = this.sysvia;
694
+ this.tapeInterface = this.acia;
711
695
  this.adconverter = new Adc(this.sysvia, this.scheduler);
712
696
  this.touchScreen = new TouchScreen(this.scheduler, this.model.cyclesPerSecond);
713
697
  this.soundChip.setScheduler(this.scheduler);
@@ -826,7 +810,7 @@ export class Cpu6502 extends Base6502 {
826
810
  readArea(addr, len) {
827
811
  let str = "";
828
812
  for (let i = 0; i < len; ++i) {
829
- str += utils.hexbyte(this.readmem(addr + i));
813
+ str += hexbyte(this.readmem(addr + i));
830
814
  }
831
815
  return str;
832
816
  }
@@ -1003,7 +987,7 @@ export class Cpu6502 extends Base6502 {
1003
987
  const offset = this.memLook[statOffset];
1004
988
  return this.ramRomOs[offset + addr];
1005
989
  } else {
1006
- return 0xff; // TODO; peekDevice -- this.peekDevice(addr);
990
+ return 0xff; // TODO(#1062) peekDevice: this.peekDevice(addr);
1007
991
  }
1008
992
  }
1009
993
 
@@ -1165,9 +1149,9 @@ export class Cpu6502 extends Base6502 {
1165
1149
  if (name.indexOf("http") !== 0) name = "roms/" + name;
1166
1150
  console.log("Loading ROM from " + name);
1167
1151
  const ramRomOs = this.ramRomOs;
1168
- let data = await utils.loadData(name);
1152
+ let data = await loadData(name);
1169
1153
  if (/\.zip/i.test(name)) {
1170
- data = (await utils.unzipRomImage(data)).data;
1154
+ data = (await unzipRomImage(data)).data;
1171
1155
  }
1172
1156
  ramRomOs.set(data, offset);
1173
1157
  }
@@ -1177,7 +1161,7 @@ export class Cpu6502 extends Base6502 {
1177
1161
  os = "roms/" + os;
1178
1162
  console.log(`Loading OS from ${os}`);
1179
1163
  const ramRomOs = this.ramRomOs;
1180
- const data = await utils.loadData(os);
1164
+ const data = await loadData(os);
1181
1165
  const len = data.length;
1182
1166
  if (len < 16384 || len & 16383) throw new Error(`Broken OS ROM file (length=${len})`);
1183
1167
  ramRomOs.set(data, this.osOffset);
@@ -1410,7 +1394,7 @@ export class Cpu6502 extends Base6502 {
1410
1394
  }
1411
1395
 
1412
1396
  updateKeyLayout() {
1413
- this.sysvia.setKeyLayout(this.config.keyLayout);
1397
+ this.sysvia.setKeyLayout(this.keyLayout);
1414
1398
  }
1415
1399
 
1416
1400
  polltimeAddr(cycles, addr, isWrite) {
@@ -1555,6 +1539,12 @@ export class Cpu6502 extends Base6502 {
1555
1539
  this.halted = true;
1556
1540
  }
1557
1541
 
1542
+ /** Changes the host key layout for the keyboard, and for every reset after it. */
1543
+ setKeyLayout(layout) {
1544
+ this.keyLayout = layout;
1545
+ this.sysvia.setKeyLayout(layout);
1546
+ }
1547
+
1558
1548
  dumpTrace(maxToShow, func) {
1559
1549
  if (!maxToShow) maxToShow = 256;
1560
1550
  if (maxToShow > 256) maxToShow = 256;
@@ -1564,11 +1554,11 @@ export class Cpu6502 extends Base6502 {
1564
1554
  function (pc, a, x, y) {
1565
1555
  const dis = disassembler.disassemble(pc, true)[0];
1566
1556
  console.log(
1567
- utils.hexword(pc),
1557
+ hexword(pc),
1568
1558
  (dis + " ").substring(0, 15),
1569
- utils.hexbyte(a),
1570
- utils.hexbyte(x),
1571
- utils.hexbyte(y),
1559
+ hexbyte(a),
1560
+ hexbyte(x),
1561
+ hexbyte(y),
1572
1562
  );
1573
1563
  };
1574
1564
  for (let i = maxToShow - 2; i >= 0; --i) {
@@ -1613,12 +1603,19 @@ const NumBranquartBanks = 16;
1613
1603
  const AtomRomBlockSize = 0x1000; // 4KB
1614
1604
 
1615
1605
  export class AtomCpu6502 extends Cpu6502 {
1606
+ setKeyLayout(layout) {
1607
+ this.keyLayout = layout;
1608
+ this.atomppia.setKeyLayout(layout);
1609
+ }
1610
+
1616
1611
  constructor(model, options) {
1617
1612
  super(model, options);
1618
1613
 
1619
1614
  // Atom peripherals
1620
- this.atomppia = new AtomPPIA(this, this.config.keyLayout, this.scheduler);
1615
+ this.atomppia = new AtomPPIA(this, this.keyLayout, this.scheduler);
1621
1616
  this.atommc = new AtomMMC2(this);
1617
+ this.keyboardInterface = this.atomppia;
1618
+ this.tapeInterface = this.atomppia;
1622
1619
 
1623
1620
  // Branquart bank selection
1624
1621
  this.branquartLatch = 0;
@@ -1785,7 +1782,7 @@ export class AtomCpu6502 extends Cpu6502 {
1785
1782
  const bankRoms = this.model.banks || [];
1786
1783
  os = "roms/" + os;
1787
1784
  console.log(`Loading Atom OS from ${os}`);
1788
- const data = await utils.loadData(os);
1785
+ const data = await loadData(os);
1789
1786
  const len = data.length;
1790
1787
 
1791
1788
  if (len < AtomRomBlockSize || len % AtomRomBlockSize !== 0) {
@@ -1825,9 +1822,9 @@ export class AtomCpu6502 extends Cpu6502 {
1825
1822
  // Override loadRom to accept 4KB ROMs
1826
1823
  async loadRom(name, offset) {
1827
1824
  if (name.indexOf("http") !== 0) name = "roms/" + name;
1828
- let data = await utils.loadData(name);
1825
+ let data = await loadData(name);
1829
1826
  if (/\.zip/i.test(name)) {
1830
- data = (await utils.unzipRomImage(data)).data;
1827
+ data = (await unzipRomImage(data)).data;
1831
1828
  }
1832
1829
  const len = data.length;
1833
1830
  if (len !== 16384 && len !== 8192 && len !== 4096) {
@@ -1838,7 +1835,7 @@ export class AtomCpu6502 extends Cpu6502 {
1838
1835
 
1839
1836
  // Atom key layout goes through PPIA, not SysVia
1840
1837
  updateKeyLayout() {
1841
- this.atomppia.setKeyLayout(this.config.keyLayout);
1838
+ this.atomppia.setKeyLayout(this.keyLayout);
1842
1839
  }
1843
1840
 
1844
1841
  snapshotState(options) {
@@ -1,9 +1,5 @@
1
- "use strict";
2
- import * as utils from "./utils.js";
3
-
4
- const hexword = utils.hexword;
5
- const hexbyte = utils.hexbyte;
6
- const signExtend = utils.signExtend;
1
+ import { signExtend } from "./binary.js";
2
+ import { hexbyte, hexword } from "./hex.js";
7
3
 
8
4
  function rotate(left, logical) {
9
5
  const lines = [];
@@ -1072,13 +1068,13 @@ class Disassemble6502 {
1072
1068
  case "()": {
1073
1069
  const zp = this.cpu.peekmem(addr + 1);
1074
1070
  const destAddr = this.cpu.peekmem(zp) | (this.cpu.peekmem(zp + 1) << 8);
1075
- return [`${split[0]} ($${hexbyte(zp)})${suffix} ; $${utils.hexword(destAddr)}${suffix2}`, addr + 2];
1071
+ return [`${split[0]} ($${hexbyte(zp)})${suffix} ; $${hexword(destAddr)}${suffix2}`, addr + 2];
1076
1072
  }
1077
1073
  case "(abs)": {
1078
1074
  const destAddr = this.cpu.peekmem(addr + 1) | (this.cpu.peekmem(addr + 2) << 8);
1079
1075
  const indDest = this.cpu.peekmem(destAddr) | (this.cpu.peekmem(destAddr + 1) << 8);
1080
1076
  return [
1081
- `${split[0]} ($${formatJumpAddr(destAddr)})${suffix} ; $${utils.hexword(indDest)}${suffix2}`,
1077
+ `${split[0]} ($${formatJumpAddr(destAddr)})${suffix} ; $${hexword(indDest)}${suffix2}`,
1082
1078
  addr + 3,
1083
1079
  indDest,
1084
1080
  ];
@@ -1390,12 +1386,10 @@ function makeCpuFunctions(cpu, opcodes, undocumented, is65c12, cycleAccurate = t
1390
1386
  indent +
1391
1387
  [
1392
1388
  '"use strict";',
1393
- `// ${utils.hexbyte(opcodeNum)} - ${opcode}
1389
+ `// ${hexbyte(opcodeNum)} - ${opcode}
1394
1390
  `,
1395
1391
  ].concat(
1396
- opcode
1397
- ? getInstruction(opcode, !!needsReg)
1398
- : [`this.invalidOpcode(cpu, 0x${utils.hexbyte(opcodeNum)});`],
1392
+ opcode ? getInstruction(opcode, !!needsReg) : [`this.invalidOpcode(cpu, 0x${hexbyte(opcodeNum)});`],
1399
1393
  ).join(`
1400
1394
  ${indent}`)
1401
1395
  );
@@ -1408,7 +1402,7 @@ ${indent}`)
1408
1402
  const funcs = [];
1409
1403
  for (let opcodeNum = 0; opcodeNum < 256; ++opcodeNum) {
1410
1404
  const opcodeFunc = new Function("cpu", getIndentedSource(" ", opcodeNum, true));
1411
- let funcName = `exec_${utils.hexbyte(opcodeNum)}_`;
1405
+ let funcName = `exec_${hexbyte(opcodeNum)}_`;
1412
1406
  if (opcodes[opcodeNum]) {
1413
1407
  const instrName = opcodes[opcodeNum]
1414
1408
  .replace("()", "ind")
package/src/6847.js CHANGED
@@ -1,7 +1,6 @@
1
- "use strict";
2
- import * as utils from "./utils.js";
3
1
  import * as fontData from "./6847_fontdata.js";
4
2
  import { encodeLineGrid } from "./video-filters/pixel-grid.js";
3
+ import { makeFast32 } from "./binary.js";
5
4
 
6
5
  const VDISPENABLE = 1 << 0,
7
6
  HDISPENABLE = 1 << 1,
@@ -114,7 +113,7 @@ const MODE_AG = 0x10; // graphics mode
114
113
 
115
114
  // The MC6847 datasheet specifies 3.579545 MHz, but 3.638004 is used here as an
116
115
  // empirical correction to align VSync/interrupt timing with the CPU clock.
117
- // TODO: revisit once full integration is testable.
116
+ // TODO(#1067) revisit once full integration is testable.
118
117
  const VdgClockMhz = 3.638004;
119
118
 
120
119
  export class Video6847 {
@@ -127,7 +126,7 @@ export class Video6847 {
127
126
 
128
127
  // 8 colours (alpha on MSB)
129
128
  //
130
- this.collook = utils.makeFast32(
129
+ this.collook = makeFast32(
131
130
  new Uint32Array([
132
131
  0xff000000, // #00000000, // black
133
132
  0xff03b91e, // #00ff00, // green
@@ -496,7 +495,7 @@ export class Video6847 {
496
495
  // Render data depending on display enable state.
497
496
  if (this.bitmapX >= 0 && this.bitmapX < 1024 && this.bitmapY < 625) {
498
497
  {
499
- // TODO: Add in the INTEXT modifiers to mode (if necessary)
498
+ // TODO(#1067) Add in the INTEXT modifiers to mode (if necessary)
500
499
  // blit into the fb32 buffer which is painted by VIDEO
501
500
  const textMode = (mode & MODE_AG) === 0; // 0x10 is the AG bit
502
501
  this.recordLineGrid(textMode);
@@ -1,5 +1,3 @@
1
- "use strict";
2
-
3
1
  // MC6847 internal character ROM data (PAL square pixel variant, 8x12).
4
2
  // Derived from the MAME project's MC6847 VDG emulation:
5
3
  // https://github.com/mamedev/mame/blob/master/src/devices/video/mc6847.cpp
package/src/acia.js CHANGED
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  // Some info:
3
2
  // http://www.playvectrex.com/designit/lecture/UP12.HTM
4
3
  // https://books.google.com/books?id=wUecAQAAQBAJ&pg=PA431&lpg=PA431&dq=acia+tdre&source=bl&ots=mp-yF-mK-P&sig=e6aXkFRfiIOb57WZmrvdIGsCooI&hl=en&sa=X&ei=0g2fVdDyFIXT-QG8-JD4BA&ved=0CCwQ6AEwAw#v=onepage&q=acia%20tdre&f=false
@@ -52,7 +51,7 @@ export class Acia extends EventTarget {
52
51
  }
53
52
 
54
53
  reset() {
55
- // TODO: testing on a real beeb seems to suggest that reset also
54
+ // TODO(#1064) testing on a real beeb seems to suggest that reset also
56
55
  // clears CR bits (i.e. things stop working until CR is rewritten
57
56
  // with sane value). This disagrees with the datasheet.
58
57
  // CTS and DTD are based on external inputs so leave them alone.
@@ -199,7 +198,7 @@ export class Acia extends EventTarget {
199
198
  byte |= 0;
200
199
  if (this.sr & 0x01) {
201
200
  // Overrun.
202
- // TODO: this doesn't match the datasheet:
201
+ // TODO(#1064) this doesn't match the datasheet:
203
202
  // "The Overrun does not occur in the Status Register until the
204
203
  // valid character prior to Overrun has been read."
205
204
  this.sr |= 0xa0;
package/src/app/app.js CHANGED
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  import { app, BrowserWindow, dialog, ipcMain, Menu, shell, nativeImage } from "electron";
3
2
  import Store from "electron-store";
4
3
  import * as fs from "fs";
package/src/app/args.js CHANGED
@@ -1,5 +1,3 @@
1
- "use strict";
2
-
3
1
  /**
4
2
  * Returns the command-line arguments the user actually passed to jsbeeb, with
5
3
  * the Electron binary path(s) and known runtime-injected flags stripped.
@@ -1,10 +1,8 @@
1
- "use strict";
2
-
3
1
  // Electron integration for jsbeeb desktop application.
4
2
  // Handles IPC communication for loading disc/tape images and showing modals from Electron's main process.
5
3
 
6
4
  function init(args) {
7
- const { loadDiscImage, loadTapeImage, loadStateFile, processor, modals, actions, config, media } = args;
5
+ const { loadDiscImage, loadTapeImage, loadStateFile, processor, modals, actions, settings, media } = args;
8
6
  const api = window.electronAPI;
9
7
 
10
8
  api.onLoadDisc(async (message) => {
@@ -16,7 +14,7 @@ function init(args) {
16
14
  api.onLoadTape(async (message) => {
17
15
  const { path } = message;
18
16
  const tape = await loadTapeImage(path);
19
- processor.acia.setTape(tape);
17
+ processor.tapeInterface.setTape(tape);
20
18
  });
21
19
 
22
20
  api.onShowModal((message) => {
@@ -54,8 +52,8 @@ function init(args) {
54
52
  }
55
53
 
56
54
  // Save settings when they change
57
- if (config) {
58
- config.addEventListener("settings-changed", (e) => {
55
+ if (settings) {
56
+ settings.addEventListener("change", (e) => {
59
57
  api.saveSettings(e.detail);
60
58
  });
61
59
  }
package/src/app-bench.js CHANGED
@@ -1,5 +1,3 @@
1
- "use strict";
2
-
3
1
  import { fake6502 } from "./fake6502.js";
4
2
  import * as models from "./models.js";
5
3
  import * as disc from "./fdc.js";
@@ -23,7 +21,7 @@ async function main() {
23
21
  const cpu = fake6502(models.findModel("B"));
24
22
  await cpu.initialise();
25
23
  const data = await disc.load("discs/" + discName + ".ssd");
26
- cpu.fdc.loadDisc(0, disc.discFor(cpu.fdc, discName, data));
24
+ cpu.fdc.loadDisc(0, disc.discFor(discName, data));
27
25
  cpu.sysvia.keyDown(16);
28
26
  cpu.execute(10 * 1000 * 1000);
29
27
  cpu.sysvia.keyUp(16);