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,232 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
-
3
- import { Disc, DiscConfig, IbmDiscFormat, loadSsd, loadAdf, toSsdOrDsd } from "../../src/disc.js";
4
- import * as fs from "node:fs";
5
-
6
- describe("IBM disc format tests", function () {
7
- it("calculates FM crcs", () => {
8
- let crc = IbmDiscFormat.crcInit(false);
9
- crc = IbmDiscFormat.crcAddByte(crc, 0x12);
10
- crc = IbmDiscFormat.crcAddByte(crc, 0x34);
11
- crc = IbmDiscFormat.crcAddByte(crc, 0x56);
12
- crc = IbmDiscFormat.crcAddByte(crc, 0x70);
13
- expect(crc).toBe(0xb1e4);
14
- });
15
- it("calculates MFM crcs", () => {
16
- let crc = IbmDiscFormat.crcInit(true);
17
- crc = IbmDiscFormat.crcAddByte(crc, 0x12);
18
- crc = IbmDiscFormat.crcAddByte(crc, 0x34);
19
- crc = IbmDiscFormat.crcAddByte(crc, 0x56);
20
- crc = IbmDiscFormat.crcAddByte(crc, 0x70);
21
- expect(crc).toBe(0x9d39);
22
- });
23
- it("converts to FM pulses", () => {
24
- expect(IbmDiscFormat.fmTo2usPulses(0xff, 0x00)).toBe(0x44444444);
25
- expect(IbmDiscFormat.fmTo2usPulses(0xff, 0xff)).toBe(0x55555555);
26
- expect(IbmDiscFormat.fmTo2usPulses(0xc7, 0xfe)).toBe(0x55111554);
27
- });
28
- it("converts from FM pulses", () => {
29
- // TODO either fix these or understand why beebjit doesn't use same bit posn for bits.
30
- const deliberateFudge = 1;
31
- expect(IbmDiscFormat._2usPulsesToFm(0x44444444 << deliberateFudge)).toEqual({
32
- clocks: 0xff,
33
- data: 0x00,
34
- iffyPulses: false,
35
- });
36
- expect(IbmDiscFormat._2usPulsesToFm(0x55555555 << deliberateFudge)).toEqual({
37
- clocks: 0xff,
38
- data: 0xff,
39
- iffyPulses: false,
40
- });
41
- expect(IbmDiscFormat._2usPulsesToFm(0x55111554 << deliberateFudge)).toEqual({
42
- clocks: 0xc7,
43
- data: 0xfe,
44
- iffyPulses: false,
45
- });
46
- expect(IbmDiscFormat._2usPulsesToFm((0x55111554 << deliberateFudge) | 0x05)).toEqual({
47
- clocks: 0xc7,
48
- data: 0xfe,
49
- iffyPulses: true,
50
- });
51
- });
52
- it("converts to MFM pulses", () => {
53
- expect(IbmDiscFormat.mfmTo2usPulses(false, 0x00)).toEqual({ lastBit: false, pulses: 0xaaaa });
54
- expect(IbmDiscFormat.mfmTo2usPulses(true, 0x00)).toEqual({ lastBit: false, pulses: 0x2aaa });
55
- expect(IbmDiscFormat.mfmTo2usPulses(false, 0xff)).toEqual({ lastBit: true, pulses: 0x5555 });
56
- expect(IbmDiscFormat.mfmTo2usPulses(true, 0xff)).toEqual({ lastBit: true, pulses: 0x5555 });
57
- expect(IbmDiscFormat.mfmTo2usPulses(false, 0x37)).toEqual({ lastBit: true, pulses: 0xa515 });
58
- expect(IbmDiscFormat.mfmTo2usPulses(true, 0x37)).toEqual({ lastBit: true, pulses: 0x2515 });
59
- });
60
- it("Converts from MFM pulses", () => {
61
- expect(IbmDiscFormat._2usPulsesToMfm(0xaaaa)).toBe(0);
62
- expect(IbmDiscFormat._2usPulsesToMfm(0x2aaa)).toBe(0);
63
- expect(IbmDiscFormat._2usPulsesToMfm(0x5555)).toBe(0xff);
64
- expect(IbmDiscFormat._2usPulsesToMfm(0xa515)).toBe(0x37);
65
- expect(IbmDiscFormat._2usPulsesToMfm(0x2515)).toBe(0x37);
66
- });
67
- it("checks gaps between MFM pulses", () => {
68
- expect(IbmDiscFormat.checkPulse(0.0, true)).toBe(false);
69
- expect(IbmDiscFormat.checkPulse(3.49, true)).toBe(false);
70
- expect(IbmDiscFormat.checkPulse(4.51, true)).toBe(false);
71
- expect(IbmDiscFormat.checkPulse(7.49, true)).toBe(false);
72
- expect(IbmDiscFormat.checkPulse(8.51, true)).toBe(false);
73
-
74
- expect(IbmDiscFormat.checkPulse(4.0, true)).toBe(true);
75
- expect(IbmDiscFormat.checkPulse(5.51, true)).toBe(true);
76
- expect(IbmDiscFormat.checkPulse(6.0, true)).toBe(true);
77
- expect(IbmDiscFormat.checkPulse(6.49, true)).toBe(true);
78
- expect(IbmDiscFormat.checkPulse(8.0, true)).toBe(true);
79
- });
80
- it("checks gaps between FM pulses", () => {
81
- expect(IbmDiscFormat.checkPulse(0.0, false)).toBe(false);
82
- expect(IbmDiscFormat.checkPulse(3.49, false)).toBe(false);
83
- expect(IbmDiscFormat.checkPulse(4.51, false)).toBe(false);
84
- expect(IbmDiscFormat.checkPulse(5.51, false)).toBe(false);
85
- expect(IbmDiscFormat.checkPulse(6.0, false)).toBe(false);
86
- expect(IbmDiscFormat.checkPulse(6.49, false)).toBe(false);
87
- expect(IbmDiscFormat.checkPulse(7.49, false)).toBe(false);
88
- expect(IbmDiscFormat.checkPulse(8.51, false)).toBe(false);
89
-
90
- expect(IbmDiscFormat.checkPulse(4.0, false)).toBe(true);
91
- expect(IbmDiscFormat.checkPulse(8.0, false)).toBe(true);
92
- });
93
- });
94
-
95
- describe("Disc builder tests", () => {
96
- const someData = new Uint8Array(256);
97
- someData.fill(0x33);
98
- it("should write a simple FM track without blowing up", () => {
99
- const disc = new Disc(true, new DiscConfig(), "test.ssd");
100
- const builder = disc.buildTrack(false, 0);
101
- builder
102
- .appendRepeatFmByte(0xff, IbmDiscFormat.stdGap1FFs)
103
- .appendRepeatFmByte(0x00, IbmDiscFormat.stdSync00s)
104
- .resetCrc()
105
- .appendFmDataAndClocks(IbmDiscFormat.idMarkDataPattern, IbmDiscFormat.markClockPattern)
106
- .appendFmByte(0) // track
107
- .appendFmByte(0)
108
- .appendFmByte(0) // sector
109
- .appendFmByte(1)
110
- .appendCrc(false)
111
- .appendRepeatFmByte(0xff, IbmDiscFormat.stdGap2FFs)
112
- .appendRepeatFmByte(0x00, IbmDiscFormat.stdSync00s)
113
- .resetCrc()
114
- .appendFmDataAndClocks(IbmDiscFormat.dataMarkDataPattern, IbmDiscFormat.markClockPattern)
115
- .appendFmChunk(someData)
116
- .appendCrc(false)
117
- .fillFmByte(0xff);
118
- });
119
-
120
- it("should write a simple MFM track without blowing up", () => {
121
- const disc = new Disc(true, new DiscConfig());
122
- const builder = disc.buildTrack(false, 0);
123
- builder
124
- .appendRepeatMfmByte(0x4e, 60)
125
- .appendRepeatMfmByte(0x00, 12)
126
- .resetCrc()
127
- .appendMfm3xA1Sync()
128
- .appendMfmByte(IbmDiscFormat.idMarkDataPattern)
129
- .appendMfmByte(0) // track
130
- .appendMfmByte(0)
131
- .appendMfmByte(0) // sector
132
- .appendMfmByte(1)
133
- .appendCrc(true)
134
- .appendRepeatMfmByte(0x4e, 22)
135
- .appendRepeatMfmByte(0x00, 12)
136
- .resetCrc()
137
- .appendMfm3xA1Sync()
138
- .appendMfmByte(IbmDiscFormat.dataMarkDataPattern)
139
- .appendMfmChunk(someData)
140
- .appendCrc(true)
141
- .appendRepeatMfmByte(0x4e, 24)
142
- .fillMfmByte(0x4e);
143
- });
144
-
145
- it("should note how much disc is being used", () => {
146
- const disc = new Disc(true, new DiscConfig(), "test.ssd");
147
- expect(disc.tracksUsed).toBe(0);
148
- expect(disc.isDoubleSided).toBe(false);
149
- disc.buildTrack(false, 0);
150
- expect(disc.tracksUsed).toBe(1);
151
- expect(disc.isDoubleSided).toBe(false);
152
- disc.buildTrack(false, 3);
153
- expect(disc.tracksUsed).toBe(4);
154
- expect(disc.isDoubleSided).toBe(false);
155
- disc.buildTrack(true, 1);
156
- expect(disc.tracksUsed).toBe(4);
157
- expect(disc.isDoubleSided).toBe(true);
158
- });
159
-
160
- it("should build from FM pulses", () => {
161
- const disc = new Disc(true, new DiscConfig(), "test.ssd");
162
- const builder = disc.buildTrack(false, 0);
163
- const pulses = [4, 4, 8, 8, 4, 8, 8, 8, 8, 8, 8, 8, 8];
164
- builder.buildFromPulses(pulses, false);
165
- expect(builder.track.length).toBe(1);
166
- });
167
-
168
- it("should build from MFM pulses", () => {
169
- const disc = new Disc(true, new DiscConfig(), "test.ssd");
170
- const builder = disc.buildTrack(false, 0);
171
- const pulses = [4, 4, 6, 6, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6];
172
- builder.buildFromPulses(pulses, true);
173
- expect(builder.track.length).toBe(1);
174
- });
175
- });
176
-
177
- describe(
178
- "SSD loader tests",
179
- {
180
- timeout: 60000, // roundtripping elite can be slow
181
- },
182
- function () {
183
- const data = fs.readFileSync("public/discs/elite.ssd");
184
- it("should load Elite", () => {
185
- const disc = new Disc(true, new DiscConfig(), "test.ssd");
186
- loadSsd(disc, data, false);
187
- expect(disc.tracksUsed).toBe(80);
188
- });
189
- it("should roundtrip Elite", () => {
190
- const disc = new Disc(true, new DiscConfig(), "test.ssd");
191
- loadSsd(disc, data, false);
192
- const ssdSaved = toSsdOrDsd(disc);
193
- // // Check the first few bytes, else a diff blows things up
194
- const maxDiff = 50;
195
- expect(ssdSaved.slice(0, maxDiff)).toEqual(new Uint8Array(data.slice(0, maxDiff)));
196
-
197
- // But also check everything else; and the padding should be all zeros.
198
- expect(ssdSaved.length >= data.length).toBe(true);
199
- for (let i = 0; i < data.length; ++i) {
200
- expect(ssdSaved[i]).toBe(data[i]);
201
- }
202
- for (let i = data.length; i < ssdSaved.length; ++i) {
203
- expect(ssdSaved[i]).toBe(0);
204
- }
205
- });
206
- it("should have sane tracks", () => {
207
- const disc = new Disc(true, new DiscConfig(), "test.ssd");
208
- loadSsd(disc, data, false);
209
- const sectors = disc.getTrack(false, 0).findSectors();
210
- expect(sectors.length).toBe(10);
211
- for (const sector of sectors) {
212
- expect(sector.hasHeaderCrcError).toBe(false);
213
- expect(sector.hasDataCrcError).toBe(false);
214
- }
215
- });
216
- },
217
- );
218
-
219
- describe("ADF loader tests", function () {
220
- it("should load a somewhat blank ADFS disc", () => {
221
- const data = new Uint8Array(327680);
222
- const disc = new Disc(true, new DiscConfig(), "test.adf");
223
- loadAdf(disc, data, true);
224
- expect(disc.tracksUsed).toBe(40);
225
- const sectors = disc.getTrack(false, 0).findSectors();
226
- expect(sectors.length).toBe(16);
227
- for (const sector of sectors) {
228
- expect(sector.hasHeaderCrcError).toBe(false);
229
- expect(sector.hasDataCrcError).toBe(false);
230
- }
231
- });
232
- });
@@ -1,35 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
-
3
- import { Fifo } from "../../src/utils.js";
4
-
5
- describe("FIFO tests", function () {
6
- "use strict";
7
- it("creates ok", function () {
8
- new Fifo(16);
9
- });
10
- it("works for simple cases", function () {
11
- const f = new Fifo(16);
12
- expect(f.size).toBe(0);
13
- f.put(123);
14
- expect(f.size).toBe(1);
15
- expect(f.get()).toBe(123);
16
- expect(f.size).toBe(0);
17
- });
18
-
19
- it("works when full", function () {
20
- const f = new Fifo(4);
21
- expect(f.size).toBe(0);
22
- f.put(123);
23
- f.put(125);
24
- f.put(126);
25
- f.put(127);
26
- expect(f.size).toBe(4);
27
- f.put(100);
28
- expect(f.size).toBe(4);
29
- expect(f.get()).toBe(123);
30
- expect(f.get()).toBe(125);
31
- expect(f.get()).toBe(126);
32
- expect(f.get()).toBe(127);
33
- expect(f.size).toBe(0);
34
- });
35
- });
@@ -1,67 +0,0 @@
1
- import { describe, it, expect, beforeEach } from "vitest";
2
- import { GamepadSource } from "../../src/gamepad-source.js";
3
-
4
- describe("GamepadSource", () => {
5
- // Mock gamepads with various axis positions
6
- const mockGamepads = [
7
- {
8
- axes: [0.5, -0.5, 0.25, -0.75], // pad1: right, up, slight right, mostly up
9
- },
10
- {
11
- axes: [-0.8, 0.3], // pad2: mostly left, slight down
12
- },
13
- ];
14
-
15
- let gamepadSource;
16
-
17
- beforeEach(() => {
18
- // Create a fake getGamepads function that returns our mocks
19
- const getGamepads = () => mockGamepads;
20
- gamepadSource = new GamepadSource(getGamepads);
21
- });
22
-
23
- describe("getValue", () => {
24
- it("should convert gamepad axis 0 value correctly", () => {
25
- // First axis of first gamepad is 0.5
26
- // Formula: Math.floor(((1 - 0.5) / 2) * 0xffff)
27
- // = Math.floor(0.25 * 0xffff) = 0x3fff
28
- const value = gamepadSource.getValue(0);
29
- expect(value).toBe(0x3fff);
30
- });
31
-
32
- it("should convert gamepad axis 1 value correctly", () => {
33
- // Second axis of first gamepad is -0.5
34
- // Formula: Math.floor(((1 - (-0.5)) / 2) * 0xffff)
35
- // = Math.floor(0.75 * 0xffff) = 0xbfff
36
- const value = gamepadSource.getValue(1);
37
- expect(value).toBe(0xbfff);
38
- });
39
-
40
- it("should use second gamepad for channel 2 if available", () => {
41
- // First axis of second gamepad is -0.8
42
- // Formula: Math.floor(((1 - (-0.8)) / 2) * 0xffff)
43
- // = Math.floor(0.9 * 0xffff) ≈ 58981
44
- const value = gamepadSource.getValue(2);
45
- expect(value).toBe(58981);
46
- });
47
-
48
- it("should use second gamepad for channel 3 if available", () => {
49
- // Second axis of second gamepad is 0.3
50
- // Formula: Math.floor(((1 - 0.3) / 2) * 0xffff)
51
- // = Math.floor(0.35 * 0xffff) ≈ 22937
52
- const value = gamepadSource.getValue(3);
53
- expect(value).toBe(22937);
54
- });
55
-
56
- it("should return center value (0x8000) when no gamepads are connected", () => {
57
- // Create a source that returns no gamepads
58
- const noGamepadsSource = new GamepadSource(() => []);
59
- expect(noGamepadsSource.getValue(0)).toBe(0x8000);
60
- });
61
-
62
- it("should return center value for invalid channel", () => {
63
- expect(gamepadSource.getValue(4)).toBe(0x8000);
64
- expect(gamepadSource.getValue(-1)).toBe(0x8000);
65
- });
66
- });
67
- });
@@ -1,22 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import * as fs from "fs";
3
- import * as utils from "../../src/utils.js";
4
-
5
- import { dirname, join } from "path";
6
- import { fileURLToPath } from "url";
7
-
8
- const __dirname = dirname(fileURLToPath(import.meta.url));
9
-
10
- function testOneFile(file) {
11
- const compressed = new Uint8Array(fs.readFileSync(`${file}.gz`));
12
- const expected = new Uint8Array(fs.readFileSync(file));
13
- expect(utils.ungzip(compressed)).toEqual(expected);
14
- }
15
-
16
- describe("gzip tests", function () {
17
- for (let fileIndex = 1; ; fileIndex++) {
18
- let file = join(__dirname, "gzip", `test-${fileIndex}`);
19
- if (!fs.existsSync(file)) break;
20
- it("handles test case " + file, () => testOneFile(file));
21
- }
22
- });
@@ -1,93 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
-
3
- import { Scheduler } from "../../src/scheduler.js";
4
- import { IntelFdc } from "../../src/intel-fdc.js";
5
- import { fake6502 } from "../../src/fake6502.js";
6
-
7
- class FakeDrive {
8
- constructor() {
9
- this.spinning = false;
10
- this.pulsesCallback = null;
11
- this.upperSide = false;
12
- this.track = 0;
13
- }
14
- selectSide(side) {
15
- this.upperSide = side;
16
- }
17
- setPulsesCallback(callback) {
18
- this.pulsesCallback = callback;
19
- }
20
- startSpinning() {
21
- this.spinning = true;
22
- }
23
- stopSpinning() {
24
- this.spinning = false;
25
- }
26
- seekOneTrack(dir) {
27
- this.track = this.track + dir;
28
- }
29
- notifySeek() {}
30
- }
31
-
32
- /**
33
- * @param {IntelFdc} fdc
34
- * @param {Number} command
35
- * @param {...Number} params
36
- */
37
- function sendCommand(fdc, command, ...params) {
38
- fdc.write(0, command);
39
- for (const param of params) fdc.write(1, param);
40
- }
41
-
42
- describe("Intel 8271 tests", function () {
43
- it("should contruct and start out idle", () => {
44
- const fakeCpu = fake6502();
45
- const scheduler = new Scheduler();
46
- const fdc = new IntelFdc(fakeCpu, scheduler);
47
- expect(fdc.internalStatus).toBe(0);
48
- expect(scheduler.headroom()).toBe(Scheduler.MaxHeadroom);
49
- });
50
-
51
- it("should go busy as soon as a command is registered", () => {
52
- const fakeCpu = fake6502();
53
- const scheduler = new Scheduler();
54
- const fdc = new IntelFdc(fakeCpu, scheduler);
55
- fdc.write(0, 0x3a);
56
- expect(fdc.internalStatus).toBe(0x80); // 0x80 = busy
57
- });
58
-
59
- const loadHead = 0x08;
60
- const select1 = 0x40;
61
- const writeRegCmd = 0x3a;
62
- const mmioWrite = 0x23;
63
- const seekCmd = (0x0a << 2) | select1 | 1;
64
-
65
- it("should spin up when poked", () => {
66
- const fakeCpu = fake6502();
67
- const scheduler = new Scheduler();
68
- const fakeDrive = new FakeDrive();
69
- const fdc = new IntelFdc(fakeCpu, scheduler, [fakeDrive]);
70
- expect(fdc._driveOut & loadHead).toBe(0);
71
- expect(fakeDrive.spinning).toBe(false);
72
- sendCommand(fdc, writeRegCmd, mmioWrite, loadHead | select1);
73
- expect(fdc._driveOut & loadHead).toBe(loadHead);
74
- expect(fakeDrive.spinning).toBe(true);
75
- });
76
- it("should seek to a track", () => {
77
- const fakeCpu = fake6502();
78
- const scheduler = new Scheduler();
79
- const fakeDrive = new FakeDrive();
80
- const fdc = new IntelFdc(fakeCpu, scheduler, [fakeDrive]);
81
- sendCommand(fdc, writeRegCmd, mmioWrite, loadHead | select1);
82
- // nb will seek two more due to bad track nonsense
83
- sendCommand(fdc, seekCmd, 2);
84
- expect(fakeDrive.track).toBe(1);
85
- // We should have some 3ms step scheduled
86
- expect(scheduler.headroom()).toBe(6000);
87
- scheduler.polltime(6000);
88
- expect(fakeDrive.track).toBe(2);
89
- // We should reach and stop at track 4.
90
- scheduler.polltime(6000 * 10);
91
- expect(fakeDrive.track).toBe(4);
92
- });
93
- });