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,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Media
|
|
5
|
+
# A program loading into a C64 or a C128 once it has booted
|
|
6
|
+
# (Media.attach). The VIC-20 has its own (Vic20Basic).
|
|
7
|
+
module Program
|
|
8
|
+
class << self
|
|
9
|
+
# Loads the program where it says, and RUNs one that loads at the
|
|
10
|
+
# start of BASIC.
|
|
11
|
+
def load(computer, data, autostart:)
|
|
12
|
+
load_addr = computer.load_prg(data)
|
|
13
|
+
# Run only makes sense for programs at BASIC start, or a byte ahead
|
|
14
|
+
# of it, where BASIC keeps the zero before its first line. BASIC 7.0
|
|
15
|
+
# starts at $1C01 and keeps the end of its text at $1210.
|
|
16
|
+
start, text_end = computer.family == :c128 && computer.mode == :c128 ? [0x1c01, 0x1210] : [BASIC_START, 0x2d]
|
|
17
|
+
return unless autostart && (load_addr == start || load_addr == start - 1)
|
|
18
|
+
|
|
19
|
+
# The end of the program, where BASIC's variables start, and where
|
|
20
|
+
# the KERNAL's LOAD leaves its end address.
|
|
21
|
+
end_addr = load_addr + data.length - 2
|
|
22
|
+
[text_end, 0xae].each { |pointer| computer.ram.write(pointer, [end_addr & 0xff, end_addr >> 8]) }
|
|
23
|
+
computer.type_text("run\r")
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -9,7 +9,7 @@ module Badline
|
|
|
9
9
|
# disk's raw GCR, which only a true drive reads, so it plugs one in
|
|
10
10
|
# when there's none yet. The 1541 reads only .d64 and .g64 images, the
|
|
11
11
|
# 1571 .d71 and .g71 as well, and the 1581 only .d81, so a .d81 swaps
|
|
12
|
-
# the drive on device 8 for a 1581 (
|
|
12
|
+
# the drive on device 8 for a 1581 (Drives::Model1581::Slot), and another disk
|
|
13
13
|
# image swaps a 1581 back for the machine's own drive. The traps' other
|
|
14
14
|
# disk media, a .t64 or a host directory, raise Error.
|
|
15
15
|
module TrueDrive
|
|
@@ -32,9 +32,10 @@ module Badline
|
|
|
32
32
|
# other disk media, which the traps would mount, when a true drive
|
|
33
33
|
# is device 8.
|
|
34
34
|
def takes?(computer, path)
|
|
35
|
-
|
|
35
|
+
kind = Extensions.kind(path)
|
|
36
|
+
return true if kind == :gcr
|
|
36
37
|
|
|
37
|
-
!drive(computer).nil? && (File.directory?(path) ||
|
|
38
|
+
!drive(computer).nil? && (File.directory?(path) || %i[disk archive].include?(kind))
|
|
38
39
|
end
|
|
39
40
|
|
|
40
41
|
# Puts the image in the drive on device 8, plugging one in that
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Media
|
|
5
|
+
# A .sid tune on a machine with a SID (Media.attach): its data and the
|
|
6
|
+
# player the tune boots with go in RAM once the KERNAL has booted, and
|
|
7
|
+
# the autostart types what starts it.
|
|
8
|
+
module Tune
|
|
9
|
+
class << self
|
|
10
|
+
# Plays `subtune`, or the tune's own start subtune, and says what
|
|
11
|
+
# plays. A tune for more than one SID raises FormatError.
|
|
12
|
+
def attach(computer, path, autostart:, subtune:)
|
|
13
|
+
tune = SIDTune::File.new(path)
|
|
14
|
+
if tune.sids > 1
|
|
15
|
+
raise SIDTune::File::FormatError, "Written for #{tune.sids} SIDs, which only the SID player plays"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
subtune = (subtune || tune.start_subtune).clamp(1, tune.subtunes)
|
|
19
|
+
computer.on_init { start(computer, tune, autostart:, subtune:) }
|
|
20
|
+
title = tune.name.empty? ? path : tune.name
|
|
21
|
+
title += " (subtune #{subtune})" if tune.subtunes > 1
|
|
22
|
+
autostart ? "Playing #{title}" : "Loaded #{title}"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def start(computer, tune, autostart:, subtune:)
|
|
28
|
+
computer.ram.write(tune.load_address, tune.data)
|
|
29
|
+
tune.boot_memory(subtune:).each { |address, bytes| computer.ram.write(address, bytes) }
|
|
30
|
+
computer.type_text(tune.boot_command) if autostart
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -26,12 +26,6 @@ module Badline
|
|
|
26
26
|
parts.map { |part| rom_chip(part) }
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
-
# A program's bytes, unwrapped from a .p00.
|
|
30
|
-
def program_bytes(path)
|
|
31
|
-
bytes = File.binread(path).bytes
|
|
32
|
-
Storage::P00.wraps?(bytes) ? Storage::P00.data(bytes) : bytes
|
|
33
|
-
end
|
|
34
|
-
|
|
35
29
|
private
|
|
36
30
|
|
|
37
31
|
def load_address(data)
|
|
@@ -42,7 +36,7 @@ module Badline
|
|
|
42
36
|
name = part_names(path, own, address).find { |candidate| File.file?(candidate) }
|
|
43
37
|
return unless name
|
|
44
38
|
|
|
45
|
-
part = program_bytes(name)
|
|
39
|
+
part = Media.program_bytes(name)
|
|
46
40
|
part if load_address(part) == address
|
|
47
41
|
end
|
|
48
42
|
|
|
@@ -2,45 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
module Badline
|
|
4
4
|
module Media
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
# RUNs. A program that loads into
|
|
8
|
-
# instead, as are the parts of a set
|
|
9
|
-
# (Vic20Cartridge), and goes in with a power cycle,
|
|
10
|
-
# Disks mount on device 8 through the KERNAL traps, or
|
|
11
|
-
# 1541 (TrueDrive), and tapes play on the datasette.
|
|
5
|
+
# What a VIC-20 does with media of its own (Media.attach). A program
|
|
6
|
+
# loads once the KERNAL has booted: a BASIC program at the start of
|
|
7
|
+
# BASIC, wherever the RAM puts it, and RUNs. A program that loads into
|
|
8
|
+
# BLK5 at $A000 is a cartridge's ROM instead, as are the parts of a set
|
|
9
|
+
# that includes one (Vic20Cartridge), and goes in with a power cycle,
|
|
10
|
+
# as a .crt does. Disks mount on device 8 through the KERNAL traps, or
|
|
11
|
+
# go in a true 1541 (TrueDrive), and tapes play on the datasette.
|
|
12
12
|
module Vic20Media
|
|
13
13
|
# The expansions that fill BLK1, BLK2 and BLK3 one block after
|
|
14
14
|
# another, each with the last address it fills.
|
|
15
15
|
BLOCK_EXPANSIONS = [[0x3fff, :"8k"], [0x5fff, :"16k"], [0x7fff, :"24k"]].freeze
|
|
16
16
|
|
|
17
17
|
# What a VIC-20 doesn't take.
|
|
18
|
-
UNSUPPORTED = %
|
|
18
|
+
UNSUPPORTED = Extensions.of(%i[tune])
|
|
19
19
|
|
|
20
20
|
# The platform byte of a VIC-20 tape (Storage::TAP#platform).
|
|
21
21
|
TAPE_PLATFORM = 1
|
|
22
22
|
|
|
23
23
|
class << self
|
|
24
|
-
def attach(machine, path, autostart:, **options)
|
|
25
|
-
extension = File.extname(path).downcase
|
|
26
|
-
raise ArgumentError, "#{path} doesn't go in a VIC-20" if UNSUPPORTED.include?(extension)
|
|
27
|
-
|
|
28
|
-
if TrueDrive.takes?(machine, path)
|
|
29
|
-
attach_true_drive(machine, path, options.fetch(:disk, {}), autostart:)
|
|
30
|
-
elsif File.directory?(path)
|
|
31
|
-
machine.mount(Storage::HostDirectory.new(path))
|
|
32
|
-
"Mounted #{path} as device 8"
|
|
33
|
-
elsif extension == ".crt"
|
|
34
|
-
attach_cartridge(machine, path, Storage::CRTFile.new(path, machine: :vic20).chips)
|
|
35
|
-
elsif extension == ".tap"
|
|
36
|
-
attach_tape(machine, path, autostart:)
|
|
37
|
-
elsif MOUNT_TYPES.key?(extension)
|
|
38
|
-
attach_storage(machine, path, options.fetch(:disk, {}), autostart:)
|
|
39
|
-
else
|
|
40
|
-
attach_prg(machine, path, autostart:)
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
24
|
# The RAM expansion (Vic20::Bus::RAM_CONFIGURATIONS) a VIC-20 needs
|
|
45
25
|
# for the program at `path`, or for the first program on the disk
|
|
46
26
|
# or in the directory there, by where it loads. A BASIC program
|
|
@@ -60,72 +40,50 @@ module Badline
|
|
|
60
40
|
end
|
|
61
41
|
end
|
|
62
42
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def expansion_reaching(last)
|
|
66
|
-
BLOCK_EXPANSIONS.each { |reach, ram| return ram if last <= reach }
|
|
67
|
-
BLOCK_EXPANSIONS.last.last
|
|
68
|
-
end
|
|
69
|
-
|
|
43
|
+
# The program at `path`, or the first on the disk or in the
|
|
44
|
+
# directory there, or nil.
|
|
70
45
|
def first_program(path)
|
|
71
|
-
|
|
72
|
-
if File.directory?(path) ||
|
|
73
|
-
open_storage(path).read_file("*")
|
|
74
|
-
elsif File.file?(path) && !%
|
|
75
|
-
|
|
46
|
+
kind = Extensions.kind(path)
|
|
47
|
+
if File.directory?(path) || %i[disk archive].include?(kind)
|
|
48
|
+
Media.open_storage(path).read_file("*")
|
|
49
|
+
elsif File.file?(path) && !%i[tune cartridge tape gcr].include?(kind)
|
|
50
|
+
Media.program_bytes(path)
|
|
76
51
|
end
|
|
77
52
|
end
|
|
78
53
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
storage = MOUNT_TYPES.fetch(File.extname(path).downcase)
|
|
83
|
-
storage < Storage::DiskImage ? storage.new(path, **disk) : storage.new(path)
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def attach_cartridge(machine, path, chips)
|
|
87
|
-
machine.attach_cartridge(chips)
|
|
88
|
-
"Attached cartridge #{path}"
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
# A tape made for another machine plays all the same, and says so.
|
|
92
|
-
def attach_tape(machine, path, autostart:)
|
|
93
|
-
tape = Storage::TAP.new(path)
|
|
94
|
-
machine.datasette.insert(tape)
|
|
95
|
-
machine.datasette.play!
|
|
96
|
-
machine.type_text(TAPE_AUTOSTART) if autostart
|
|
97
|
-
message = "Inserted #{path} in the datasette"
|
|
98
|
-
tape.platform == TAPE_PLATFORM ? message : "#{message}, a tape for another machine than the VIC-20"
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def attach_true_drive(machine, path, disk, autostart:)
|
|
102
|
-
message = TrueDrive.insert(machine, path, read_only: disk.fetch(:read_only, false))
|
|
103
|
-
machine.type_text(disk_autostart(first_program(path))) if autostart
|
|
104
|
-
message
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def attach_storage(machine, path, disk, autostart:)
|
|
108
|
-
storage = open_storage(path, disk)
|
|
109
|
-
machine.mount(storage)
|
|
110
|
-
machine.type_text(disk_autostart(storage.read_file("*"))) if autostart
|
|
111
|
-
"Mounted #{path} as device 8"
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
# A BASIC program loads relocated to the start of BASIC, and anything
|
|
115
|
-
# else where it says.
|
|
54
|
+
# What loads and runs `data`, the first program on the disk in
|
|
55
|
+
# device 8: a BASIC program loads relocated to the start of BASIC,
|
|
56
|
+
# and anything else where it says.
|
|
116
57
|
def disk_autostart(data)
|
|
117
58
|
basic = data && data.length > 2 && Vic20Basic::BASIC_STARTS.key?(data[0] | (data[1] << 8))
|
|
118
59
|
basic ? %(lO"*",8\rrun\r) : AUTOSTART
|
|
119
60
|
end
|
|
120
61
|
|
|
121
|
-
|
|
122
|
-
|
|
62
|
+
# Loads the program, `bytes` from the file at `path`, as Vic20Basic
|
|
63
|
+
# has it once the KERNAL has booted, or attaches the cartridge it's
|
|
64
|
+
# a part of (Vic20Cartridge), and says which.
|
|
65
|
+
def attach_program(machine, path, bytes, autostart:)
|
|
123
66
|
chips = Vic20Cartridge.chips(path, bytes)
|
|
124
|
-
|
|
67
|
+
if chips
|
|
68
|
+
machine.attach_cartridge(chips)
|
|
69
|
+
return "Attached cartridge #{path}"
|
|
70
|
+
end
|
|
125
71
|
|
|
126
72
|
machine.on_init { Vic20Basic.load_program(machine, bytes, autostart:) }
|
|
127
73
|
"Loading #{path}"
|
|
128
74
|
end
|
|
75
|
+
|
|
76
|
+
# A tape made for another machine plays all the same, and says so.
|
|
77
|
+
def tape_message(tape, message)
|
|
78
|
+
tape.platform == TAPE_PLATFORM ? message : "#{message}, a tape for another machine than the VIC-20"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
def expansion_reaching(last)
|
|
84
|
+
BLOCK_EXPANSIONS.each { |reach, ram| return ram if last <= reach }
|
|
85
|
+
BLOCK_EXPANSIONS.last.last
|
|
86
|
+
end
|
|
129
87
|
end
|
|
130
88
|
end
|
|
131
89
|
end
|
data/lib/badline/media.rb
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "badline/media/extensions"
|
|
3
4
|
require "badline/media/true_drive"
|
|
4
5
|
require "badline/media/boot_disk"
|
|
5
6
|
require "badline/media/not_disk"
|
|
6
|
-
require "badline/
|
|
7
|
+
require "badline/audio/queue"
|
|
7
8
|
require "badline/media/disk_set"
|
|
8
9
|
require "badline/media/disk_list"
|
|
9
10
|
require "badline/media/vic20_basic"
|
|
10
11
|
require "badline/media/vic20_cartridge"
|
|
11
12
|
require "badline/media/vic20_media"
|
|
13
|
+
require "badline/media/tune"
|
|
14
|
+
require "badline/media/program"
|
|
12
15
|
|
|
13
16
|
module Badline
|
|
14
17
|
module Media
|
|
@@ -16,6 +19,7 @@ module Badline
|
|
|
16
19
|
TAPE_AUTOSTART = %(lO\rrun\r)
|
|
17
20
|
BASIC_START = 0x0801
|
|
18
21
|
|
|
22
|
+
# The storage that opens each of Extensions::MOUNTABLE.
|
|
19
23
|
MOUNT_TYPES = {
|
|
20
24
|
".d64" => Storage::D64Image,
|
|
21
25
|
".d71" => Storage::D71Image,
|
|
@@ -38,13 +42,17 @@ module Badline
|
|
|
38
42
|
# KERNAL to boot at power-on, with nothing typed (BootDisk).
|
|
39
43
|
#
|
|
40
44
|
# An .m3u or .vfl list of disks attaches the first disk it lists
|
|
41
|
-
# (DiskList).
|
|
42
|
-
#
|
|
45
|
+
# (DiskList). Every machine takes each kind of medium the same way,
|
|
46
|
+
# except that the VIC-20 (Vic20Media) has cartridges, programs and a
|
|
47
|
+
# disk autostart of its own, and takes no .sid tunes. The C128 in C64
|
|
48
|
+
# mode takes a C64's.
|
|
43
49
|
def attach(computer, path, autostart: true, subtune: nil, **)
|
|
44
50
|
path = DiskList.disk(path)
|
|
45
|
-
|
|
51
|
+
if computer.family == :vic20 && Vic20Media::UNSUPPORTED.include?(File.extname(path).downcase)
|
|
52
|
+
raise ArgumentError, "#{path} doesn't go in a VIC-20"
|
|
53
|
+
end
|
|
46
54
|
|
|
47
|
-
BootDisk.attach(computer, path, **) ||
|
|
55
|
+
BootDisk.attach(computer, path, **) || attach_kind(computer, path, autostart:, subtune:, **)
|
|
48
56
|
end
|
|
49
57
|
|
|
50
58
|
# Swaps the disk in device 8 for a disk image or a host directory,
|
|
@@ -73,109 +81,104 @@ module Badline
|
|
|
73
81
|
# The SID a machine for `path` should be built with. A .sid tune names
|
|
74
82
|
# its own; everything else gets `otherwise`.
|
|
75
83
|
def sid_model(path, otherwise: :mos6581)
|
|
76
|
-
return otherwise unless path &&
|
|
84
|
+
return otherwise unless path && Extensions.kind(path) == :tune
|
|
77
85
|
|
|
78
|
-
|
|
86
|
+
SIDTune::File.new(path).sid_model
|
|
79
87
|
end
|
|
80
88
|
|
|
81
|
-
|
|
89
|
+
# What the medium at `path` is to `computer`, which attach goes by:
|
|
90
|
+
# :true_drive for a disk that goes in a true drive (TrueDrive),
|
|
91
|
+
# :directory, :storage for a disk image or a .t64 that the traps
|
|
92
|
+
# mount, and otherwise its kind by its extension (Extensions).
|
|
93
|
+
def kind(computer, path)
|
|
94
|
+
return :true_drive if TrueDrive.takes?(computer, path)
|
|
95
|
+
return :directory if File.directory?(path)
|
|
82
96
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
attach_true_drive(computer, path, options.fetch(:disk, {}), autostart:)
|
|
86
|
-
elsif File.directory?(path)
|
|
87
|
-
computer.mount(Storage::HostDirectory.new(path))
|
|
88
|
-
"Mounted #{path} as device 8"
|
|
89
|
-
elsif File.extname(path).downcase == ".crt"
|
|
90
|
-
attach_cartridge(computer, path, options.fetch(:cartridge, {}))
|
|
91
|
-
elsif File.extname(path).downcase == ".sid"
|
|
92
|
-
attach_sid(computer, path, autostart:, subtune:)
|
|
93
|
-
elsif File.extname(path).downcase == ".tap"
|
|
94
|
-
attach_tape(computer, path, autostart:)
|
|
95
|
-
elsif MOUNT_TYPES.key?(File.extname(path).downcase)
|
|
96
|
-
attach_storage(computer, path, options.fetch(:disk, {}), autostart:)
|
|
97
|
-
else
|
|
98
|
-
attach_prg(computer, path, autostart:)
|
|
99
|
-
end
|
|
97
|
+
kind = Extensions.kind(path)
|
|
98
|
+
%i[disk archive].include?(kind) ? :storage : kind
|
|
100
99
|
end
|
|
101
100
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
# Disk images take the `disk` options. A .t64 is read-only whatever
|
|
108
|
-
# it's given.
|
|
109
|
-
def open_storage(path, disk)
|
|
101
|
+
# What device 8 serves through the traps for a host directory, a disk
|
|
102
|
+
# image or a .t64. Disk images take the `disk` options. A .t64 is
|
|
103
|
+
# read-only whatever it's given.
|
|
104
|
+
def open_storage(path, disk = {})
|
|
110
105
|
return Storage::HostDirectory.new(path) if File.directory?(path)
|
|
111
106
|
|
|
112
|
-
storage = MOUNT_TYPES
|
|
107
|
+
storage = MOUNT_TYPES.fetch(File.extname(path).downcase)
|
|
113
108
|
storage < Storage::DiskImage ? storage.new(path, **disk) : storage.new(path)
|
|
114
109
|
end
|
|
115
110
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
111
|
+
# A program file's bytes, unwrapped from a .p00.
|
|
112
|
+
def program_bytes(path)
|
|
113
|
+
bytes = File.binread(path).bytes
|
|
114
|
+
Storage::P00.wraps?(bytes) ? Storage::P00.data(bytes) : bytes
|
|
119
115
|
end
|
|
120
116
|
|
|
121
|
-
|
|
122
|
-
tune = Storage::SIDFile.new(path)
|
|
123
|
-
if tune.sids > 1
|
|
124
|
-
raise Storage::SIDFile::FormatError, "Written for #{tune.sids} SIDs, which only the SID player plays"
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
subtune = (subtune || tune.start_subtune).clamp(1, tune.subtunes)
|
|
128
|
-
computer.on_init { start_tune(computer, tune, autostart:, subtune:) }
|
|
129
|
-
title = tune.name.empty? ? path : tune.name
|
|
130
|
-
title += " (subtune #{subtune})" if tune.subtunes > 1
|
|
131
|
-
autostart ? "Playing #{title}" : "Loaded #{title}"
|
|
132
|
-
end
|
|
117
|
+
private
|
|
133
118
|
|
|
134
|
-
def
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
computer
|
|
119
|
+
def attach_kind(computer, path, autostart:, subtune:, **options)
|
|
120
|
+
disk = options.fetch(:disk, {})
|
|
121
|
+
case kind(computer, path)
|
|
122
|
+
when :true_drive then attach_true_drive(computer, path, disk, autostart:)
|
|
123
|
+
when :directory then mount(computer, path, disk, autostart: false)
|
|
124
|
+
when :storage then mount(computer, path, disk, autostart:)
|
|
125
|
+
when :cartridge then attach_cartridge(computer, path, options.fetch(:cartridge, {}))
|
|
126
|
+
when :tune then Tune.attach(computer, path, autostart:, subtune:)
|
|
127
|
+
when :tape then attach_tape(computer, path, autostart:)
|
|
128
|
+
else attach_prg(computer, path, autostart:)
|
|
129
|
+
end
|
|
138
130
|
end
|
|
139
131
|
|
|
140
|
-
def
|
|
141
|
-
computer.datasette.insert(Storage::TAP.new(path))
|
|
142
|
-
computer.datasette.play!
|
|
143
|
-
computer.type_text(TAPE_AUTOSTART) if autostart
|
|
144
|
-
"Inserted #{path} in the datasette"
|
|
145
|
-
end
|
|
132
|
+
def disk?(path) = File.directory?(path) || Extensions.kind(path) == :disk
|
|
146
133
|
|
|
147
134
|
def attach_true_drive(computer, path, disk, autostart:)
|
|
148
135
|
message = TrueDrive.insert(computer, path, read_only: disk.fetch(:read_only, false))
|
|
149
|
-
computer.type_text(
|
|
136
|
+
computer.type_text(disk_autostart(computer) { Vic20Media.first_program(path) }) if autostart
|
|
150
137
|
message
|
|
151
138
|
end
|
|
152
139
|
|
|
153
|
-
def
|
|
154
|
-
|
|
155
|
-
computer.
|
|
140
|
+
def mount(computer, path, disk, autostart:)
|
|
141
|
+
storage = open_storage(path, disk)
|
|
142
|
+
computer.mount(storage)
|
|
143
|
+
computer.type_text(disk_autostart(computer) { storage.read_file("*") }) if autostart
|
|
156
144
|
"Mounted #{path} as device 8"
|
|
157
145
|
end
|
|
158
146
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
147
|
+
# What loads and runs the first program on the disk in device 8. A
|
|
148
|
+
# VIC-20 goes by that program, which the block gives
|
|
149
|
+
# (Vic20Media.disk_autostart).
|
|
150
|
+
def disk_autostart(computer)
|
|
151
|
+
computer.family == :vic20 ? Vic20Media.disk_autostart(yield) : AUTOSTART
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# A VIC-20 cartridge is its ROM chips.
|
|
155
|
+
def attach_cartridge(computer, path, options)
|
|
156
|
+
if computer.family == :vic20
|
|
157
|
+
computer.attach_cartridge(Storage::CRTFile.new(path, machine: :vic20).chips)
|
|
158
|
+
else
|
|
159
|
+
computer.attach_cartridge(C64::Cartridge.from_file(path, **options))
|
|
160
|
+
end
|
|
161
|
+
"Attached cartridge #{path}"
|
|
164
162
|
end
|
|
165
163
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
164
|
+
# A VIC-20 says when the tape was made for another machine
|
|
165
|
+
# (Vic20Media.tape_message).
|
|
166
|
+
def attach_tape(computer, path, autostart:)
|
|
167
|
+
tape = Storage::TAP.new(path)
|
|
168
|
+
computer.datasette.insert(tape)
|
|
169
|
+
computer.datasette.play!
|
|
170
|
+
computer.type_text(TAPE_AUTOSTART) if autostart
|
|
171
|
+
message = "Inserted #{path} in the datasette"
|
|
172
|
+
computer.family == :vic20 ? Vic20Media.tape_message(tape, message) : message
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# A VIC-20 has programs of its own (Vic20Media.attach_program).
|
|
176
|
+
def attach_prg(computer, path, autostart:)
|
|
177
|
+
bytes = program_bytes(path)
|
|
178
|
+
return Vic20Media.attach_program(computer, path, bytes, autostart:) if computer.family == :vic20
|
|
179
|
+
|
|
180
|
+
computer.on_init { Program.load(computer, bytes, autostart:) }
|
|
181
|
+
"Loading #{path}"
|
|
179
182
|
end
|
|
180
183
|
end
|
|
181
184
|
end
|
data/lib/badline/model.rb
CHANGED
|
@@ -7,7 +7,7 @@ module Badline
|
|
|
7
7
|
# each was sold with, its video standard, its KERNAL and whether it has
|
|
8
8
|
# a datasette. The names are x64sc's.
|
|
9
9
|
module Model
|
|
10
|
-
# Each field but the name is a keyword
|
|
10
|
+
# Each field but the name is a keyword C64.new takes.
|
|
11
11
|
Profile = Data.define(:name, :vic_model, :cia_model, :sid_model, :region, :kernal, :datasette, :board)
|
|
12
12
|
|
|
13
13
|
# The breadbin PAL C64: the 6569 VIC-II, 6526 CIAs and the 6581 SID.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "badline/media/extensions"
|
|
4
|
+
|
|
3
5
|
module Badline
|
|
4
6
|
class Options
|
|
5
7
|
# One event of --at or --script: what to do, with its argument, once
|
|
@@ -23,7 +25,7 @@ module Badline
|
|
|
23
25
|
|
|
24
26
|
# What insert takes: disk images, tapes and cartridges, or an .m3u
|
|
25
27
|
# or .vfl list of disks or a directory to mount as device 8.
|
|
26
|
-
INSERTABLE = %
|
|
28
|
+
INSERTABLE = Media::Extensions.of(%i[disk gcr archive tape cartridge disk_list])
|
|
27
29
|
|
|
28
30
|
attr_reader :frame, :action, :argument
|
|
29
31
|
|
data/lib/badline/roms/README
CHANGED
|
@@ -20,7 +20,7 @@ The character generator ROM.
|
|
|
20
20
|
kernal-sx64.rom
|
|
21
21
|
---------------
|
|
22
22
|
The SX-64's KERNAL, 251104-04. It boots with the SX-64's banner and
|
|
23
|
-
colours, and loads from device 8 rather than tape.
|
|
23
|
+
colours, and loads from device 8 rather than tape. C64.new(kernal:
|
|
24
24
|
:sx64) fits it, as --model sx64 does.
|
|
25
25
|
|
|
26
26
|
Downloaded from
|
|
@@ -32,7 +32,7 @@ kernal-pet64.rom
|
|
|
32
32
|
The KERNAL of the PET 64, 4064 and Educator 64, 901246-01. It boots
|
|
33
33
|
with the "**** COMMODORE 4064 BASIC V2.0 ****" banner and a white
|
|
34
34
|
cursor, and its interrupt routine keeps the border, background and
|
|
35
|
-
sprite colours black unless bit 7 of $0286 is set.
|
|
35
|
+
sprite colours black unless bit 7 of $0286 is set. C64.new(kernal:
|
|
36
36
|
:pet64) fits it, as --model pet64 does.
|
|
37
37
|
|
|
38
38
|
Downloaded from
|
|
@@ -45,7 +45,7 @@ The C64GS's BASIC and KERNAL, 390852-01, 16 KB: BASIC for $A000-$BFFF
|
|
|
45
45
|
followed by the KERNAL for $E000-$FFFF. Its BASIC is 901226-01's but
|
|
46
46
|
for 30 unused bytes. Its KERNAL is 901227-03's with most changes in
|
|
47
47
|
$F72C-$FC92, the cassette routines' place, and many jumps redirected to
|
|
48
|
-
I/O error 5.
|
|
48
|
+
I/O error 5. C64.new(kernal: :gs) fits both, as --model c64gs does.
|
|
49
49
|
|
|
50
50
|
Downloaded from
|
|
51
51
|
https://www.zimmers.net/anonftp/pub/cbm/firmware/computers/c64/64gs.390852-01.bin
|
|
@@ -54,7 +54,7 @@ MD5 049e657afafbdd802e8c6a4f88f3d730.
|
|
|
54
54
|
dos1541.rom
|
|
55
55
|
-----------
|
|
56
56
|
The 1541 disk drive's DOS 2.6, 16 KB for $C000-$FFFF: 325302-01
|
|
57
|
-
($C000-$DFFF) followed by 901229-05 ($E000-$FFFF).
|
|
57
|
+
($C000-$DFFF) followed by 901229-05 ($E000-$FFFF). Drives::Model1541 loads it.
|
|
58
58
|
|
|
59
59
|
Both halves downloaded from
|
|
60
60
|
https://www.zimmers.net/anonftp/pub/cbm/firmware/drives/new/1541/
|
|
@@ -64,7 +64,7 @@ SHA-1 ab16f56989b27d89babe5f89c5a8cb3da71a82f0.
|
|
|
64
64
|
dos1571.rom
|
|
65
65
|
-----------
|
|
66
66
|
The 1571 disk drive's DOS 3.0, 310654-05, 32 KB for $8000-$FFFF.
|
|
67
|
-
|
|
67
|
+
Drives::Model1571 loads it.
|
|
68
68
|
|
|
69
69
|
Downloaded from
|
|
70
70
|
https://www.zimmers.net/anonftp/pub/cbm/firmware/drives/new/1571/1571-rom.310654-05.bin
|
|
@@ -73,7 +73,7 @@ SHA-1 f1be619c106641a685f6609e4d43d6fc9eac1e70.
|
|
|
73
73
|
dos1581.rom
|
|
74
74
|
-----------
|
|
75
75
|
The 1581 disk drive's DOS, 318045-02, 32 KB for $8000-$FFFF.
|
|
76
|
-
|
|
76
|
+
Drives::Model1581 loads it.
|
|
77
77
|
|
|
78
78
|
Downloaded from
|
|
79
79
|
https://www.zimmers.net/anonftp/pub/cbm/firmware/drives/new/1581/1581-rom.318045-02.bin
|
data/lib/badline/sdl.rb
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
require "digest"
|
|
4
4
|
|
|
5
5
|
module Badline
|
|
6
|
-
module
|
|
6
|
+
module SIDTune
|
|
7
7
|
# PSID/RSID tunes: a memory image plus the addresses of the routines
|
|
8
8
|
# that initialise it and produce one frame of music.
|
|
9
|
-
class
|
|
9
|
+
class File
|
|
10
10
|
include IntegerHelper
|
|
11
11
|
|
|
12
12
|
class FormatError < StandardError; end
|
|
@@ -147,7 +147,7 @@ module Badline
|
|
|
147
147
|
attr_reader :format
|
|
148
148
|
|
|
149
149
|
def initialize(path)
|
|
150
|
-
@bytes = File.binread(path).bytes
|
|
150
|
+
@bytes = ::File.binread(path).bytes
|
|
151
151
|
@format = @bytes[0, 4].pack("C*")
|
|
152
152
|
raise FormatError, "Missing PSID or RSID signature" unless %w[PSID RSID].include?(@format)
|
|
153
153
|
raise FormatError, "Truncated header" if truncated?
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Badline
|
|
4
|
-
module
|
|
4
|
+
module SIDTune
|
|
5
5
|
# The layout of an HVSC collection: tunes in directories under its root,
|
|
6
6
|
# and databases about them in `DOCUMENTS`. A tune's HVSC path is its path
|
|
7
7
|
# from the root, as `/MUSICIANS/H/Hubbard_Rob/Commando.sid`.
|
|
@@ -10,15 +10,15 @@ module Badline
|
|
|
10
10
|
# The named file in the DOCUMENTS directory of a collection above the
|
|
11
11
|
# tune, or else of the one `$HVSC_BASE` points at.
|
|
12
12
|
def document(tune_path, name)
|
|
13
|
-
candidates(tune_path).map { |dir| File.join(dir, "DOCUMENTS", name) }
|
|
14
|
-
.find { |path| File.file?(path) }
|
|
13
|
+
candidates(tune_path).map { |dir| ::File.join(dir, "DOCUMENTS", name) }
|
|
14
|
+
.find { |path| ::File.file?(path) }
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
# The tune's HVSC path in the collection that holds the document, or
|
|
18
18
|
# nil when the tune lies outside it.
|
|
19
19
|
def path(tune_path, document)
|
|
20
|
-
root = File.dirname(File.expand_path(document), 2)
|
|
21
|
-
tune = File.expand_path(tune_path)
|
|
20
|
+
root = ::File.dirname(::File.expand_path(document), 2)
|
|
21
|
+
tune = ::File.expand_path(tune_path)
|
|
22
22
|
tune.start_with?("#{root}/") ? tune[root.length..] : nil
|
|
23
23
|
end
|
|
24
24
|
|
|
@@ -26,10 +26,10 @@ module Badline
|
|
|
26
26
|
|
|
27
27
|
def candidates(tune_path)
|
|
28
28
|
dirs = []
|
|
29
|
-
dir = File.dirname(File.expand_path(tune_path))
|
|
29
|
+
dir = ::File.dirname(::File.expand_path(tune_path))
|
|
30
30
|
until dirs.last == dir
|
|
31
31
|
dirs << dir
|
|
32
|
-
dir = File.dirname(dir)
|
|
32
|
+
dir = ::File.dirname(dir)
|
|
33
33
|
end
|
|
34
34
|
base = ENV.fetch("HVSC_BASE", nil)
|
|
35
35
|
dirs << base if base
|