jsbeeb 1.1.1 → 1.3.3

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 (418) hide show
  1. package/package.json +26 -12
  2. package/src/6502.js +51 -41
  3. package/src/app/app.js +99 -8
  4. package/src/app/electron.js +47 -5
  5. package/src/app/preload.js +11 -1
  6. package/src/config.js +9 -2
  7. package/src/disc.js +2 -2
  8. package/src/filestore.js +1 -4
  9. package/src/gamepad-source.js +1 -1
  10. package/src/machine-session.js +393 -0
  11. package/src/main.js +36 -7
  12. package/src/music5000-worklet.js +1 -0
  13. package/src/music5000.js +1 -9
  14. package/src/sth.js +3 -1
  15. package/src/utils.js +14 -2
  16. package/src/web/audio-renderer.js +1 -1
  17. package/src/web/debug.js +2 -2
  18. package/tests/test-machine.js +82 -1
  19. package/.editorconfig +0 -15
  20. package/.git-blame-ignore-revs +0 -3
  21. package/.github/copilot-instructions.md +0 -94
  22. package/.github/workflows/claude-issue-triage.yml +0 -105
  23. package/.github/workflows/claude.yml +0 -63
  24. package/.github/workflows/release-please.yml +0 -75
  25. package/.github/workflows/test-and-deploy.yml +0 -86
  26. package/.gitmodules +0 -6
  27. package/.husky/pre-commit +0 -1
  28. package/.idea/codeStyleSettings.xml +0 -9
  29. package/.idea/codeStyles/Project.xml +0 -62
  30. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  31. package/.idea/compiler.xml +0 -22
  32. package/.idea/copyright/profiles_settings.xml +0 -3
  33. package/.idea/encodings.xml +0 -6
  34. package/.idea/inspectionProfiles/Project_Default.xml +0 -7
  35. package/.idea/jsLibraryMappings.xml +0 -6
  36. package/.idea/jsLinters/jshint.xml +0 -85
  37. package/.idea/jsLinters/jslint.xml +0 -15
  38. package/.idea/jsbeeb.iml +0 -11
  39. package/.idea/misc.xml +0 -6
  40. package/.idea/modules.xml +0 -8
  41. package/.idea/prettier.xml +0 -7
  42. package/.idea/runConfigurations/Debug.xml +0 -5
  43. package/.idea/scopes/scope_settings.xml +0 -5
  44. package/.idea/vcs.xml +0 -8
  45. package/.prettierignore +0 -4
  46. package/.prettierrc.json +0 -1
  47. package/.release-please-manifest.json +0 -3
  48. package/.vscode/launch.json +0 -14
  49. package/.vscode/settings.json +0 -6
  50. package/CHANGELOG.md +0 -32
  51. package/CLAUDE.md +0 -136
  52. package/Dockerfile +0 -22
  53. package/Makefile +0 -30
  54. package/docker/nginx-default.conf +0 -10
  55. package/docs/pal-comb-filter-research.md +0 -129
  56. package/docs/pal-simulation-design.md +0 -368
  57. package/eslint.config.js +0 -35
  58. package/index.html +0 -954
  59. package/jsconfig.json +0 -10
  60. package/public/discs/README.Irq-Timing +0 -3
  61. package/public/discs/README.bcdtest +0 -5
  62. package/public/discs/README.elite +0 -6
  63. package/public/discs/README.eng_test +0 -3
  64. package/public/discs/README.protection +0 -7
  65. package/public/favicon.ico +0 -0
  66. package/public/images/botbar.png +0 -0
  67. package/public/images/cub-monitor.png +0 -0
  68. package/public/images/jsbeeb-example.png +0 -0
  69. package/public/images/placeholder.png +0 -0
  70. package/public/images/red-off-16.png +0 -0
  71. package/public/images/red-on-16.png +0 -0
  72. package/public/images/sb/CD-left.jpg +0 -0
  73. package/public/images/sb/CD-right.jpg +0 -0
  74. package/public/images/sidebar.png +0 -0
  75. package/public/images/tv.png +0 -0
  76. package/public/images/yellow-off-16.png +0 -0
  77. package/public/images/yellow-on-16.png +0 -0
  78. package/public/jsbeeb-icon.png +0 -0
  79. package/public/robots.txt +0 -3
  80. package/public/sounds/disc525/motor.wav +0 -0
  81. package/public/sounds/disc525/motoroff.wav +0 -0
  82. package/public/sounds/disc525/motoron.wav +0 -0
  83. package/public/sounds/disc525/seek.wav +0 -0
  84. package/public/sounds/disc525/seek2.wav +0 -0
  85. package/public/sounds/disc525/seek3.wav +0 -0
  86. package/public/sounds/disc525/step.wav +0 -0
  87. package/public/teletext/txt0.dat +0 -0
  88. package/public/teletext/txt1.dat +0 -0
  89. package/public/teletext/txt2.dat +0 -0
  90. package/public/teletext/txt3.dat +0 -0
  91. package/release-please-config.json +0 -13
  92. package/run-container.sh +0 -92
  93. package/tests/integration/RmwX.asm +0 -47
  94. package/tests/integration/TestInstructionsSource +0 -27
  95. package/tests/integration/TestTimingsResults +0 -27
  96. package/tests/integration/TestTimingsSource +0 -61
  97. package/tests/integration/bcd.js +0 -23
  98. package/tests/integration/dormann.js +0 -101
  99. package/tests/integration/dp111timing.js +0 -42
  100. package/tests/integration/ensure-submodules.js +0 -25
  101. package/tests/integration/nops.bas +0 -119
  102. package/tests/integration/nops.js +0 -24
  103. package/tests/integration/protection.js +0 -26
  104. package/tests/integration/rmw.js +0 -69
  105. package/tests/integration/teletext/expected_bug_469.png +0 -0
  106. package/tests/integration/teletext/expected_flash_0.png +0 -0
  107. package/tests/integration/teletext/expected_flash_1.png +0 -0
  108. package/tests/integration/teletext/expected_hoglet_held_char.png +0 -0
  109. package/tests/integration/teletext/expected_reveal_flash_0.png +0 -0
  110. package/tests/integration/teletext/expected_reveal_flash_1.png +0 -0
  111. package/tests/integration/teletext.js +0 -126
  112. package/tests/integration/timings.js +0 -56
  113. package/tests/integration/via.js +0 -1125
  114. package/tests/suite/README.md +0 -7
  115. package/tests/suite/Test Suite 2.15.txt +0 -373
  116. package/tests/suite/bin/ start +0 -0
  117. package/tests/suite/bin/adca +0 -0
  118. package/tests/suite/bin/adcax +0 -0
  119. package/tests/suite/bin/adcay +0 -0
  120. package/tests/suite/bin/adcb +0 -0
  121. package/tests/suite/bin/adcix +0 -0
  122. package/tests/suite/bin/adciy +0 -0
  123. package/tests/suite/bin/adcz +0 -0
  124. package/tests/suite/bin/adczx +0 -0
  125. package/tests/suite/bin/alrb +0 -0
  126. package/tests/suite/bin/ancb +0 -0
  127. package/tests/suite/bin/anda +0 -0
  128. package/tests/suite/bin/andax +0 -0
  129. package/tests/suite/bin/anday +0 -0
  130. package/tests/suite/bin/andb +0 -0
  131. package/tests/suite/bin/andix +0 -0
  132. package/tests/suite/bin/andiy +0 -0
  133. package/tests/suite/bin/andz +0 -0
  134. package/tests/suite/bin/andzx +0 -0
  135. package/tests/suite/bin/aneb +0 -0
  136. package/tests/suite/bin/arrb +0 -0
  137. package/tests/suite/bin/asla +0 -0
  138. package/tests/suite/bin/aslax +0 -0
  139. package/tests/suite/bin/asln +0 -0
  140. package/tests/suite/bin/aslz +0 -0
  141. package/tests/suite/bin/aslzx +0 -0
  142. package/tests/suite/bin/asoa +0 -0
  143. package/tests/suite/bin/asoax +0 -0
  144. package/tests/suite/bin/asoay +0 -0
  145. package/tests/suite/bin/asoix +0 -0
  146. package/tests/suite/bin/asoiy +0 -0
  147. package/tests/suite/bin/asoz +0 -0
  148. package/tests/suite/bin/asozx +0 -0
  149. package/tests/suite/bin/axsa +0 -0
  150. package/tests/suite/bin/axsix +0 -0
  151. package/tests/suite/bin/axsz +0 -0
  152. package/tests/suite/bin/axszy +0 -0
  153. package/tests/suite/bin/bccr +0 -0
  154. package/tests/suite/bin/bcsr +0 -0
  155. package/tests/suite/bin/beqr +0 -0
  156. package/tests/suite/bin/bita +0 -0
  157. package/tests/suite/bin/bitz +0 -0
  158. package/tests/suite/bin/bmir +0 -0
  159. package/tests/suite/bin/bner +0 -0
  160. package/tests/suite/bin/bplr +0 -0
  161. package/tests/suite/bin/branchwrap +0 -0
  162. package/tests/suite/bin/brkn +0 -0
  163. package/tests/suite/bin/bvcr +0 -0
  164. package/tests/suite/bin/bvsr +0 -0
  165. package/tests/suite/bin/cia1pb6 +0 -0
  166. package/tests/suite/bin/cia1pb7 +0 -0
  167. package/tests/suite/bin/cia1ta +0 -0
  168. package/tests/suite/bin/cia1tab +0 -0
  169. package/tests/suite/bin/cia1tb +0 -0
  170. package/tests/suite/bin/cia1tb123 +0 -0
  171. package/tests/suite/bin/cia2pb6 +0 -0
  172. package/tests/suite/bin/cia2pb7 +0 -0
  173. package/tests/suite/bin/cia2ta +0 -0
  174. package/tests/suite/bin/cia2tb +0 -0
  175. package/tests/suite/bin/cia2tb123 +0 -0
  176. package/tests/suite/bin/clcn +0 -0
  177. package/tests/suite/bin/cldn +0 -0
  178. package/tests/suite/bin/clin +0 -0
  179. package/tests/suite/bin/clvn +0 -0
  180. package/tests/suite/bin/cmpa +0 -0
  181. package/tests/suite/bin/cmpax +0 -0
  182. package/tests/suite/bin/cmpay +0 -0
  183. package/tests/suite/bin/cmpb +0 -0
  184. package/tests/suite/bin/cmpix +0 -0
  185. package/tests/suite/bin/cmpiy +0 -0
  186. package/tests/suite/bin/cmpz +0 -0
  187. package/tests/suite/bin/cmpzx +0 -0
  188. package/tests/suite/bin/cntdef +0 -0
  189. package/tests/suite/bin/cnto2 +0 -0
  190. package/tests/suite/bin/cpuport +0 -0
  191. package/tests/suite/bin/cputiming +0 -0
  192. package/tests/suite/bin/cpxa +0 -0
  193. package/tests/suite/bin/cpxb +0 -0
  194. package/tests/suite/bin/cpxz +0 -0
  195. package/tests/suite/bin/cpya +0 -0
  196. package/tests/suite/bin/cpyb +0 -0
  197. package/tests/suite/bin/cpyz +0 -0
  198. package/tests/suite/bin/dcma +0 -0
  199. package/tests/suite/bin/dcmax +0 -0
  200. package/tests/suite/bin/dcmay +0 -0
  201. package/tests/suite/bin/dcmix +0 -0
  202. package/tests/suite/bin/dcmiy +0 -0
  203. package/tests/suite/bin/dcmz +0 -0
  204. package/tests/suite/bin/dcmzx +0 -0
  205. package/tests/suite/bin/deca +0 -0
  206. package/tests/suite/bin/decax +0 -0
  207. package/tests/suite/bin/decz +0 -0
  208. package/tests/suite/bin/deczx +0 -0
  209. package/tests/suite/bin/dexn +0 -0
  210. package/tests/suite/bin/deyn +0 -0
  211. package/tests/suite/bin/eora +0 -0
  212. package/tests/suite/bin/eorax +0 -0
  213. package/tests/suite/bin/eoray +0 -0
  214. package/tests/suite/bin/eorb +0 -0
  215. package/tests/suite/bin/eorix +0 -0
  216. package/tests/suite/bin/eoriy +0 -0
  217. package/tests/suite/bin/eorz +0 -0
  218. package/tests/suite/bin/eorzx +0 -0
  219. package/tests/suite/bin/finish +0 -0
  220. package/tests/suite/bin/flipos +0 -0
  221. package/tests/suite/bin/icr01 +0 -0
  222. package/tests/suite/bin/imr +0 -0
  223. package/tests/suite/bin/inca +0 -0
  224. package/tests/suite/bin/incax +0 -0
  225. package/tests/suite/bin/incz +0 -0
  226. package/tests/suite/bin/inczx +0 -0
  227. package/tests/suite/bin/insa +0 -0
  228. package/tests/suite/bin/insax +0 -0
  229. package/tests/suite/bin/insay +0 -0
  230. package/tests/suite/bin/insix +0 -0
  231. package/tests/suite/bin/insiy +0 -0
  232. package/tests/suite/bin/insz +0 -0
  233. package/tests/suite/bin/inszx +0 -0
  234. package/tests/suite/bin/inxn +0 -0
  235. package/tests/suite/bin/inyn +0 -0
  236. package/tests/suite/bin/irq +0 -0
  237. package/tests/suite/bin/jmpi +0 -0
  238. package/tests/suite/bin/jmpw +0 -0
  239. package/tests/suite/bin/jsrw +0 -0
  240. package/tests/suite/bin/lasay +0 -0
  241. package/tests/suite/bin/laxa +0 -0
  242. package/tests/suite/bin/laxay +0 -0
  243. package/tests/suite/bin/laxix +0 -0
  244. package/tests/suite/bin/laxiy +0 -0
  245. package/tests/suite/bin/laxz +0 -0
  246. package/tests/suite/bin/laxzy +0 -0
  247. package/tests/suite/bin/ldaa +0 -0
  248. package/tests/suite/bin/ldaax +0 -0
  249. package/tests/suite/bin/ldaay +0 -0
  250. package/tests/suite/bin/ldab +0 -0
  251. package/tests/suite/bin/ldaix +0 -0
  252. package/tests/suite/bin/ldaiy +0 -0
  253. package/tests/suite/bin/ldaz +0 -0
  254. package/tests/suite/bin/ldazx +0 -0
  255. package/tests/suite/bin/ldxa +0 -0
  256. package/tests/suite/bin/ldxay +0 -0
  257. package/tests/suite/bin/ldxb +0 -0
  258. package/tests/suite/bin/ldxz +0 -0
  259. package/tests/suite/bin/ldxzy +0 -0
  260. package/tests/suite/bin/ldya +0 -0
  261. package/tests/suite/bin/ldyax +0 -0
  262. package/tests/suite/bin/ldyb +0 -0
  263. package/tests/suite/bin/ldyz +0 -0
  264. package/tests/suite/bin/ldyzx +0 -0
  265. package/tests/suite/bin/loadth +0 -0
  266. package/tests/suite/bin/lsea +0 -0
  267. package/tests/suite/bin/lseax +0 -0
  268. package/tests/suite/bin/lseay +0 -0
  269. package/tests/suite/bin/lseix +0 -0
  270. package/tests/suite/bin/lseiy +0 -0
  271. package/tests/suite/bin/lsez +0 -0
  272. package/tests/suite/bin/lsezx +0 -0
  273. package/tests/suite/bin/lsra +0 -0
  274. package/tests/suite/bin/lsrax +0 -0
  275. package/tests/suite/bin/lsrn +0 -0
  276. package/tests/suite/bin/lsrz +0 -0
  277. package/tests/suite/bin/lsrzx +0 -0
  278. package/tests/suite/bin/lxab +0 -0
  279. package/tests/suite/bin/mmu +0 -0
  280. package/tests/suite/bin/mmufetch +0 -0
  281. package/tests/suite/bin/nmi +0 -0
  282. package/tests/suite/bin/nopa +0 -0
  283. package/tests/suite/bin/nopax +0 -0
  284. package/tests/suite/bin/nopb +0 -0
  285. package/tests/suite/bin/nopn +0 -0
  286. package/tests/suite/bin/nopz +0 -0
  287. package/tests/suite/bin/nopzx +0 -0
  288. package/tests/suite/bin/oneshot +0 -0
  289. package/tests/suite/bin/oraa +0 -0
  290. package/tests/suite/bin/oraax +0 -0
  291. package/tests/suite/bin/oraay +0 -0
  292. package/tests/suite/bin/orab +0 -0
  293. package/tests/suite/bin/oraix +0 -0
  294. package/tests/suite/bin/oraiy +0 -0
  295. package/tests/suite/bin/oraz +0 -0
  296. package/tests/suite/bin/orazx +0 -0
  297. package/tests/suite/bin/phan +0 -0
  298. package/tests/suite/bin/phpn +0 -0
  299. package/tests/suite/bin/plan +0 -0
  300. package/tests/suite/bin/plpn +0 -0
  301. package/tests/suite/bin/rlaa +0 -0
  302. package/tests/suite/bin/rlaax +0 -0
  303. package/tests/suite/bin/rlaay +0 -0
  304. package/tests/suite/bin/rlaix +0 -0
  305. package/tests/suite/bin/rlaiy +0 -0
  306. package/tests/suite/bin/rlaz +0 -0
  307. package/tests/suite/bin/rlazx +0 -0
  308. package/tests/suite/bin/rola +0 -0
  309. package/tests/suite/bin/rolax +0 -0
  310. package/tests/suite/bin/roln +0 -0
  311. package/tests/suite/bin/rolz +0 -0
  312. package/tests/suite/bin/rolzx +0 -0
  313. package/tests/suite/bin/rora +0 -0
  314. package/tests/suite/bin/rorax +0 -0
  315. package/tests/suite/bin/rorn +0 -0
  316. package/tests/suite/bin/rorz +0 -0
  317. package/tests/suite/bin/rorzx +0 -0
  318. package/tests/suite/bin/rraa +0 -0
  319. package/tests/suite/bin/rraax +0 -0
  320. package/tests/suite/bin/rraay +0 -0
  321. package/tests/suite/bin/rraix +0 -0
  322. package/tests/suite/bin/rraiy +0 -0
  323. package/tests/suite/bin/rraz +0 -0
  324. package/tests/suite/bin/rrazx +0 -0
  325. package/tests/suite/bin/rtin +0 -0
  326. package/tests/suite/bin/rtsn +0 -0
  327. package/tests/suite/bin/sbca +0 -0
  328. package/tests/suite/bin/sbcax +0 -0
  329. package/tests/suite/bin/sbcay +0 -0
  330. package/tests/suite/bin/sbcb +0 -0
  331. package/tests/suite/bin/sbcb(eb) +0 -0
  332. package/tests/suite/bin/sbcix +0 -0
  333. package/tests/suite/bin/sbciy +0 -0
  334. package/tests/suite/bin/sbcz +0 -0
  335. package/tests/suite/bin/sbczx +0 -0
  336. package/tests/suite/bin/sbxb +0 -0
  337. package/tests/suite/bin/secn +0 -0
  338. package/tests/suite/bin/sedn +0 -0
  339. package/tests/suite/bin/sein +0 -0
  340. package/tests/suite/bin/shaay +0 -0
  341. package/tests/suite/bin/shaiy +0 -0
  342. package/tests/suite/bin/shsay +0 -0
  343. package/tests/suite/bin/shxay +0 -0
  344. package/tests/suite/bin/shyax +0 -0
  345. package/tests/suite/bin/staa +0 -0
  346. package/tests/suite/bin/staax +0 -0
  347. package/tests/suite/bin/staay +0 -0
  348. package/tests/suite/bin/staix +0 -0
  349. package/tests/suite/bin/staiy +0 -0
  350. package/tests/suite/bin/staz +0 -0
  351. package/tests/suite/bin/stazx +0 -0
  352. package/tests/suite/bin/stxa +0 -0
  353. package/tests/suite/bin/stxz +0 -0
  354. package/tests/suite/bin/stxzy +0 -0
  355. package/tests/suite/bin/stya +0 -0
  356. package/tests/suite/bin/styz +0 -0
  357. package/tests/suite/bin/styzx +0 -0
  358. package/tests/suite/bin/taxn +0 -0
  359. package/tests/suite/bin/tayn +0 -0
  360. package/tests/suite/bin/trap1 +0 -0
  361. package/tests/suite/bin/trap10 +0 -0
  362. package/tests/suite/bin/trap11 +0 -0
  363. package/tests/suite/bin/trap12 +0 -0
  364. package/tests/suite/bin/trap13 +0 -0
  365. package/tests/suite/bin/trap14 +0 -0
  366. package/tests/suite/bin/trap15 +0 -0
  367. package/tests/suite/bin/trap16 +0 -0
  368. package/tests/suite/bin/trap17 +0 -0
  369. package/tests/suite/bin/trap2 +0 -0
  370. package/tests/suite/bin/trap3 +0 -0
  371. package/tests/suite/bin/trap4 +0 -0
  372. package/tests/suite/bin/trap5 +0 -0
  373. package/tests/suite/bin/trap6 +0 -0
  374. package/tests/suite/bin/trap7 +0 -0
  375. package/tests/suite/bin/trap8 +0 -0
  376. package/tests/suite/bin/trap9 +0 -0
  377. package/tests/suite/bin/tsxn +0 -0
  378. package/tests/suite/bin/txan +0 -0
  379. package/tests/suite/bin/txsn +0 -0
  380. package/tests/suite/bin/tyan +0 -0
  381. package/tests/suite/cbm-hackers-post.html +0 -178
  382. package/tests/suite/cbm-hackers-post.md +0 -78
  383. package/tests/test-suite.js +0 -147
  384. package/tests/test.css +0 -7
  385. package/tests/unit/gzip/test-1 +0 -0
  386. package/tests/unit/gzip/test-1.gz +0 -0
  387. package/tests/unit/gzip/test-2 +0 -0
  388. package/tests/unit/gzip/test-2.gz +0 -0
  389. package/tests/unit/gzip/test-3 +0 -0
  390. package/tests/unit/gzip/test-3.gz +0 -0
  391. package/tests/unit/gzip/test-4 +0 -0
  392. package/tests/unit/gzip/test-4.gz +0 -0
  393. package/tests/unit/test-adc.js +0 -307
  394. package/tests/unit/test-bcd.js +0 -30
  395. package/tests/unit/test-cmos.js +0 -266
  396. package/tests/unit/test-disc-drive.js +0 -85
  397. package/tests/unit/test-disc-hfe.js +0 -347
  398. package/tests/unit/test-disc.js +0 -232
  399. package/tests/unit/test-fifo.js +0 -35
  400. package/tests/unit/test-gamepad-source.js +0 -67
  401. package/tests/unit/test-gzip.js +0 -22
  402. package/tests/unit/test-intel-fdc.js +0 -93
  403. package/tests/unit/test-keyboard.js +0 -410
  404. package/tests/unit/test-mouse-joystick-source.js +0 -128
  405. package/tests/unit/test-scheduler.js +0 -190
  406. package/tests/unit/test-serial.js +0 -154
  407. package/tests/unit/test-teletext-adaptor.js +0 -359
  408. package/tests/unit/test-tokenise.js +0 -65
  409. package/tests/unit/test-url-params.js +0 -398
  410. package/tests/unit/test-utils.js +0 -276
  411. package/tests/unit/test-video.js +0 -498
  412. package/tests/unit/test-zip.js +0 -56
  413. package/tests/unit/zip/test-mixed.zip +0 -0
  414. package/tests/unit/zip/test-rom.zip +0 -0
  415. package/tests/unit/zip/test-ssd.zip +0 -0
  416. package/tools/fir-generator.js +0 -80
  417. package/tools/vite-plugin-fir-shader.js +0 -131
  418. package/vite.config.js +0 -34
