jsbeeb 1.1.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 (498) hide show
  1. package/.editorconfig +15 -0
  2. package/.git-blame-ignore-revs +3 -0
  3. package/.github/copilot-instructions.md +94 -0
  4. package/.github/workflows/claude-issue-triage.yml +105 -0
  5. package/.github/workflows/claude.yml +63 -0
  6. package/.github/workflows/release-please.yml +75 -0
  7. package/.github/workflows/test-and-deploy.yml +86 -0
  8. package/.gitmodules +6 -0
  9. package/.husky/pre-commit +1 -0
  10. package/.idea/codeStyleSettings.xml +9 -0
  11. package/.idea/codeStyles/Project.xml +62 -0
  12. package/.idea/codeStyles/codeStyleConfig.xml +5 -0
  13. package/.idea/compiler.xml +22 -0
  14. package/.idea/copyright/profiles_settings.xml +3 -0
  15. package/.idea/encodings.xml +6 -0
  16. package/.idea/inspectionProfiles/Project_Default.xml +7 -0
  17. package/.idea/jsLibraryMappings.xml +6 -0
  18. package/.idea/jsLinters/jshint.xml +85 -0
  19. package/.idea/jsLinters/jslint.xml +15 -0
  20. package/.idea/jsbeeb.iml +11 -0
  21. package/.idea/misc.xml +6 -0
  22. package/.idea/modules.xml +8 -0
  23. package/.idea/prettier.xml +7 -0
  24. package/.idea/runConfigurations/Debug.xml +5 -0
  25. package/.idea/scopes/scope_settings.xml +5 -0
  26. package/.idea/vcs.xml +8 -0
  27. package/.prettierignore +4 -0
  28. package/.prettierrc.json +1 -0
  29. package/.release-please-manifest.json +3 -0
  30. package/.vscode/launch.json +14 -0
  31. package/.vscode/settings.json +6 -0
  32. package/CHANGELOG.md +32 -0
  33. package/CLAUDE.md +136 -0
  34. package/COPYING +674 -0
  35. package/Dockerfile +22 -0
  36. package/Makefile +30 -0
  37. package/README.md +259 -0
  38. package/docker/nginx-default.conf +10 -0
  39. package/docs/pal-comb-filter-research.md +129 -0
  40. package/docs/pal-simulation-design.md +368 -0
  41. package/eslint.config.js +35 -0
  42. package/index.html +954 -0
  43. package/jsconfig.json +10 -0
  44. package/package.json +102 -0
  45. package/public/discs/README.Irq-Timing +3 -0
  46. package/public/discs/README.bcdtest +5 -0
  47. package/public/discs/README.elite +6 -0
  48. package/public/discs/README.eng_test +3 -0
  49. package/public/discs/README.protection +7 -0
  50. package/public/favicon.ico +0 -0
  51. package/public/images/botbar.png +0 -0
  52. package/public/images/cub-monitor.png +0 -0
  53. package/public/images/jsbeeb-example.png +0 -0
  54. package/public/images/placeholder.png +0 -0
  55. package/public/images/red-off-16.png +0 -0
  56. package/public/images/red-on-16.png +0 -0
  57. package/public/images/sb/CD-left.jpg +0 -0
  58. package/public/images/sb/CD-right.jpg +0 -0
  59. package/public/images/sidebar.png +0 -0
  60. package/public/images/tv.png +0 -0
  61. package/public/images/yellow-off-16.png +0 -0
  62. package/public/images/yellow-on-16.png +0 -0
  63. package/public/jsbeeb-icon.png +0 -0
  64. package/public/robots.txt +3 -0
  65. package/public/roms/ADFS1-53.rom +0 -0
  66. package/public/roms/BASIC.ROM +0 -0
  67. package/public/roms/README +4 -0
  68. package/public/roms/a01/BASIC1.rom +0 -0
  69. package/public/roms/ample.rom +0 -0
  70. package/public/roms/ats-3.0.rom +0 -0
  71. package/public/roms/b/DFS-0.9.rom +0 -0
  72. package/public/roms/b/DFS-1.2.rom +0 -0
  73. package/public/roms/b1770/dfs1770.rom +0 -0
  74. package/public/roms/b1770/zADFS.ROM +0 -0
  75. package/public/roms/bp/dfs.rom +0 -0
  76. package/public/roms/bp/zADFS.ROM +0 -0
  77. package/public/roms/bpos.rom +0 -0
  78. package/public/roms/compact/adfs210.rom +0 -0
  79. package/public/roms/compact/basic48.rom +0 -0
  80. package/public/roms/compact/basic486.rom +0 -0
  81. package/public/roms/compact/os51.rom +0 -0
  82. package/public/roms/compact/utils.rom +0 -0
  83. package/public/roms/deos.rom +0 -0
  84. package/public/roms/master/anfs-4.25.rom +0 -0
  85. package/public/roms/master/mos.txt +68819 -0
  86. package/public/roms/master/mos3.20 +0 -0
  87. package/public/roms/os.rom +0 -0
  88. package/public/roms/os01.rom +0 -0
  89. package/public/roms/tube/6502Tube.rom +0 -0
  90. package/public/roms/tube/ARMeval_100.rom +0 -0
  91. package/public/roms/tube/BIOS.ROM +0 -0
  92. package/public/roms/tube/ReCo6502ROM_816 +0 -0
  93. package/public/roms/tube/Z80_120.rom +0 -0
  94. package/public/roms/us/USBASIC.rom +0 -0
  95. package/public/roms/us/USDNFS.rom +0 -0
  96. package/public/roms/usmos.rom +0 -0
  97. package/public/sounds/disc525/motor.wav +0 -0
  98. package/public/sounds/disc525/motoroff.wav +0 -0
  99. package/public/sounds/disc525/motoron.wav +0 -0
  100. package/public/sounds/disc525/seek.wav +0 -0
  101. package/public/sounds/disc525/seek2.wav +0 -0
  102. package/public/sounds/disc525/seek3.wav +0 -0
  103. package/public/sounds/disc525/step.wav +0 -0
  104. package/public/teletext/txt0.dat +0 -0
  105. package/public/teletext/txt1.dat +0 -0
  106. package/public/teletext/txt2.dat +0 -0
  107. package/public/teletext/txt3.dat +0 -0
  108. package/release-please-config.json +13 -0
  109. package/run-container.sh +92 -0
  110. package/src/6502.js +1347 -0
  111. package/src/6502.opcodes.js +1411 -0
  112. package/src/acia.js +261 -0
  113. package/src/adc.js +149 -0
  114. package/src/analogue-source.js +21 -0
  115. package/src/app/app.js +175 -0
  116. package/src/app/electron.js +20 -0
  117. package/src/app/preload.js +8 -0
  118. package/src/app-bench.js +33 -0
  119. package/src/basic/multiline-tetris +9 -0
  120. package/src/basic-tokenise.js +104 -0
  121. package/src/canvas.js +177 -0
  122. package/src/cmos.js +141 -0
  123. package/src/config.js +165 -0
  124. package/src/ddnoise.js +138 -0
  125. package/src/disc-drive.js +371 -0
  126. package/src/disc-hfe.js +396 -0
  127. package/src/disc.js +997 -0
  128. package/src/econet/L3FS.dat +0 -0
  129. package/src/econet/scsi.dat +0 -0
  130. package/src/econet.js +714 -0
  131. package/src/fake6502.js +32 -0
  132. package/src/fdc.js +248 -0
  133. package/src/filestore.js +666 -0
  134. package/src/gamepad-source.js +59 -0
  135. package/src/gamepads.js +268 -0
  136. package/src/google-drive.js +160 -0
  137. package/src/intel-fdc.js +1717 -0
  138. package/src/jsbeeb.css +363 -0
  139. package/src/keyboard.js +411 -0
  140. package/src/lib/README +1 -0
  141. package/src/lib/webgl-debug.js +911 -0
  142. package/src/main.js +1759 -0
  143. package/src/microphone-input.js +149 -0
  144. package/src/models.js +200 -0
  145. package/src/mouse-joystick-source.js +107 -0
  146. package/src/music5000-worklet.js +43 -0
  147. package/src/music5000.js +207 -0
  148. package/src/scheduler.js +148 -0
  149. package/src/serial.js +31 -0
  150. package/src/soundchip.js +314 -0
  151. package/src/sth.js +59 -0
  152. package/src/tapes.js +265 -0
  153. package/src/teletext.js +348 -0
  154. package/src/teletext_adaptor.js +172 -0
  155. package/src/teletext_data.js +1064 -0
  156. package/src/touchscreen.js +86 -0
  157. package/src/tube.js +349 -0
  158. package/src/url-params.js +256 -0
  159. package/src/utils.js +1090 -0
  160. package/src/via.js +702 -0
  161. package/src/video-filters/pal-composite.js +94 -0
  162. package/src/video-filters/passthrough-filter.js +70 -0
  163. package/src/video-filters/shaders/pal-composite.frag.glsl +147 -0
  164. package/src/video-filters/shaders/pal-composite.vert.glsl +8 -0
  165. package/src/video-filters/shaders/passthrough.frag.glsl +6 -0
  166. package/src/video-filters/shaders/passthrough.vert.glsl +7 -0
  167. package/src/video.js +794 -0
  168. package/src/wd-fdc.js +1344 -0
  169. package/src/web/audio-handler.js +146 -0
  170. package/src/web/audio-renderer.js +115 -0
  171. package/src/web/debug.js +529 -0
  172. package/tests/integration/RmwX.asm +47 -0
  173. package/tests/integration/TestInstructionsSource +27 -0
  174. package/tests/integration/TestTimingsResults +27 -0
  175. package/tests/integration/TestTimingsSource +61 -0
  176. package/tests/integration/bcd.js +23 -0
  177. package/tests/integration/dormann.js +101 -0
  178. package/tests/integration/dp111timing.js +42 -0
  179. package/tests/integration/ensure-submodules.js +25 -0
  180. package/tests/integration/nops.bas +119 -0
  181. package/tests/integration/nops.js +24 -0
  182. package/tests/integration/protection.js +26 -0
  183. package/tests/integration/rmw.js +69 -0
  184. package/tests/integration/teletext/expected_bug_469.png +0 -0
  185. package/tests/integration/teletext/expected_flash_0.png +0 -0
  186. package/tests/integration/teletext/expected_flash_1.png +0 -0
  187. package/tests/integration/teletext/expected_hoglet_held_char.png +0 -0
  188. package/tests/integration/teletext/expected_reveal_flash_0.png +0 -0
  189. package/tests/integration/teletext/expected_reveal_flash_1.png +0 -0
  190. package/tests/integration/teletext.js +126 -0
  191. package/tests/integration/timings.js +56 -0
  192. package/tests/integration/via.js +1125 -0
  193. package/tests/suite/README.md +7 -0
  194. package/tests/suite/Test Suite 2.15.txt +373 -0
  195. package/tests/suite/bin/ start +0 -0
  196. package/tests/suite/bin/adca +0 -0
  197. package/tests/suite/bin/adcax +0 -0
  198. package/tests/suite/bin/adcay +0 -0
  199. package/tests/suite/bin/adcb +0 -0
  200. package/tests/suite/bin/adcix +0 -0
  201. package/tests/suite/bin/adciy +0 -0
  202. package/tests/suite/bin/adcz +0 -0
  203. package/tests/suite/bin/adczx +0 -0
  204. package/tests/suite/bin/alrb +0 -0
  205. package/tests/suite/bin/ancb +0 -0
  206. package/tests/suite/bin/anda +0 -0
  207. package/tests/suite/bin/andax +0 -0
  208. package/tests/suite/bin/anday +0 -0
  209. package/tests/suite/bin/andb +0 -0
  210. package/tests/suite/bin/andix +0 -0
  211. package/tests/suite/bin/andiy +0 -0
  212. package/tests/suite/bin/andz +0 -0
  213. package/tests/suite/bin/andzx +0 -0
  214. package/tests/suite/bin/aneb +0 -0
  215. package/tests/suite/bin/arrb +0 -0
  216. package/tests/suite/bin/asla +0 -0
  217. package/tests/suite/bin/aslax +0 -0
  218. package/tests/suite/bin/asln +0 -0
  219. package/tests/suite/bin/aslz +0 -0
  220. package/tests/suite/bin/aslzx +0 -0
  221. package/tests/suite/bin/asoa +0 -0
  222. package/tests/suite/bin/asoax +0 -0
  223. package/tests/suite/bin/asoay +0 -0
  224. package/tests/suite/bin/asoix +0 -0
  225. package/tests/suite/bin/asoiy +0 -0
  226. package/tests/suite/bin/asoz +0 -0
  227. package/tests/suite/bin/asozx +0 -0
  228. package/tests/suite/bin/axsa +0 -0
  229. package/tests/suite/bin/axsix +0 -0
  230. package/tests/suite/bin/axsz +0 -0
  231. package/tests/suite/bin/axszy +0 -0
  232. package/tests/suite/bin/bccr +0 -0
  233. package/tests/suite/bin/bcsr +0 -0
  234. package/tests/suite/bin/beqr +0 -0
  235. package/tests/suite/bin/bita +0 -0
  236. package/tests/suite/bin/bitz +0 -0
  237. package/tests/suite/bin/bmir +0 -0
  238. package/tests/suite/bin/bner +0 -0
  239. package/tests/suite/bin/bplr +0 -0
  240. package/tests/suite/bin/branchwrap +0 -0
  241. package/tests/suite/bin/brkn +0 -0
  242. package/tests/suite/bin/bvcr +0 -0
  243. package/tests/suite/bin/bvsr +0 -0
  244. package/tests/suite/bin/cia1pb6 +0 -0
  245. package/tests/suite/bin/cia1pb7 +0 -0
  246. package/tests/suite/bin/cia1ta +0 -0
  247. package/tests/suite/bin/cia1tab +0 -0
  248. package/tests/suite/bin/cia1tb +0 -0
  249. package/tests/suite/bin/cia1tb123 +0 -0
  250. package/tests/suite/bin/cia2pb6 +0 -0
  251. package/tests/suite/bin/cia2pb7 +0 -0
  252. package/tests/suite/bin/cia2ta +0 -0
  253. package/tests/suite/bin/cia2tb +0 -0
  254. package/tests/suite/bin/cia2tb123 +0 -0
  255. package/tests/suite/bin/clcn +0 -0
  256. package/tests/suite/bin/cldn +0 -0
  257. package/tests/suite/bin/clin +0 -0
  258. package/tests/suite/bin/clvn +0 -0
  259. package/tests/suite/bin/cmpa +0 -0
  260. package/tests/suite/bin/cmpax +0 -0
  261. package/tests/suite/bin/cmpay +0 -0
  262. package/tests/suite/bin/cmpb +0 -0
  263. package/tests/suite/bin/cmpix +0 -0
  264. package/tests/suite/bin/cmpiy +0 -0
  265. package/tests/suite/bin/cmpz +0 -0
  266. package/tests/suite/bin/cmpzx +0 -0
  267. package/tests/suite/bin/cntdef +0 -0
  268. package/tests/suite/bin/cnto2 +0 -0
  269. package/tests/suite/bin/cpuport +0 -0
  270. package/tests/suite/bin/cputiming +0 -0
  271. package/tests/suite/bin/cpxa +0 -0
  272. package/tests/suite/bin/cpxb +0 -0
  273. package/tests/suite/bin/cpxz +0 -0
  274. package/tests/suite/bin/cpya +0 -0
  275. package/tests/suite/bin/cpyb +0 -0
  276. package/tests/suite/bin/cpyz +0 -0
  277. package/tests/suite/bin/dcma +0 -0
  278. package/tests/suite/bin/dcmax +0 -0
  279. package/tests/suite/bin/dcmay +0 -0
  280. package/tests/suite/bin/dcmix +0 -0
  281. package/tests/suite/bin/dcmiy +0 -0
  282. package/tests/suite/bin/dcmz +0 -0
  283. package/tests/suite/bin/dcmzx +0 -0
  284. package/tests/suite/bin/deca +0 -0
  285. package/tests/suite/bin/decax +0 -0
  286. package/tests/suite/bin/decz +0 -0
  287. package/tests/suite/bin/deczx +0 -0
  288. package/tests/suite/bin/dexn +0 -0
  289. package/tests/suite/bin/deyn +0 -0
  290. package/tests/suite/bin/eora +0 -0
  291. package/tests/suite/bin/eorax +0 -0
  292. package/tests/suite/bin/eoray +0 -0
  293. package/tests/suite/bin/eorb +0 -0
  294. package/tests/suite/bin/eorix +0 -0
  295. package/tests/suite/bin/eoriy +0 -0
  296. package/tests/suite/bin/eorz +0 -0
  297. package/tests/suite/bin/eorzx +0 -0
  298. package/tests/suite/bin/finish +0 -0
  299. package/tests/suite/bin/flipos +0 -0
  300. package/tests/suite/bin/icr01 +0 -0
  301. package/tests/suite/bin/imr +0 -0
  302. package/tests/suite/bin/inca +0 -0
  303. package/tests/suite/bin/incax +0 -0
  304. package/tests/suite/bin/incz +0 -0
  305. package/tests/suite/bin/inczx +0 -0
  306. package/tests/suite/bin/insa +0 -0
  307. package/tests/suite/bin/insax +0 -0
  308. package/tests/suite/bin/insay +0 -0
  309. package/tests/suite/bin/insix +0 -0
  310. package/tests/suite/bin/insiy +0 -0
  311. package/tests/suite/bin/insz +0 -0
  312. package/tests/suite/bin/inszx +0 -0
  313. package/tests/suite/bin/inxn +0 -0
  314. package/tests/suite/bin/inyn +0 -0
  315. package/tests/suite/bin/irq +0 -0
  316. package/tests/suite/bin/jmpi +0 -0
  317. package/tests/suite/bin/jmpw +0 -0
  318. package/tests/suite/bin/jsrw +0 -0
  319. package/tests/suite/bin/lasay +0 -0
  320. package/tests/suite/bin/laxa +0 -0
  321. package/tests/suite/bin/laxay +0 -0
  322. package/tests/suite/bin/laxix +0 -0
  323. package/tests/suite/bin/laxiy +0 -0
  324. package/tests/suite/bin/laxz +0 -0
  325. package/tests/suite/bin/laxzy +0 -0
  326. package/tests/suite/bin/ldaa +0 -0
  327. package/tests/suite/bin/ldaax +0 -0
  328. package/tests/suite/bin/ldaay +0 -0
  329. package/tests/suite/bin/ldab +0 -0
  330. package/tests/suite/bin/ldaix +0 -0
  331. package/tests/suite/bin/ldaiy +0 -0
  332. package/tests/suite/bin/ldaz +0 -0
  333. package/tests/suite/bin/ldazx +0 -0
  334. package/tests/suite/bin/ldxa +0 -0
  335. package/tests/suite/bin/ldxay +0 -0
  336. package/tests/suite/bin/ldxb +0 -0
  337. package/tests/suite/bin/ldxz +0 -0
  338. package/tests/suite/bin/ldxzy +0 -0
  339. package/tests/suite/bin/ldya +0 -0
  340. package/tests/suite/bin/ldyax +0 -0
  341. package/tests/suite/bin/ldyb +0 -0
  342. package/tests/suite/bin/ldyz +0 -0
  343. package/tests/suite/bin/ldyzx +0 -0
  344. package/tests/suite/bin/loadth +0 -0
  345. package/tests/suite/bin/lsea +0 -0
  346. package/tests/suite/bin/lseax +0 -0
  347. package/tests/suite/bin/lseay +0 -0
  348. package/tests/suite/bin/lseix +0 -0
  349. package/tests/suite/bin/lseiy +0 -0
  350. package/tests/suite/bin/lsez +0 -0
  351. package/tests/suite/bin/lsezx +0 -0
  352. package/tests/suite/bin/lsra +0 -0
  353. package/tests/suite/bin/lsrax +0 -0
  354. package/tests/suite/bin/lsrn +0 -0
  355. package/tests/suite/bin/lsrz +0 -0
  356. package/tests/suite/bin/lsrzx +0 -0
  357. package/tests/suite/bin/lxab +0 -0
  358. package/tests/suite/bin/mmu +0 -0
  359. package/tests/suite/bin/mmufetch +0 -0
  360. package/tests/suite/bin/nmi +0 -0
  361. package/tests/suite/bin/nopa +0 -0
  362. package/tests/suite/bin/nopax +0 -0
  363. package/tests/suite/bin/nopb +0 -0
  364. package/tests/suite/bin/nopn +0 -0
  365. package/tests/suite/bin/nopz +0 -0
  366. package/tests/suite/bin/nopzx +0 -0
  367. package/tests/suite/bin/oneshot +0 -0
  368. package/tests/suite/bin/oraa +0 -0
  369. package/tests/suite/bin/oraax +0 -0
  370. package/tests/suite/bin/oraay +0 -0
  371. package/tests/suite/bin/orab +0 -0
  372. package/tests/suite/bin/oraix +0 -0
  373. package/tests/suite/bin/oraiy +0 -0
  374. package/tests/suite/bin/oraz +0 -0
  375. package/tests/suite/bin/orazx +0 -0
  376. package/tests/suite/bin/phan +0 -0
  377. package/tests/suite/bin/phpn +0 -0
  378. package/tests/suite/bin/plan +0 -0
  379. package/tests/suite/bin/plpn +0 -0
  380. package/tests/suite/bin/rlaa +0 -0
  381. package/tests/suite/bin/rlaax +0 -0
  382. package/tests/suite/bin/rlaay +0 -0
  383. package/tests/suite/bin/rlaix +0 -0
  384. package/tests/suite/bin/rlaiy +0 -0
  385. package/tests/suite/bin/rlaz +0 -0
  386. package/tests/suite/bin/rlazx +0 -0
  387. package/tests/suite/bin/rola +0 -0
  388. package/tests/suite/bin/rolax +0 -0
  389. package/tests/suite/bin/roln +0 -0
  390. package/tests/suite/bin/rolz +0 -0
  391. package/tests/suite/bin/rolzx +0 -0
  392. package/tests/suite/bin/rora +0 -0
  393. package/tests/suite/bin/rorax +0 -0
  394. package/tests/suite/bin/rorn +0 -0
  395. package/tests/suite/bin/rorz +0 -0
  396. package/tests/suite/bin/rorzx +0 -0
  397. package/tests/suite/bin/rraa +0 -0
  398. package/tests/suite/bin/rraax +0 -0
  399. package/tests/suite/bin/rraay +0 -0
  400. package/tests/suite/bin/rraix +0 -0
  401. package/tests/suite/bin/rraiy +0 -0
  402. package/tests/suite/bin/rraz +0 -0
  403. package/tests/suite/bin/rrazx +0 -0
  404. package/tests/suite/bin/rtin +0 -0
  405. package/tests/suite/bin/rtsn +0 -0
  406. package/tests/suite/bin/sbca +0 -0
  407. package/tests/suite/bin/sbcax +0 -0
  408. package/tests/suite/bin/sbcay +0 -0
  409. package/tests/suite/bin/sbcb +0 -0
  410. package/tests/suite/bin/sbcb(eb) +0 -0
  411. package/tests/suite/bin/sbcix +0 -0
  412. package/tests/suite/bin/sbciy +0 -0
  413. package/tests/suite/bin/sbcz +0 -0
  414. package/tests/suite/bin/sbczx +0 -0
  415. package/tests/suite/bin/sbxb +0 -0
  416. package/tests/suite/bin/secn +0 -0
  417. package/tests/suite/bin/sedn +0 -0
  418. package/tests/suite/bin/sein +0 -0
  419. package/tests/suite/bin/shaay +0 -0
  420. package/tests/suite/bin/shaiy +0 -0
  421. package/tests/suite/bin/shsay +0 -0
  422. package/tests/suite/bin/shxay +0 -0
  423. package/tests/suite/bin/shyax +0 -0
  424. package/tests/suite/bin/staa +0 -0
  425. package/tests/suite/bin/staax +0 -0
  426. package/tests/suite/bin/staay +0 -0
  427. package/tests/suite/bin/staix +0 -0
  428. package/tests/suite/bin/staiy +0 -0
  429. package/tests/suite/bin/staz +0 -0
  430. package/tests/suite/bin/stazx +0 -0
  431. package/tests/suite/bin/stxa +0 -0
  432. package/tests/suite/bin/stxz +0 -0
  433. package/tests/suite/bin/stxzy +0 -0
  434. package/tests/suite/bin/stya +0 -0
  435. package/tests/suite/bin/styz +0 -0
  436. package/tests/suite/bin/styzx +0 -0
  437. package/tests/suite/bin/taxn +0 -0
  438. package/tests/suite/bin/tayn +0 -0
  439. package/tests/suite/bin/trap1 +0 -0
  440. package/tests/suite/bin/trap10 +0 -0
  441. package/tests/suite/bin/trap11 +0 -0
  442. package/tests/suite/bin/trap12 +0 -0
  443. package/tests/suite/bin/trap13 +0 -0
  444. package/tests/suite/bin/trap14 +0 -0
  445. package/tests/suite/bin/trap15 +0 -0
  446. package/tests/suite/bin/trap16 +0 -0
  447. package/tests/suite/bin/trap17 +0 -0
  448. package/tests/suite/bin/trap2 +0 -0
  449. package/tests/suite/bin/trap3 +0 -0
  450. package/tests/suite/bin/trap4 +0 -0
  451. package/tests/suite/bin/trap5 +0 -0
  452. package/tests/suite/bin/trap6 +0 -0
  453. package/tests/suite/bin/trap7 +0 -0
  454. package/tests/suite/bin/trap8 +0 -0
  455. package/tests/suite/bin/trap9 +0 -0
  456. package/tests/suite/bin/tsxn +0 -0
  457. package/tests/suite/bin/txan +0 -0
  458. package/tests/suite/bin/txsn +0 -0
  459. package/tests/suite/bin/tyan +0 -0
  460. package/tests/suite/cbm-hackers-post.html +178 -0
  461. package/tests/suite/cbm-hackers-post.md +78 -0
  462. package/tests/test-machine.js +288 -0
  463. package/tests/test-suite.js +147 -0
  464. package/tests/test.css +7 -0
  465. package/tests/unit/gzip/test-1 +0 -0
  466. package/tests/unit/gzip/test-1.gz +0 -0
  467. package/tests/unit/gzip/test-2 +0 -0
  468. package/tests/unit/gzip/test-2.gz +0 -0
  469. package/tests/unit/gzip/test-3 +0 -0
  470. package/tests/unit/gzip/test-3.gz +0 -0
  471. package/tests/unit/gzip/test-4 +0 -0
  472. package/tests/unit/gzip/test-4.gz +0 -0
  473. package/tests/unit/test-adc.js +307 -0
  474. package/tests/unit/test-bcd.js +30 -0
  475. package/tests/unit/test-cmos.js +266 -0
  476. package/tests/unit/test-disc-drive.js +85 -0
  477. package/tests/unit/test-disc-hfe.js +347 -0
  478. package/tests/unit/test-disc.js +232 -0
  479. package/tests/unit/test-fifo.js +35 -0
  480. package/tests/unit/test-gamepad-source.js +67 -0
  481. package/tests/unit/test-gzip.js +22 -0
  482. package/tests/unit/test-intel-fdc.js +93 -0
  483. package/tests/unit/test-keyboard.js +410 -0
  484. package/tests/unit/test-mouse-joystick-source.js +128 -0
  485. package/tests/unit/test-scheduler.js +190 -0
  486. package/tests/unit/test-serial.js +154 -0
  487. package/tests/unit/test-teletext-adaptor.js +359 -0
  488. package/tests/unit/test-tokenise.js +65 -0
  489. package/tests/unit/test-url-params.js +398 -0
  490. package/tests/unit/test-utils.js +276 -0
  491. package/tests/unit/test-video.js +498 -0
  492. package/tests/unit/test-zip.js +56 -0
  493. package/tests/unit/zip/test-mixed.zip +0 -0
  494. package/tests/unit/zip/test-rom.zip +0 -0
  495. package/tests/unit/zip/test-ssd.zip +0 -0
  496. package/tools/fir-generator.js +80 -0
  497. package/tools/vite-plugin-fir-shader.js +131 -0
  498. package/vite.config.js +34 -0
