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/econet.js
ADDED
|
@@ -0,0 +1,714 @@
|
|
|
1
|
+
// Code ported from Beebem (C to .js) by Jason Robson
|
|
2
|
+
// The majority of the commentary here is also from Beebem
|
|
3
|
+
|
|
4
|
+
// Econet support classes
|
|
5
|
+
class ADLC {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.control1 = 0;
|
|
8
|
+
this.control2 = 0;
|
|
9
|
+
this.control3 = 0;
|
|
10
|
+
this.control4 = 0;
|
|
11
|
+
this.txfifo = new Uint8Array(3);
|
|
12
|
+
this.rxfifo = new Uint8Array(3);
|
|
13
|
+
this.txfptr = 0; // first empty byte in fifo
|
|
14
|
+
this.rxfptr = 0; // first empty byte in fifo
|
|
15
|
+
this.txftl = 0; // tx fifo tx lst flags. (bits relate to subscripts)
|
|
16
|
+
this.rxffc = 0; // rx fifo fc flags bitss
|
|
17
|
+
this.rxap = 0; // rx fifo ap flags. (bits relate to subscripts)
|
|
18
|
+
|
|
19
|
+
this.status1 = 0;
|
|
20
|
+
this.status2 = 0;
|
|
21
|
+
this.sr2pse = 0; // PSE level for SR2 rx bits
|
|
22
|
+
this.cts = 0; // signal up
|
|
23
|
+
this.idle = 0;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class EconetPacket {
|
|
28
|
+
constructor(...values) {
|
|
29
|
+
this.buffer = new Uint8Array(32 * 1024);
|
|
30
|
+
this.pointer = 0;
|
|
31
|
+
this.bytesInBuffer = values.length;
|
|
32
|
+
this.controlFlag = 0;
|
|
33
|
+
this.port = 0;
|
|
34
|
+
|
|
35
|
+
// Populate packet contents from values
|
|
36
|
+
for (let i = 0; i < values.length; i++) {
|
|
37
|
+
this.buffer[i] = values[i];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
get full() {
|
|
42
|
+
return this.pointer >= this.buffer.length;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export class ReceiveBlock {
|
|
47
|
+
constructor(id, controlFlag, receivePort, bufferStart, bufferEnd) {
|
|
48
|
+
this.id = id;
|
|
49
|
+
this.controlFlag = controlFlag;
|
|
50
|
+
this.receivePort = receivePort;
|
|
51
|
+
this.bufferStart = bufferStart;
|
|
52
|
+
this.bufferEnd = bufferEnd;
|
|
53
|
+
this.data = new EconetPacket();
|
|
54
|
+
this.stationId = 0;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Econet class definition
|
|
59
|
+
export class Econet {
|
|
60
|
+
constructor(stationId_) {
|
|
61
|
+
// Config parameters
|
|
62
|
+
this.TIME_BETWEEN_BYTES = 128;
|
|
63
|
+
this.SERVER_STATION_ID = 254;
|
|
64
|
+
|
|
65
|
+
// 4-way handshake states
|
|
66
|
+
this.FWH_Idle = 0;
|
|
67
|
+
this.FWH_RX_Scout_Received = 1;
|
|
68
|
+
this.FWH_RX_ScoutAck_Received = 2;
|
|
69
|
+
this.FWH_RX_Body_Received = 3;
|
|
70
|
+
this.FWH_TX_Scout_Sent = 4;
|
|
71
|
+
|
|
72
|
+
// Econet properties
|
|
73
|
+
this.stationId = stationId_;
|
|
74
|
+
this.ADLC = new ADLC();
|
|
75
|
+
this.ADLCprev = new ADLC();
|
|
76
|
+
this.beebTx = new EconetPacket();
|
|
77
|
+
this.beebRx = new EconetPacket();
|
|
78
|
+
this.serverTx = new EconetPacket();
|
|
79
|
+
|
|
80
|
+
this.pollTotalCycles = 0;
|
|
81
|
+
this.pollNextTrigger = 0;
|
|
82
|
+
this.powers = [1, 2, 4, 8];
|
|
83
|
+
|
|
84
|
+
this.econetNMIEnabled = true;
|
|
85
|
+
this.econetStateChanged = false;
|
|
86
|
+
|
|
87
|
+
this.receiveBlocks = [];
|
|
88
|
+
this.nextReceiveBlockNumber = 1;
|
|
89
|
+
|
|
90
|
+
this.wireState = this.FWH_Idle;
|
|
91
|
+
this.wireStateEntryTimer = 0;
|
|
92
|
+
this.statusLight = false;
|
|
93
|
+
this.txPort = 0;
|
|
94
|
+
this.txControlFlag = 0;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
copyBuffer(destination, source) {
|
|
98
|
+
destination.bytesInBuffer = source.bytesInBuffer;
|
|
99
|
+
destination.pointer = source.pointer;
|
|
100
|
+
destination.buffer = source.buffer.slice();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
sniffBuffer(data) {
|
|
104
|
+
// Construct a debug string describing the first bytes of the frame
|
|
105
|
+
let length = Math.min(30, data.pointer);
|
|
106
|
+
let outputString = "";
|
|
107
|
+
|
|
108
|
+
for (let i = 0; i < length; i++) {
|
|
109
|
+
outputString += (data.buffer[i] < 16 ? "0" : "") + data.buffer[i].toString(16) + " ";
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
outputString += "(" + data.pointer + " bytes)";
|
|
113
|
+
return outputString;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
deleteReceiveBlock(id) {
|
|
117
|
+
let pos = this.receiveBlocks.findIndex((e) => e.id === id);
|
|
118
|
+
if (pos >= 0) {
|
|
119
|
+
this.receiveBlocks.splice(pos, 1);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
activityLight() {
|
|
124
|
+
return this.statusLight;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
advanceState(stage) {
|
|
128
|
+
this.wireState = stage;
|
|
129
|
+
this.wireStateEntryTimer = this.pollTotalCycles;
|
|
130
|
+
if (this.wireState > 0) {
|
|
131
|
+
this.statusLight = true;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
polltime(cycles) {
|
|
136
|
+
this.pollTotalCycles += cycles;
|
|
137
|
+
|
|
138
|
+
if (this.pollNextTrigger <= this.pollTotalCycles || this.econetStateChanged) {
|
|
139
|
+
this.econetStateChanged = false;
|
|
140
|
+
|
|
141
|
+
if (this.wireState === this.FWH_Idle && this.serverTx.bytesInBuffer > 0) {
|
|
142
|
+
this.beebRx = new EconetPacket(
|
|
143
|
+
this.stationId,
|
|
144
|
+
0,
|
|
145
|
+
this.SERVER_STATION_ID,
|
|
146
|
+
0,
|
|
147
|
+
this.serverTx.controlFlag,
|
|
148
|
+
this.serverTx.port,
|
|
149
|
+
);
|
|
150
|
+
this.advanceState(this.FWH_RX_Scout_Received); // 1 - RX Received scout - waiting for ack sent
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (this.wireState === this.FWH_RX_ScoutAck_Received) {
|
|
154
|
+
this.copyBuffer(this.beebRx, this.serverTx);
|
|
155
|
+
this.advanceState(this.FWH_RX_Body_Received); // 3 - RX Body received - waiting for final ack
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Re-tries
|
|
159
|
+
if (this.pollTotalCycles > this.wireStateEntryTimer + 1000000) {
|
|
160
|
+
if (this.wireState !== this.FWH_Idle) {
|
|
161
|
+
switch (this.wireState) {
|
|
162
|
+
case this.FWH_RX_Scout_Received:
|
|
163
|
+
// No ack was sent and we were expecting one, send the scout again
|
|
164
|
+
this.beebRx = new EconetPacket(
|
|
165
|
+
this.stationId,
|
|
166
|
+
0,
|
|
167
|
+
this.SERVER_STATION_ID,
|
|
168
|
+
0,
|
|
169
|
+
this.serverTx.controlFlag,
|
|
170
|
+
this.serverTx.port,
|
|
171
|
+
);
|
|
172
|
+
this.advanceState(this.FWH_RX_Scout_Received); // reset timer
|
|
173
|
+
break;
|
|
174
|
+
case this.FWH_RX_Body_Received:
|
|
175
|
+
this.copyBuffer(this.beebRx, this.serverTx);
|
|
176
|
+
this.advanceState(this.FWH_RX_Body_Received); // reset timer
|
|
177
|
+
break;
|
|
178
|
+
default:
|
|
179
|
+
this.beebRx = new EconetPacket(this.SERVER_STATION_ID, 0, this.stationId, 0); // Send an ack?
|
|
180
|
+
}
|
|
181
|
+
} else {
|
|
182
|
+
this.statusLight = false;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
this.updateRegisters();
|
|
187
|
+
if (this.pollNextTrigger <= this.pollTotalCycles) {
|
|
188
|
+
this.transmit();
|
|
189
|
+
this.receive();
|
|
190
|
+
}
|
|
191
|
+
this.status();
|
|
192
|
+
|
|
193
|
+
return this.checkForNMI();
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
reset() {
|
|
200
|
+
console.log("Econet: initialisation");
|
|
201
|
+
|
|
202
|
+
// Hardware operations:
|
|
203
|
+
// set RxReset and TxReset
|
|
204
|
+
this.ADLC.control1 = 192;
|
|
205
|
+
// reset TxAbort, RTS, LoopMode, DTR
|
|
206
|
+
this.ADLC.control4 = 0; //ADLC.control4 & 223;
|
|
207
|
+
this.ADLC.control2 = 0; //ADLC.control2 & 127;
|
|
208
|
+
this.ADLC.control3 = 0; //ADLC.control3 & 95;
|
|
209
|
+
|
|
210
|
+
// clear all status conditions
|
|
211
|
+
this.ADLC.status1 = 0; //cts - clear to send line input (no collissions talking udp)
|
|
212
|
+
this.ADLC.status2 = 0; //dcd - no clock (until sockets initialised and open)
|
|
213
|
+
this.ADLC.sr2pse = 0;
|
|
214
|
+
this.ADLC.rxfptr = 0;
|
|
215
|
+
this.ADLC.rxap = 0;
|
|
216
|
+
this.ADLC.rxffc = 0;
|
|
217
|
+
this.ADLC.txfptr = 0;
|
|
218
|
+
this.ADLC.txftl = 0;
|
|
219
|
+
this.ADLC.idle = 1;
|
|
220
|
+
this.ADLC.cts = 0;
|
|
221
|
+
|
|
222
|
+
this.irqcause = 0;
|
|
223
|
+
this.sr1b2cause = 0;
|
|
224
|
+
|
|
225
|
+
// Initialise the start trigger of the polling routine
|
|
226
|
+
this.pollNextTrigger = this.pollTotalCycles + this.TIME_BETWEEN_BYTES;
|
|
227
|
+
this.econetStateChanged = true;
|
|
228
|
+
|
|
229
|
+
// Reset any open receive blocks
|
|
230
|
+
this.receiveBlocks = [];
|
|
231
|
+
this.nextReceiveBlockNumber = 1;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
readRegister(register) {
|
|
235
|
+
if (register === 0) {
|
|
236
|
+
return this.ADLC.status1;
|
|
237
|
+
}
|
|
238
|
+
if (register === 1) {
|
|
239
|
+
return this.ADLC.status2;
|
|
240
|
+
}
|
|
241
|
+
if (register > 1) {
|
|
242
|
+
if ((this.ADLC.control1 & 64) === 0 && this.ADLC.rxfptr) {
|
|
243
|
+
// rxreset not set and something in fifo
|
|
244
|
+
if (this.ADLC.rxfptr) {
|
|
245
|
+
this.econetStateChanged = true;
|
|
246
|
+
return this.ADLC.rxfifo[--this.ADLC.rxfptr]; // read rx buffer
|
|
247
|
+
} else {
|
|
248
|
+
return 0;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return 0;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
writeRegister(register, value) {
|
|
256
|
+
// Command registers are really just a set of flags that affect
|
|
257
|
+
// operation of the rest of the device.
|
|
258
|
+
if (register === 0) {
|
|
259
|
+
// adr 00
|
|
260
|
+
this.ADLC.control1 = value;
|
|
261
|
+
} else if (register === 1 && !(this.ADLC.control1 & 1)) {
|
|
262
|
+
// adr 01 & AC=0
|
|
263
|
+
this.ADLC.control2 = value;
|
|
264
|
+
} else if (register === 1 && this.ADLC.control1 & 1) {
|
|
265
|
+
// adr 01 & AC=1
|
|
266
|
+
this.ADLC.control3 = value;
|
|
267
|
+
} else if (register === 3 && this.ADLC.control1 & 1) {
|
|
268
|
+
// adr 03 & AC=1
|
|
269
|
+
this.ADLC.control4 = value;
|
|
270
|
+
} else if (register === 2 || register === 3) {
|
|
271
|
+
if ((this.ADLC.control1 & 128) === 0) {
|
|
272
|
+
this.ADLC.txfifo[2] = this.ADLC.txfifo[1];
|
|
273
|
+
this.ADLC.txfifo[1] = this.ADLC.txfifo[0];
|
|
274
|
+
this.ADLC.txfifo[0] = value;
|
|
275
|
+
this.ADLC.txfptr++;
|
|
276
|
+
this.ADLC.txftl = this.ADLC.txftl << 1; /// shift txlast bits up.
|
|
277
|
+
if (register === 3) this.ADLC.control2 |= 16; // set txlast control flag ourself
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
this.econetStateChanged = true;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
updateRegisters() {
|
|
285
|
+
// Save flags
|
|
286
|
+
this.ADLCprev.status1 = this.ADLC.status1;
|
|
287
|
+
this.ADLCprev.status2 = this.ADLC.status2;
|
|
288
|
+
|
|
289
|
+
if (this.ADLC.control1 & 32) {
|
|
290
|
+
this.beebRx.pointer = 0;
|
|
291
|
+
this.beebRx.bytesInBuffer = 0;
|
|
292
|
+
this.ADLC.rxfptr = 0;
|
|
293
|
+
this.ADLC.rxap = 0;
|
|
294
|
+
this.ADLC.rxffc = 0;
|
|
295
|
+
this.ADLC.control1 &= ~32; // reset flag
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (this.ADLC.control2 & 16) {
|
|
299
|
+
// TxLast set
|
|
300
|
+
this.ADLC.txftl |= 1; // set b0 - flag for fifo[0]
|
|
301
|
+
this.ADLC.control2 &= ~16; // clear flag.
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// CR2b5 - CLR RxST - Clear Receiver Status - reset status bits
|
|
305
|
+
if (this.ADLC.control2 & 32 || this.ADLC.control1 & 64) {
|
|
306
|
+
// or rxreset
|
|
307
|
+
this.ADLC.control2 &= ~32; // clear this bit
|
|
308
|
+
this.ADLC.status1 &= ~10; // clear sr2rq, FD
|
|
309
|
+
this.ADLC.status2 &= ~126; // clear FV, RxIdle, RxAbt, Err, OVRN, DCD
|
|
310
|
+
|
|
311
|
+
if (this.ADLC.control2 & 1 && this.ADLC.sr2pse) {
|
|
312
|
+
// PSE active?
|
|
313
|
+
this.ADLC.sr2pse++; // Advance PSE to next priority
|
|
314
|
+
if (this.ADLC.sr2pse > 4) this.ADLC.sr2pse = 0;
|
|
315
|
+
} else {
|
|
316
|
+
this.ADLC.sr2pse = 0;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
this.sr1b2cause = 0; // clear cause of sr2b1 going up
|
|
320
|
+
if (this.ADLC.control1 & 64) {
|
|
321
|
+
// rx reset,clear buffers.
|
|
322
|
+
this.beebRx.pointer = 0;
|
|
323
|
+
this.beebRx.bytesInBuffer = 0;
|
|
324
|
+
this.ADLC.rxfptr = 0;
|
|
325
|
+
this.ADLC.rxap = 0;
|
|
326
|
+
this.ADLC.rxffc = 0;
|
|
327
|
+
this.ADLC.sr2pse = 0;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// CR2b6 - CLT TxST - Clear Transmitter Status - reset status bits
|
|
332
|
+
if (this.ADLC.control2 & 64 || this.ADLC.control1 & 128) {
|
|
333
|
+
// or txreset
|
|
334
|
+
this.ADLC.control2 &= ~64; // clear this bit
|
|
335
|
+
this.ADLC.status1 &= ~0x70; // clear TXU , cts, TDRA/FC
|
|
336
|
+
if (this.ADLC.cts) {
|
|
337
|
+
this.ADLC.status1 |= 16; //cts follows signal, reset high again
|
|
338
|
+
this.ADLCprev.status1 |= 16; // don't trigger another interrupt instantly
|
|
339
|
+
}
|
|
340
|
+
if (this.ADLC.control1 & 128) {
|
|
341
|
+
// tx reset,clear buffers.
|
|
342
|
+
this.beebTx.pointer = 0;
|
|
343
|
+
this.beebTx.bytesInBuffer = 0;
|
|
344
|
+
this.ADLC.txfptr = 0;
|
|
345
|
+
this.ADLC.txftl = 0;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (this.ADLC.control4 & 32) {
|
|
350
|
+
// ABORT
|
|
351
|
+
this.ADLC.txfptr = 0; // reset fifo
|
|
352
|
+
this.ADLC.txftl = 0; // reset fifo flags
|
|
353
|
+
this.beebTx.pointer = 0;
|
|
354
|
+
this.beebTx.bytesInBuffer = 0;
|
|
355
|
+
this.ADLC.control4 &= ~32; // reset flag.
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
transmit() {
|
|
360
|
+
// Transmit data
|
|
361
|
+
if (!(this.ADLC.control1 & 128)) {
|
|
362
|
+
// tx reset off
|
|
363
|
+
if (this.ADLC.txfptr) {
|
|
364
|
+
// there is data in tx fifo
|
|
365
|
+
let TXlast = false;
|
|
366
|
+
if (this.ADLC.txftl & this.powers[this.ADLC.txfptr - 1]) TXlast = true; // TxLast set
|
|
367
|
+
if (
|
|
368
|
+
this.beebTx.full || // overflow IP buffer
|
|
369
|
+
this.ADLC.txfptr > 4
|
|
370
|
+
) {
|
|
371
|
+
// overflowed fifo
|
|
372
|
+
this.ADLC.status1 |= 32; // set tx underrun flag
|
|
373
|
+
this.beebTx.pointer = 0; // wipe buffer
|
|
374
|
+
this.beebTx.bytesInBuffer = 0;
|
|
375
|
+
this.ADLC.txfptr = 0;
|
|
376
|
+
this.ADLC.txftl = 0;
|
|
377
|
+
} else {
|
|
378
|
+
this.beebTx.buffer[this.beebTx.pointer] = this.ADLC.txfifo[--this.ADLC.txfptr];
|
|
379
|
+
this.beebTx.pointer++;
|
|
380
|
+
}
|
|
381
|
+
if (TXlast) {
|
|
382
|
+
// TxLast set
|
|
383
|
+
this.beebTx.bytesInBuffer = this.beebTx.pointer;
|
|
384
|
+
|
|
385
|
+
/*console.log(
|
|
386
|
+
"Econet: " +
|
|
387
|
+
this.stationId +
|
|
388
|
+
" TX->" +
|
|
389
|
+
this.beebTx.buffer[0] +
|
|
390
|
+
": " +
|
|
391
|
+
this.sniffBuffer(this.beebTx)
|
|
392
|
+
);*/
|
|
393
|
+
|
|
394
|
+
// Is this an immediate operation ? Assume it is a machine peek
|
|
395
|
+
if (
|
|
396
|
+
this.beebTx.bytesInBuffer === 10 &&
|
|
397
|
+
this.beebTx.buffer[5] === 0 &&
|
|
398
|
+
this.beebTx.buffer[4] >= 0x82 &&
|
|
399
|
+
this.beebTx.buffer[4] <= 0x88
|
|
400
|
+
) {
|
|
401
|
+
this.beebRx = new EconetPacket(this.stationId, 0, this.SERVER_STATION_ID, 0, 1, 0, 0x60, 0x03);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// Is this an ack?
|
|
405
|
+
if (this.beebTx.bytesInBuffer === 4) {
|
|
406
|
+
// if state = 1, move to state 2
|
|
407
|
+
//if state = 3, clear FileStoreTX and move to state 0
|
|
408
|
+
|
|
409
|
+
if (this.wireState === this.FWH_RX_Scout_Received) {
|
|
410
|
+
// 1 - RX Received scout - waiting for ack sent
|
|
411
|
+
this.advanceState(this.FWH_RX_ScoutAck_Received); // 2 - RX Scout ack received - waiting for body
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
if (this.wireState === this.FWH_RX_Body_Received) {
|
|
415
|
+
// 3 - RX Body received - waiting for final ack
|
|
416
|
+
this.serverTx.bytesInBuffer = 0;
|
|
417
|
+
this.advanceState(this.FWH_Idle);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// Is this a body ?
|
|
422
|
+
if (this.beebTx.bytesInBuffer >= 6 && this.wireState === this.FWH_TX_Scout_Sent) {
|
|
423
|
+
// if at state 4, copy to server RX block, drop ack into BeebRX and move to state 0
|
|
424
|
+
let serverReceiveBlock = this.receiveBlocks.find(
|
|
425
|
+
(element) => element.receivePort === this.txPort,
|
|
426
|
+
);
|
|
427
|
+
if (serverReceiveBlock) {
|
|
428
|
+
this.copyBuffer(serverReceiveBlock.data, this.beebTx);
|
|
429
|
+
serverReceiveBlock.stationId = this.stationId;
|
|
430
|
+
serverReceiveBlock.controlFlag = this.txControlFlag;
|
|
431
|
+
}
|
|
432
|
+
this.beebRx = new EconetPacket(this.stationId, 0, this.SERVER_STATION_ID, 0);
|
|
433
|
+
this.advanceState(this.FWH_Idle);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// Is this a scout ?
|
|
437
|
+
if (this.beebTx.bytesInBuffer === 6) {
|
|
438
|
+
//if state = 0, remember port and control byte
|
|
439
|
+
// move to state 4 if there is a server RX block set up and drop ack into BeebRX,
|
|
440
|
+
// otherwise ignore
|
|
441
|
+
|
|
442
|
+
if (this.wireState === this.FWH_Idle) {
|
|
443
|
+
this.txControlFlag = this.beebTx.buffer[4];
|
|
444
|
+
this.txPort = this.beebTx.buffer[5];
|
|
445
|
+
|
|
446
|
+
// Send an ack if the server has a port open for this
|
|
447
|
+
if (this.receiveBlocks.find((element) => element.receivePort === this.txPort)) {
|
|
448
|
+
this.beebRx = new EconetPacket(this.stationId, 0, this.SERVER_STATION_ID, 0);
|
|
449
|
+
this.advanceState(this.FWH_TX_Scout_Sent); // 4 - TX Scout sent - waiting for ack
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// Wipe the transmit buffer ready for the next frame
|
|
455
|
+
this.beebTx.pointer = 0;
|
|
456
|
+
this.beebTx.bytesInBuffer = 0;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
receive() {
|
|
463
|
+
if (!(this.ADLC.control1 & 64)) {
|
|
464
|
+
// rx reset off
|
|
465
|
+
if (this.beebRx.pointer < this.beebRx.bytesInBuffer) {
|
|
466
|
+
// something waiting to be given to the processor
|
|
467
|
+
if (this.ADLC.rxfptr < 3) {
|
|
468
|
+
// space in fifo
|
|
469
|
+
this.ADLC.rxfifo[2] = this.ADLC.rxfifo[1];
|
|
470
|
+
this.ADLC.rxfifo[1] = this.ADLC.rxfifo[0];
|
|
471
|
+
this.ADLC.rxfifo[0] = this.beebRx.buffer[this.beebRx.pointer];
|
|
472
|
+
this.ADLC.rxfptr++;
|
|
473
|
+
this.ADLC.rxffc = (this.ADLC.rxffc << 1) & 7;
|
|
474
|
+
this.ADLC.rxap = (this.ADLC.rxap << 1) & 7;
|
|
475
|
+
if (this.beebRx.pointer === 0) this.ADLC.rxap |= 1; // 2 bytes? adr extention mode
|
|
476
|
+
this.beebRx.pointer++;
|
|
477
|
+
if (this.beebRx.pointer >= this.beebRx.bytesInBuffer) {
|
|
478
|
+
// that was last byte!
|
|
479
|
+
this.ADLC.rxffc |= 1; // set FV flag (this was last byte of frame)
|
|
480
|
+
|
|
481
|
+
/*console.log(
|
|
482
|
+
"Econet: " +
|
|
483
|
+
this.stationId +
|
|
484
|
+
" RX<-" +
|
|
485
|
+
this.beebRx.buffer[2] +
|
|
486
|
+
": " +
|
|
487
|
+
this.sniffBuffer(this.beebRx)
|
|
488
|
+
);*/
|
|
489
|
+
|
|
490
|
+
this.beebRx.pointer = 0; // Reset read for next packet
|
|
491
|
+
this.beebRx.bytesInBuffer = 0;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
if (this.ADLC.rxfptr === 0) {
|
|
497
|
+
// still nothing in buffers (and thus nothing in Econetrx buffer)
|
|
498
|
+
this.ADLC.control1 &= ~32; // reset discontinue flag
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// Update idle status
|
|
503
|
+
if (
|
|
504
|
+
!(this.ADLC.control1 & 0x40) && // not rxreset
|
|
505
|
+
!this.ADLC.rxfptr && // nothing in fifo
|
|
506
|
+
!(this.ADLC.status2 & 2) && // no FV
|
|
507
|
+
this.beebRx.bytesInBuffer === 0
|
|
508
|
+
) {
|
|
509
|
+
// nothing in ip buffer
|
|
510
|
+
this.ADLC.idle = true;
|
|
511
|
+
} else {
|
|
512
|
+
this.ADLC.idle = false;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
//----------------------------------------------------------------------------------
|
|
516
|
+
// how long before we come back in here?
|
|
517
|
+
this.pollNextTrigger = this.pollTotalCycles + this.TIME_BETWEEN_BYTES;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
status() {
|
|
521
|
+
// SR1b0 - RDA - received data available.
|
|
522
|
+
if (!(this.ADLC.control1 & 64)) {
|
|
523
|
+
// rx reset off
|
|
524
|
+
if (
|
|
525
|
+
(this.ADLC.rxfptr && !(this.ADLC.control2 & 2)) || // 1 byte mode
|
|
526
|
+
(this.ADLC.rxfptr > 1 && this.ADLC.control2 & 2)
|
|
527
|
+
) {
|
|
528
|
+
// 2 byte mode
|
|
529
|
+
this.ADLC.status1 |= 1; // set RDA copy
|
|
530
|
+
this.ADLC.status2 |= 128;
|
|
531
|
+
} else {
|
|
532
|
+
this.ADLC.status1 &= ~1;
|
|
533
|
+
this.ADLC.status2 &= ~128;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
this.ADLC.status1 &= ~8;
|
|
538
|
+
|
|
539
|
+
if (this.ADLC.control2 & 128) {
|
|
540
|
+
// clock + RTS
|
|
541
|
+
this.ADLC.cts = false;
|
|
542
|
+
this.ADLC.status1 &= ~16;
|
|
543
|
+
} else {
|
|
544
|
+
this.ADLC.cts = true;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// and then set the status bit if the line is high! (status bit stays
|
|
548
|
+
// up until cpu tries to clear it) (& still stays up if cts line still high)
|
|
549
|
+
if (this.ADLC.control1 & 128 && this.ADLC.cts) {
|
|
550
|
+
this.ADLC.status1 |= 16; // set CTS now
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// SR1b5 - TXU - Tx Underrun.
|
|
554
|
+
if (this.ADLC.txfptr > 4) {
|
|
555
|
+
// probably not needed
|
|
556
|
+
this.ADLC.status1 |= 32;
|
|
557
|
+
this.ADLC.txfptr = 4;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// SR1b6 TDRA flag - another complicated derivation
|
|
561
|
+
if (!(this.ADLC.control1 & 128)) {
|
|
562
|
+
// not txreset
|
|
563
|
+
if (!(this.ADLC.control2 & 8)) {
|
|
564
|
+
// tdra mode
|
|
565
|
+
if (
|
|
566
|
+
((this.ADLC.txfptr < 3 && !(this.ADLC.control2 & 2)) || // space in fifo?
|
|
567
|
+
(this.ADLC.txfptr < 2 && this.ADLC.control2 & 2)) && // space in fifo?
|
|
568
|
+
!(this.ADLC.status1 & 16) && // clear to send is ok
|
|
569
|
+
!(this.ADLC.status2 & 32)
|
|
570
|
+
) {
|
|
571
|
+
// DTR not high
|
|
572
|
+
|
|
573
|
+
this.ADLC.status1 |= 64; // set Tx Reg Data Available flag.
|
|
574
|
+
} else {
|
|
575
|
+
this.ADLC.status1 &= ~64; // clear Tx Reg Data Available flag.
|
|
576
|
+
}
|
|
577
|
+
} else {
|
|
578
|
+
// FC mode
|
|
579
|
+
if (!this.ADLC.txfptr) {
|
|
580
|
+
// nothing in fifo
|
|
581
|
+
this.ADLC.status1 |= 64; // set Tx Reg Data Available flag.
|
|
582
|
+
} else {
|
|
583
|
+
this.ADLC.status1 &= ~64; // clear Tx Reg Data Available flag.
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
// SR1b7 IRQ flag - see below
|
|
588
|
+
|
|
589
|
+
// SR2b0 - AP - Address present
|
|
590
|
+
if (!(this.ADLC.control1 & 64)) {
|
|
591
|
+
// not rxreset
|
|
592
|
+
if (this.ADLC.rxfptr && this.ADLC.rxap & this.powers[this.ADLC.rxfptr - 1]) {
|
|
593
|
+
// ap bits set on fifo
|
|
594
|
+
this.ADLC.status2 |= 1;
|
|
595
|
+
} else {
|
|
596
|
+
this.ADLC.status2 &= ~1;
|
|
597
|
+
}
|
|
598
|
+
// SR2b1 - FV -Frame Valid - set in rx - only reset by ClearRx or RxReset
|
|
599
|
+
if (this.ADLC.rxfptr && this.ADLC.rxffc & this.powers[this.ADLC.rxfptr - 1]) {
|
|
600
|
+
this.ADLC.status2 |= 2;
|
|
601
|
+
}
|
|
602
|
+
// SR2b2 - Inactive Idle Received - sets irq!
|
|
603
|
+
if (this.ADLC.idle) {
|
|
604
|
+
// && !this.flagFillActive) {
|
|
605
|
+
this.ADLC.status2 |= 4;
|
|
606
|
+
} else {
|
|
607
|
+
this.ADLC.status2 &= ~4;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
this.ADLC.status2 &= ~32;
|
|
612
|
+
if (this.ADLC.rxfptr > 4) {
|
|
613
|
+
this.ADLC.status2 |= 64;
|
|
614
|
+
this.ADLC.rxfptr = 4;
|
|
615
|
+
}
|
|
616
|
+
// SR2b7 - RDA. As per SR1b0 - set above.
|
|
617
|
+
|
|
618
|
+
// Handle PSE - only for SR2 Rx bits at the moment
|
|
619
|
+
if (this.ADLC.control2 & 1) {
|
|
620
|
+
if (this.ADLC.sr2pse <= 1 && this.ADLC.status2 & 0x7a) {
|
|
621
|
+
// ERR, FV, DCD, OVRN, ABT
|
|
622
|
+
this.ADLC.sr2pse = 1;
|
|
623
|
+
this.ADLC.status2 &= ~0x85;
|
|
624
|
+
} else if (this.ADLC.sr2pse <= 2 && this.ADLC.status2 & 0x04) {
|
|
625
|
+
// Idle
|
|
626
|
+
this.ADLC.sr2pse = 2;
|
|
627
|
+
this.ADLC.status2 &= ~0x81;
|
|
628
|
+
} else if (this.ADLC.sr2pse <= 3 && this.ADLC.status2 & 0x01) {
|
|
629
|
+
// AP
|
|
630
|
+
this.ADLC.sr2pse = 3;
|
|
631
|
+
this.ADLC.status2 &= ~0x80;
|
|
632
|
+
} else if (this.ADLC.status2 & 0x80) {
|
|
633
|
+
// RDA
|
|
634
|
+
this.ADLC.sr2pse = 4;
|
|
635
|
+
this.ADLC.status2 &= ~0x02;
|
|
636
|
+
} else {
|
|
637
|
+
this.ADLC.sr2pse = 0; // No relevant bits set
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// Set SR1 RDA copy
|
|
641
|
+
if (this.ADLC.status2 & 0x80) this.ADLC.status1 |= 1;
|
|
642
|
+
else this.ADLC.status1 &= ~1;
|
|
643
|
+
} else {
|
|
644
|
+
// PSE inactive
|
|
645
|
+
this.ADLC.sr2pse = 0;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
checkForNMI() {
|
|
650
|
+
// Do we need to flag an interrupt?
|
|
651
|
+
let raiseNMI = false;
|
|
652
|
+
if (this.ADLC.status1 !== this.ADLCprev.status1 || this.ADLC.status2 !== this.ADLCprev.status2) {
|
|
653
|
+
// something changed
|
|
654
|
+
let tempcause, temp2;
|
|
655
|
+
|
|
656
|
+
// SR1b1 - S2RQ - Status2 request. New bit set in S2?
|
|
657
|
+
tempcause = (this.ADLC.status2 ^ this.ADLCprev.status2) & this.ADLC.status2 & ~128;
|
|
658
|
+
|
|
659
|
+
if (!(this.ADLC.control1 & 2)) {
|
|
660
|
+
// RIE not set,
|
|
661
|
+
tempcause = 0;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
if (tempcause) {
|
|
665
|
+
//something got set
|
|
666
|
+
this.ADLC.status1 |= 2;
|
|
667
|
+
this.sr1b2cause = this.sr1b2cause | tempcause;
|
|
668
|
+
} else if (!(this.ADLC.status2 & this.sr1b2cause)) {
|
|
669
|
+
//cause has gone
|
|
670
|
+
this.ADLC.status1 &= ~2;
|
|
671
|
+
this.sr1b2cause = 0;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
// New bit set in S1?
|
|
675
|
+
tempcause = (this.ADLC.status1 ^ this.ADLCprev.status1) & this.ADLC.status1 & ~128;
|
|
676
|
+
|
|
677
|
+
if (!(this.ADLC.control1 & 2)) {
|
|
678
|
+
// RIE not set,
|
|
679
|
+
tempcause = tempcause & ~11;
|
|
680
|
+
}
|
|
681
|
+
if (!(this.ADLC.control1 & 4)) {
|
|
682
|
+
// TIE not set,
|
|
683
|
+
tempcause = tempcause & ~0x70;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
if (tempcause) {
|
|
687
|
+
//something got set
|
|
688
|
+
raiseNMI = true;
|
|
689
|
+
this.irqcause = this.irqcause | tempcause; // remember which bit went high to flag irq
|
|
690
|
+
// SR1b7 IRQ flag
|
|
691
|
+
this.ADLC.status1 |= 128;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// Bit cleared in S1?
|
|
695
|
+
temp2 = (this.ADLC.status1 ^ this.ADLCprev.status1) & this.ADLCprev.status1 & ~128;
|
|
696
|
+
if (temp2) {
|
|
697
|
+
// something went off
|
|
698
|
+
this.irqcause = this.irqcause & ~temp2; // clear flags that went off
|
|
699
|
+
if (this.irqcause === 0) {
|
|
700
|
+
// all flag gone off now
|
|
701
|
+
// clear irq status bit when cause has gone.
|
|
702
|
+
this.ADLC.status1 &= ~128;
|
|
703
|
+
} else {
|
|
704
|
+
// interrupt again because still have flags set
|
|
705
|
+
if (this.ADLC.control2 & 1) {
|
|
706
|
+
raiseNMI = true;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
return raiseNMI;
|
|
713
|
+
}
|
|
714
|
+
}
|