@@ -1,65 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import * as Tokeniser from "../../src/basic-tokenise.js";
3
- const tokeniser = Tokeniser.create();
4
-
5
- describe("Tokeniser", function () {
6
- "use strict";
7
-
8
- async function check(text, expected) {
9
- try {
10
- const t = await tokeniser;
11
- expect(t.tokenise(text)).toBe(expected);
12
- } catch (e) {
13
- console.log("Failed:", e);
14
- expect(e).toBe("");
15
- }
16
- }
17
-
18
- async function checkThrows(text, expectedError) {
19
- try {
20
- const t = await tokeniser;
21
- t.tokenise(text);
22
- console.log("Failed to give exception with message:", expectedError);
23
- expect.fail("Expected an exception to be thrown");
24
- } catch (e) {
25
- expect(e.message).toBe(expectedError);
26
- }
27
- }
28
-
29
- it("handles a simple program", async function () {
30
- await check(
31
- '10 PRINT "hello"\n20 GOTO 10\n',
32
- '\r\x00\x0a\x0e \xf1 "hello"\r\x00\x14\x0b \xe5 \x8d\x54\x4a\x40\r\xff',
33
- );
34
- });
35
- it("handles assignment to HIMEM", async function () {
36
- await check("HIMEM=&6000", "\r\x00\x0a\x0b\xd3=&6000\r\xff");
37
- });
38
- it("handles reading from HIMEM", async function () {
39
- await check("PRINT HIMEM", "\r\x00\x0a\x07\xf1 \x93\r\xff");
40
- });
41
- it("deals with colons", async function () {
42
- await check("PRINT HIMEM:HIMEM=&6000", "\r\x00\x0a\x0f\xf1 \x93:\xd3=&6000\r\xff");
43
- });
44
- it("handles MODE", async function () {
45
- await check("IF0ELSEMODE0", "\r\x00\x0a\x09\xe70\x8b\xeb0\r\xff");
46
- });
47
- it("handles a snippet from one line Tetris", async function () {
48
- await check(
49
- "d=d:IFd VDUd:p=POINT(64*POS,1E3-VPOS*32):RETURN ELSEMODE2:GCOL0,-9:CLG",
50
- "\r\x00\x0a\x2dd=d:\xe7d \xefd:p=\xb064*\xb1,1E3-\xbc*32):\xf8 \x8b\xeb2:\xe60,-9:\xda\r\xff",
51
- );
52
- });
53
- it("copes with token names inside strings", async function () {
54
- await check('PRINT "IF ""IF"" IF"', '\r\x00\x0a\x14\xf1 "IF ""IF"" IF"\r\xff');
55
- });
56
- it("handles REM", async function () {
57
- await check("10REM I am a monkey", "\r\x00\x0a\x13\xf4 I am a monkey\r\xff");
58
- });
59
- it("handles extra long input", async function () {
60
- await check("10" + "ENVELOPE".repeat(251), "\r\x00\x0a\xff" + "\xe2".repeat(251) + "\r\xff");
61
- });
62
- it("gives error for overlong input", async function () {
63
- await checkThrows("10" + "ENVELOPE".repeat(252), "Line 10 tokenised length 252 > 251 bytes");
64
- });
65
- });
@@ -1,398 +0,0 @@
1
- import { describe, it, expect, vi } from "vitest";
2
-
3
- import {
4
- parseQueryString,
5
- buildUrlFromParams,
6
- processKeyboardParams,
7
- processAutobootParams,
8
- parseMediaParams,
9
- guessModelFromHostname,
10
- ParamTypes,
11
- } from "../../src/url-params.js";
12
-
13
- describe("URL Parameters", () => {
14
- describe("parseQueryString", () => {
15
- it("should parse empty query string", () => {
16
- expect(parseQueryString("")).toEqual({});
17
- });
18
-
19
- it("should parse basic query string parameters", () => {
20
- const qs = "model=B&disc=elite.ssd";
21
- expect(parseQueryString(qs)).toEqual({
22
- model: "B",
23
- disc: "elite.ssd",
24
- });
25
- });
26
-
27
- it("should handle URL encoded components", () => {
28
- const qs = "text=Hello%20World&path=file%2Fname.txt";
29
- expect(parseQueryString(qs)).toEqual({
30
- text: "Hello World",
31
- path: "file/name.txt",
32
- });
33
- });
34
-
35
- it("should handle parameters without values", () => {
36
- const qs = "debug&verbose&disc=test.ssd&noseek";
37
- expect(parseQueryString(qs)).toEqual({
38
- debug: null,
39
- verbose: null,
40
- disc: "test.ssd",
41
- noseek: null,
42
- });
43
- });
44
-
45
- it("should handle query strings ending with /", () => {
46
- const qs = "model=B&disc=elite.ssd/";
47
- expect(parseQueryString(qs)).toEqual({
48
- model: "B",
49
- disc: "elite.ssd",
50
- });
51
- });
52
-
53
- it("should handle array parameters", () => {
54
- const qs = "rom=os.rom&rom=basic.rom&rom=dfs.rom&model=B";
55
- expect(parseQueryString(qs, { rom: ParamTypes.ARRAY })).toEqual({
56
- rom: ["os.rom", "basic.rom", "dfs.rom"],
57
- model: "B",
58
- });
59
- });
60
-
61
- it("should handle array parameters with single value", () => {
62
- const qs = "rom=os.rom&model=B";
63
- expect(parseQueryString(qs, { rom: ParamTypes.ARRAY })).toEqual({
64
- rom: ["os.rom"],
65
- model: "B",
66
- });
67
- });
68
-
69
- it("should handle empty array parameters", () => {
70
- const qs = "rom=&model=B";
71
- expect(parseQueryString(qs, { rom: ParamTypes.ARRAY })).toEqual({
72
- rom: [""],
73
- model: "B",
74
- });
75
- });
76
-
77
- it("should handle multiple array parameter types", () => {
78
- const qs = "rom=os.rom&rom=basic.rom&disc=elite.ssd&disc=other.ssd";
79
- expect(parseQueryString(qs, { rom: ParamTypes.ARRAY, disc: ParamTypes.ARRAY })).toEqual({
80
- rom: ["os.rom", "basic.rom"],
81
- disc: ["elite.ssd", "other.ssd"],
82
- });
83
- });
84
-
85
- // Tests for new parameter types
86
- it("should parse parameter types - string", () => {
87
- const qs = "name=jsbeeb&title=BBC%20Emulator";
88
- expect(parseQueryString(qs, { name: ParamTypes.STRING, title: ParamTypes.STRING })).toEqual({
89
- name: "jsbeeb",
90
- title: "BBC Emulator",
91
- });
92
- });
93
-
94
- it("should parse parameter types - int", () => {
95
- const qs = "speed=100&cycles=50";
96
- expect(parseQueryString(qs, { speed: ParamTypes.INT, cycles: ParamTypes.INT })).toEqual({
97
- speed: 100,
98
- cycles: 50,
99
- });
100
- });
101
-
102
- it("should parse parameter types - float", () => {
103
- const qs = "volume=0.5&zoom=1.25";
104
- expect(parseQueryString(qs, { volume: ParamTypes.FLOAT, zoom: ParamTypes.FLOAT })).toEqual({
105
- volume: 0.5,
106
- zoom: 1.25,
107
- });
108
- });
109
-
110
- it("should parse parameter types - bool", () => {
111
- const qs = "debug&verbose=false&noseek=true";
112
- expect(
113
- parseQueryString(qs, { debug: ParamTypes.BOOL, verbose: ParamTypes.BOOL, noseek: ParamTypes.BOOL }),
114
- ).toEqual({
115
- debug: true,
116
- verbose: false,
117
- noseek: true,
118
- });
119
- });
120
-
121
- it("should handle mixed parameter types", () => {
122
- const qs = "model=B&rom=os.rom&rom=basic.rom&speed=4&volume=0.8&debug";
123
- const paramTypes = {
124
- model: ParamTypes.STRING,
125
- rom: ParamTypes.ARRAY,
126
- speed: ParamTypes.INT,
127
- volume: ParamTypes.FLOAT,
128
- debug: ParamTypes.BOOL,
129
- };
130
-
131
- expect(parseQueryString(qs, paramTypes)).toEqual({
132
- model: "B",
133
- rom: ["os.rom", "basic.rom"],
134
- speed: 4,
135
- volume: 0.8,
136
- debug: true,
137
- });
138
- });
139
- });
140
-
141
- describe("buildUrlFromParams", () => {
142
- const baseUrl = "http://localhost:8080/index.html";
143
-
144
- it("should build URL with basic parameters", () => {
145
- const params = { model: "B", disc: "elite.ssd" };
146
- expect(buildUrlFromParams(baseUrl, params)).toBe("http://localhost:8080/index.html?model=B&disc=elite.ssd");
147
- });
148
-
149
- it("should handle array parameters in URL", () => {
150
- const params = {
151
- model: "B",
152
- rom: ["os.rom", "basic.rom", "dfs.rom"],
153
- };
154
- expect(buildUrlFromParams(baseUrl, params, { rom: ParamTypes.ARRAY })).toBe(
155
- "http://localhost:8080/index.html?model=B&rom=os.rom&rom=basic.rom&rom=dfs.rom",
156
- );
157
- });
158
-
159
- it("should skip empty or falsy values", () => {
160
- const params = {
161
- model: "B",
162
- disc: "",
163
- debug: null,
164
- rom: [],
165
- };
166
- expect(buildUrlFromParams(baseUrl, params, { rom: ParamTypes.ARRAY })).toBe(
167
- "http://localhost:8080/index.html?model=B",
168
- );
169
- });
170
-
171
- it("should handle mixed parameter types", () => {
172
- const params = {
173
- model: "B",
174
- disc: "test.ssd",
175
- rom: ["os.rom", "basic.rom"],
176
- };
177
- expect(buildUrlFromParams(baseUrl, params, { rom: ParamTypes.ARRAY })).toBe(
178
- "http://localhost:8080/index.html?model=B&disc=test.ssd&rom=os.rom&rom=basic.rom",
179
- );
180
- });
181
-
182
- // Tests for new parameter types with buildUrlFromParams
183
- it("should build URL with typed parameters", () => {
184
- const params = {
185
- model: "B",
186
- rom: ["os.rom", "basic.rom"],
187
- speed: 4,
188
- volume: 0.8,
189
- debug: true,
190
- noseek: false, // Should be omitted as it's false
191
- };
192
-
193
- const paramTypes = {
194
- model: ParamTypes.STRING,
195
- rom: ParamTypes.ARRAY,
196
- speed: ParamTypes.INT,
197
- volume: ParamTypes.FLOAT,
198
- debug: ParamTypes.BOOL,
199
- noseek: ParamTypes.BOOL,
200
- };
201
-
202
- expect(buildUrlFromParams(baseUrl, params, paramTypes)).toBe(
203
- "http://localhost:8080/index.html?model=B&rom=os.rom&rom=basic.rom&speed=4&volume=0.8&debug",
204
- );
205
- });
206
-
207
- it("should handle zero values correctly", () => {
208
- const params = {
209
- speed: 0,
210
- volume: 0.0,
211
- };
212
-
213
- const paramTypes = {
214
- speed: ParamTypes.INT,
215
- volume: ParamTypes.FLOAT,
216
- };
217
-
218
- expect(buildUrlFromParams(baseUrl, params, paramTypes)).toBe(
219
- "http://localhost:8080/index.html?speed=0&volume=0",
220
- );
221
- });
222
- });
223
-
224
- describe("processKeyboardParams", () => {
225
- it("should process keyboard mappings", () => {
226
- const BBC = { CTRL: "CTRL", SHIFT: "SHIFT" };
227
- const keyCodes = { A: 65, B: 66 };
228
- const userKeymap = [];
229
- const gamepad = { remap: vi.fn() };
230
-
231
- const parsedQuery = {
232
- "KEY.A": "CTRL",
233
- "KEY.B": "SHIFT",
234
- "GP.FIRE2": "RETURN",
235
- UP: "Q",
236
- other: "value",
237
- };
238
-
239
- processKeyboardParams(parsedQuery, BBC, keyCodes, userKeymap, gamepad);
240
-
241
- expect(userKeymap).toEqual([
242
- { native: "A", bbc: "CTRL" },
243
- { native: "B", bbc: "SHIFT" },
244
- ]);
245
-
246
- expect(gamepad.remap).toHaveBeenCalledTimes(2);
247
- expect(gamepad.remap).toHaveBeenCalledWith("FIRE2", "RETURN");
248
- expect(gamepad.remap).toHaveBeenCalledWith("UP", "Q");
249
- });
250
- });
251
-
252
- describe("processAutobootParams", () => {
253
- it("should process autoboot parameters with boolean values", () => {
254
- const params = {
255
- autoboot: true,
256
- other: "value",
257
- };
258
- expect(processAutobootParams(params)).toEqual({
259
- needsAutoboot: "boot",
260
- autoType: "",
261
- });
262
-
263
- expect(processAutobootParams({ autochain: true })).toEqual({
264
- needsAutoboot: "chain",
265
- autoType: "",
266
- });
267
-
268
- expect(processAutobootParams({ autorun: true })).toEqual({
269
- needsAutoboot: "run",
270
- autoType: "",
271
- });
272
-
273
- expect(processAutobootParams({ autotype: "HELLO" })).toEqual({
274
- needsAutoboot: "type",
275
- autoType: "HELLO",
276
- });
277
-
278
- expect(processAutobootParams({ other: "value" })).toEqual({
279
- needsAutoboot: false,
280
- autoType: "",
281
- });
282
- });
283
-
284
- it("should handle legacy autoboot parameters (backward compatibility)", () => {
285
- // For backward compatibility, handle string values from parseQueryString legacy mode
286
- expect(processAutobootParams({ autoboot: "" })).toEqual({
287
- needsAutoboot: "boot",
288
- autoType: "",
289
- });
290
-
291
- expect(processAutobootParams({ autochain: "" })).toEqual({
292
- needsAutoboot: "chain",
293
- autoType: "",
294
- });
295
-
296
- expect(processAutobootParams({ autorun: "" })).toEqual({
297
- needsAutoboot: "run",
298
- autoType: "",
299
- });
300
- });
301
- });
302
-
303
- describe("parseMediaParams", () => {
304
- it("should extract disc and tape images from query params", () => {
305
- const params = {
306
- disc: "elite.ssd",
307
- disc2: "games.ssd",
308
- tape: "welcome.uef",
309
- other: "value",
310
- };
311
-
312
- expect(parseMediaParams(params)).toEqual({
313
- discImage: "elite.ssd",
314
- secondDiscImage: "games.ssd",
315
- tapeImage: "welcome.uef",
316
- });
317
-
318
- expect(parseMediaParams({ disc1: "disc1.ssd" })).toEqual({
319
- discImage: "disc1.ssd",
320
- secondDiscImage: undefined,
321
- tapeImage: undefined,
322
- });
323
- });
324
- });
325
-
326
- describe("guessModelFromHostname", () => {
327
- it("should return B-DFS1.2 for hostnames starting with 'bbc'", () => {
328
- expect(guessModelFromHostname("bbc.example.com")).toBe("B-DFS1.2");
329
- expect(guessModelFromHostname("bbcmicro.local")).toBe("B-DFS1.2");
330
- });
331
-
332
- it("should return Master for hostnames starting with 'master'", () => {
333
- expect(guessModelFromHostname("master.example.com")).toBe("Master");
334
- expect(guessModelFromHostname("mastercompact.local")).toBe("Master");
335
- });
336
-
337
- it("should return default model for other hostnames", () => {
338
- expect(guessModelFromHostname("example.com")).toBe("B-DFS1.2");
339
- expect(guessModelFromHostname("localhost")).toBe("B-DFS1.2");
340
- expect(guessModelFromHostname("")).toBe("B-DFS1.2");
341
- });
342
- });
343
-
344
- describe("parseQueryString additional tests", () => {
345
- it("should handle invalid/malformed query strings", () => {
346
- expect(parseQueryString("=value")).toEqual({ "": "value" });
347
- expect(parseQueryString("key=")).toEqual({ key: "" });
348
- expect(parseQueryString("&&&")).toEqual({});
349
- expect(parseQueryString("key&key=value")).toEqual({ key: "value" });
350
- });
351
-
352
- it("should handle special characters in query parameters", () => {
353
- const qs = "text=Hello%20%26%20World%21&file=file%2Bname%40domain.com";
354
- expect(parseQueryString(qs)).toEqual({
355
- text: "Hello & World!",
356
- file: "file+name@domain.com",
357
- });
358
- });
359
- });
360
-
361
- describe("buildUrlFromParams additional tests", () => {
362
- const baseUrl = "http://localhost:8080/index.html";
363
-
364
- it("should handle empty parameter object", () => {
365
- expect(buildUrlFromParams(baseUrl, {})).toBe(baseUrl);
366
- });
367
-
368
- it("should encode special characters in URL parameters", () => {
369
- const params = {
370
- text: "Hello & World!",
371
- file: "file+name@domain.com",
372
- };
373
- const expected = "http://localhost:8080/index.html?text=Hello%20%26%20World!&file=file%2Bname%40domain.com";
374
- expect(buildUrlFromParams(baseUrl, params)).toBe(expected);
375
- });
376
-
377
- it("should handle explicit parameter types", () => {
378
- const params = {
379
- name: "jsbeeb",
380
- roms: ["os.rom", "basic.rom"],
381
- debug: true,
382
- };
383
-
384
- // With ARRAY type for roms - we should get separate parameters
385
- expect(buildUrlFromParams(baseUrl, params, { roms: ParamTypes.ARRAY })).toBe(
386
- "http://localhost:8080/index.html?name=jsbeeb&roms=os.rom&roms=basic.rom&debug=true",
387
- );
388
-
389
- // With BOOL type for debug and ARRAY type for roms
390
- expect(
391
- buildUrlFromParams(baseUrl, params, {
392
- debug: ParamTypes.BOOL,
393
- roms: ParamTypes.ARRAY,
394
- }),
395
- ).toBe("http://localhost:8080/index.html?name=jsbeeb&roms=os.rom&roms=basic.rom&debug");
396
- });
397
- });
398
- });