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.
- package/.editorconfig +15 -0
- package/.git-blame-ignore-revs +3 -0
- package/.github/copilot-instructions.md +94 -0
- package/.github/workflows/claude-issue-triage.yml +105 -0
- package/.github/workflows/claude.yml +63 -0
- package/.github/workflows/release-please.yml +75 -0
- package/.github/workflows/test-and-deploy.yml +86 -0
- package/.gitmodules +6 -0
- package/.husky/pre-commit +1 -0
- package/.idea/codeStyleSettings.xml +9 -0
- package/.idea/codeStyles/Project.xml +62 -0
- package/.idea/codeStyles/codeStyleConfig.xml +5 -0
- package/.idea/compiler.xml +22 -0
- package/.idea/copyright/profiles_settings.xml +3 -0
- package/.idea/encodings.xml +6 -0
- package/.idea/inspectionProfiles/Project_Default.xml +7 -0
- package/.idea/jsLibraryMappings.xml +6 -0
- package/.idea/jsLinters/jshint.xml +85 -0
- package/.idea/jsLinters/jslint.xml +15 -0
- package/.idea/jsbeeb.iml +11 -0
- package/.idea/misc.xml +6 -0
- package/.idea/modules.xml +8 -0
- package/.idea/prettier.xml +7 -0
- package/.idea/runConfigurations/Debug.xml +5 -0
- package/.idea/scopes/scope_settings.xml +5 -0
- package/.idea/vcs.xml +8 -0
- package/.prettierignore +4 -0
- package/.prettierrc.json +1 -0
- package/.release-please-manifest.json +3 -0
- package/.vscode/launch.json +14 -0
- package/.vscode/settings.json +6 -0
- package/CHANGELOG.md +32 -0
- package/CLAUDE.md +136 -0
- package/COPYING +674 -0
- package/Dockerfile +22 -0
- package/Makefile +30 -0
- package/README.md +259 -0
- package/docker/nginx-default.conf +10 -0
- package/docs/pal-comb-filter-research.md +129 -0
- package/docs/pal-simulation-design.md +368 -0
- package/eslint.config.js +35 -0
- package/index.html +954 -0
- package/jsconfig.json +10 -0
- package/package.json +102 -0
- package/public/discs/README.Irq-Timing +3 -0
- package/public/discs/README.bcdtest +5 -0
- package/public/discs/README.elite +6 -0
- package/public/discs/README.eng_test +3 -0
- package/public/discs/README.protection +7 -0
- package/public/favicon.ico +0 -0
- package/public/images/botbar.png +0 -0
- package/public/images/cub-monitor.png +0 -0
- package/public/images/jsbeeb-example.png +0 -0
- package/public/images/placeholder.png +0 -0
- package/public/images/red-off-16.png +0 -0
- package/public/images/red-on-16.png +0 -0
- package/public/images/sb/CD-left.jpg +0 -0
- package/public/images/sb/CD-right.jpg +0 -0
- package/public/images/sidebar.png +0 -0
- package/public/images/tv.png +0 -0
- package/public/images/yellow-off-16.png +0 -0
- package/public/images/yellow-on-16.png +0 -0
- package/public/jsbeeb-icon.png +0 -0
- package/public/robots.txt +3 -0
- package/public/roms/ADFS1-53.rom +0 -0
- package/public/roms/BASIC.ROM +0 -0
- package/public/roms/README +4 -0
- package/public/roms/a01/BASIC1.rom +0 -0
- package/public/roms/ample.rom +0 -0
- package/public/roms/ats-3.0.rom +0 -0
- package/public/roms/b/DFS-0.9.rom +0 -0
- package/public/roms/b/DFS-1.2.rom +0 -0
- package/public/roms/b1770/dfs1770.rom +0 -0
- package/public/roms/b1770/zADFS.ROM +0 -0
- package/public/roms/bp/dfs.rom +0 -0
- package/public/roms/bp/zADFS.ROM +0 -0
- package/public/roms/bpos.rom +0 -0
- package/public/roms/compact/adfs210.rom +0 -0
- package/public/roms/compact/basic48.rom +0 -0
- package/public/roms/compact/basic486.rom +0 -0
- package/public/roms/compact/os51.rom +0 -0
- package/public/roms/compact/utils.rom +0 -0
- package/public/roms/deos.rom +0 -0
- package/public/roms/master/anfs-4.25.rom +0 -0
- package/public/roms/master/mos.txt +68819 -0
- package/public/roms/master/mos3.20 +0 -0
- package/public/roms/os.rom +0 -0
- package/public/roms/os01.rom +0 -0
- package/public/roms/tube/6502Tube.rom +0 -0
- package/public/roms/tube/ARMeval_100.rom +0 -0
- package/public/roms/tube/BIOS.ROM +0 -0
- package/public/roms/tube/ReCo6502ROM_816 +0 -0
- package/public/roms/tube/Z80_120.rom +0 -0
- package/public/roms/us/USBASIC.rom +0 -0
- package/public/roms/us/USDNFS.rom +0 -0
- package/public/roms/usmos.rom +0 -0
- package/public/sounds/disc525/motor.wav +0 -0
- package/public/sounds/disc525/motoroff.wav +0 -0
- package/public/sounds/disc525/motoron.wav +0 -0
- package/public/sounds/disc525/seek.wav +0 -0
- package/public/sounds/disc525/seek2.wav +0 -0
- package/public/sounds/disc525/seek3.wav +0 -0
- package/public/sounds/disc525/step.wav +0 -0
- package/public/teletext/txt0.dat +0 -0
- package/public/teletext/txt1.dat +0 -0
- package/public/teletext/txt2.dat +0 -0
- package/public/teletext/txt3.dat +0 -0
- package/release-please-config.json +13 -0
- package/run-container.sh +92 -0
- package/src/6502.js +1347 -0
- package/src/6502.opcodes.js +1411 -0
- package/src/acia.js +261 -0
- package/src/adc.js +149 -0
- package/src/analogue-source.js +21 -0
- package/src/app/app.js +175 -0
- package/src/app/electron.js +20 -0
- package/src/app/preload.js +8 -0
- package/src/app-bench.js +33 -0
- package/src/basic/multiline-tetris +9 -0
- package/src/basic-tokenise.js +104 -0
- package/src/canvas.js +177 -0
- package/src/cmos.js +141 -0
- package/src/config.js +165 -0
- package/src/ddnoise.js +138 -0
- package/src/disc-drive.js +371 -0
- package/src/disc-hfe.js +396 -0
- package/src/disc.js +997 -0
- package/src/econet/L3FS.dat +0 -0
- package/src/econet/scsi.dat +0 -0
- package/src/econet.js +714 -0
- package/src/fake6502.js +32 -0
- package/src/fdc.js +248 -0
- package/src/filestore.js +666 -0
- package/src/gamepad-source.js +59 -0
- package/src/gamepads.js +268 -0
- package/src/google-drive.js +160 -0
- package/src/intel-fdc.js +1717 -0
- package/src/jsbeeb.css +363 -0
- package/src/keyboard.js +411 -0
- package/src/lib/README +1 -0
- package/src/lib/webgl-debug.js +911 -0
- package/src/main.js +1759 -0
- package/src/microphone-input.js +149 -0
- package/src/models.js +200 -0
- package/src/mouse-joystick-source.js +107 -0
- package/src/music5000-worklet.js +43 -0
- package/src/music5000.js +207 -0
- package/src/scheduler.js +148 -0
- package/src/serial.js +31 -0
- package/src/soundchip.js +314 -0
- package/src/sth.js +59 -0
- package/src/tapes.js +265 -0
- package/src/teletext.js +348 -0
- package/src/teletext_adaptor.js +172 -0
- package/src/teletext_data.js +1064 -0
- package/src/touchscreen.js +86 -0
- package/src/tube.js +349 -0
- package/src/url-params.js +256 -0
- package/src/utils.js +1090 -0
- package/src/via.js +702 -0
- package/src/video-filters/pal-composite.js +94 -0
- package/src/video-filters/passthrough-filter.js +70 -0
- package/src/video-filters/shaders/pal-composite.frag.glsl +147 -0
- package/src/video-filters/shaders/pal-composite.vert.glsl +8 -0
- package/src/video-filters/shaders/passthrough.frag.glsl +6 -0
- package/src/video-filters/shaders/passthrough.vert.glsl +7 -0
- package/src/video.js +794 -0
- package/src/wd-fdc.js +1344 -0
- package/src/web/audio-handler.js +146 -0
- package/src/web/audio-renderer.js +115 -0
- package/src/web/debug.js +529 -0
- package/tests/integration/RmwX.asm +47 -0
- package/tests/integration/TestInstructionsSource +27 -0
- package/tests/integration/TestTimingsResults +27 -0
- package/tests/integration/TestTimingsSource +61 -0
- package/tests/integration/bcd.js +23 -0
- package/tests/integration/dormann.js +101 -0
- package/tests/integration/dp111timing.js +42 -0
- package/tests/integration/ensure-submodules.js +25 -0
- package/tests/integration/nops.bas +119 -0
- package/tests/integration/nops.js +24 -0
- package/tests/integration/protection.js +26 -0
- package/tests/integration/rmw.js +69 -0
- package/tests/integration/teletext/expected_bug_469.png +0 -0
- package/tests/integration/teletext/expected_flash_0.png +0 -0
- package/tests/integration/teletext/expected_flash_1.png +0 -0
- package/tests/integration/teletext/expected_hoglet_held_char.png +0 -0
- package/tests/integration/teletext/expected_reveal_flash_0.png +0 -0
- package/tests/integration/teletext/expected_reveal_flash_1.png +0 -0
- package/tests/integration/teletext.js +126 -0
- package/tests/integration/timings.js +56 -0
- package/tests/integration/via.js +1125 -0
- package/tests/suite/README.md +7 -0
- package/tests/suite/Test Suite 2.15.txt +373 -0
- package/tests/suite/bin/ start +0 -0
- package/tests/suite/bin/adca +0 -0
- package/tests/suite/bin/adcax +0 -0
- package/tests/suite/bin/adcay +0 -0
- package/tests/suite/bin/adcb +0 -0
- package/tests/suite/bin/adcix +0 -0
- package/tests/suite/bin/adciy +0 -0
- package/tests/suite/bin/adcz +0 -0
- package/tests/suite/bin/adczx +0 -0
- package/tests/suite/bin/alrb +0 -0
- package/tests/suite/bin/ancb +0 -0
- package/tests/suite/bin/anda +0 -0
- package/tests/suite/bin/andax +0 -0
- package/tests/suite/bin/anday +0 -0
- package/tests/suite/bin/andb +0 -0
- package/tests/suite/bin/andix +0 -0
- package/tests/suite/bin/andiy +0 -0
- package/tests/suite/bin/andz +0 -0
- package/tests/suite/bin/andzx +0 -0
- package/tests/suite/bin/aneb +0 -0
- package/tests/suite/bin/arrb +0 -0
- package/tests/suite/bin/asla +0 -0
- package/tests/suite/bin/aslax +0 -0
- package/tests/suite/bin/asln +0 -0
- package/tests/suite/bin/aslz +0 -0
- package/tests/suite/bin/aslzx +0 -0
- package/tests/suite/bin/asoa +0 -0
- package/tests/suite/bin/asoax +0 -0
- package/tests/suite/bin/asoay +0 -0
- package/tests/suite/bin/asoix +0 -0
- package/tests/suite/bin/asoiy +0 -0
- package/tests/suite/bin/asoz +0 -0
- package/tests/suite/bin/asozx +0 -0
- package/tests/suite/bin/axsa +0 -0
- package/tests/suite/bin/axsix +0 -0
- package/tests/suite/bin/axsz +0 -0
- package/tests/suite/bin/axszy +0 -0
- package/tests/suite/bin/bccr +0 -0
- package/tests/suite/bin/bcsr +0 -0
- package/tests/suite/bin/beqr +0 -0
- package/tests/suite/bin/bita +0 -0
- package/tests/suite/bin/bitz +0 -0
- package/tests/suite/bin/bmir +0 -0
- package/tests/suite/bin/bner +0 -0
- package/tests/suite/bin/bplr +0 -0
- package/tests/suite/bin/branchwrap +0 -0
- package/tests/suite/bin/brkn +0 -0
- package/tests/suite/bin/bvcr +0 -0
- package/tests/suite/bin/bvsr +0 -0
- package/tests/suite/bin/cia1pb6 +0 -0
- package/tests/suite/bin/cia1pb7 +0 -0
- package/tests/suite/bin/cia1ta +0 -0
- package/tests/suite/bin/cia1tab +0 -0
- package/tests/suite/bin/cia1tb +0 -0
- package/tests/suite/bin/cia1tb123 +0 -0
- package/tests/suite/bin/cia2pb6 +0 -0
- package/tests/suite/bin/cia2pb7 +0 -0
- package/tests/suite/bin/cia2ta +0 -0
- package/tests/suite/bin/cia2tb +0 -0
- package/tests/suite/bin/cia2tb123 +0 -0
- package/tests/suite/bin/clcn +0 -0
- package/tests/suite/bin/cldn +0 -0
- package/tests/suite/bin/clin +0 -0
- package/tests/suite/bin/clvn +0 -0
- package/tests/suite/bin/cmpa +0 -0
- package/tests/suite/bin/cmpax +0 -0
- package/tests/suite/bin/cmpay +0 -0
- package/tests/suite/bin/cmpb +0 -0
- package/tests/suite/bin/cmpix +0 -0
- package/tests/suite/bin/cmpiy +0 -0
- package/tests/suite/bin/cmpz +0 -0
- package/tests/suite/bin/cmpzx +0 -0
- package/tests/suite/bin/cntdef +0 -0
- package/tests/suite/bin/cnto2 +0 -0
- package/tests/suite/bin/cpuport +0 -0
- package/tests/suite/bin/cputiming +0 -0
- package/tests/suite/bin/cpxa +0 -0
- package/tests/suite/bin/cpxb +0 -0
- package/tests/suite/bin/cpxz +0 -0
- package/tests/suite/bin/cpya +0 -0
- package/tests/suite/bin/cpyb +0 -0
- package/tests/suite/bin/cpyz +0 -0
- package/tests/suite/bin/dcma +0 -0
- package/tests/suite/bin/dcmax +0 -0
- package/tests/suite/bin/dcmay +0 -0
- package/tests/suite/bin/dcmix +0 -0
- package/tests/suite/bin/dcmiy +0 -0
- package/tests/suite/bin/dcmz +0 -0
- package/tests/suite/bin/dcmzx +0 -0
- package/tests/suite/bin/deca +0 -0
- package/tests/suite/bin/decax +0 -0
- package/tests/suite/bin/decz +0 -0
- package/tests/suite/bin/deczx +0 -0
- package/tests/suite/bin/dexn +0 -0
- package/tests/suite/bin/deyn +0 -0
- package/tests/suite/bin/eora +0 -0
- package/tests/suite/bin/eorax +0 -0
- package/tests/suite/bin/eoray +0 -0
- package/tests/suite/bin/eorb +0 -0
- package/tests/suite/bin/eorix +0 -0
- package/tests/suite/bin/eoriy +0 -0
- package/tests/suite/bin/eorz +0 -0
- package/tests/suite/bin/eorzx +0 -0
- package/tests/suite/bin/finish +0 -0
- package/tests/suite/bin/flipos +0 -0
- package/tests/suite/bin/icr01 +0 -0
- package/tests/suite/bin/imr +0 -0
- package/tests/suite/bin/inca +0 -0
- package/tests/suite/bin/incax +0 -0
- package/tests/suite/bin/incz +0 -0
- package/tests/suite/bin/inczx +0 -0
- package/tests/suite/bin/insa +0 -0
- package/tests/suite/bin/insax +0 -0
- package/tests/suite/bin/insay +0 -0
- package/tests/suite/bin/insix +0 -0
- package/tests/suite/bin/insiy +0 -0
- package/tests/suite/bin/insz +0 -0
- package/tests/suite/bin/inszx +0 -0
- package/tests/suite/bin/inxn +0 -0
- package/tests/suite/bin/inyn +0 -0
- package/tests/suite/bin/irq +0 -0
- package/tests/suite/bin/jmpi +0 -0
- package/tests/suite/bin/jmpw +0 -0
- package/tests/suite/bin/jsrw +0 -0
- package/tests/suite/bin/lasay +0 -0
- package/tests/suite/bin/laxa +0 -0
- package/tests/suite/bin/laxay +0 -0
- package/tests/suite/bin/laxix +0 -0
- package/tests/suite/bin/laxiy +0 -0
- package/tests/suite/bin/laxz +0 -0
- package/tests/suite/bin/laxzy +0 -0
- package/tests/suite/bin/ldaa +0 -0
- package/tests/suite/bin/ldaax +0 -0
- package/tests/suite/bin/ldaay +0 -0
- package/tests/suite/bin/ldab +0 -0
- package/tests/suite/bin/ldaix +0 -0
- package/tests/suite/bin/ldaiy +0 -0
- package/tests/suite/bin/ldaz +0 -0
- package/tests/suite/bin/ldazx +0 -0
- package/tests/suite/bin/ldxa +0 -0
- package/tests/suite/bin/ldxay +0 -0
- package/tests/suite/bin/ldxb +0 -0
- package/tests/suite/bin/ldxz +0 -0
- package/tests/suite/bin/ldxzy +0 -0
- package/tests/suite/bin/ldya +0 -0
- package/tests/suite/bin/ldyax +0 -0
- package/tests/suite/bin/ldyb +0 -0
- package/tests/suite/bin/ldyz +0 -0
- package/tests/suite/bin/ldyzx +0 -0
- package/tests/suite/bin/loadth +0 -0
- package/tests/suite/bin/lsea +0 -0
- package/tests/suite/bin/lseax +0 -0
- package/tests/suite/bin/lseay +0 -0
- package/tests/suite/bin/lseix +0 -0
- package/tests/suite/bin/lseiy +0 -0
- package/tests/suite/bin/lsez +0 -0
- package/tests/suite/bin/lsezx +0 -0
- package/tests/suite/bin/lsra +0 -0
- package/tests/suite/bin/lsrax +0 -0
- package/tests/suite/bin/lsrn +0 -0
- package/tests/suite/bin/lsrz +0 -0
- package/tests/suite/bin/lsrzx +0 -0
- package/tests/suite/bin/lxab +0 -0
- package/tests/suite/bin/mmu +0 -0
- package/tests/suite/bin/mmufetch +0 -0
- package/tests/suite/bin/nmi +0 -0
- package/tests/suite/bin/nopa +0 -0
- package/tests/suite/bin/nopax +0 -0
- package/tests/suite/bin/nopb +0 -0
- package/tests/suite/bin/nopn +0 -0
- package/tests/suite/bin/nopz +0 -0
- package/tests/suite/bin/nopzx +0 -0
- package/tests/suite/bin/oneshot +0 -0
- package/tests/suite/bin/oraa +0 -0
- package/tests/suite/bin/oraax +0 -0
- package/tests/suite/bin/oraay +0 -0
- package/tests/suite/bin/orab +0 -0
- package/tests/suite/bin/oraix +0 -0
- package/tests/suite/bin/oraiy +0 -0
- package/tests/suite/bin/oraz +0 -0
- package/tests/suite/bin/orazx +0 -0
- package/tests/suite/bin/phan +0 -0
- package/tests/suite/bin/phpn +0 -0
- package/tests/suite/bin/plan +0 -0
- package/tests/suite/bin/plpn +0 -0
- package/tests/suite/bin/rlaa +0 -0
- package/tests/suite/bin/rlaax +0 -0
- package/tests/suite/bin/rlaay +0 -0
- package/tests/suite/bin/rlaix +0 -0
- package/tests/suite/bin/rlaiy +0 -0
- package/tests/suite/bin/rlaz +0 -0
- package/tests/suite/bin/rlazx +0 -0
- package/tests/suite/bin/rola +0 -0
- package/tests/suite/bin/rolax +0 -0
- package/tests/suite/bin/roln +0 -0
- package/tests/suite/bin/rolz +0 -0
- package/tests/suite/bin/rolzx +0 -0
- package/tests/suite/bin/rora +0 -0
- package/tests/suite/bin/rorax +0 -0
- package/tests/suite/bin/rorn +0 -0
- package/tests/suite/bin/rorz +0 -0
- package/tests/suite/bin/rorzx +0 -0
- package/tests/suite/bin/rraa +0 -0
- package/tests/suite/bin/rraax +0 -0
- package/tests/suite/bin/rraay +0 -0
- package/tests/suite/bin/rraix +0 -0
- package/tests/suite/bin/rraiy +0 -0
- package/tests/suite/bin/rraz +0 -0
- package/tests/suite/bin/rrazx +0 -0
- package/tests/suite/bin/rtin +0 -0
- package/tests/suite/bin/rtsn +0 -0
- package/tests/suite/bin/sbca +0 -0
- package/tests/suite/bin/sbcax +0 -0
- package/tests/suite/bin/sbcay +0 -0
- package/tests/suite/bin/sbcb +0 -0
- package/tests/suite/bin/sbcb(eb) +0 -0
- package/tests/suite/bin/sbcix +0 -0
- package/tests/suite/bin/sbciy +0 -0
- package/tests/suite/bin/sbcz +0 -0
- package/tests/suite/bin/sbczx +0 -0
- package/tests/suite/bin/sbxb +0 -0
- package/tests/suite/bin/secn +0 -0
- package/tests/suite/bin/sedn +0 -0
- package/tests/suite/bin/sein +0 -0
- package/tests/suite/bin/shaay +0 -0
- package/tests/suite/bin/shaiy +0 -0
- package/tests/suite/bin/shsay +0 -0
- package/tests/suite/bin/shxay +0 -0
- package/tests/suite/bin/shyax +0 -0
- package/tests/suite/bin/staa +0 -0
- package/tests/suite/bin/staax +0 -0
- package/tests/suite/bin/staay +0 -0
- package/tests/suite/bin/staix +0 -0
- package/tests/suite/bin/staiy +0 -0
- package/tests/suite/bin/staz +0 -0
- package/tests/suite/bin/stazx +0 -0
- package/tests/suite/bin/stxa +0 -0
- package/tests/suite/bin/stxz +0 -0
- package/tests/suite/bin/stxzy +0 -0
- package/tests/suite/bin/stya +0 -0
- package/tests/suite/bin/styz +0 -0
- package/tests/suite/bin/styzx +0 -0
- package/tests/suite/bin/taxn +0 -0
- package/tests/suite/bin/tayn +0 -0
- package/tests/suite/bin/trap1 +0 -0
- package/tests/suite/bin/trap10 +0 -0
- package/tests/suite/bin/trap11 +0 -0
- package/tests/suite/bin/trap12 +0 -0
- package/tests/suite/bin/trap13 +0 -0
- package/tests/suite/bin/trap14 +0 -0
- package/tests/suite/bin/trap15 +0 -0
- package/tests/suite/bin/trap16 +0 -0
- package/tests/suite/bin/trap17 +0 -0
- package/tests/suite/bin/trap2 +0 -0
- package/tests/suite/bin/trap3 +0 -0
- package/tests/suite/bin/trap4 +0 -0
- package/tests/suite/bin/trap5 +0 -0
- package/tests/suite/bin/trap6 +0 -0
- package/tests/suite/bin/trap7 +0 -0
- package/tests/suite/bin/trap8 +0 -0
- package/tests/suite/bin/trap9 +0 -0
- package/tests/suite/bin/tsxn +0 -0
- package/tests/suite/bin/txan +0 -0
- package/tests/suite/bin/txsn +0 -0
- package/tests/suite/bin/tyan +0 -0
- package/tests/suite/cbm-hackers-post.html +178 -0
- package/tests/suite/cbm-hackers-post.md +78 -0
- package/tests/test-machine.js +288 -0
- package/tests/test-suite.js +147 -0
- package/tests/test.css +7 -0
- package/tests/unit/gzip/test-1 +0 -0
- package/tests/unit/gzip/test-1.gz +0 -0
- package/tests/unit/gzip/test-2 +0 -0
- package/tests/unit/gzip/test-2.gz +0 -0
- package/tests/unit/gzip/test-3 +0 -0
- package/tests/unit/gzip/test-3.gz +0 -0
- package/tests/unit/gzip/test-4 +0 -0
- package/tests/unit/gzip/test-4.gz +0 -0
- package/tests/unit/test-adc.js +307 -0
- package/tests/unit/test-bcd.js +30 -0
- package/tests/unit/test-cmos.js +266 -0
- package/tests/unit/test-disc-drive.js +85 -0
- package/tests/unit/test-disc-hfe.js +347 -0
- package/tests/unit/test-disc.js +232 -0
- package/tests/unit/test-fifo.js +35 -0
- package/tests/unit/test-gamepad-source.js +67 -0
- package/tests/unit/test-gzip.js +22 -0
- package/tests/unit/test-intel-fdc.js +93 -0
- package/tests/unit/test-keyboard.js +410 -0
- package/tests/unit/test-mouse-joystick-source.js +128 -0
- package/tests/unit/test-scheduler.js +190 -0
- package/tests/unit/test-serial.js +154 -0
- package/tests/unit/test-teletext-adaptor.js +359 -0
- package/tests/unit/test-tokenise.js +65 -0
- package/tests/unit/test-url-params.js +398 -0
- package/tests/unit/test-utils.js +276 -0
- package/tests/unit/test-video.js +498 -0
- package/tests/unit/test-zip.js +56 -0
- package/tests/unit/zip/test-mixed.zip +0 -0
- package/tests/unit/zip/test-rom.zip +0 -0
- package/tests/unit/zip/test-ssd.zip +0 -0
- package/tools/fir-generator.js +80 -0
- package/tools/vite-plugin-fir-shader.js +131 -0
- package/vite.config.js +34 -0
package/src/disc-hfe.js
ADDED
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
// HFE format implementation for disc image loading and saving
|
|
2
|
+
// Translated from beebjit by Chris Evans and expanded by Matt Godbolt.
|
|
3
|
+
|
|
4
|
+
import { IbmDiscFormat } from "./disc.js";
|
|
5
|
+
|
|
6
|
+
// HFE format constants
|
|
7
|
+
const HfeHeaderV1 = "HXCPICFE";
|
|
8
|
+
const HfeHeaderV3 = "HXCHFEV3";
|
|
9
|
+
const HfeV3OpcodeMask = 0xf0;
|
|
10
|
+
const HfeV3OpcodeNop = 0xf0;
|
|
11
|
+
const HfeV3OpcodeSetIndex = 0xf1;
|
|
12
|
+
const HfeV3OpcodeSetBitrate = 0xf2;
|
|
13
|
+
const HfeV3OpcodeSkipBits = 0xf3;
|
|
14
|
+
const HfeV3OpcodeRand = 0xf4;
|
|
15
|
+
const HfeBlockSideSize = 256;
|
|
16
|
+
const HfeBlockSize = HfeBlockSideSize * 2;
|
|
17
|
+
const HfeShugartDdFloppyMode = 7;
|
|
18
|
+
const HfeIsoIbmFmEncoding = 2;
|
|
19
|
+
|
|
20
|
+
// 250kbit bitrate value per HFE format specification
|
|
21
|
+
const Bitrate250k = 72;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Flip the bits in a byte for HFE encoding
|
|
25
|
+
* @param {number} val - Byte value to flip
|
|
26
|
+
* @returns {number} - Flipped byte value
|
|
27
|
+
*/
|
|
28
|
+
function hfeByteFlip(val) {
|
|
29
|
+
let ret = 0;
|
|
30
|
+
if (val & 0x80) ret |= 0x01;
|
|
31
|
+
if (val & 0x40) ret |= 0x02;
|
|
32
|
+
if (val & 0x20) ret |= 0x04;
|
|
33
|
+
if (val & 0x10) ret |= 0x08;
|
|
34
|
+
if (val & 0x08) ret |= 0x10;
|
|
35
|
+
if (val & 0x04) ret |= 0x20;
|
|
36
|
+
if (val & 0x02) ret |= 0x40;
|
|
37
|
+
if (val & 0x01) ret |= 0x80;
|
|
38
|
+
|
|
39
|
+
return ret;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Get the track offset and length from HFE metadata
|
|
44
|
+
* @param {Uint8Array} metadata - HFE lookup table metadata
|
|
45
|
+
* @param {number} track - Track number
|
|
46
|
+
* @returns {{offset: number, length: number}} - Track offset and length
|
|
47
|
+
*/
|
|
48
|
+
function hfeGetTrackOffsetAndLength(metadata, track) {
|
|
49
|
+
const index = track << 2;
|
|
50
|
+
const offset = HfeBlockSize * (metadata[index] + (metadata[index + 1] << 8));
|
|
51
|
+
const length = metadata[index + 2] + (metadata[index + 3] << 8);
|
|
52
|
+
return { offset, length };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Load a disc image in HFE format (v1 or v3)
|
|
57
|
+
* @param {import("./disc.js").Disc} disc - The disc object to load into
|
|
58
|
+
* @param {Uint8Array} data - The HFE file data
|
|
59
|
+
* @param {function(Uint8Array): void} onChange - Optional callback when disc content changes
|
|
60
|
+
* @returns {import("./disc.js").Disc} - The loaded disc object
|
|
61
|
+
*/
|
|
62
|
+
export function loadHfe(disc, data, onChange) {
|
|
63
|
+
if (data.length < HfeBlockSize) throw new Error("HFE file missing header");
|
|
64
|
+
const header = new TextDecoder("ascii").decode(data.slice(0, 8));
|
|
65
|
+
let isV3 = false;
|
|
66
|
+
let hfeVersion = 1;
|
|
67
|
+
|
|
68
|
+
if (header === HfeHeaderV1) {
|
|
69
|
+
// HFE v1 format
|
|
70
|
+
} else if (header === HfeHeaderV3) {
|
|
71
|
+
hfeVersion = 3;
|
|
72
|
+
isV3 = true;
|
|
73
|
+
} else {
|
|
74
|
+
throw new Error(`HFE file bad header '${header}'`);
|
|
75
|
+
}
|
|
76
|
+
if (data[8] !== 0) throw new Error("HFE file revision not 0");
|
|
77
|
+
if (data[11] !== 2 && data[11] !== 0) {
|
|
78
|
+
if (data[11] === 0xff) {
|
|
79
|
+
console.log(`Unknown HFE encoding ${data[11]}, trying anyway`);
|
|
80
|
+
} else {
|
|
81
|
+
throw new Error(`HFE encoding not ISOIBM_(M)FM_ENCODING: ${data[11]}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const numSides = data[10];
|
|
85
|
+
if (numSides < 1 || numSides > 2) throw new Error(`Invalid number of sides: ${numSides}`);
|
|
86
|
+
|
|
87
|
+
const numTracks = data[9];
|
|
88
|
+
if (numTracks > IbmDiscFormat.tracksPerDisc) throw new Error(`Too many tracks: ${numTracks}`);
|
|
89
|
+
let expandShift = 0;
|
|
90
|
+
if (disc.config.expandTo80 && numTracks * 2 <= IbmDiscFormat.tracksPerDisc) {
|
|
91
|
+
expandShift = 1;
|
|
92
|
+
console.log("Expanding 40 tracks to 80");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
console.log(`HFE v${hfeVersion} loading ${numSides} sides, ${numTracks} tracks`);
|
|
96
|
+
|
|
97
|
+
const lutOffset = HfeBlockSize * (data[18] + (data[19] << 8));
|
|
98
|
+
if (lutOffset + HfeBlockSize > data.length) throw new Error("HFE LUT doesn't fit");
|
|
99
|
+
|
|
100
|
+
const metadata = data.slice(lutOffset, lutOffset + HfeBlockSize);
|
|
101
|
+
|
|
102
|
+
for (let trackNum = 0; trackNum < numTracks; ++trackNum) {
|
|
103
|
+
let actualTrackNum = trackNum;
|
|
104
|
+
if (disc.config.isSkipOddTracks) {
|
|
105
|
+
if (trackNum & 1) continue;
|
|
106
|
+
actualTrackNum = trackNum >>> 1;
|
|
107
|
+
}
|
|
108
|
+
actualTrackNum = actualTrackNum << expandShift;
|
|
109
|
+
const { offset, length } = hfeGetTrackOffsetAndLength(metadata, trackNum);
|
|
110
|
+
if (offset + length > data.length)
|
|
111
|
+
throw new Error(
|
|
112
|
+
`HFE track ${trackNum} doesn't fit (length ${length} offset ${offset} file length ${data.length})`,
|
|
113
|
+
);
|
|
114
|
+
const trackData = data.slice(offset, offset + length);
|
|
115
|
+
|
|
116
|
+
for (let sideNum = 0; sideNum < numSides; ++sideNum) {
|
|
117
|
+
const bufLen = length >> 1;
|
|
118
|
+
let bytesWritten = 0;
|
|
119
|
+
if (disc.config.isSkipUpperSide && sideNum === 1) continue;
|
|
120
|
+
|
|
121
|
+
let isSetBitRate = false;
|
|
122
|
+
let isSkipBits = false;
|
|
123
|
+
let skipBitsLength = 0;
|
|
124
|
+
let pulses = 0;
|
|
125
|
+
let shiftCounter = 0;
|
|
126
|
+
|
|
127
|
+
const trackObj = disc.getTrack(sideNum === 1, actualTrackNum);
|
|
128
|
+
disc.setTrackUsed(sideNum === 1, actualTrackNum);
|
|
129
|
+
const rawPulses = trackObj.pulses2Us;
|
|
130
|
+
for (let byteIndex = 0; byteIndex < bufLen; ++byteIndex) {
|
|
131
|
+
if (bytesWritten === rawPulses.length) {
|
|
132
|
+
throw new Error(`HFE track ${trackNum} truncated`);
|
|
133
|
+
}
|
|
134
|
+
const index = ((byteIndex >>> 8) << 9) + (sideNum << 8) + (byteIndex & 0xff);
|
|
135
|
+
let byte = hfeByteFlip(trackData[index]);
|
|
136
|
+
let numBits = 8;
|
|
137
|
+
|
|
138
|
+
if (isSetBitRate) {
|
|
139
|
+
isSetBitRate = false;
|
|
140
|
+
if (byte < 64 || byte > 80) {
|
|
141
|
+
console.log(`HFE v3 SETBITRATE wild (72=250kbit) track: ${trackNum} ${byte}`);
|
|
142
|
+
}
|
|
143
|
+
continue;
|
|
144
|
+
} else if (isSkipBits) {
|
|
145
|
+
isSkipBits = false;
|
|
146
|
+
if (byte === 0 || byte >= 8) {
|
|
147
|
+
throw new Error(`HFE v3 invalid skipbits ${byte}`);
|
|
148
|
+
}
|
|
149
|
+
skipBitsLength = byte;
|
|
150
|
+
continue;
|
|
151
|
+
} else if (skipBitsLength) {
|
|
152
|
+
byte = (byte << (8 - skipBitsLength)) & 0xff;
|
|
153
|
+
numBits = skipBitsLength;
|
|
154
|
+
skipBitsLength = 0;
|
|
155
|
+
} else if (isV3 && (byte & HfeV3OpcodeMask) === HfeV3OpcodeMask) {
|
|
156
|
+
switch (byte) {
|
|
157
|
+
case HfeV3OpcodeNop:
|
|
158
|
+
continue; // NB continue
|
|
159
|
+
case HfeV3OpcodeSetIndex:
|
|
160
|
+
if (bytesWritten !== 0)
|
|
161
|
+
console.log(`HFEv3 SETINDEX not at byte 0, track ${trackNum}: ${bytesWritten}`);
|
|
162
|
+
continue; // NB continue
|
|
163
|
+
case HfeV3OpcodeSetBitrate:
|
|
164
|
+
isSetBitRate = true;
|
|
165
|
+
continue; // NB continue
|
|
166
|
+
case HfeV3OpcodeSkipBits:
|
|
167
|
+
isSkipBits = true;
|
|
168
|
+
continue; // NB continue
|
|
169
|
+
case HfeV3OpcodeRand:
|
|
170
|
+
// internally we represent weak bits on disc as a no flux area.
|
|
171
|
+
byte = 0;
|
|
172
|
+
break; // NB a break
|
|
173
|
+
default:
|
|
174
|
+
throw new Error(`Unknown HFE v3 opcode ${byte}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
for (let bitIndex = 0; bitIndex < numBits; ++bitIndex) {
|
|
179
|
+
pulses = ((pulses << 1) & 0xffffffff) | (byte & 0x80 ? 1 : 0);
|
|
180
|
+
byte = (byte << 1) & 0xff;
|
|
181
|
+
if (++shiftCounter === 32) {
|
|
182
|
+
rawPulses[bytesWritten] = pulses;
|
|
183
|
+
bytesWritten++;
|
|
184
|
+
pulses = 0;
|
|
185
|
+
shiftCounter = 0;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
trackObj.length = bytesWritten;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Set up write track callback if onChange is provided
|
|
194
|
+
if (onChange) {
|
|
195
|
+
disc.setWriteTrackCallback((_side, _trackNum, _trackObj) => {
|
|
196
|
+
// Generate a complete HFE image from the current disc state
|
|
197
|
+
const hfeData = toHfe(disc);
|
|
198
|
+
// Call the onChange handler with the updated HFE data
|
|
199
|
+
onChange(hfeData);
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return disc;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Check if a byte could be mistakenly interpreted as a v3 opcode
|
|
208
|
+
* @param {number} byte - The byte to check after bit flipping
|
|
209
|
+
* @returns {boolean} - True if the byte could be interpreted as a v3 opcode
|
|
210
|
+
*/
|
|
211
|
+
function isHfeV3OpcodeCollision(byte) {
|
|
212
|
+
// After bit flipping, check if the lower 4 bits are all 1s (0x0F)
|
|
213
|
+
return (byte & 0x0f) === 0x0f;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Encode a single 32-bit pulse value to 4 bytes in HFE v3 format
|
|
218
|
+
* Handles opcode collisions by replacing with RAND opcode if needed
|
|
219
|
+
* @param {number} pulsesWord - The 32-bit pulse value
|
|
220
|
+
* @returns {Uint8Array} - 4 bytes of HFE v3 encoded data
|
|
221
|
+
*/
|
|
222
|
+
function encodeHfeV3Pulses(pulsesWord) {
|
|
223
|
+
const result = new Uint8Array(4);
|
|
224
|
+
|
|
225
|
+
for (let i = 0; i < 4; i++) {
|
|
226
|
+
const byte = (pulsesWord >>> 24) & 0xff;
|
|
227
|
+
const flippedByte = hfeByteFlip(byte);
|
|
228
|
+
|
|
229
|
+
// Check if the byte could be mistakenly interpreted as a v3 opcode
|
|
230
|
+
if (isHfeV3OpcodeCollision(flippedByte)) {
|
|
231
|
+
// Replace with bit-flipped RAND opcode
|
|
232
|
+
result[i] = hfeByteFlip(HfeV3OpcodeRand);
|
|
233
|
+
} else {
|
|
234
|
+
result[i] = flippedByte;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
pulsesWord <<= 8;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return result;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Convert track data to HFE v3 format, handling weak pulses and opcode collisions
|
|
245
|
+
* @param {Uint32Array|Array<number>} pulses - Array of 32-bit pulse values for the track
|
|
246
|
+
* @returns {Uint8Array} - The track data in HFE v3 format
|
|
247
|
+
*/
|
|
248
|
+
export function convertTrackToHfeV3(pulses) {
|
|
249
|
+
// Calculate the max potential size (4 bytes per pulse value + 3 bytes header)
|
|
250
|
+
const buffer = new Uint8Array(pulses.length * 4 + 3);
|
|
251
|
+
let bufferIndex = 0;
|
|
252
|
+
|
|
253
|
+
// Add HFE v3 header opcodes (SETINDEX, SETBITRATE, Bitrate250k)
|
|
254
|
+
buffer[bufferIndex++] = hfeByteFlip(HfeV3OpcodeSetIndex);
|
|
255
|
+
buffer[bufferIndex++] = hfeByteFlip(HfeV3OpcodeSetBitrate);
|
|
256
|
+
buffer[bufferIndex++] = hfeByteFlip(Bitrate250k);
|
|
257
|
+
|
|
258
|
+
// Process each pulse
|
|
259
|
+
for (let i = 0; i < pulses.length; i++) {
|
|
260
|
+
const pulse = pulses[i];
|
|
261
|
+
|
|
262
|
+
if (pulse === 0) {
|
|
263
|
+
// Handle weak bits explicitly in HFEv3 with RAND opcode
|
|
264
|
+
const randOpcode = hfeByteFlip(HfeV3OpcodeRand);
|
|
265
|
+
buffer.fill(randOpcode, bufferIndex, bufferIndex + 4);
|
|
266
|
+
} else {
|
|
267
|
+
// Encode normal pulses, handling potential opcode collisions
|
|
268
|
+
const encodedPulses = encodeHfeV3Pulses(pulse);
|
|
269
|
+
buffer.set(encodedPulses, bufferIndex);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
bufferIndex += 4;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Return only the used part of the buffer
|
|
276
|
+
return buffer.slice(0, bufferIndex);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Convert disc to HFE v3 format
|
|
281
|
+
* HFE is a format used by the HxC Floppy Emulator for storing disk images.
|
|
282
|
+
* This implementation supports variable track lengths without truncation.
|
|
283
|
+
* Reference: https://hxc2001.com/download/floppy_drive_emulator/SDCard_HxC_Floppy_Emulator_HFE_file_format.pdf
|
|
284
|
+
* @param {import("./disc.js").Disc} disc - The disc to convert to HFE
|
|
285
|
+
* @returns {Uint8Array} - The HFE file data
|
|
286
|
+
*/
|
|
287
|
+
export function toHfe(disc) {
|
|
288
|
+
const numSides = disc.isDoubleSided ? 2 : 1;
|
|
289
|
+
const numTracks = disc.tracksUsed;
|
|
290
|
+
|
|
291
|
+
// Pre-calculate sizes for each track to properly support variable track lengths
|
|
292
|
+
const trackSizes = [];
|
|
293
|
+
const trackOffsetDeltas = [];
|
|
294
|
+
for (let trackNum = 0; trackNum < numTracks; trackNum++) {
|
|
295
|
+
const track0 = disc.getTrack(false, trackNum);
|
|
296
|
+
const track1 = numSides > 1 ? disc.getTrack(true, trackNum) : { length: 0 };
|
|
297
|
+
|
|
298
|
+
// Calculate the actual size needed for this specific track
|
|
299
|
+
// From C code: 4 bytes per 32-bit word, 3 "header" HFEv3 bytes, 2 sides
|
|
300
|
+
const trackLen = Math.max(track0.length, track1.length);
|
|
301
|
+
const hfeTrackLen = (trackLen * 4 + 3) * 2;
|
|
302
|
+
const hfeOffsetDelta = Math.floor(hfeTrackLen / HfeBlockSize) + 1;
|
|
303
|
+
|
|
304
|
+
trackSizes.push(hfeTrackLen);
|
|
305
|
+
trackOffsetDeltas.push(hfeOffsetDelta);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Build header
|
|
309
|
+
const header = new Uint8Array(512);
|
|
310
|
+
header.fill(0xff);
|
|
311
|
+
|
|
312
|
+
// Write HFE v3 signature
|
|
313
|
+
const encoder = new TextEncoder();
|
|
314
|
+
header.set(encoder.encode("HXCHFEV3"), 0);
|
|
315
|
+
header[8] = 0; // Revision 0
|
|
316
|
+
header[9] = numTracks;
|
|
317
|
+
header[10] = numSides;
|
|
318
|
+
header[11] = HfeIsoIbmFmEncoding; // IBM FM/MFM encoding
|
|
319
|
+
header[12] = 250; // Bit rate (nb we use the set bitrate command per track)
|
|
320
|
+
header[13] = 0;
|
|
321
|
+
header[14] = 0; // RPM (unused)
|
|
322
|
+
header[15] = 0;
|
|
323
|
+
header[16] = HfeShugartDdFloppyMode; // Mode: Shugart DD
|
|
324
|
+
header[17] = 0xff; // Unused
|
|
325
|
+
header[18] = 1; // LUT offset at block 1 (512 bytes)
|
|
326
|
+
header[19] = 0;
|
|
327
|
+
header[20] = 0xff; // Write allowed
|
|
328
|
+
header[21] = 0xff; // Single step
|
|
329
|
+
header[22] = 0xff; // No alternate track options
|
|
330
|
+
header[23] = 0xff;
|
|
331
|
+
header[24] = 0xff;
|
|
332
|
+
header[25] = 0xff;
|
|
333
|
+
|
|
334
|
+
const headerSize = HfeBlockSize;
|
|
335
|
+
// Assume everything will fit into one block.
|
|
336
|
+
const lutSize = 1 * HfeBlockSize;
|
|
337
|
+
|
|
338
|
+
// Build LUT (Lookup Table) for track offsets
|
|
339
|
+
const lut = new Uint8Array(lutSize);
|
|
340
|
+
const lutDataView = new DataView(lut.buffer);
|
|
341
|
+
let hfeOffset = 2; // Start at block 2 (after header and LUT)
|
|
342
|
+
|
|
343
|
+
// Calculate total file size and build LUT
|
|
344
|
+
let totalSize = headerSize + lutSize;
|
|
345
|
+
|
|
346
|
+
for (let trackNum = 0; trackNum < numTracks; trackNum++) {
|
|
347
|
+
const byteOffset = trackNum * 4;
|
|
348
|
+
lutDataView.setUint16(byteOffset, hfeOffset, true); // Offset in 512-byte blocks
|
|
349
|
+
lutDataView.setUint16(byteOffset + 2, trackSizes[trackNum], true); // Track-specific length in bytes
|
|
350
|
+
|
|
351
|
+
// Add this track's size to the total and advance offset
|
|
352
|
+
totalSize += trackOffsetDeltas[trackNum] * HfeBlockSize;
|
|
353
|
+
hfeOffset += trackOffsetDeltas[trackNum];
|
|
354
|
+
}
|
|
355
|
+
const hfeData = new Uint8Array(totalSize);
|
|
356
|
+
|
|
357
|
+
// Write header
|
|
358
|
+
hfeData.set(header, 0);
|
|
359
|
+
// Write LUT
|
|
360
|
+
hfeData.set(lut, headerSize);
|
|
361
|
+
|
|
362
|
+
// Write track data
|
|
363
|
+
let trackOffset = 1024; // Start after header and LUT
|
|
364
|
+
for (let trackNum = 0; trackNum < numTracks; trackNum++) {
|
|
365
|
+
// Process each side separately
|
|
366
|
+
for (let side = 0; side < numSides; side++) {
|
|
367
|
+
const track = disc.getTrack(side === 1, trackNum);
|
|
368
|
+
const pulses = track.pulses2Us;
|
|
369
|
+
|
|
370
|
+
const trackBuffer = convertTrackToHfeV3(pulses.slice(0, track.length));
|
|
371
|
+
let bufferIndex = trackBuffer.length;
|
|
372
|
+
|
|
373
|
+
// Write track data in per-side sized chunks, interleaved according to HFE format
|
|
374
|
+
let writePos = trackOffset + (side === 1 ? HfeBlockSideSize : 0);
|
|
375
|
+
let iByte = 0;
|
|
376
|
+
|
|
377
|
+
while (iByte < bufferIndex) {
|
|
378
|
+
const chunkLen = Math.min(HfeBlockSideSize, bufferIndex - iByte);
|
|
379
|
+
const chunk = new Uint8Array(HfeBlockSideSize);
|
|
380
|
+
|
|
381
|
+
if (chunkLen > 0) {
|
|
382
|
+
chunk.set(trackBuffer.slice(iByte, iByte + chunkLen));
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
hfeData.set(chunk, writePos);
|
|
386
|
+
writePos += HfeBlockSize;
|
|
387
|
+
iByte += chunkLen;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Move to the next track after processing all sides
|
|
392
|
+
trackOffset += trackOffsetDeltas[trackNum] * HfeBlockSize;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
return hfeData;
|
|
396
|
+
}
|