badline 0.12.0 → 0.13.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -0
- data/CLAUDE.md +59 -31
- data/README.md +1 -1
- data/doc/library.md +9 -9
- data/doc/pinned-behaviour.md +105 -105
- data/doc/snapshots.md +1 -4
- data/lib/badline/audio/bare_player.rb +4 -4
- data/lib/badline/audio/cli.rb +6 -6
- data/lib/badline/audio/jukebox.rb +2 -2
- data/lib/badline/audio/machine_player.rb +2 -2
- data/lib/badline/{media → audio}/queue.rb +1 -1
- data/lib/badline/audio/queued_tune.rb +6 -6
- data/lib/badline/audio/renderer.rb +5 -5
- data/lib/badline/audio/stereo.rb +1 -1
- data/lib/badline/c128/{bus_state.rb → bus/saved_state.rb} +6 -6
- data/lib/badline/c128/bus.rb +30 -51
- data/lib/badline/c128/color_lines.rb +2 -2
- data/lib/badline/c128/cpu.rb +1 -1
- data/lib/badline/c128/drives.rb +10 -11
- data/lib/badline/c128/fast_serial.rb +5 -5
- data/lib/badline/c128/mmu_pages.rb +1 -1
- data/lib/badline/c128/modes.rb +2 -2
- data/lib/badline/c128/saved_state.rb +21 -47
- data/lib/badline/c128/z80.rb +2 -2
- data/lib/badline/c128.rb +18 -72
- data/lib/badline/{computer → c64}/attachments.rb +16 -47
- data/lib/badline/c64/banked_ram/banking.rb +32 -0
- data/lib/badline/c64/banked_ram/plus256k.rb +56 -0
- data/lib/badline/c64/banked_ram/plus60k.rb +45 -0
- data/lib/badline/c64/banked_ram/unexpanded.rb +30 -0
- data/lib/badline/c64/banked_ram.rb +23 -0
- data/lib/badline/c64/bus/extra_sids.rb +32 -0
- data/lib/badline/c64/bus/fittings.rb +40 -0
- data/lib/badline/c64/bus/pla.rb +149 -0
- data/lib/badline/c64/bus/roms.rb +41 -0
- data/lib/badline/c64/bus/saved_state.rb +68 -0
- data/lib/badline/c64/bus/sid_slots.rb +44 -0
- data/lib/badline/c64/bus.rb +218 -0
- data/lib/badline/c64/cartridge/action_replay.rb +128 -0
- data/lib/badline/c64/cartridge/atomic_power.rb +26 -0
- data/lib/badline/c64/cartridge/bank.rb +83 -0
- data/lib/badline/c64/cartridge/comal80.rb +52 -0
- data/lib/badline/c64/cartridge/dinamic.rb +36 -0
- data/lib/badline/c64/cartridge/easy_flash.rb +147 -0
- data/lib/badline/c64/cartridge/epyx_fastload.rb +81 -0
- data/lib/badline/c64/cartridge/final_cartridge3.rb +91 -0
- data/lib/badline/c64/cartridge/flash/saved_state.rb +40 -0
- data/lib/badline/c64/cartridge/flash.rb +279 -0
- data/lib/badline/c64/cartridge/freezer.rb +35 -0
- data/lib/badline/c64/cartridge/fun_play.rb +40 -0
- data/lib/badline/c64/cartridge/g_mod2.rb +76 -0
- data/lib/badline/c64/cartridge/game_system.rb +42 -0
- data/lib/badline/c64/cartridge/geo_ram.rb +81 -0
- data/lib/badline/c64/cartridge/kcs_power.rb +77 -0
- data/lib/badline/c64/cartridge/mach5.rb +34 -0
- data/lib/badline/c64/cartridge/magic_desk.rb +32 -0
- data/lib/badline/c64/cartridge/ocean.rb +37 -0
- data/lib/badline/c64/cartridge/pagefox.rb +70 -0
- data/lib/badline/c64/cartridge/retro_replay/saved_state.rb +47 -0
- data/lib/badline/c64/cartridge/retro_replay.rb +286 -0
- data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
- data/lib/badline/c64/cartridge/rgcd.rb +60 -0
- data/lib/badline/c64/cartridge/saved_state.rb +63 -0
- data/lib/badline/c64/cartridge/simons_basic.rb +37 -0
- data/lib/badline/c64/cartridge/standard.rb +17 -0
- data/lib/badline/c64/cartridge/super_games.rb +50 -0
- data/lib/badline/c64/cartridge/westermann.rb +32 -0
- data/lib/badline/c64/cartridge/zaxxon.rb +68 -0
- data/lib/badline/c64/cartridge.rb +258 -0
- data/lib/badline/c64/color_memory.rb +27 -0
- data/lib/badline/c64/common.rb +34 -0
- data/lib/badline/c64/kernal_traps.rb +89 -0
- data/lib/badline/c64/reu/dma/saved_state.rb +52 -0
- data/lib/badline/c64/reu/dma.rb +275 -0
- data/lib/badline/c64/reu/ram.rb +109 -0
- data/lib/badline/c64/reu/saved_state.rb +55 -0
- data/lib/badline/c64/reu/trigger.rb +34 -0
- data/lib/badline/c64/reu.rb +291 -0
- data/lib/badline/{computer → c64}/saved_state.rb +13 -18
- data/lib/badline/{computer → c64}/true_drives.rb +20 -31
- data/lib/badline/{computer.rb → c64.rb} +22 -80
- data/lib/badline/chips/cia/fast_forward.rb +62 -0
- data/lib/badline/chips/cia/interrupt_register.rb +145 -0
- data/lib/badline/chips/cia/saved_state.rb +49 -0
- data/lib/badline/chips/cia/serial/saved_state.rb +45 -0
- data/lib/badline/chips/cia/serial.rb +250 -0
- data/lib/badline/chips/cia/time_of_day.rb +232 -0
- data/lib/badline/chips/cia/timer.rb +208 -0
- data/lib/badline/chips/cia.rb +281 -0
- data/lib/badline/chips/cpu/addressing.rb +133 -0
- data/lib/badline/chips/cpu/boundary.rb +56 -0
- data/lib/badline/chips/cpu/core.rb +167 -0
- data/lib/badline/chips/cpu/instruction.rb +338 -0
- data/lib/badline/chips/cpu/instruction_set/arithmetic.rb +118 -0
- data/lib/badline/chips/cpu/instruction_set/bitwise.rb +130 -0
- data/lib/badline/chips/cpu/instruction_set/branch.rb +83 -0
- data/lib/badline/chips/cpu/instruction_set/flag.rb +67 -0
- data/lib/badline/chips/cpu/instruction_set/illegal.rb +274 -0
- data/lib/badline/chips/cpu/instruction_set/inc_dec.rb +73 -0
- data/lib/badline/chips/cpu/instruction_set/stack.rb +56 -0
- data/lib/badline/chips/cpu/instruction_set/transfer.rb +141 -0
- data/lib/badline/chips/cpu/instruction_set.rb +59 -0
- data/lib/badline/chips/cpu/interrupts.rb +108 -0
- data/lib/badline/chips/cpu/microcode.rb +179 -0
- data/lib/badline/chips/cpu/operations.rb +90 -0
- data/lib/badline/chips/cpu/port.rb +116 -0
- data/lib/badline/chips/cpu/saved_state.rb +117 -0
- data/lib/badline/chips/cpu/stack_operations.rb +84 -0
- data/lib/badline/chips/cpu/traps.rb +23 -0
- data/lib/badline/chips/cpu.rb +12 -0
- data/lib/badline/chips/sid/catch_up.rb +122 -0
- data/lib/badline/chips/sid/decimator.rb +66 -0
- data/lib/badline/chips/sid/envelope/saved_state.rb +70 -0
- data/lib/badline/chips/sid/envelope.rb +241 -0
- data/lib/badline/chips/sid/filter/saved_state.rb +42 -0
- data/lib/badline/chips/sid/filter.rb +241 -0
- data/lib/badline/chips/sid/saved_state.rb +52 -0
- data/lib/badline/chips/sid/voice.rb +79 -0
- data/lib/badline/chips/sid/waveform/combined.rb +128 -0
- data/lib/badline/chips/sid/waveform/fast_forward.rb +107 -0
- data/lib/badline/chips/sid/waveform/noise_writeback.rb +124 -0
- data/lib/badline/chips/sid/waveform/saved_state.rb +68 -0
- data/lib/badline/chips/sid/waveform.rb +307 -0
- data/lib/badline/chips/sid.rb +265 -0
- data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
- data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -1
- data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -1
- data/lib/badline/chips/vdc/saved_state.rb +36 -0
- data/lib/badline/{c128 → chips}/vdc/window.rb +1 -1
- data/lib/badline/{c128 → chips}/vdc.rb +7 -31
- data/lib/badline/chips/via/control_lines.rb +124 -0
- data/lib/badline/chips/via/fast_forward.rb +55 -0
- data/lib/badline/chips/via/interrupt_register.rb +69 -0
- data/lib/badline/chips/via/saved_state.rb +44 -0
- data/lib/badline/chips/via/shift_register.rb +182 -0
- data/lib/badline/chips/via/timer1.rb +133 -0
- data/lib/badline/chips/via/timer2.rb +135 -0
- data/lib/badline/chips/via.rb +268 -0
- data/lib/badline/chips/vic/bank.rb +135 -0
- data/lib/badline/chips/vic/border_mask.rb +88 -0
- data/lib/badline/chips/vic/collisions.rb +117 -0
- data/lib/badline/chips/vic/color_patches.rb +49 -0
- data/lib/badline/chips/vic/display_state.rb +187 -0
- data/lib/badline/chips/vic/graphics_mode.rb +166 -0
- data/lib/badline/chips/vic/graphics_shifter/saved_state.rb +40 -0
- data/lib/badline/chips/vic/graphics_shifter.rb +187 -0
- data/lib/badline/chips/vic/register_log.rb +83 -0
- data/lib/badline/chips/vic/registers.rb +197 -0
- data/lib/badline/chips/vic/saved_state.rb +82 -0
- data/lib/badline/chips/vic/sequencer/saved_state.rb +91 -0
- data/lib/badline/chips/vic/sequencer.rb +277 -0
- data/lib/badline/chips/vic/sequencer_output.rb +118 -0
- data/lib/badline/chips/vic/sprite/internal_bus.rb +70 -0
- data/lib/badline/chips/vic/sprite/saved_state.rb +66 -0
- data/lib/badline/chips/vic/sprite/shifter.rb +148 -0
- data/lib/badline/chips/vic/sprite/timing.rb +58 -0
- data/lib/badline/chips/vic/sprite.rb +339 -0
- data/lib/badline/chips/vic/sprites/saved_state.rb +59 -0
- data/lib/badline/chips/vic/sprites.rb +284 -0
- data/lib/badline/chips/vic.rb +783 -0
- data/lib/badline/chips/vic_i/painter/saved_state.rb +40 -0
- data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +6 -30
- data/lib/badline/{vic20/vic → chips/vic_i}/saved_state.rb +2 -2
- data/lib/badline/chips/vic_i/sound/output.rb +85 -0
- data/lib/badline/chips/vic_i/sound.rb +235 -0
- data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
- data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +5 -5
- data/lib/badline/chips/z80/arithmetic.rb +119 -0
- data/lib/badline/chips/z80/bit_page.rb +57 -0
- data/lib/badline/chips/z80/block_io.rb +60 -0
- data/lib/badline/chips/z80/block_transfers.rb +61 -0
- data/lib/badline/chips/z80/bus_cycles.rb +113 -0
- data/lib/badline/chips/z80/core.rb +115 -0
- data/lib/badline/chips/z80/exchanges.rb +52 -0
- data/lib/badline/chips/z80/extended_page.rb +91 -0
- data/lib/badline/chips/z80/flags.rb +39 -0
- data/lib/badline/chips/z80/interrupt_acceptance.rb +48 -0
- data/lib/badline/chips/z80/jumps.rb +84 -0
- data/lib/badline/chips/z80/loads.rb +100 -0
- data/lib/badline/chips/z80/main_page.rb +136 -0
- data/lib/badline/chips/z80/registers.rb +122 -0
- data/lib/badline/chips/z80/saved_state.rb +71 -0
- data/lib/badline/chips/z80/shifts.rb +66 -0
- data/lib/badline/chips/z80.rb +13 -0
- data/lib/badline/core.rb +27 -29
- data/lib/badline/drives/datasette/saved_state.rb +37 -0
- data/lib/badline/drives/datasette.rb +140 -0
- data/lib/badline/drives/engine/core.rb +149 -0
- data/lib/badline/drives/engine/fast_serial.rb +75 -0
- data/lib/badline/drives/engine/idle.rb +127 -0
- data/lib/badline/drives/engine/idle_cpu.rb +30 -0
- data/lib/badline/drives/engine/orbit.rb +81 -0
- data/lib/badline/drives/engine/serial_lines.rb +75 -0
- data/lib/badline/drives/engine/sleep.rb +114 -0
- data/lib/badline/drives/engine/vias.rb +86 -0
- data/lib/badline/drives/engine/watch.rb +152 -0
- data/lib/badline/drives/engine.rb +11 -0
- data/lib/badline/drives/model1541/bus.rb +88 -0
- data/lib/badline/drives/model1541/byte_ready.rb +50 -0
- data/lib/badline/drives/model1541/cpu.rb +13 -0
- data/lib/badline/drives/model1541/disk/saved_state.rb +88 -0
- data/lib/badline/drives/model1541/disk.rb +317 -0
- data/lib/badline/drives/model1541/disk_via.rb +38 -0
- data/lib/badline/drives/model1541/gcr.rb +59 -0
- data/lib/badline/drives/model1541/mechanism/saved_state.rb +72 -0
- data/lib/badline/drives/model1541/mechanism.rb +315 -0
- data/lib/badline/drives/model1541/rotation.rb +123 -0
- data/lib/badline/drives/model1541/saved_state.rb +44 -0
- data/lib/badline/drives/model1541/sector_reader.rb +78 -0
- data/lib/badline/drives/model1541/serial_port.rb +20 -0
- data/lib/badline/drives/model1541/track.rb +100 -0
- data/lib/badline/drives/model1541.rb +81 -0
- data/lib/badline/drives/model1571/bus.rb +113 -0
- data/lib/badline/drives/model1571/cpu.rb +13 -0
- data/lib/badline/drives/model1571/saved_state.rb +47 -0
- data/lib/badline/drives/model1571/serial_port.rb +39 -0
- data/lib/badline/drives/model1571/serial_via.rb +27 -0
- data/lib/badline/drives/model1571/wd1770.rb +122 -0
- data/lib/badline/drives/model1571.rb +142 -0
- data/lib/badline/drives/model1581/bus.rb +139 -0
- data/lib/badline/drives/model1581/cpu.rb +13 -0
- data/lib/badline/drives/model1581/disk/saved_state.rb +89 -0
- data/lib/badline/drives/model1581/disk.rb +137 -0
- data/lib/badline/drives/model1581/mechanism.rb +119 -0
- data/lib/badline/drives/model1581/saved_state.rb +42 -0
- data/lib/badline/drives/model1581/serial_port.rb +54 -0
- data/lib/badline/drives/model1581/slot.rb +79 -0
- data/lib/badline/drives/model1581/track.rb +102 -0
- data/lib/badline/drives/model1581/track_bytes.rb +77 -0
- data/lib/badline/drives/model1581/wd1772/registers.rb +91 -0
- data/lib/badline/drives/model1581/wd1772/saved_state.rb +68 -0
- data/lib/badline/drives/model1581/wd1772/sector_writes.rb +75 -0
- data/lib/badline/drives/model1581/wd1772/sectors.rb +152 -0
- data/lib/badline/drives/model1581/wd1772/stepping.rb +111 -0
- data/lib/badline/drives/model1581/wd1772/tracks.rb +127 -0
- data/lib/badline/drives/model1581/wd1772/turn.rb +75 -0
- data/lib/badline/drives/model1581/wd1772.rb +218 -0
- data/lib/badline/drives/model1581.rb +206 -0
- data/lib/badline/drives/serial_bus.rb +161 -0
- data/lib/badline/frontend/boot.rb +10 -61
- data/lib/badline/frontend/machine_window.rb +3 -1
- data/lib/badline/frontend/player/filter_view.rb +1 -1
- data/lib/badline/frontend/player/player_controller.rb +2 -2
- data/lib/badline/frontend/player/player_screen.rb +1 -0
- data/lib/badline/frontend/player/theme.rb +7 -7
- data/lib/badline/frontend/timeline.rb +3 -3
- data/lib/badline/input/control_ports.rb +78 -0
- data/lib/badline/input/joystick.rb +27 -0
- data/lib/badline/input/keyboard.rb +114 -0
- data/lib/badline/input.rb +3 -0
- data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
- data/lib/badline/kernal_trap/dos/channel.rb +183 -0
- data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
- data/lib/badline/kernal_trap/{drive.rb → dos.rb} +11 -10
- data/lib/badline/kernal_trap/{file.rb → file_routine.rb} +1 -1
- data/lib/badline/kernal_trap/load.rb +6 -6
- data/lib/badline/kernal_trap/save.rb +5 -5
- data/lib/badline/kernal_trap/serial.rb +7 -7
- data/lib/badline/kernal_trap.rb +2 -3
- data/lib/badline/machine/clocking.rb +50 -0
- data/lib/badline/machine.rb +63 -7
- data/lib/badline/media/boot_disk.rb +2 -2
- data/lib/badline/media/disk_list.rb +3 -3
- data/lib/badline/media/disk_set.rb +1 -1
- data/lib/badline/media/extensions.rb +33 -0
- data/lib/badline/media/program.rb +28 -0
- data/lib/badline/media/true_drive.rb +4 -3
- data/lib/badline/media/tune.rb +35 -0
- data/lib/badline/media/vic20_cartridge.rb +1 -7
- data/lib/badline/media/vic20_media.rb +38 -80
- data/lib/badline/media.rb +84 -81
- data/lib/badline/model.rb +1 -1
- data/lib/badline/options/event.rb +3 -1
- data/lib/badline/roms/README +6 -6
- data/lib/badline/sdl.rb +1 -0
- data/lib/badline/{storage/sid_file.rb → sid_tune/file.rb} +3 -3
- data/lib/badline/{storage → sid_tune}/hvsc.rb +7 -7
- data/lib/badline/{storage → sid_tune}/song_lengths.rb +2 -2
- data/lib/badline/{storage → sid_tune}/stil/credit.rb +1 -1
- data/lib/badline/{storage → sid_tune}/stil.rb +3 -3
- data/lib/badline/sid_tune.rb +6 -0
- data/lib/badline/snapshot/c128_setup.rb +43 -0
- data/lib/badline/snapshot/c64_setup.rb +79 -0
- data/lib/badline/snapshot/image.rb +5 -25
- data/lib/badline/snapshot/machine_state.rb +10 -2
- data/lib/badline/snapshot/setup.rb +22 -66
- data/lib/badline/snapshot/state.rb +8 -17
- data/lib/badline/snapshot/storage_setup.rb +68 -0
- data/lib/badline/snapshot/vic20_setup.rb +37 -0
- data/lib/badline/snapshot/vice/c64_mem.rb +1 -1
- data/lib/badline/snapshot/vice/restore.rb +1 -1
- data/lib/badline/snapshot/vice/reu1764.rb +1 -1
- data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
- data/lib/badline/snapshot/vice.rb +7 -5
- data/lib/badline/snapshot.rb +13 -12
- data/lib/badline/storage/d64_image.rb +15 -9
- data/lib/badline/storage/d71_image.rb +0 -2
- data/lib/badline/storage/d81_image.rb +0 -2
- data/lib/badline/storage/disk_image/writing.rb +2 -2
- data/lib/badline/storage/disk_image.rb +3 -6
- data/lib/badline/storage/g64_image.rb +2 -2
- data/lib/badline/storage/host_directory.rb +0 -5
- data/lib/badline/storage/t64.rb +2 -8
- data/lib/badline/storage/unavailable.rb +1 -1
- data/lib/badline/storage.rb +0 -37
- data/lib/badline/support/c128_checkpoint.rb +39 -0
- data/lib/badline/support/checkpoint.rb +108 -0
- data/lib/badline/support/vic20_checkpoint.rb +38 -0
- data/lib/badline/support.rb +5 -0
- data/lib/badline/version.rb +1 -1
- data/lib/badline/vic20/attachments.rb +11 -81
- data/lib/badline/vic20/bus/saved_state.rb +35 -0
- data/lib/badline/vic20/bus.rb +3 -25
- data/lib/badline/vic20/cpu.rb +1 -1
- data/lib/badline/vic20/port_wiring.rb +4 -4
- data/lib/badline/vic20/saved_state.rb +16 -60
- data/lib/badline/vic20/user_via_ports.rb +2 -2
- data/lib/badline/vic20.rb +20 -51
- metadata +250 -221
- data/lib/badline/address_bus/extra_sids.rb +0 -30
- data/lib/badline/address_bus/fittings.rb +0 -38
- data/lib/badline/address_bus/pla.rb +0 -147
- data/lib/badline/address_bus/roms.rb +0 -39
- data/lib/badline/address_bus/saved_state.rb +0 -72
- data/lib/badline/address_bus/sid_slots.rb +0 -42
- data/lib/badline/address_bus.rb +0 -235
- data/lib/badline/cartridge/action_replay.rb +0 -126
- data/lib/badline/cartridge/atomic_power.rb +0 -24
- data/lib/badline/cartridge/bank.rb +0 -81
- data/lib/badline/cartridge/comal80.rb +0 -50
- data/lib/badline/cartridge/dinamic.rb +0 -34
- data/lib/badline/cartridge/easy_flash.rb +0 -145
- data/lib/badline/cartridge/epyx_fastload.rb +0 -79
- data/lib/badline/cartridge/final_cartridge3.rb +0 -89
- data/lib/badline/cartridge/flash.rb +0 -306
- data/lib/badline/cartridge/freezer.rb +0 -33
- data/lib/badline/cartridge/fun_play.rb +0 -38
- data/lib/badline/cartridge/g_mod2.rb +0 -74
- data/lib/badline/cartridge/game_system.rb +0 -40
- data/lib/badline/cartridge/geo_ram.rb +0 -79
- data/lib/badline/cartridge/kcs_power.rb +0 -75
- data/lib/badline/cartridge/mach5.rb +0 -32
- data/lib/badline/cartridge/magic_desk.rb +0 -30
- data/lib/badline/cartridge/ocean.rb +0 -35
- data/lib/badline/cartridge/pagefox.rb +0 -68
- data/lib/badline/cartridge/retro_replay.rb +0 -320
- data/lib/badline/cartridge/rex_utility.rb +0 -29
- data/lib/badline/cartridge/rgcd.rb +0 -58
- data/lib/badline/cartridge/simons_basic.rb +0 -35
- data/lib/badline/cartridge/standard.rb +0 -15
- data/lib/badline/cartridge/super_games.rb +0 -48
- data/lib/badline/cartridge/westermann.rb +0 -30
- data/lib/badline/cartridge/zaxxon.rb +0 -66
- data/lib/badline/cartridge.rb +0 -303
- data/lib/badline/checkpoint.rb +0 -98
- data/lib/badline/cia/fast_forward.rb +0 -60
- data/lib/badline/cia/interrupt_register.rb +0 -143
- data/lib/badline/cia/serial.rb +0 -275
- data/lib/badline/cia/state.rb +0 -47
- data/lib/badline/cia/timer.rb +0 -206
- data/lib/badline/cia.rb +0 -279
- data/lib/badline/color_memory.rb +0 -25
- data/lib/badline/computer/kernal_traps.rb +0 -29
- data/lib/badline/control_ports.rb +0 -76
- data/lib/badline/cpu/addressing.rb +0 -131
- data/lib/badline/cpu/boundary.rb +0 -54
- data/lib/badline/cpu/core.rb +0 -165
- data/lib/badline/cpu/microcode.rb +0 -177
- data/lib/badline/cpu/operations.rb +0 -88
- data/lib/badline/cpu/saved_state.rb +0 -115
- data/lib/badline/cpu/stack_operations.rb +0 -82
- data/lib/badline/cpu.rb +0 -10
- data/lib/badline/cycleable.rb +0 -38
- data/lib/badline/datasette.rb +0 -161
- data/lib/badline/drive/core.rb +0 -147
- data/lib/badline/drive/fast_serial.rb +0 -73
- data/lib/badline/drive/idle.rb +0 -125
- data/lib/badline/drive/idle_cpu.rb +0 -28
- data/lib/badline/drive/orbit.rb +0 -79
- data/lib/badline/drive/serial_lines.rb +0 -73
- data/lib/badline/drive/sleep.rb +0 -112
- data/lib/badline/drive/vias.rb +0 -84
- data/lib/badline/drive/watch.rb +0 -150
- data/lib/badline/drive.rb +0 -11
- data/lib/badline/drive1541/bus.rb +0 -86
- data/lib/badline/drive1541/byte_ready.rb +0 -48
- data/lib/badline/drive1541/cpu.rb +0 -11
- data/lib/badline/drive1541/disk.rb +0 -318
- data/lib/badline/drive1541/disk_state.rb +0 -94
- data/lib/badline/drive1541/disk_via.rb +0 -36
- data/lib/badline/drive1541/gcr.rb +0 -57
- data/lib/badline/drive1541/mechanism.rb +0 -313
- data/lib/badline/drive1541/mechanism_state.rb +0 -68
- data/lib/badline/drive1541/rotation.rb +0 -121
- data/lib/badline/drive1541/sector_reader.rb +0 -76
- data/lib/badline/drive1541/serial_port.rb +0 -18
- data/lib/badline/drive1541/track.rb +0 -98
- data/lib/badline/drive1541.rb +0 -111
- data/lib/badline/drive1571/bus.rb +0 -111
- data/lib/badline/drive1571/cpu.rb +0 -11
- data/lib/badline/drive1571/serial_port.rb +0 -37
- data/lib/badline/drive1571/serial_via.rb +0 -25
- data/lib/badline/drive1571/wd1770.rb +0 -120
- data/lib/badline/drive1571.rb +0 -175
- data/lib/badline/drive1581/bus.rb +0 -137
- data/lib/badline/drive1581/cpu.rb +0 -11
- data/lib/badline/drive1581/disk.rb +0 -135
- data/lib/badline/drive1581/disk_state.rb +0 -87
- data/lib/badline/drive1581/mechanism.rb +0 -117
- data/lib/badline/drive1581/serial_port.rb +0 -52
- data/lib/badline/drive1581/slot.rb +0 -78
- data/lib/badline/drive1581/track.rb +0 -100
- data/lib/badline/drive1581/track_bytes.rb +0 -75
- data/lib/badline/drive1581/wd1772/registers.rb +0 -89
- data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
- data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
- data/lib/badline/drive1581/wd1772/state.rb +0 -66
- data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
- data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
- data/lib/badline/drive1581/wd1772/turn.rb +0 -73
- data/lib/badline/drive1581/wd1772.rb +0 -216
- data/lib/badline/drive1581.rb +0 -233
- data/lib/badline/iec_bus.rb +0 -159
- data/lib/badline/instruction.rb +0 -334
- data/lib/badline/instruction_set/arithmetic.rb +0 -114
- data/lib/badline/instruction_set/bitwise.rb +0 -126
- data/lib/badline/instruction_set/branch.rb +0 -79
- data/lib/badline/instruction_set/flag.rb +0 -63
- data/lib/badline/instruction_set/illegal.rb +0 -270
- data/lib/badline/instruction_set/inc_dec.rb +0 -69
- data/lib/badline/instruction_set/stack.rb +0 -52
- data/lib/badline/instruction_set/transfer.rb +0 -137
- data/lib/badline/instruction_set.rb +0 -55
- data/lib/badline/interrupts.rb +0 -104
- data/lib/badline/joystick.rb +0 -25
- data/lib/badline/kernal_trap/channel.rb +0 -181
- data/lib/badline/keyboard.rb +0 -112
- data/lib/badline/ram_expansion/banking.rb +0 -30
- data/lib/badline/ram_expansion/plus256k.rb +0 -54
- data/lib/badline/ram_expansion/plus60k.rb +0 -43
- data/lib/badline/ram_expansion/unexpanded.rb +0 -28
- data/lib/badline/ram_expansion.rb +0 -21
- data/lib/badline/reu/dma/saved_state.rb +0 -50
- data/lib/badline/reu/dma.rb +0 -273
- data/lib/badline/reu/ram.rb +0 -107
- data/lib/badline/reu/saved_state.rb +0 -80
- data/lib/badline/reu/trigger.rb +0 -32
- data/lib/badline/reu.rb +0 -289
- data/lib/badline/sid/catch_up.rb +0 -120
- data/lib/badline/sid/decimator.rb +0 -64
- data/lib/badline/sid/envelope/state.rb +0 -68
- data/lib/badline/sid/envelope.rb +0 -239
- data/lib/badline/sid/filter.rb +0 -263
- data/lib/badline/sid/voice.rb +0 -77
- data/lib/badline/sid/waveform/combined.rb +0 -126
- data/lib/badline/sid/waveform/fast_forward.rb +0 -105
- data/lib/badline/sid/waveform/noise_writeback.rb +0 -122
- data/lib/badline/sid/waveform/state.rb +0 -66
- data/lib/badline/sid/waveform.rb +0 -305
- data/lib/badline/sid.rb +0 -303
- data/lib/badline/time_of_day.rb +0 -228
- data/lib/badline/traps.rb +0 -19
- data/lib/badline/via/control_lines.rb +0 -122
- data/lib/badline/via/fast_forward.rb +0 -53
- data/lib/badline/via/interrupt_register.rb +0 -67
- data/lib/badline/via/shift_register.rb +0 -180
- data/lib/badline/via/state.rb +0 -42
- data/lib/badline/via/timer1.rb +0 -131
- data/lib/badline/via/timer2.rb +0 -133
- data/lib/badline/via.rb +0 -266
- data/lib/badline/vic/bank.rb +0 -133
- data/lib/badline/vic/border_mask.rb +0 -86
- data/lib/badline/vic/collisions.rb +0 -115
- data/lib/badline/vic/color_patches.rb +0 -47
- data/lib/badline/vic/display_state.rb +0 -185
- data/lib/badline/vic/graphics_mode.rb +0 -164
- data/lib/badline/vic/graphics_shifter.rb +0 -207
- data/lib/badline/vic/register_log.rb +0 -81
- data/lib/badline/vic/registers.rb +0 -195
- data/lib/badline/vic/sequencer.rb +0 -275
- data/lib/badline/vic/sequencer_output.rb +0 -116
- data/lib/badline/vic/sequencer_state.rb +0 -89
- data/lib/badline/vic/sprite/internal_bus.rb +0 -68
- data/lib/badline/vic/sprite/saved_state.rb +0 -64
- data/lib/badline/vic/sprite/shifter.rb +0 -146
- data/lib/badline/vic/sprite/timing.rb +0 -56
- data/lib/badline/vic/sprite.rb +0 -337
- data/lib/badline/vic/sprites.rb +0 -282
- data/lib/badline/vic/sprites_state.rb +0 -57
- data/lib/badline/vic.rb +0 -852
- data/lib/badline/vic20/sound/output.rb +0 -83
- data/lib/badline/vic20/sound.rb +0 -233
- data/lib/badline/z80/arithmetic.rb +0 -117
- data/lib/badline/z80/bit_page.rb +0 -55
- data/lib/badline/z80/block_io.rb +0 -58
- data/lib/badline/z80/block_transfers.rb +0 -59
- data/lib/badline/z80/bus_cycles.rb +0 -111
- data/lib/badline/z80/core.rb +0 -113
- data/lib/badline/z80/exchanges.rb +0 -50
- data/lib/badline/z80/extended_page.rb +0 -89
- data/lib/badline/z80/flags.rb +0 -37
- data/lib/badline/z80/interrupt_acceptance.rb +0 -46
- data/lib/badline/z80/jumps.rb +0 -82
- data/lib/badline/z80/loads.rb +0 -98
- data/lib/badline/z80/main_page.rb +0 -134
- data/lib/badline/z80/registers.rb +0 -120
- data/lib/badline/z80/saved_state.rb +0 -69
- data/lib/badline/z80/shifts.rb +0 -64
- data/lib/badline/z80.rb +0 -11
- /data/lib/badline/snapshot/{fields.rb → vice/fields.rb} +0 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module KernalTrap
|
|
5
|
+
class DOS
|
|
6
|
+
# One open channel on the virtual drive, holding a file, a block buffer
|
|
7
|
+
# or the command channel's status message. It gives out one byte at a
|
|
8
|
+
# time and flags the last one, so the bus can raise EOI with it. A
|
|
9
|
+
# channel cut short by a read error never flags one, and holds the
|
|
10
|
+
# error for the drive to report once its bytes run out.
|
|
11
|
+
class Channel
|
|
12
|
+
attr_accessor :buffer
|
|
13
|
+
attr_reader :error, :pointer
|
|
14
|
+
attr_writer :lead
|
|
15
|
+
|
|
16
|
+
def initialize(bytes = [], error: nil, writable: false, base: 0)
|
|
17
|
+
@base = base
|
|
18
|
+
replace(bytes)
|
|
19
|
+
@error = error
|
|
20
|
+
@writable = writable
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# A block buffer opened with "#", which reads and writes one of the
|
|
24
|
+
# drive's buffers in its RAM, so M-R and M-W reach the same bytes. It
|
|
25
|
+
# hands out the whole block unless a B-R sets a shorter end, and
|
|
26
|
+
# flags that byte as the last. The DOS opens it with the pointer at 1
|
|
27
|
+
# and the buffer's number as the byte to send, so the first read
|
|
28
|
+
# answers with the number and the next one moves on to the third
|
|
29
|
+
# byte.
|
|
30
|
+
def self.buffer(memory, number)
|
|
31
|
+
new(memory.ram, writable: true, base: Memory.buffer_address(number)).tap do |channel|
|
|
32
|
+
channel.buffer = number
|
|
33
|
+
channel.rewind(BLOCK_SIZE)
|
|
34
|
+
channel.pointer = 1
|
|
35
|
+
channel.lead = number
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# A file's bytes, up to the first block its chain can't read. The
|
|
40
|
+
# drive reads a block ahead before sending the last byte of the one
|
|
41
|
+
# before, so a bad block holds that byte back too, and a bad first
|
|
42
|
+
# block or a missing file leaves nothing to send.
|
|
43
|
+
def self.for_file(storage, name, type)
|
|
44
|
+
data = storage.read_file(name, type:)
|
|
45
|
+
return new([], error: [FILE_NOT_FOUND]) unless data
|
|
46
|
+
|
|
47
|
+
failure = storage.respond_to?(:read_error) && storage.read_error(name, type:)
|
|
48
|
+
return new(data) unless failure
|
|
49
|
+
|
|
50
|
+
new(data[0, failure[:offset] - 1] || [], error: failure.values_at(:error, :track, :sector))
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# The file an open names. The drive keeps the first block of the file
|
|
54
|
+
# a LOAD (secondary address 0) opens at $7E and $026F of its memory,
|
|
55
|
+
# and a LOAD of a name starting with "*" reopens that file rather than
|
|
56
|
+
# the first one on the disk. Loaders write the block there with M-W
|
|
57
|
+
# to load a file the directory doesn't list. A LOAD of "$" reads the
|
|
58
|
+
# directory as a BASIC program, which a pattern after a colon narrows
|
|
59
|
+
# to the files it names.
|
|
60
|
+
def self.for_name(storage, memory, secondary, name, type)
|
|
61
|
+
return new(storage.directory.bytes(name)) if listing?(storage, secondary, name)
|
|
62
|
+
|
|
63
|
+
file = Storage.parse_name(name).first
|
|
64
|
+
return for_file(storage, file, type) unless secondary.zero? && storage.respond_to?(:first_block)
|
|
65
|
+
|
|
66
|
+
last = memory.last_program if name.start_with?("*")
|
|
67
|
+
return at_block(storage, *last) if last
|
|
68
|
+
|
|
69
|
+
block = storage.first_block(file, type:)
|
|
70
|
+
memory.last_program = block if block
|
|
71
|
+
for_file(storage, file, type)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def self.listing?(storage, secondary, name)
|
|
75
|
+
secondary.zero? && name.start_with?("$") && storage.respond_to?(:directory)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# The file whose chain starts at the block.
|
|
79
|
+
def self.at_block(storage, track, sector)
|
|
80
|
+
data = storage.read_file_at(track, sector)
|
|
81
|
+
data ? new(data) : new([], error: [ILLEGAL_TRACK_OR_SECTOR, track, sector])
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Reads what save_state wrote after the flag that marks a file open
|
|
85
|
+
# for writing (Channels.channel_from_state). A buffer channel
|
|
86
|
+
# takes its block in `ram`, the drive's RAM, again.
|
|
87
|
+
def self.from_state(input, ram)
|
|
88
|
+
new.tap { |channel| channel.load_state(input, ram) }
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# A buffer channel's bytes are the drive's RAM, which the drive
|
|
92
|
+
# writes itself.
|
|
93
|
+
def save_state(out)
|
|
94
|
+
out.boolean(false).boolean(@writable).int(@base).int(@length).int(@pointer)
|
|
95
|
+
out.optional_int(@lead).optional_int(@buffer).boolean(!@error.nil?)
|
|
96
|
+
out.ints(@error) if @error
|
|
97
|
+
out.blob(@bytes) unless @writable
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def load_state(input, ram)
|
|
101
|
+
@writable = input.boolean?
|
|
102
|
+
@base = input.int
|
|
103
|
+
@length = input.int
|
|
104
|
+
@pointer = input.int
|
|
105
|
+
@lead = input.optional_int
|
|
106
|
+
@buffer = input.optional_int
|
|
107
|
+
@error = input.boolean? ? input.ints : nil
|
|
108
|
+
@bytes = @writable ? ram : input.blob
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def replace(bytes, length = bytes.length)
|
|
112
|
+
@bytes = bytes
|
|
113
|
+
rewind(length)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def rewind(length)
|
|
117
|
+
@length = length
|
|
118
|
+
self.pointer = 0
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def pointer=(position)
|
|
122
|
+
@pointer = position
|
|
123
|
+
@lead = nil
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# A block read into the channel. A buffer channel takes it into its
|
|
127
|
+
# buffer, a file channel hands it out in place of the file.
|
|
128
|
+
def load(block, length)
|
|
129
|
+
return replace(block.dup, length) unless @writable
|
|
130
|
+
|
|
131
|
+
@bytes[@base, block.length] = block
|
|
132
|
+
rewind(length)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def writable? = @writable
|
|
136
|
+
|
|
137
|
+
# A buffer channel's block, as a block write puts it on the disk.
|
|
138
|
+
def block = @bytes[@base, BLOCK_SIZE]
|
|
139
|
+
|
|
140
|
+
def exhausted?
|
|
141
|
+
@pointer >= @length
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# A file that holds nothing but its error never opened.
|
|
145
|
+
def failed?
|
|
146
|
+
exhausted? && !@error.nil?
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Each byte lands at the pointer, which wraps within the block.
|
|
150
|
+
def write(bytes)
|
|
151
|
+
@lead = nil
|
|
152
|
+
bytes.each do |byte|
|
|
153
|
+
@bytes[@base + @pointer] = byte
|
|
154
|
+
@pointer = (@pointer + 1) & 0xff
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def read
|
|
159
|
+
return read_buffer if @writable
|
|
160
|
+
return if exhausted?
|
|
161
|
+
|
|
162
|
+
byte = @lead || @bytes[@base + @pointer]
|
|
163
|
+
@lead = nil
|
|
164
|
+
@pointer += 1
|
|
165
|
+
[byte, exhausted? && !@error]
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
private
|
|
169
|
+
|
|
170
|
+
# A buffer never runs out. Past its last byte, which goes out with
|
|
171
|
+
# EOI, the pointer wraps back to the second, and a pointer set past
|
|
172
|
+
# the end runs on around the block to it.
|
|
173
|
+
def read_buffer
|
|
174
|
+
byte = @lead || @bytes[@base + @pointer]
|
|
175
|
+
@lead = nil
|
|
176
|
+
last = @pointer == @length - 1
|
|
177
|
+
@pointer = last ? 1 : (@pointer + 1) & 0xff
|
|
178
|
+
[byte, last]
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Badline
|
|
4
4
|
module KernalTrap
|
|
5
|
-
class
|
|
5
|
+
class DOS
|
|
6
6
|
# The drive's open data channels by secondary address, and the five
|
|
7
7
|
# buffers they hold. The DOS hands out the highest free buffer.
|
|
8
8
|
# Reading the BAM when it initializes the disk takes buffer 4, so
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Badline
|
|
4
4
|
module KernalTrap
|
|
5
|
-
class
|
|
5
|
+
class DOS
|
|
6
6
|
# The drive's 2K of RAM, as M-W and M-R reach it, with the job queue
|
|
7
7
|
# that runs a read job written into it: a job code for each of five
|
|
8
8
|
# buffers at $00, their track and sector pairs from $06, and the
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Badline
|
|
4
4
|
module KernalTrap
|
|
5
|
-
class
|
|
5
|
+
class DOS
|
|
6
6
|
# The numbers a DOS command takes. The DOS skips spaces, commas and
|
|
7
7
|
# cursor-rights before a parameter, reads it from the characters $30
|
|
8
8
|
# to $3F that follow, the low nibble of each, and skips whatever
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Badline
|
|
4
4
|
module KernalTrap
|
|
5
|
-
class
|
|
5
|
+
class DOS
|
|
6
6
|
# A channel open for writing a file. It gathers the bytes sent to it,
|
|
7
7
|
# and the drive writes the file to the disk when the channel closes.
|
|
8
8
|
# An append starts from the file's end, a replace writes over the
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Badline
|
|
4
4
|
module KernalTrap
|
|
5
|
-
class
|
|
5
|
+
class DOS
|
|
6
6
|
# Opens for writing, the S command and the reports a write makes. A
|
|
7
7
|
# file open for writing takes the type its name asks for, or SEQ on a
|
|
8
8
|
# data channel. On a write-protected disk, or storage that doesn't
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "badline/kernal_trap/
|
|
4
|
-
require "badline/kernal_trap/
|
|
5
|
-
require "badline/kernal_trap/
|
|
6
|
-
require "badline/kernal_trap/
|
|
7
|
-
require "badline/kernal_trap/
|
|
8
|
-
require "badline/kernal_trap/
|
|
9
|
-
require "badline/kernal_trap/
|
|
3
|
+
require "badline/kernal_trap/dos/block_commands"
|
|
4
|
+
require "badline/kernal_trap/dos/channel"
|
|
5
|
+
require "badline/kernal_trap/dos/channels"
|
|
6
|
+
require "badline/kernal_trap/dos/memory"
|
|
7
|
+
require "badline/kernal_trap/dos/parameters"
|
|
8
|
+
require "badline/kernal_trap/dos/status"
|
|
9
|
+
require "badline/kernal_trap/dos/writes"
|
|
10
|
+
require "badline/kernal_trap/dos/write_file"
|
|
10
11
|
|
|
11
12
|
module Badline
|
|
12
13
|
module KernalTrap
|
|
@@ -16,7 +17,7 @@ module Badline
|
|
|
16
17
|
# LOAD. A disk image whose host file takes writes takes files, blocks
|
|
17
18
|
# and BAM changes too. Other disks are write-protected, though storage
|
|
18
19
|
# that can write files still takes a SAVE handed over whole.
|
|
19
|
-
class
|
|
20
|
+
class DOS
|
|
20
21
|
include BlockCommands
|
|
21
22
|
include Writes
|
|
22
23
|
|
|
@@ -146,10 +147,10 @@ module Badline
|
|
|
146
147
|
# vector, as U: does.
|
|
147
148
|
def reset! = reset(cold: true)
|
|
148
149
|
|
|
149
|
-
# The mounted storage's setup
|
|
150
|
+
# The mounted storage's setup (Snapshot::StorageSetup), then the drive's
|
|
150
151
|
# RAM, its status and its open channels.
|
|
151
152
|
def save_state(out)
|
|
152
|
-
@storage
|
|
153
|
+
Snapshot::StorageSetup.write(@storage, out)
|
|
153
154
|
out.marker("TRAP DRIVE")
|
|
154
155
|
@memory.save_state(out)
|
|
155
156
|
@status.save_state(out)
|
|
@@ -12,7 +12,7 @@ module Badline
|
|
|
12
12
|
# below $0334, into the zero page, the stack or the KERNAL vectors: the
|
|
13
13
|
# ROM's byte loop then loads it through the serial traps, and a loader
|
|
14
14
|
# that overwrites ISTOP takes over mid-load as it does on a real drive.
|
|
15
|
-
class Load <
|
|
15
|
+
class Load < FileRoutine
|
|
16
16
|
# ST bits at $90
|
|
17
17
|
EOI = 0x40
|
|
18
18
|
VERIFY_MISMATCH = 0x10
|
|
@@ -23,9 +23,9 @@ module Badline
|
|
|
23
23
|
# address even when the first one relocated.
|
|
24
24
|
LOAD_SECONDARY = 0x60
|
|
25
25
|
|
|
26
|
-
def initialize(cpu:, bus:, layout:,
|
|
26
|
+
def initialize(cpu:, bus:, layout:, dos:)
|
|
27
27
|
super(cpu:, bus:, layout:)
|
|
28
|
-
@
|
|
28
|
+
@dos = dos
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def call
|
|
@@ -38,7 +38,7 @@ module Badline
|
|
|
38
38
|
|
|
39
39
|
data, complete = receive(name)
|
|
40
40
|
if low_memory?(data)
|
|
41
|
-
@
|
|
41
|
+
@dos.close(0)
|
|
42
42
|
else
|
|
43
43
|
finish(data, complete)
|
|
44
44
|
end
|
|
@@ -50,10 +50,10 @@ module Badline
|
|
|
50
50
|
# flagged EOI. A read error in the file's chain stops the bytes early,
|
|
51
51
|
# with no EOI.
|
|
52
52
|
def receive(name)
|
|
53
|
-
@
|
|
53
|
+
@dos.open(0, name)
|
|
54
54
|
data = []
|
|
55
55
|
loop do
|
|
56
|
-
byte, eoi = @
|
|
56
|
+
byte, eoi = @dos.read(0)
|
|
57
57
|
return [data, false] unless byte
|
|
58
58
|
|
|
59
59
|
data << byte
|
|
@@ -15,15 +15,15 @@ module Badline
|
|
|
15
15
|
# write: the drive stops listening, so ST reads DEVICE NOT PRESENT,
|
|
16
16
|
# and the ROM returns without an error. A "@" before the drive prefix
|
|
17
17
|
# writes over a file of the same name.
|
|
18
|
-
class Save <
|
|
18
|
+
class Save < FileRoutine
|
|
19
19
|
SECONDARY = 0x61
|
|
20
20
|
|
|
21
21
|
# ST bit at $90
|
|
22
22
|
DEVICE_NOT_PRESENT = 0x80
|
|
23
23
|
|
|
24
|
-
def initialize(cpu:, bus:, layout:,
|
|
24
|
+
def initialize(cpu:, bus:, layout:, dos:)
|
|
25
25
|
super(cpu:, bus:, layout:)
|
|
26
|
-
@
|
|
26
|
+
@dos = dos
|
|
27
27
|
@saving = false
|
|
28
28
|
end
|
|
29
29
|
|
|
@@ -38,7 +38,7 @@ module Badline
|
|
|
38
38
|
def call
|
|
39
39
|
return unless active?
|
|
40
40
|
return finish if @saving
|
|
41
|
-
return unless @
|
|
41
|
+
return unless @dos.saves?
|
|
42
42
|
|
|
43
43
|
@bus.poke(0xb9, SECONDARY)
|
|
44
44
|
return @cpu.program_counter = @layout.missing_file_name_exit if name.empty?
|
|
@@ -56,7 +56,7 @@ module Badline
|
|
|
56
56
|
|
|
57
57
|
def finish
|
|
58
58
|
@saving = false
|
|
59
|
-
saved = @
|
|
59
|
+
saved = @dos.save(name, payload, replace: full_filename.start_with?("@"))
|
|
60
60
|
@bus.poke(0x90, DEVICE_NOT_PRESENT) unless saved
|
|
61
61
|
@bus.poke(0xac, @bus.peek(0xae))
|
|
62
62
|
@bus.poke(0xad, @bus.peek(0xaf))
|
|
@@ -23,9 +23,9 @@ module Badline
|
|
|
23
23
|
|
|
24
24
|
NO_DATA = [0x0d, EOI | READ_TIMEOUT].freeze
|
|
25
25
|
|
|
26
|
-
def initialize(cpu:, bus:, layout:,
|
|
26
|
+
def initialize(cpu:, bus:, layout:, dos:, device: DEVICE)
|
|
27
27
|
super(cpu:, bus:, layout:)
|
|
28
|
-
@
|
|
28
|
+
@dos = dos
|
|
29
29
|
@device = device
|
|
30
30
|
@listening = false
|
|
31
31
|
@talking = false
|
|
@@ -144,7 +144,7 @@ module Badline
|
|
|
144
144
|
# takes data only on a channel it has open. Otherwise nothing holds
|
|
145
145
|
# the data line when a byte starts, so the KERNAL finds no device.
|
|
146
146
|
def accepted?
|
|
147
|
-
[OPEN, CLOSE].include?(@frame) || @
|
|
147
|
+
[OPEN, CLOSE].include?(@frame) || @dos.listening?(@listen_channel)
|
|
148
148
|
end
|
|
149
149
|
|
|
150
150
|
def unlisten
|
|
@@ -188,15 +188,15 @@ module Badline
|
|
|
188
188
|
return unless @listen_channel
|
|
189
189
|
|
|
190
190
|
case @frame
|
|
191
|
-
when OPEN then @
|
|
192
|
-
when CLOSE then @
|
|
193
|
-
else @
|
|
191
|
+
when OPEN then @dos.open(@listen_channel, @buffer.pack("C*"))
|
|
192
|
+
when CLOSE then @dos.close(@listen_channel)
|
|
193
|
+
else @dos.write(@listen_channel, @buffer)
|
|
194
194
|
end
|
|
195
195
|
@buffer = []
|
|
196
196
|
end
|
|
197
197
|
|
|
198
198
|
def received
|
|
199
|
-
byte, eoi = @
|
|
199
|
+
byte, eoi = @dos.read(@talk_channel)
|
|
200
200
|
return NO_DATA unless byte
|
|
201
201
|
|
|
202
202
|
[byte, eoi ? EOI : 0]
|
data/lib/badline/kernal_trap.rb
CHANGED
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
require "badline/kernal_trap/layout"
|
|
4
4
|
require "badline/kernal_trap/routine"
|
|
5
|
-
require "badline/kernal_trap/
|
|
6
|
-
require "badline/kernal_trap/
|
|
7
|
-
require "badline/kernal_trap/file"
|
|
5
|
+
require "badline/kernal_trap/dos"
|
|
6
|
+
require "badline/kernal_trap/file_routine"
|
|
8
7
|
require "badline/kernal_trap/load"
|
|
9
8
|
require "badline/kernal_trap/save"
|
|
10
9
|
require "badline/kernal_trap/serial"
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Machine
|
|
5
|
+
# Running a machine from outside its own #cycle!, and the handlers that
|
|
6
|
+
# wait for its KERNAL to boot. C64, Vic20 and C128 each include it
|
|
7
|
+
# and answer #cycle!, #cycles and #init_threshold, the cycle at which
|
|
8
|
+
# #on_init's handlers run, and keep the handlers in @init_handlers.
|
|
9
|
+
module Clocking
|
|
10
|
+
# Runs `count` cycles, one #cycle! after another.
|
|
11
|
+
def run_cycles(count)
|
|
12
|
+
i = 0
|
|
13
|
+
while i < count
|
|
14
|
+
cycle!
|
|
15
|
+
i += 1
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Runs cycles until the block returns true or the cycle count passes
|
|
20
|
+
# `limit`, checking before each cycle.
|
|
21
|
+
def run_until(limit)
|
|
22
|
+
cycle! until yield || @cycles > limit
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Runs the block once the KERNAL has booted (see init_threshold), or
|
|
26
|
+
# now if it has.
|
|
27
|
+
def on_init(&block)
|
|
28
|
+
if booting?
|
|
29
|
+
@init_handlers << block
|
|
30
|
+
else
|
|
31
|
+
block.call
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def inspect
|
|
36
|
+
"#<#{self.class.name} cycles=#{@cycles} cpu=(#{@cpu.inspect})>"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def booting?
|
|
42
|
+
@cycles < init_threshold
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def handle_init
|
|
46
|
+
@init_handlers.each(&:call)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
data/lib/badline/machine.rb
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "badline/machine/clocking"
|
|
4
|
+
|
|
3
5
|
module Badline
|
|
4
6
|
# = Machine
|
|
5
7
|
#
|
|
6
8
|
# The machines badline builds by family, as the command line's
|
|
7
|
-
# subcommand names them: the C64,
|
|
9
|
+
# subcommand names them: the C64, Badline::C64, the VIC-20, Vic20, and the
|
|
8
10
|
# C128 in C64 mode, C128.
|
|
9
11
|
#
|
|
10
12
|
# A machine answers what the front end, Media, the runners and the
|
|
@@ -26,7 +28,7 @@ module Badline
|
|
|
26
28
|
# +press_cartridge_button+, +release_cartridge_button+,
|
|
27
29
|
# +attach_drive1541+, +drive1541+, +true_drive+ and +plug_true_drive+
|
|
28
30
|
# for the drive Media::TrueDrive plugs in, +attach_drive1581+,
|
|
29
|
-
# +drive1581+ and +plug_drive1581+ for a 1581 (
|
|
31
|
+
# +drive1581+ and +plug_drive1581+ for a 1581 (Drives::Model1581::Slot), and
|
|
30
32
|
# +address_bus+ for its +cartridge+ and +detach_cartridge+.
|
|
31
33
|
# - Snapshots and tests: +snapshot+, +restore+, +save_snapshot+,
|
|
32
34
|
# +install_debug_register+ and +capture_output+.
|
|
@@ -44,22 +46,48 @@ module Badline
|
|
|
44
46
|
# +press_caps_lock+, +release_caps_lock+, +press_display_key+,
|
|
45
47
|
# +release_display_key+, and +attach_drive1571+ and +drive1571+ for the
|
|
46
48
|
# C128D's 1571, its true drive.
|
|
49
|
+
#
|
|
50
|
+
# Each machine includes Machine::Clocking for the clocking part.
|
|
47
51
|
module Machine
|
|
52
|
+
# Media the machine named doesn't take.
|
|
53
|
+
class Unsupported < ArgumentError; end
|
|
54
|
+
|
|
48
55
|
# A new machine of `family`, :c64, :vic20 or :c128, the model of it
|
|
49
56
|
# `model` names. A C64's model is one of Model::ALL, with its SID
|
|
50
57
|
# `sid_model` when not nil and an REU of `reu` K when not nil. A
|
|
51
58
|
# VIC-20's is "pal", with the RAM expansion `ram` names
|
|
52
59
|
# (Vic20::Bus::RAM_CONFIGURATIONS), unexpanded when nil. A C128's is
|
|
53
|
-
# one of C128::Model::ALL, with its SID `sid_model` when not nil
|
|
60
|
+
# one of C128::Model::ALL, with its SID `sid_model` when not nil, built
|
|
61
|
+
# for C64 mode.
|
|
54
62
|
def self.build(family, model:, sid_model: nil, reu: nil, ram: nil)
|
|
55
63
|
return vic20(model, ram) if family == :vic20
|
|
56
|
-
return
|
|
64
|
+
return c128(model, sid_model, :c64) if family == :c128
|
|
57
65
|
raise ArgumentError, "no machine family named #{family}" unless family == :c64
|
|
58
66
|
|
|
59
67
|
profile = Model.named(model)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
68
|
+
C64.new(vic_model: profile.vic_model, cia_model: profile.cia_model,
|
|
69
|
+
sid_model: sid_model || profile.sid_model, region: profile.region, reu:,
|
|
70
|
+
kernal: profile.kernal, datasette: profile.datasette, board: profile.board)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# The machine the command line's `options` name, to start `media`, a
|
|
74
|
+
# path or nil. A C64 or a C128 without a SID named takes the one a .sid
|
|
75
|
+
# tune names. The C128 is built for C128 mode, with C= held through the
|
|
76
|
+
# reset, so its KERNAL starts C64 mode, for --c64 (+c64_mode?+) or media
|
|
77
|
+
# only C64 mode runs: a .sid tune or a program that loads at the C64's
|
|
78
|
+
# BASIC start. A VIC-20 without RAM named gets the expansion the media
|
|
79
|
+
# needs (Media::Vic20Media.ram_for) and yields a line saying so. Raises
|
|
80
|
+
# Unsupported for media a VIC-20 doesn't take.
|
|
81
|
+
def self.for_options(options, media, &)
|
|
82
|
+
family = options.family
|
|
83
|
+
return vic20_for(media, options.model, options.ram, &) if family == :vic20
|
|
84
|
+
|
|
85
|
+
sid_model = options.sid_model || Media.sid_model(media, otherwise: nil)
|
|
86
|
+
return build(:c64, model: options.model, sid_model:, reu: options.reu) unless family == :c128
|
|
87
|
+
|
|
88
|
+
machine = c128(options.model, sid_model, :c128)
|
|
89
|
+
machine.hold_commodore_key if options.c64_mode? || c64_media?(media)
|
|
90
|
+
machine
|
|
63
91
|
end
|
|
64
92
|
|
|
65
93
|
def self.vic20(model, ram)
|
|
@@ -68,5 +96,33 @@ module Badline
|
|
|
68
96
|
Vic20.new(ram: ram || :unexpanded)
|
|
69
97
|
end
|
|
70
98
|
private_class_method :vic20
|
|
99
|
+
|
|
100
|
+
def self.c128(model, sid_model, mode) = C128.new(model:, sid_model:, mode:)
|
|
101
|
+
private_class_method :c128
|
|
102
|
+
|
|
103
|
+
def self.vic20_for(media, model, ram)
|
|
104
|
+
unless media.nil?
|
|
105
|
+
unsupported = Media::Vic20Media::UNSUPPORTED.include?(File.extname(media).downcase)
|
|
106
|
+
raise Unsupported, "doesn't go in a VIC-20" if unsupported
|
|
107
|
+
|
|
108
|
+
unless ram
|
|
109
|
+
ram = Media::Vic20Media.ram_for(media)
|
|
110
|
+
yield "RAM expansion: #{ram}"
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
build(:vic20, model:, ram:)
|
|
114
|
+
end
|
|
115
|
+
private_class_method :vic20_for
|
|
116
|
+
|
|
117
|
+
def self.c64_media?(media)
|
|
118
|
+
return false if media.nil? || !File.file?(media)
|
|
119
|
+
|
|
120
|
+
extension = File.extname(media).downcase
|
|
121
|
+
return true if extension == ".sid"
|
|
122
|
+
return false unless %w[.prg .p00].include?(extension)
|
|
123
|
+
|
|
124
|
+
[Media::BASIC_START, Media::BASIC_START - 1].include?(Storage::P00.load_address(media))
|
|
125
|
+
end
|
|
126
|
+
private_class_method :c64_media?
|
|
71
127
|
end
|
|
72
128
|
end
|
|
@@ -15,7 +15,7 @@ module Badline
|
|
|
15
15
|
module BootDisk
|
|
16
16
|
SIGNATURE = "CBM".bytes.freeze
|
|
17
17
|
AUTO_BOOT = "copyright cbm 86"
|
|
18
|
-
TYPES = %
|
|
18
|
+
TYPES = Extensions.of(%i[disk])
|
|
19
19
|
|
|
20
20
|
class << self
|
|
21
21
|
def takes?(computer, path)
|
|
@@ -38,7 +38,7 @@ module Badline
|
|
|
38
38
|
type = File.extname(path).downcase
|
|
39
39
|
return false unless TYPES.include?(type) && File.file?(path)
|
|
40
40
|
|
|
41
|
-
image =
|
|
41
|
+
image = Media.open_storage(path, { read_only: true })
|
|
42
42
|
block = image.read_block(1, 0)
|
|
43
43
|
return true if block && block[0, 3] == SIGNATURE
|
|
44
44
|
|
|
@@ -11,9 +11,9 @@ module Badline
|
|
|
11
11
|
# A list naming no disk image that's there.
|
|
12
12
|
class Error < ArgumentError; end
|
|
13
13
|
|
|
14
|
-
EXTENSIONS = %
|
|
14
|
+
EXTENSIONS = Extensions.of(%i[disk_list])
|
|
15
15
|
|
|
16
|
-
def self.list?(path) =
|
|
16
|
+
def self.list?(path) = Extensions.kind(path) == :disk_list
|
|
17
17
|
|
|
18
18
|
# The disk `path` puts in the drive: a list's first disk, or the
|
|
19
19
|
# path itself.
|
|
@@ -32,7 +32,7 @@ module Badline
|
|
|
32
32
|
found = []
|
|
33
33
|
entries(list).each do |entry|
|
|
34
34
|
disk = entry.start_with?("/") ? entry : File.join(directory, entry)
|
|
35
|
-
found << disk if
|
|
35
|
+
found << disk if Extensions::DISKS.include?(File.extname(disk).downcase) && File.file?(disk)
|
|
36
36
|
end
|
|
37
37
|
found
|
|
38
38
|
end
|
|
@@ -13,7 +13,7 @@ module Badline
|
|
|
13
13
|
# ahead of the names.
|
|
14
14
|
module DiskSet
|
|
15
15
|
KINDS = %w[disk disc side part].freeze
|
|
16
|
-
EXTENSIONS =
|
|
16
|
+
EXTENSIONS = Extensions::DISKS
|
|
17
17
|
|
|
18
18
|
# The paths of the set's disks in order, or just `path` when it
|
|
19
19
|
# belongs to none. A list's set is the disks it lists.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Media
|
|
5
|
+
# The kind of medium each file extension names, which every check of a
|
|
6
|
+
# path's extension reads. A file with any other extension is a program.
|
|
7
|
+
# It loads on its own, for Options.
|
|
8
|
+
#
|
|
9
|
+
# - :disk, a disk image that the traps mount and a true drive reads
|
|
10
|
+
# - :gcr, a disk's raw GCR, which only a true drive reads
|
|
11
|
+
# - :archive, a .t64, which the traps mount read-only
|
|
12
|
+
# - :tape, :cartridge and :tune
|
|
13
|
+
# - :disk_list, a list of the disks of a set (DiskList)
|
|
14
|
+
module Extensions
|
|
15
|
+
KINDS = {
|
|
16
|
+
".d64" => :disk, ".d71" => :disk, ".d81" => :disk, ".g64" => :gcr, ".g71" => :gcr, ".t64" => :archive,
|
|
17
|
+
".tap" => :tape, ".crt" => :cartridge, ".sid" => :tune, ".m3u" => :disk_list, ".vfl" => :disk_list
|
|
18
|
+
}.freeze
|
|
19
|
+
|
|
20
|
+
# The kind of the medium at `path`, by its extension.
|
|
21
|
+
def self.kind(path) = KINDS.fetch(File.extname(path).downcase, :program)
|
|
22
|
+
|
|
23
|
+
# The extensions of the kinds given.
|
|
24
|
+
def self.of(kinds) = KINDS.keys.select { |extension| kinds.include?(KINDS[extension]) }.freeze
|
|
25
|
+
|
|
26
|
+
# Disk images, which a drive reads.
|
|
27
|
+
DISKS = of(%i[disk gcr])
|
|
28
|
+
|
|
29
|
+
# What goes in device 8 through the traps.
|
|
30
|
+
MOUNTABLE = of(%i[disk archive])
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|