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
package/index.html ADDED
@@ -0,0 +1,954 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <script async src="https://www.googletagmanager.com/gtag/js?id=G-Z9ZN3S7XRE"></script>
5
+ <script>
6
+ window.dataLayer = window.dataLayer || [];
7
+ function gtag() {
8
+ dataLayer.push(arguments);
9
+ }
10
+ gtag("js", new Date());
11
+
12
+ gtag("config", "G-Z9ZN3S7XRE");
13
+ </script>
14
+ <meta charset="utf-8" />
15
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
16
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
17
+ <meta name="author" content="Matt Godbolt" />
18
+ <meta name="description" content="A Javascript BBC Micro emulator" />
19
+ <meta
20
+ http-equiv="Content-Security-Policy"
21
+ content="script-src 'self' 'unsafe-inline' 'unsafe-eval' *.google-analytics.com *.google.com;"
22
+ />
23
+ <title>jsbeeb - Javascript BBC Micro emulator</title>
24
+ <link rel="shortcut icon" href="/favicon.ico" />
25
+ <script type="module" src="/src/main.js"></script>
26
+ </head>
27
+
28
+ <body>
29
+ <nav id="header-bar" class="navbar navbar-dark bg-dark navbar-expand-lg not-electron" role="navigation">
30
+ <div class="container-fluid">
31
+ <a class="navbar-brand" href="https://bbc.xania.org/" target="_top">jsbeeb</a>
32
+ <button
33
+ class="navbar-toggler"
34
+ type="button"
35
+ data-bs-toggle="collapse"
36
+ data-bs-target="#navbarSupportedContent"
37
+ aria-controls="navbarSupportedContent"
38
+ aria-expanded="false"
39
+ aria-label="Toggle navigation"
40
+ >
41
+ <span class="navbar-toggler-icon"></span>
42
+ </button>
43
+ <div class="collapse navbar-collapse" id="navbarSupportedContent">
44
+ <ul class="navbar-nav nav mb-2 mb-lg-0">
45
+ <li class="nav-item">
46
+ <a href="#configuration" class="nav-link" data-bs-toggle="modal" data-bs-target="#configuration">
47
+ <span class="bbc-model">BBC B</span></a
48
+ >
49
+ </li>
50
+ <li class="nav-item dropdown embed-hide">
51
+ <a
52
+ href="#"
53
+ class="nav-link dropdown-toggle"
54
+ id="navbarDiscs"
55
+ role="button"
56
+ data-bs-toggle="dropdown"
57
+ aria-expanded="false"
58
+ >Discs</a
59
+ >
60
+ <ul class="dropdown-menu dropdown-menu-dark" aria-labelledby="navbarDiscs">
61
+ <li>
62
+ <a href="#sth" class="dropdown-item sth" data-id="discs" data-bs-toggle="modal" data-bs-target="#sth"
63
+ >From STH archive</a
64
+ >
65
+ </li>
66
+ <li>
67
+ <a href="#discs" class="dropdown-item" data-bs-toggle="modal" data-bs-target="#discs">
68
+ From examples or local</a
69
+ >
70
+ </li>
71
+ <li class="if-drive-available">
72
+ <a href="#google-drive" class="dropdown-item" id="open-drive-link">From Google Drive</a>
73
+ </li>
74
+ <hr />
75
+ <div id="fsmenuitem">
76
+ <li>
77
+ <a href="#econetfs" class="dropdown-item" data-bs-toggle="modal" data-bs-target="#econetfs">
78
+ Econet File Server</a
79
+ >
80
+ </li>
81
+ <hr />
82
+ </div>
83
+ <li>
84
+ <a href="#download-drive" class="dropdown-item" id="download-drive-link"
85
+ >Download drive 0 image as SSD/DSD</a
86
+ >
87
+ </li>
88
+ <li>
89
+ <a href="#download-drive-hfe" class="dropdown-item" id="download-drive-hfe-link"
90
+ >Download drive 0 image as HFE</a
91
+ >
92
+ </li>
93
+ </ul>
94
+ </li>
95
+ <li class="nav-item dropdown embed-hide">
96
+ <a
97
+ href="#"
98
+ class="nav-link dropdown-toggle"
99
+ id="navbarCassettes"
100
+ role="button"
101
+ data-bs-toggle="dropdown"
102
+ aria-expanded="false"
103
+ >Cassettes</a
104
+ >
105
+ <ul class="dropdown-menu dropdown-menu-dark" id="tape-menu" aria-labelledby="navbarCassettes">
106
+ <li>
107
+ <a href="#sth" class="dropdown-item sth" data-bs-toggle="modal" data-id="tapes" data-bs-target="#sth"
108
+ >From STH archive</a
109
+ >
110
+ </li>
111
+ <li><a data-id="rewind" class="dropdown-item">Rewind cassette</a></li>
112
+ <li>
113
+ <a href="#discs" class="dropdown-item" data-bs-toggle="modal" data-bs-target="#tapes">
114
+ From local file
115
+ </a>
116
+ </li>
117
+ </ul>
118
+ </li>
119
+ <li class="nav-item dropdown embed-hide">
120
+ <a
121
+ href="#"
122
+ class="nav-link dropdown-toggle"
123
+ id="navbarReset"
124
+ role="button"
125
+ data-bs-toggle="dropdown"
126
+ aria-expanded="false"
127
+ >Reset</a
128
+ >
129
+ <ul class="dropdown-menu dropdown-menu-dark" aria-labelledby="navbarReset">
130
+ <li><a href="#" id="soft-reset" class="dropdown-item">Soft reset</a></li>
131
+ <li><a href="#" id="hard-reset" class="dropdown-item">Hard reset</a></li>
132
+ </ul>
133
+ </li>
134
+ <li class="nav-item dropdown embed-hide">
135
+ <a
136
+ href="#"
137
+ class="nav-link dropdown-toggle"
138
+ id="navbarMore"
139
+ role="button"
140
+ data-bs-toggle="dropdown"
141
+ aria-expanded="false"
142
+ >More</a
143
+ >
144
+ <ul class="dropdown-menu dropdown-menu-dark" aria-labelledby="navbarMore">
145
+ <li><a href="#" id="fs" class="dropdown-item">Fullscreen</a></li>
146
+ <li><a href="#help" class="dropdown-item" data-bs-toggle="modal" data-bs-target="#help">Help</a></li>
147
+ <li>
148
+ <a href="#pp-tos" class="dropdown-item" data-bs-toggle="modal" data-bs-target="#pp-tos"
149
+ >Privacy Policy &amp; ToS</a
150
+ >
151
+ </li>
152
+ <li><a href="mailto:matt@godbolt.org" class="dropdown-item">Contact the Author</a></li>
153
+ <li>
154
+ <a href="http://xania.org/MattGodbolt" class="dropdown-item" rel="author" target="_blank">
155
+ About the Author</a
156
+ >
157
+ </li>
158
+ <li>
159
+ <a href="#about" class="dropdown-item" data-bs-toggle="modal" data-bs-target="#info" id="about">
160
+ About jsbeeb</a
161
+ >
162
+ </li>
163
+ </ul>
164
+ </li>
165
+ </ul>
166
+ <span class="navbar-text m-auto">
167
+ Edit BBC BASIC interactively with Owlet at
168
+ <a href="https://bbcmic.ro/" target="_blank">bbcmic.ro</a>!
169
+ </span>
170
+ <form class="form-inline">
171
+ <button
172
+ id="debug-play"
173
+ type="button"
174
+ class="btn btn-sm"
175
+ title="Start running the emulator (if not running already); hiding the debugger"
176
+ >
177
+ &#x23f5;
178
+ </button>
179
+ <button
180
+ id="debug-pause"
181
+ type="button"
182
+ class="btn btn-sm"
183
+ title="Pause the running emulator and show the debugger"
184
+ >
185
+ &#x23f8;
186
+ </button>
187
+ </form>
188
+ <form class="d-flex">
189
+ <input
190
+ id="paste-text"
191
+ class="form-control me-2"
192
+ type="text"
193
+ maxlength="0"
194
+ placeholder="Paste text or drop files here..."
195
+ aria-label="Search"
196
+ />
197
+ </form>
198
+ </div>
199
+ </div>
200
+ </nav>
201
+
202
+ <div id="audio-warning" class="alert alert-warning initially-hidden">
203
+ Your browser has suspended audio -- mouse click or key press for sound.
204
+ </div>
205
+
206
+ <div>
207
+ <div id="outer">
208
+ <div id="cub-monitor">
209
+ <!-- Image is dynamically swapped by config.js based on filter.displayImage -->
210
+ <img
211
+ id="cub-monitor-pic"
212
+ width="896"
213
+ height="648"
214
+ src="images/cub-monitor.png"
215
+ alt="A fake CUB computer monitor"
216
+ />
217
+ <div class="sidebar left"><img src="images/placeholder.png" alt="" /></div>
218
+ <canvas id="screen" width="896" height="600"></canvas>
219
+ <div class="sidebar right"><img src="images/placeholder.png" alt="" /></div>
220
+ <div class="sidebar bottom"><img src="images/placeholder.png" alt="" /></div>
221
+ </div>
222
+ </div>
223
+ <canvas id="audio-stats" width="400" height="100"></canvas>
224
+ <div id="leds">
225
+ <table>
226
+ <thead>
227
+ <tr>
228
+ <th>cassette<br />motor</th>
229
+ <th>caps<br />lock</th>
230
+ <th>shift<br />lock</th>
231
+ <th>drive<br />0/2</th>
232
+ <th>drive<br />1/3</th>
233
+ <th>econet<br />tx/rx</th>
234
+ <th id="virtual-mhz-header">virtual<br />MHz</th>
235
+ </tr>
236
+ </thead>
237
+ <tbody>
238
+ <tr>
239
+ <td>
240
+ <div class="red led" id="motorlight"></div>
241
+ </td>
242
+ <td>
243
+ <div class="red led" id="capslight"></div>
244
+ </td>
245
+ <td>
246
+ <div class="red led" id="shiftlight"></div>
247
+ </td>
248
+ <td>
249
+ <div class="yellow led" id="drive0"></div>
250
+ </td>
251
+ <td>
252
+ <div class="yellow led" id="drive1"></div>
253
+ </td>
254
+ <td>
255
+ <div class="yellow led" id="networklight"></div>
256
+ </td>
257
+ <td>
258
+ <div class="virtualMHz"></div>
259
+ </td>
260
+ </tr>
261
+ </tbody>
262
+ </table>
263
+ </div>
264
+ <div id="crtc_debug" class="initially-hidden">
265
+ <div class="crtc_state">
266
+ <h6 class="dbg">6845 state</h6>
267
+ <table>
268
+ <tbody>
269
+ <tr class="template">
270
+ <th><span class="register"></span>:</th>
271
+ <td class="value"></td>
272
+ </tr>
273
+ </tbody>
274
+ </table>
275
+ </div>
276
+ <div class="crtc_regs">
277
+ <h6 class="dbg">6845 regs</h6>
278
+ <table>
279
+ <tbody>
280
+ <tr class="template">
281
+ <th><span class="register"></span>:</th>
282
+ <td class="value"></td>
283
+ </tr>
284
+ </tbody>
285
+ </table>
286
+ </div>
287
+ </div>
288
+ <div id="debug" class="initially-hidden">
289
+ <div class="debug-container">
290
+ <form id="goto-mem-addr-form" role="form">
291
+ <div class="input-group input-group-sm">
292
+ <span accesskey="m" class="input-group-text" id="mem_addr_text">
293
+ <span class="accesskey">M</span>em addr:
294
+ </span>
295
+ <input
296
+ type="text"
297
+ class="form-control form-control-sm goto-addr"
298
+ placeholder="$0000"
299
+ aria-label="Memory address"
300
+ aria-describedby="mem_addr_text"
301
+ />
302
+ </div>
303
+ </form>
304
+ <div id="memory">
305
+ <div class="template">
306
+ <span class="dis_addr">0000</span
307
+ ><span class="mem_bytes"
308
+ ><span>11</span> <span>22</span> <span>33</span> <span>44</span> <span>55</span> <span>66</span>
309
+ <span>77</span> <span>88</span></span
310
+ ><span class="mem_asc"
311
+ ><span>A</span><span>A</span><span>A</span><span>A</span><span>A</span><span>A</span><span>A</span
312
+ ><span>A</span></span
313
+ >
314
+ </div>
315
+ </div>
316
+ </div>
317
+ <div class="debug-container">
318
+ <form role="form" id="goto-dis-addr-form">
319
+ <div class="input-group input-group-sm">
320
+ <span accesskey="a" class="input-group-text" id="dis_addr_text"
321
+ ><span class="accesskey">A</span>ddr:</span
322
+ >
323
+ <input
324
+ type="text"
325
+ class="form-control form-control-sm goto-addr"
326
+ placeholder="$0000"
327
+ aria-label="Disassembly address"
328
+ aria-describedby="dis_addr_text"
329
+ />
330
+ </div>
331
+ </form>
332
+ <div id="disassembly">
333
+ <div class="template dis_elem">
334
+ <span class="bp_gutter"></span><span class="dis_addr">0000</span><span class="instr_bytes">11 22 33</span
335
+ ><span class="instr_asc">ABC</span><span class="disassembly">LDA (&amp;70), X</span>
336
+ </div>
337
+ </div>
338
+ </div>
339
+ <div id="registers">
340
+ <div>
341
+ <span class="flag" id="cpu6502_flag_c">C</span><span class="flag" id="cpu6502_flag_z">Z</span
342
+ ><span class="flag" id="cpu6502_flag_i">I</span><span class="flag" id="cpu6502_flag_d">D</span
343
+ ><span class="flag" id="cpu6502_flag_v">V</span><span class="flag" id="cpu6502_flag_n">N</span>
344
+ </div>
345
+ <div><span class="register">A</span>: <span id="cpu6502_a">00</span></div>
346
+ <div><span class="register">X</span>: <span id="cpu6502_x">00</span></div>
347
+ <div><span class="register">Y</span>: <span id="cpu6502_y">00</span></div>
348
+ <div><span class="register">S</span>: <span id="cpu6502_s">00</span></div>
349
+ <div><span class="register">PC</span>: <span id="cpu6502_pc">0000</span></div>
350
+ </div>
351
+ </div>
352
+ <div id="hardware_debug" class="initially-hidden">
353
+ <div class="via_regs" id="sysvia">
354
+ <h6 class="dbg">System VIA</h6>
355
+ <table>
356
+ <tbody>
357
+ <tr class="template">
358
+ <th><span class="register"></span>:</th>
359
+ <td class="value"></td>
360
+ </tr>
361
+ </tbody>
362
+ </table>
363
+ </div>
364
+ <div class="via_regs" id="uservia">
365
+ <h6 class="dbg">User VIA</h6>
366
+ <table>
367
+ <tbody>
368
+ <tr class="template">
369
+ <th><span class="register"></span>:</th>
370
+ <td class="value"></td>
371
+ </tr>
372
+ </tbody>
373
+ </table>
374
+ </div>
375
+ </div>
376
+ </div>
377
+
378
+ <div class="modal fade" id="info" tabindex="-1" aria-labelledby="infoModalLabel" aria-hidden="true">
379
+ <div class="modal-dialog modal-lg">
380
+ <div class="modal-content">
381
+ <div class="modal-header">
382
+ <h5 class="modal-title" id="infoModalLabel">About jsbeeb</h5>
383
+ <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
384
+ </div>
385
+ <div class="modal-body">
386
+ <div>
387
+ By <a href="https://xania.org/">Matt Godbolt</a>. Based on Sarah Walker's
388
+ <a href="http://b-em.bbcmicro.com/">b-em</a> emulator. Huge thanks to her for open sourcing her code. Big
389
+ thanks too to Richard Talbot-Watkins for his help and support. The disc loaded up by default is the
390
+ amazing Elite (thanks to <a href="http://www.iancgbell.clara.net/elite/bbc/">Ian Bell</a> for making it
391
+ available).
392
+ </div>
393
+ <div>
394
+ Source is on <a href="https://github.com/mattgodbolt/jsbeeb">GitHub</a>. Works best in Chrome or Firefox.
395
+ </div>
396
+ <div>
397
+ Cycle-accurate emulation greatly helped by the fantastic
398
+ <a href="http://www.visual6502.org/">Visual 6502</a> Project. Consider donating to them if you enjoy this
399
+ stuff as much as I do!
400
+ </div>
401
+ <div>
402
+ I f you're looking for more information on the BBC or to find like-minded people to chat about the
403
+ hardware or software, check out the <a href="http://www.stardot.org.uk/forums/">StarDot forums</a>.
404
+ </div>
405
+ </div>
406
+ <div class="modal-footer">
407
+ <span class="text-muted me-auto" id="jsbeeb-version"></span>
408
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
409
+ </div>
410
+ </div>
411
+ </div>
412
+ </div>
413
+
414
+ <div class="modal fade" id="pp-tos" tabindex="-1" aria-labelledby="ppModalLabel" aria-hidden="true">
415
+ <div class="modal-dialog modal-lg">
416
+ <div class="modal-content">
417
+ <div class="modal-header">
418
+ <h5 class="modal-title" id="ppModalLabel">Privacy Policy &amp; Terms of Service</h5>
419
+ <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
420
+ </div>
421
+ <div class="modal-body">
422
+ <div>
423
+ jsbeeb uses cookies for simple analytics. Those analytics are used to track usage and improve user
424
+ experience. If you'd like to run a local copy of jsbeeb instead, the source is on
425
+ <a href="https://github.com/mattgodbolt/jsbeeb">GitHub</a>. There's no server logs or information kept on
426
+ the jsbeeb servers, we just serve up this HTML from an AWS bucket.
427
+ </div>
428
+ <div>
429
+ No personal information is kept. If you choose to access Google Drive for disc storage, only the minimal
430
+ information needed to log in and access your own discs is kept in cookies. That information is never
431
+ shared with the jsbeeb developers.
432
+ </div>
433
+ <div>
434
+ Use of jsbeeb is at your own risk. Reasonable efforts are used to keep the site up to date and working.
435
+ You may use jsbeeb for whatever lawful purpose you wish.
436
+ </div>
437
+ </div>
438
+ <div class="modal-footer">
439
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
440
+ </div>
441
+ </div>
442
+ </div>
443
+ </div>
444
+
445
+ <div class="modal fade" id="help" tabindex="-1" aria-labelledby="helpModalLabel" aria-hidden="true">
446
+ <div class="modal-dialog">
447
+ <div class="modal-content">
448
+ <div class="modal-header">
449
+ <h5 class="modal-title" id="helpModalLabel">Help</h5>
450
+ <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
451
+ </div>
452
+ <div class="modal-body">
453
+ <div>
454
+ This is an emulator for the <a href="https://en.wikipedia.org/wiki/Bbc_micro">BBC Micro</a>, a popular
455
+ home computer in the UK in the 1980s. It emulates the BBC B &amp; Master version of the computer.
456
+ </div>
457
+ <div>
458
+ The default disc image is Elite - a pioneering 3D space trading game. To boot discs on the BBC, one would
459
+ press <span class="key">SHIFT</span> and <span class="key">BREAK</span>. The keyboard of the BBC is
460
+ slightly different from a modern PC, notably in the placement of the symbol characters. Also, the current
461
+ keyboard layout is optimized for a US keyboard; I am working on improving this situation.
462
+ </div>
463
+ <div>
464
+ <h5>Handy key mappings</h5>
465
+ <table class="keymap">
466
+ <tr>
467
+ <th>BBC</th>
468
+ <th>PC</th>
469
+ <th>OSX</th>
470
+ </tr>
471
+ <tr>
472
+ <td><span class="function key">F0</span></td>
473
+ <td><span class="key">F10</span></td>
474
+ <td><span class="key">F10</span></td>
475
+ </tr>
476
+ <tr>
477
+ <td><span class="key">BREAK</span></td>
478
+ <td><span class="key">F12</span></td>
479
+ <td><span class="key">Right &#8984;</span> + <span class="key">F12</span></td>
480
+ </tr>
481
+ <tr>
482
+ <td><span class="key">COPY</span></td>
483
+ <td><span class="key">End</span></td>
484
+ <td><span class="key">Right &#8984;</span> + <span class="key">F11</span></td>
485
+ </tr>
486
+ <tr>
487
+ <td>
488
+ <div class="dbl key">*<br />:</div>
489
+ </td>
490
+ <td>
491
+ <div class="dbl key">"<br />'</div>
492
+ </td>
493
+ <td>
494
+ <div class="dbl key">"<br />'</div>
495
+ </td>
496
+ </tr>
497
+ <tr>
498
+ <td>
499
+ <div class="dbl key">CAPS<br />LOCK</div>
500
+ </td>
501
+ <td class="key">CAPSLOCK</td>
502
+ <td>See notes</td>
503
+ </tr>
504
+ <tr>
505
+ <td>Debug</td>
506
+ <td><span class="key">Ctrl-Home</span></td>
507
+ <td><span class="key">Ctrl-Home</span></td>
508
+ </tr>
509
+ </table>
510
+ <div>
511
+ Note that caps lock doesn't work well on OS X because browsers don't give proper key down and key up
512
+ events for that key. That means jsbeeb can't know when you've released the physical key; it just guesses
513
+ that you tapped the key whenever it notices the caps lock state changes. That's fine for typing but
514
+ means that some games that use caps lock for left or fire, don't work. Consult the main documentation
515
+ for details on how to map keys.
516
+ </div>
517
+ </div>
518
+ </div>
519
+ <div class="modal-footer">
520
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
521
+ </div>
522
+ </div>
523
+ </div>
524
+ </div>
525
+
526
+ <div class="modal fade" id="discs" tabindex="-1" aria-labelledby="discModalLabel" aria-hidden="true">
527
+ <div class="modal-dialog">
528
+ <div class="modal-content">
529
+ <div class="modal-header">
530
+ <h5 class="modal-title" id="discModalLabel">Load disc image</h5>
531
+ <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
532
+ </div>
533
+ <div class="modal-body">
534
+ <ul id="disc-list">
535
+ <li class="template">
536
+ <a href="#"><span class="name"></span></a> - <span class="description"></span>
537
+ </li>
538
+ </ul>
539
+ To load a custom disc image, get an SSD, DSD, HFE, ADF, ADM or ADL file and load it below. Search the web,
540
+ or check somewhere like
541
+ <a href="http://www.bbcmicrogames.com/GettingStarted.html">here</a> for these. Be aware the images are
542
+ usually stored in a ZIP file, and you'll need to unzip first.
543
+ <div class="disc">
544
+ <label
545
+ >Load local SSD, DSD, HFE, ADF, ADM or ADL file:
546
+ <input type="file" id="disc_load" accept=".ssd,.dsd,.adf,.adm,.adl,.hfe,application/binary" />
547
+ </label>
548
+ </div>
549
+ </div>
550
+ <div class="modal-footer">
551
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
552
+ </div>
553
+ </div>
554
+ </div>
555
+ </div>
556
+
557
+ <div class="modal fade" id="econetfs" tabindex="-1" aria-labelledby="econetModalLabel" aria-hidden="true">
558
+ <div class="modal-dialog">
559
+ <div class="modal-content">
560
+ <div class="modal-header">
561
+ <h5 class="modal-title" id="econetModalLabel">Econet File Server</h5>
562
+ <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
563
+ </div>
564
+ <div class="modal-body">
565
+ <label>
566
+ Download server drive image (10mb scsi.dat):<br />
567
+
568
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal" id="download-filestore-link">
569
+ Download image
570
+ </button>
571
+ </label>
572
+
573
+ <div class="disc">
574
+ <label
575
+ >Upload a local drive image and restart the file server:
576
+ <input class="form-control" type="file" id="fs_load" accept=".dat,application/binary" />
577
+ </label>
578
+ </div>
579
+ </div>
580
+ <div class="modal-footer">
581
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
582
+ </div>
583
+ </div>
584
+ </div>
585
+ </div>
586
+
587
+ <div class="modal fade" id="tapes" tabindex="-1" aria-labelledby="tapeModalLabel" aria-hidden="true">
588
+ <div class="modal-dialog">
589
+ <div class="modal-content">
590
+ <div class="modal-header">
591
+ <h5 class="modal-title" id="tapeModalLabel">Load cassette image</h5>
592
+ <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
593
+ </div>
594
+ <div class="modal-body">
595
+ To load a custom cassette image, get a UEF file and load it below.
596
+ <div class="tape">
597
+ <label
598
+ >Load local UEF file:
599
+ <input type="file" id="tape_load" accept=".uef,application/binary" />
600
+ </label>
601
+ </div>
602
+ </div>
603
+ <div class="modal-footer">
604
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
605
+ </div>
606
+ </div>
607
+ </div>
608
+ </div>
609
+
610
+ <div class="modal fade" id="google-drive" tabindex="-1" aria-labelledby="google-driveModalLabel" aria-hidden="true">
611
+ <div class="modal-dialog">
612
+ <div class="modal-content">
613
+ <div class="modal-header">
614
+ <h5 class="modal-title" id="google-driveModalLabel">
615
+ Load or create disc from your
616
+ <a href="https://drive.google.com/">Google Drive</a>
617
+ account
618
+ </h5>
619
+ <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
620
+ </div>
621
+ <div class="modal-body">
622
+ <div class="loading">Loading...</div>
623
+ <div>
624
+ <ul class="list">
625
+ <li class="template">
626
+ <a href="#"><span class="name"></span></a>
627
+ </li>
628
+ </ul>
629
+ <div>
630
+ <form class="well" role="form" action="#">
631
+ <input type="text" placeholder="Create disc..." autofocus class="disc-name" />
632
+ <label class="checkbox-inline">
633
+ <input type="checkbox" class="create-from-existing" value="" />
634
+ Use current disc image
635
+ </label>
636
+ <button type="submit" class="btn btn-secondary create-button">Create</button>
637
+ </form>
638
+ </div>
639
+ </div>
640
+ </div>
641
+ <div class="modal-footer">
642
+ <button type="button" class="btn" data-bs-dismiss="modal">Close</button>
643
+ </div>
644
+ </div>
645
+ </div>
646
+ </div>
647
+
648
+ <!-- cannot make this one fade in else our attempts to close the modal while it's still opening fail -->
649
+ <div class="modal" id="loading-dialog" tabindex="-1" aria-labelledby="loadingModalLabel" aria-hidden="true">
650
+ <div class="modal-dialog">
651
+ <div class="modal-content">
652
+ <div class="modal-body">
653
+ <div class="modal-header">
654
+ <h5 class="modal-title loading" id="loadingModalLabel"></h5>
655
+ <button
656
+ type="button"
657
+ class="btn-close btn-close-white"
658
+ data-bs-dismiss="modal"
659
+ aria-label="Close"
660
+ ></button>
661
+ </div>
662
+ </div>
663
+ <div class="modal-body">
664
+ <div style="display: none" id="google-drive-auth">
665
+ Google Drive requires you to authorize jsbeeb to access your files by logging in.<br />
666
+ Please click Authorize to open a Google Drive pop-up to authenticate and give permission to jsbeeb.
667
+ <form class="well" role="form" action="#">
668
+ <button type="submit" class="btn btn-secondary">Authorize</button>
669
+ </form>
670
+ </div>
671
+ </div>
672
+ </div>
673
+ </div>
674
+ </div>
675
+
676
+ <div class="modal fade" id="sth" tabindex="-1" aria-labelledby="sthModalLabel" aria-hidden="true">
677
+ <div class="modal-dialog">
678
+ <div class="modal-content">
679
+ <div class="modal-header">
680
+ <h5 class="modal-title" id="sthModalLabel">
681
+ Load from
682
+ <a href="http://www.stairwaytohell.com/">Stairway to Hell</a>
683
+ archive
684
+ </h5>
685
+ <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
686
+ </div>
687
+ <div class="modal-body">
688
+ <div style="margin-bottom: 1rem">
689
+ <div class="loading">Loading catalog from STH archive...</div>
690
+ <div class="filter">
691
+ <label>Filter <input type="text" autofocus id="sth-filter" /></label>
692
+ </div>
693
+ </div>
694
+ <ul id="sth-list">
695
+ <li class="template">
696
+ <a href="#"><span class="name"></span></a>
697
+ </li>
698
+ </ul>
699
+ </div>
700
+ <div class="modal-footer">
701
+ <label class="float-xs-left checkbox-inline">
702
+ <input type="checkbox" class="autoboot" value="" />Autoboot</label
703
+ >
704
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
705
+ </div>
706
+ </div>
707
+ </div>
708
+ </div>
709
+
710
+ <div class="modal fade" id="error-dialog" tabindex="-1" aria-labelledby="errorModalLabel" aria-hidden="true">
711
+ <div class="modal-dialog">
712
+ <div class="modal-content">
713
+ <div class="modal-header">
714
+ <h5 class="modal-title" id="errorModalLabel">An error occurred - sorry!</h5>
715
+ </div>
716
+ <div class="modal-body">
717
+ <div>While <span class="context"></span>:</div>
718
+ <div class="error"></div>
719
+ </div>
720
+ <div class="modal-footer">
721
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
722
+ </div>
723
+ </div>
724
+ </div>
725
+ </div>
726
+
727
+ <div class="modal fade" id="are-you-sure" tabindex="-1" aria-labelledby="aysModalLabel" aria-hidden="true">
728
+ <div class="modal-dialog">
729
+ <div class="modal-content">
730
+ <div class="modal-header">
731
+ <h5 class="modal-title" id="aysModalLabel">Are You Sure?</h5>
732
+ <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
733
+ </div>
734
+ <div class="modal-body">
735
+ <div class="context"></div>
736
+ </div>
737
+ <div class="modal-footer">
738
+ <button type="button" class="btn btn-secondary ays-no" data-bs-dismiss="modal">No</button>
739
+ <button type="button" class="btn btn-primary ays-yes">Yes</button>
740
+ </div>
741
+ </div>
742
+ </div>
743
+ </div>
744
+
745
+ <div
746
+ class="modal fade"
747
+ id="configuration"
748
+ tabindex="-1"
749
+ aria-labelledby="configurationModalLabel"
750
+ aria-hidden="true"
751
+ >
752
+ <div class="modal-dialog">
753
+ <div class="modal-content">
754
+ <div class="modal-header">
755
+ <h5 class="modal-title" id="configurationModalLabel">Emulation Configuration</h5>
756
+ <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
757
+ </div>
758
+ <div class="modal-body">
759
+ <div class="row align-items-center">
760
+ <div class="col-sm-6">
761
+ <label for="bbc-model-dropdown" class="col-form-label"
762
+ >Base model:<br />
763
+ <small>(including disk interface)</small>
764
+ </label>
765
+ </div>
766
+ <div class="col-sm-6 dropdown">
767
+ <button
768
+ type="button"
769
+ class="btn btn-secondary dropdown-toggle"
770
+ data-bs-toggle="dropdown"
771
+ id="bbc-model-dropdown"
772
+ >
773
+ <span class="bbc-model"></span>
774
+ </button>
775
+ <ul
776
+ class="dropdown-menu dropdown-menu-dark model-menu"
777
+ role="menu"
778
+ aria-labelledby="bbc-model-dropdown"
779
+ >
780
+ <li>
781
+ <a href="#" class="dropdown-item" data-target="B-DFS1.2">BBC B with 8271 (DFS 1.2)</a>
782
+ </li>
783
+ <li>
784
+ <a href="#" class="dropdown-item" data-target="B-DFS0.9">BBC B with 8271 (DFS 0.9)</a>
785
+ </li>
786
+ <li>
787
+ <a href="#" class="dropdown-item" data-target="B1770">BBC B with 1770 (DFS)</a>
788
+ </li>
789
+ <li>
790
+ <a href="#" class="dropdown-item" data-target="B1770A">BBC B with 1770 (ADFS)</a>
791
+ </li>
792
+ <li>
793
+ <a href="#" class="dropdown-item" data-target="Master">BBC Master 128 (DFS)</a>
794
+ </li>
795
+ <li>
796
+ <a href="#" class="dropdown-item" data-target="MasterADFS">BBC Master 128 (ADFS)</a>
797
+ </li>
798
+ <li>
799
+ <a href="#" class="dropdown-item" data-target="MasterANFS">BBC Master 128 (ANFS)</a>
800
+ </li>
801
+ </ul>
802
+ </div>
803
+ </div>
804
+ <div class="row align-items-center">
805
+ <div class="col-sm-6">
806
+ <label for="keyboardDropdown" class="col-form-label">Keyboard layout:</label>
807
+ </div>
808
+ <div class="col-sm-6 dropdown">
809
+ <button
810
+ type="button"
811
+ class="btn btn-secondary dropdown-toggle"
812
+ data-bs-toggle="dropdown"
813
+ id="keyboardDropdown"
814
+ >
815
+ <span class="keyboard-layout">Physical</span>
816
+ </button>
817
+ <ul
818
+ class="dropdown-menu dropdown-menu-dark keyboard-menu"
819
+ role="menu"
820
+ aria-labelledby="keyboardDropdown"
821
+ >
822
+ <li>
823
+ <a href="#" class="dropdown-item" data-target="physical">Physical: '*' is next to Enter/Return</a>
824
+ </li>
825
+ <li>
826
+ <a href="#" class="dropdown-item" data-target="natural">Natural: '*' is shift-8</a>
827
+ </li>
828
+ <li>
829
+ <a href="#" class="dropdown-item" data-target="gaming">Gaming: handy for games like Zalaga</a>
830
+ </li>
831
+ </ul>
832
+ </div>
833
+ </div>
834
+ <div id="displaySettings" style="margin-top: 15px">
835
+ <div class="row align-items-center">
836
+ <div class="col-sm-6">
837
+ <label for="displayModeDropdown" class="col-form-label">Display mode:</label>
838
+ </div>
839
+ <div class="col-sm-6 dropdown">
840
+ <button
841
+ type="button"
842
+ class="btn btn-secondary dropdown-toggle"
843
+ data-bs-toggle="dropdown"
844
+ id="displayModeDropdown"
845
+ >
846
+ <span class="display-mode-text">CUB Monitor</span>
847
+ </button>
848
+ <ul
849
+ class="dropdown-menu dropdown-menu-dark display-mode-menu"
850
+ role="menu"
851
+ aria-labelledby="displayModeDropdown"
852
+ >
853
+ <li>
854
+ <a href="#" class="dropdown-item display-mode-option" data-mode="rgb">RGB Monitor</a>
855
+ </li>
856
+ <li>
857
+ <a href="#" class="dropdown-item display-mode-option" data-mode="pal">PAL TV</a>
858
+ </li>
859
+ </ul>
860
+ </div>
861
+ </div>
862
+ </div>
863
+ <div class="align-items-center">
864
+ <div class="row">
865
+ <div class="col-sm-6">
866
+ <label class="col-form-label"
867
+ >Additional peripherals:<br /><small
868
+ >(some combinations may cause compatibility issues)</small
869
+ ></label
870
+ >
871
+ </div>
872
+ <div class="col-sm-6">
873
+ <div class="form-check">
874
+ <input class="form-check-input" type="checkbox" id="65c02" name="65c02" />
875
+ <label class="form-check-label" for="65c02">65c02 co-processor</label>
876
+ </div>
877
+ <div class="form-check">
878
+ <input class="form-check-input" type="checkbox" id="hasMusic5000" name="hasMusic5000" />
879
+ <label class="form-check-label" for="hasMusic5000">Music 5000 synthesiser</label>
880
+ </div>
881
+ <div class="form-check">
882
+ <input class="form-check-input" type="checkbox" id="hasTeletextAdaptor" name="hasTeletextAdaptor" />
883
+ <label class="form-check-label" for="hasTeletextAdaptor">Teletext adaptor</label>
884
+ </div>
885
+ <div class="form-check">
886
+ <input class="form-check-input" type="checkbox" id="hasEconet" name="hasEconet" />
887
+ <label class="form-check-label" for="hasEconet">Econet with file server</label>
888
+ </div>
889
+ </div>
890
+ </div>
891
+ </div>
892
+
893
+ <div id="analogueAudioSettings" style="margin-top: 15px">
894
+ <div class="row align-items-center">
895
+ <div class="col-sm-6">
896
+ <label for="micInputChannel" class="col-form-label">Microphone channel:</label>
897
+ </div>
898
+ <div class="col-sm-6 dropdown">
899
+ <button
900
+ type="button"
901
+ class="btn btn-secondary dropdown-toggle"
902
+ data-bs-toggle="dropdown"
903
+ id="micInputChannel"
904
+ >
905
+ <span class="mic-channel-text">Disabled</span>
906
+ </button>
907
+ <ul
908
+ class="dropdown-menu dropdown-menu-dark mic-channel-menu"
909
+ role="menu"
910
+ aria-labelledby="micInputChannel"
911
+ >
912
+ <li><a href="#" class="dropdown-item mic-channel-option" data-channel="">Disabled</a></li>
913
+ <li><a href="#" class="dropdown-item mic-channel-option" data-channel="0">Channel 0</a></li>
914
+ <li><a href="#" class="dropdown-item mic-channel-option" data-channel="1">Channel 1</a></li>
915
+ <li><a href="#" class="dropdown-item mic-channel-option" data-channel="2">Channel 2</a></li>
916
+ <li><a href="#" class="dropdown-item mic-channel-option" data-channel="3">Channel 3</a></li>
917
+ </ul>
918
+ </div>
919
+ </div>
920
+ <div id="micPermissionStatus" class="mt-2 small text-muted"></div>
921
+ </div>
922
+
923
+ <div id="mouseJoystickSettings" style="margin-top: 15px">
924
+ <div class="row align-items-center">
925
+ <div class="col-sm-6">
926
+ <label class="col-form-label">Mouse joystick:</label>
927
+ <div class="form-check">
928
+ <input
929
+ class="form-check-input"
930
+ type="checkbox"
931
+ id="mouseJoystickEnabled"
932
+ name="mouseJoystickEnabled"
933
+ />
934
+ <label class="form-check-label" for="mouseJoystickEnabled">
935
+ Enable mouse as analogue joystick
936
+ </label>
937
+ </div>
938
+ </div>
939
+ <div class="col-sm-6">
940
+ <div class="small text-muted mt-2">
941
+ Maps mouse position on BBC display to channels 0 (X) and 1 (Y)
942
+ </div>
943
+ </div>
944
+ </div>
945
+ </div>
946
+ </div>
947
+ <div class="modal-footer">
948
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
949
+ </div>
950
+ </div>
951
+ </div>
952
+ </div>
953
+ </body>
954
+ </html>