@@ -0,0 +1,411 @@
1
+ "use strict";
2
+ import * as utils from "./utils.js";
3
+ import EventEmitter from "event-emitter-es6";
4
+
5
+ const isMac = typeof window !== "undefined" && /^Mac/i.test(window.navigator?.platform || "");
6
+
7
+ /**
8
+ * @typedef {Object} KeyboardConfig
9
+ * @property {Object} processor - The processor instance
10
+ * @property {Function} inputEnabledFunction - A function to check if input is enabled
11
+ * @property {string} [keyLayout="physical"] - The keyboard layout
12
+ * @property {Debugger} dbgr - The debugger instance
13
+ */
14
+
15
+ /**
16
+ * Keyboard class that handles all keyboard related functionality
17
+ */
18
+ export class Keyboard extends EventEmitter {
19
+ /**
20
+ * Create a new Keyboard instance with specified configuration
21
+ * @param {KeyboardConfig} config - The configuration object
22
+ */
23
+ constructor(config) {
24
+ super();
25
+ const { processor, inputEnabledFunction, keyLayout = "physical", dbgr } = config;
26
+
27
+ // Core components
28
+ this.processor = processor;
29
+ this.inputEnabledFunction = inputEnabledFunction;
30
+ this.dbgr = dbgr;
31
+
32
+ // State
33
+ this.emuKeyHandlers = {};
34
+ this.running = false;
35
+ this.pauseEmu = false;
36
+ this.stepEmuWhenPaused = false;
37
+ this.keyLayout = keyLayout;
38
+
39
+ // Modifier key states
40
+ this.lastShiftLocation = 1;
41
+ this.lastCtrlLocation = 1;
42
+ this.lastAltLocation = 1;
43
+ }
44
+
45
+ /**
46
+ * Translates a keyboard event to a BBC key code
47
+ * @param {KeyboardEvent} evt - The keyboard event
48
+ * @returns {number} - The BBC key code
49
+ */
50
+ keyCode(evt) {
51
+ const ret = evt.which || evt.charCode || evt.keyCode;
52
+ const keyCodes = utils.keyCodes;
53
+
54
+ switch (evt.location) {
55
+ default:
56
+ // keyUp events seem to pass location = 0 (Chrome)
57
+ switch (ret) {
58
+ case keyCodes.SHIFT:
59
+ return this.lastShiftLocation === 1 ? keyCodes.SHIFT_LEFT : keyCodes.SHIFT_RIGHT;
60
+ case keyCodes.ALT:
61
+ return this.lastAltLocation === 1 ? keyCodes.ALT_LEFT : keyCodes.ALT_RIGHT;
62
+ case keyCodes.CTRL:
63
+ return this.lastCtrlLocation === 1 ? keyCodes.CTRL_LEFT : keyCodes.CTRL_RIGHT;
64
+ }
65
+ break;
66
+ case 1:
67
+ switch (ret) {
68
+ case keyCodes.SHIFT:
69
+ this.lastShiftLocation = 1;
70
+ return keyCodes.SHIFT_LEFT;
71
+ case keyCodes.ALT:
72
+ this.lastAltLocation = 1;
73
+ return keyCodes.ALT_LEFT;
74
+ case keyCodes.CTRL:
75
+ this.lastCtrlLocation = 1;
76
+ return keyCodes.CTRL_LEFT;
77
+ }
78
+ break;
79
+ case 2:
80
+ switch (ret) {
81
+ case keyCodes.SHIFT:
82
+ this.lastShiftLocation = 2;
83
+ return keyCodes.SHIFT_RIGHT;
84
+ case keyCodes.ALT:
85
+ this.lastAltLocation = 2;
86
+ return keyCodes.ALT_RIGHT;
87
+ case keyCodes.CTRL:
88
+ this.lastCtrlLocation = 2;
89
+ return keyCodes.CTRL_RIGHT;
90
+ }
91
+ break;
92
+ case 3: // numpad
93
+ switch (ret) {
94
+ case keyCodes.ENTER:
95
+ return utils.keyCodes.NUMPADENTER;
96
+ case keyCodes.DELETE:
97
+ return utils.keyCodes.NUMPAD_DECIMAL_POINT;
98
+ }
99
+ break;
100
+ }
101
+
102
+ return ret;
103
+ }
104
+
105
+ /**
106
+ * Registers a handler for a specific key with optional modifiers
107
+ * @param {number} keyCode - The key code to handle
108
+ * @param {Function} handler - The handler function
109
+ * @param {Object} [options] - Options for this handler
110
+ * @param {boolean} [options.alt=true] - Whether this handler requires the Alt key
111
+ * @param {boolean} [options.ctrl=false] - Whether this handler requires the Ctrl key
112
+ */
113
+ registerKeyHandler(keyCode, handler, options = { alt: true, ctrl: false }) {
114
+ // Generate a unique key that includes modifiers
115
+ const handlerKey = `${options.alt ? "alt:" : ""}${options.ctrl ? "ctrl:" : ""}${keyCode}`;
116
+ this.emuKeyHandlers[handlerKey] = {
117
+ handler,
118
+ alt: !!options.alt,
119
+ ctrl: !!options.ctrl,
120
+ keyCode,
121
+ };
122
+ }
123
+
124
+ /**
125
+ * Updates the current key layout
126
+ * @param {string} layout - The keyboard layout to use
127
+ */
128
+ setKeyLayout(layout) {
129
+ this.keyLayout = layout;
130
+ this.processor.sysvia.setKeyLayout(layout);
131
+ }
132
+
133
+ /**
134
+ * Sets the running state of the emulator
135
+ * @param {boolean} isRunning - Whether the emulator is running
136
+ */
137
+ setRunning(isRunning) {
138
+ this.running = isRunning;
139
+ }
140
+
141
+ /**
142
+ * Find a matching key handler for the given key event
143
+ * @param {number} keyCode - The key code
144
+ * @param {boolean} altKey - Whether Alt is pressed
145
+ * @param {boolean} ctrlKey - Whether Ctrl is pressed
146
+ * @returns {Object|null} The handler object or null if none found
147
+ * @private
148
+ */
149
+ _findKeyHandler(keyCode, altKey, ctrlKey) {
150
+ // Try to find a handler with exact modifier match first
151
+ const exactModKey = `${altKey ? "alt:" : ""}${ctrlKey ? "ctrl:" : ""}${keyCode}`;
152
+ if (this.emuKeyHandlers[exactModKey]) {
153
+ return this.emuKeyHandlers[exactModKey];
154
+ }
155
+
156
+ return null;
157
+ }
158
+
159
+ /**
160
+ * Handles a key press event
161
+ * @param {KeyboardEvent} evt - The keyboard event
162
+ */
163
+ keyPress(evt) {
164
+ // Common key constants
165
+ const LOWERCASE_G = 103;
166
+ const LOWERCASE_N = 110;
167
+
168
+ // Early returns for common scenarios
169
+ // Check if input is enabled. If inputEnabledFunction returns true, keyboard events should not be processed.
170
+ if (this.inputEnabledFunction()) return;
171
+ if (this.running || (!this.dbgr.enabled() && !this.pauseEmu)) return;
172
+
173
+ const code = this.keyCode(evt);
174
+
175
+ // Handle debugger 'g' key press
176
+ if (this.dbgr.enabled() && code === LOWERCASE_G) {
177
+ this.dbgr.hide();
178
+ this.emit("resume");
179
+ return;
180
+ }
181
+
182
+ // Handle pause/step control keys
183
+ if (this.pauseEmu) {
184
+ if (code === LOWERCASE_G) {
185
+ this.resumeEmulation();
186
+ return;
187
+ } else if (code === LOWERCASE_N) {
188
+ this.requestStep();
189
+ this.emit("resume");
190
+ return;
191
+ }
192
+ }
193
+
194
+ // Pass any other keys to the debugger if it's enabled
195
+ if (this.dbgr.enabled()) {
196
+ const handled = this.dbgr.keyPress(this.keyCode(evt));
197
+ if (handled) evt.preventDefault();
198
+ }
199
+ }
200
+
201
+ /**
202
+ * Handles a key down event
203
+ * @param {KeyboardEvent} evt - The keyboard event
204
+ */
205
+ keyDown(evt) {
206
+ // Early returns for common scenarios
207
+ if (this.inputEnabledFunction()) return;
208
+ if (!this.running) return;
209
+
210
+ const code = this.keyCode(evt);
211
+ evt.preventDefault();
212
+
213
+ // Special handling cases that we always want to keep within keyboard.js
214
+ const isSpecialHandled = this._handleSpecialKeys(code);
215
+ if (isSpecialHandled) return;
216
+
217
+ // Always pass the key to the BBC Micro (unless it was a special key)
218
+ this.processor.sysvia.keyDown(code, evt.shiftKey);
219
+
220
+ // Check for registered handlers
221
+ const handler = this._findKeyHandler(code, evt.altKey, evt.ctrlKey);
222
+ if (handler) {
223
+ handler.handler(true, code);
224
+ }
225
+ }
226
+
227
+ /**
228
+ * Handle special keys that must remain in keyboard.js
229
+ * @param {number} code - The key code
230
+ * @returns {boolean} True if the key was handled specially
231
+ * @private
232
+ */
233
+ _handleSpecialKeys(code) {
234
+ if (code === utils.keyCodes.F12 || code === utils.keyCodes.BREAK) {
235
+ this.emit("break", true);
236
+ this.processor.setReset(true);
237
+ return true;
238
+ } else if (isMac && code === utils.keyCodes.CAPSLOCK) {
239
+ // Special CapsLock handling for Mac
240
+ this.handleMacCapsLock();
241
+ return true;
242
+ }
243
+
244
+ return false;
245
+ }
246
+
247
+ /**
248
+ * Handles a key up event
249
+ * @param {KeyboardEvent} evt - The keyboard event
250
+ */
251
+ keyUp(evt) {
252
+ // Early return for text input
253
+ if (this.inputEnabledFunction()) return;
254
+
255
+ // Always let the key ups come through to avoid sticky keys in the debugger
256
+ const code = this.keyCode(evt);
257
+ this.processor.sysvia.keyUp(code);
258
+
259
+ // No further special handling needed if not running
260
+ if (!this.running) return;
261
+
262
+ evt.preventDefault();
263
+
264
+ // Handle special key cases
265
+ if (code === utils.keyCodes.F12 || code === utils.keyCodes.BREAK) {
266
+ this.emit("break", false);
267
+ this.processor.setReset(false);
268
+ return;
269
+ } else if (isMac && code === utils.keyCodes.CAPSLOCK) {
270
+ // Special CapsLock handling for Mac
271
+ this.handleMacCapsLock();
272
+ return;
273
+ }
274
+
275
+ // Check for registered handlers
276
+ const handler = this._findKeyHandler(code, evt.altKey, evt.ctrlKey);
277
+ if (handler) {
278
+ handler.handler(false, code);
279
+ }
280
+ }
281
+
282
+ /**
283
+ * Special handling for Mac's Caps Lock key behavior
284
+ */
285
+ handleMacCapsLock() {
286
+ const CAPS_LOCK_DELAY = 100;
287
+
288
+ // Mac browsers seem to model caps lock as a physical key that's down when capslock is on, and up when it's off.
289
+ // No event is generated when it is physically released on the keyboard. So, we simulate a "tap" here.
290
+ this.processor.sysvia.keyDown(utils.keyCodes.CAPSLOCK);
291
+
292
+ // Simulate a key release after a short delay
293
+ setTimeout(() => this.processor.sysvia.keyUp(utils.keyCodes.CAPSLOCK), CAPS_LOCK_DELAY);
294
+
295
+ if (isMac && window.localStorage && !window.localStorage.getItem("warnedAboutRubbishMacs")) {
296
+ this.emit("showError", {
297
+ context: "handling caps lock on Mac OS X",
298
+ error: `Mac OS X does not generate key up events for caps lock presses.
299
+ jsbeeb can only simulate a 'tap' of the caps lock key. This means it doesn't work well for games
300
+ that use caps lock for left or fire, as we can't tell if it's being held down. If you need to play
301
+ such a game, please see the documentation about remapping keys.
302
+ Close this window to continue (you won't see this error again)`,
303
+ });
304
+ window.localStorage.setItem("warnedAboutRubbishMacs", "true");
305
+ }
306
+ }
307
+
308
+ /**
309
+ * Send raw keyboard input to the BBC
310
+ * @param {Array} keysToSend - Array of keys to send
311
+ * @param {boolean} checkCapsAndShiftLocks - Whether to check caps and shift locks
312
+ */
313
+ sendRawKeyboardToBBC(keysToSend, checkCapsAndShiftLocks) {
314
+ let lastChar;
315
+ let nextKeyMillis = 0;
316
+ this.processor.sysvia.disableKeyboard();
317
+ const clocksPerSecond = Math.floor(this.processor.cpuMultiplier * 2000000);
318
+
319
+ if (checkCapsAndShiftLocks) {
320
+ let toggleKey = null;
321
+ if (!this.processor.sysvia.capsLockLight) toggleKey = utils.BBC.CAPSLOCK;
322
+ else if (this.processor.sysvia.shiftLockLight) toggleKey = utils.BBC.SHIFTLOCK;
323
+ if (toggleKey) {
324
+ keysToSend.unshift(toggleKey);
325
+ keysToSend.push(toggleKey);
326
+ }
327
+ }
328
+
329
+ const sendCharHook = this.processor.debugInstruction.add(() => {
330
+ const millis = this.processor.cycleSeconds * 1000 + this.processor.currentCycles / (clocksPerSecond / 1000);
331
+ if (millis < nextKeyMillis) {
332
+ return;
333
+ }
334
+
335
+ if (lastChar && lastChar !== utils.BBC.SHIFT) {
336
+ this.processor.sysvia.keyToggleRaw(lastChar);
337
+ }
338
+
339
+ if (keysToSend.length === 0) {
340
+ // Finished
341
+ this.processor.sysvia.enableKeyboard();
342
+ sendCharHook.remove();
343
+ return;
344
+ }
345
+
346
+ const ch = keysToSend[0];
347
+ const debounce = lastChar === ch;
348
+ lastChar = ch;
349
+ if (debounce) {
350
+ lastChar = undefined;
351
+ nextKeyMillis = millis + 30;
352
+ return;
353
+ }
354
+
355
+ let time = 50;
356
+ if (typeof lastChar === "number") {
357
+ time = lastChar;
358
+ lastChar = undefined;
359
+ } else {
360
+ this.processor.sysvia.keyToggleRaw(lastChar);
361
+ }
362
+
363
+ // remove first character
364
+ keysToSend.shift();
365
+
366
+ nextKeyMillis = millis + time;
367
+ });
368
+ }
369
+
370
+ /**
371
+ * Clears all pressed keys
372
+ */
373
+ clearKeys() {
374
+ this.processor.sysvia.clearKeys();
375
+ }
376
+
377
+ /**
378
+ * Called after each frame to determine if emulation should pause
379
+ * @returns {boolean} - True if emulation should pause
380
+ */
381
+ postFrameShouldPause() {
382
+ if (this.stepEmuWhenPaused) {
383
+ this.stepEmuWhenPaused = false;
384
+ return true;
385
+ }
386
+ return false;
387
+ }
388
+
389
+ /**
390
+ * Request a single step of the emulator
391
+ */
392
+ requestStep() {
393
+ this.stepEmuWhenPaused = true;
394
+ }
395
+
396
+ /**
397
+ * Pause the emulator
398
+ */
399
+ pauseEmulation() {
400
+ this.pauseEmu = true;
401
+ this.emit("pause");
402
+ }
403
+
404
+ /**
405
+ * Resume the emulator
406
+ */
407
+ resumeEmulation() {
408
+ this.pauseEmu = false;
409
+ this.emit("resume");
410
+ }
411
+ }
package/src/lib/README ADDED
@@ -0,0 +1 @@
1
+ webgl-debug is from Khronos