badline 0.12.1 → 0.14.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 +66 -1
- data/CLAUDE.md +86 -38
- data/CONTRIBUTING.md +4 -3
- data/README.md +9 -6
- data/doc/library.md +9 -9
- data/doc/media.md +2 -1
- data/doc/pinned-behaviour.md +134 -105
- data/doc/snapshot-format.md +1047 -0
- data/doc/snapshots.md +73 -43
- data/lib/badline/audio/bare_player.rb +53 -20
- data/lib/badline/audio/cli.rb +6 -6
- data/lib/badline/audio/jukebox.rb +2 -2
- data/lib/badline/audio/machine_player.rb +16 -10
- data/lib/badline/{media → audio}/queue.rb +1 -1
- data/lib/badline/audio/queued_tune.rb +6 -6
- data/lib/badline/audio/renderer.rb +33 -22
- data/lib/badline/audio/stereo.rb +1 -1
- data/lib/badline/c128/banks.rb +6 -3
- data/lib/badline/c128/bus/keyed_state.rb +45 -0
- data/lib/badline/c128/bus.rb +35 -20
- data/lib/badline/c128/color_lines.rb +2 -2
- data/lib/badline/c128/cpu.rb +1 -1
- data/lib/badline/c128/drives.rb +14 -34
- data/lib/badline/c128/fast_serial.rb +5 -5
- data/lib/badline/c128/keyed_modules.rb +117 -0
- data/lib/badline/c128/keyed_state.rb +91 -0
- data/lib/badline/c128/keys.rb +9 -0
- data/lib/badline/c128/mmu.rb +9 -8
- data/lib/badline/c128/mmu_pages.rb +21 -1
- data/lib/badline/c128/modes.rb +21 -11
- data/lib/badline/c128/z80.rb +2 -2
- data/lib/badline/c128/z80_turns.rb +1 -1
- data/lib/badline/c128.rb +21 -16
- data/lib/badline/c64/attachments.rb +42 -0
- data/lib/badline/c64/banked_ram/banking.rb +32 -0
- data/lib/badline/c64/banked_ram/plus256k.rb +64 -0
- data/lib/badline/c64/banked_ram/plus60k.rb +47 -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/debug_register.rb +32 -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/keyed_state.rb +41 -0
- data/lib/badline/c64/bus/pla.rb +149 -0
- data/lib/badline/c64/bus/roms.rb +41 -0
- data/lib/badline/c64/bus/sid_slots.rb +44 -0
- data/lib/badline/c64/bus.rb +219 -0
- data/lib/badline/c64/cartridge/action_replay.rb +115 -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 +132 -0
- data/lib/badline/c64/cartridge/epyx_fastload.rb +73 -0
- data/lib/badline/c64/cartridge/final_cartridge3.rb +79 -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 +64 -0
- data/lib/badline/c64/cartridge/game_system.rb +42 -0
- data/lib/badline/c64/cartridge/geo_ram.rb +65 -0
- data/lib/badline/c64/cartridge/kcs_power.rb +69 -0
- data/lib/badline/c64/cartridge/keyed_state.rb +393 -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 +60 -0
- data/lib/badline/c64/cartridge/retro_replay.rb +278 -0
- data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
- data/lib/badline/c64/cartridge/rgcd.rb +50 -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 +40 -0
- data/lib/badline/c64/cartridge/westermann.rb +32 -0
- data/lib/badline/c64/cartridge/zaxxon.rb +52 -0
- data/lib/badline/c64/cartridge.rb +232 -0
- data/lib/badline/c64/color_memory.rb +27 -0
- data/lib/badline/{computer → c64}/common.rb +2 -2
- data/lib/badline/{computer → c64}/kernal_traps.rb +39 -36
- data/lib/badline/c64/keyed_modules.rb +111 -0
- data/lib/badline/c64/keyed_state.rb +68 -0
- data/lib/badline/c64/reu/dma.rb +271 -0
- data/lib/badline/c64/reu/keyed_state.rb +140 -0
- data/lib/badline/c64/reu/ram.rb +94 -0
- data/lib/badline/c64/reu/trigger.rb +34 -0
- data/lib/badline/c64/reu.rb +289 -0
- data/lib/badline/c64/true_drives.rb +120 -0
- data/lib/badline/{computer.rb → c64.rb} +24 -15
- data/lib/badline/chips/cia/fast_forward.rb +62 -0
- data/lib/badline/chips/cia/interrupt_register.rb +128 -0
- data/lib/badline/chips/cia/keyed_parts.rb +213 -0
- data/lib/badline/chips/cia/serial.rb +246 -0
- data/lib/badline/chips/cia/time_of_day.rb +210 -0
- data/lib/badline/chips/cia/timer.rb +188 -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 +183 -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/keyed_state.rb +177 -0
- data/lib/badline/chips/cpu/microcode.rb +195 -0
- data/lib/badline/chips/cpu/operations.rb +90 -0
- data/lib/badline/chips/cpu/port.rb +133 -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 +17 -0
- data/lib/badline/chips/sid/catch_up.rb +122 -0
- data/lib/badline/chips/sid/decimator.rb +68 -0
- data/lib/badline/chips/sid/envelope.rb +236 -0
- data/lib/badline/chips/sid/filter.rb +227 -0
- data/lib/badline/chips/sid/keyed_parts.rb +286 -0
- data/lib/badline/chips/sid/voice.rb +69 -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.rb +305 -0
- data/lib/badline/chips/sid.rb +264 -0
- data/lib/badline/chips/ted/beam.rb +119 -0
- data/lib/badline/chips/ted/timers.rb +66 -0
- data/lib/badline/chips/ted.rb +143 -0
- data/lib/badline/chips/tia.rb +49 -0
- data/lib/badline/chips/vdc/keyed_parts.rb +105 -0
- data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
- data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -13
- data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -17
- data/lib/badline/{c128 → chips}/vdc/window.rb +1 -10
- data/lib/badline/{c128 → chips}/vdc.rb +6 -31
- data/lib/badline/chips/via/control_lines.rb +109 -0
- data/lib/badline/chips/via/fast_forward.rb +55 -0
- data/lib/badline/chips/via/interrupt_register.rb +60 -0
- data/lib/badline/chips/via/keyed_parts.rb +163 -0
- data/lib/badline/chips/via/shift_register.rb +168 -0
- data/lib/badline/chips/via/timer1.rb +120 -0
- data/lib/badline/chips/via/timer2.rb +117 -0
- data/lib/badline/chips/via.rb +267 -0
- data/lib/badline/chips/vic/bank.rb +135 -0
- data/lib/badline/chips/vic/border_mask.rb +78 -0
- data/lib/badline/chips/vic/collisions.rb +106 -0
- data/lib/badline/chips/vic/color_patches.rb +38 -0
- data/lib/badline/chips/vic/display_state.rb +168 -0
- data/lib/badline/chips/vic/graphics_mode.rb +166 -0
- data/lib/badline/chips/vic/graphics_shifter.rb +183 -0
- data/lib/badline/chips/vic/keyed_parts.rb +228 -0
- data/lib/badline/chips/vic/keyed_sprites.rb +225 -0
- data/lib/badline/chips/vic/keyed_state.rb +102 -0
- data/lib/badline/chips/vic/register_log.rb +65 -0
- data/lib/badline/chips/vic/registers.rb +188 -0
- data/lib/badline/chips/vic/sequencer.rb +275 -0
- data/lib/badline/chips/vic/sequencer_output.rb +118 -0
- data/lib/badline/chips/vic/sprite/internal_bus.rb +59 -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 +337 -0
- data/lib/badline/chips/vic/sprites.rb +281 -0
- data/lib/badline/chips/vic.rb +787 -0
- data/lib/badline/chips/vic_i/keyed_parts.rb +142 -0
- data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +2 -30
- data/lib/badline/chips/vic_i/sound/output.rb +85 -0
- data/lib/badline/chips/vic_i/sound.rb +227 -0
- data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
- data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +6 -6
- 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/keyed_state.rb +73 -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/shifts.rb +66 -0
- data/lib/badline/chips/z80.rb +13 -0
- data/lib/badline/chips.rb +10 -0
- data/lib/badline/core.rb +13 -32
- data/lib/badline/drives/datasette/keyed_state.rb +38 -0
- data/lib/badline/drives/datasette.rb +173 -0
- data/lib/badline/drives/engine/core.rb +152 -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 +72 -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 +75 -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.rb +318 -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/keyed_state.rb +251 -0
- data/lib/badline/drives/model1541/mechanism.rb +313 -0
- data/lib/badline/drives/model1541/rotation.rb +123 -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 +80 -0
- data/lib/badline/drives/model1571/bus.rb +100 -0
- data/lib/badline/drives/model1571/cpu.rb +13 -0
- data/lib/badline/drives/model1571/keyed_state.rb +108 -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 +108 -0
- data/lib/badline/drives/model1571.rb +141 -0
- data/lib/badline/drives/model1581/bus.rb +126 -0
- data/lib/badline/drives/model1581/cpu.rb +13 -0
- data/lib/badline/drives/model1581/disk.rb +133 -0
- data/lib/badline/drives/model1581/keyed_state.rb +280 -0
- data/lib/badline/drives/model1581/mechanism.rb +98 -0
- data/lib/badline/drives/model1581/serial_port.rb +54 -0
- data/lib/badline/drives/model1581/slot.rb +61 -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/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 +216 -0
- data/lib/badline/drives/model1581.rb +206 -0
- data/lib/badline/drives/serial_bus.rb +161 -0
- data/lib/badline/drives.rb +8 -0
- data/lib/badline/frontend/app.rb +3 -3
- data/lib/badline/frontend/boot.rb +4 -4
- data/lib/badline/frontend/controls.rb +19 -3
- data/lib/badline/frontend/drive_led.rb +44 -21
- data/lib/badline/frontend/machine_window.rb +3 -1
- data/lib/badline/frontend/menu/menu_dialogs.rb +2 -2
- 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/snapshots.rb +12 -1
- data/lib/badline/frontend/timeline.rb +30 -12
- 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/matrix_typist.rb +98 -0
- data/lib/badline/input.rb +4 -0
- data/lib/badline/kernal_trap/chrout.rb +45 -0
- data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
- data/lib/badline/kernal_trap/dos/channel.rb +156 -0
- data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -26
- data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -10
- data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -9
- data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -19
- data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
- data/lib/badline/kernal_trap/{drive.rb → dos.rb} +9 -27
- data/lib/badline/kernal_trap/file_routine.rb +4 -4
- data/lib/badline/kernal_trap/keyed_state.rb +150 -0
- data/lib/badline/kernal_trap/layout.rb +75 -11
- data/lib/badline/kernal_trap/load.rb +19 -21
- data/lib/badline/kernal_trap/routine.rb +12 -0
- data/lib/badline/kernal_trap/save.rb +12 -22
- data/lib/badline/kernal_trap/serial.rb +8 -24
- data/lib/badline/kernal_trap.rb +3 -2
- data/lib/badline/machine/clocking.rb +1 -1
- data/lib/badline/machine/keyboard_buffer.rb +49 -0
- data/lib/badline/machine/settling.rb +29 -0
- data/lib/badline/machine.rb +10 -7
- data/lib/badline/media/boot_disk.rb +14 -2
- data/lib/badline/media/extensions.rb +10 -0
- data/lib/badline/media/true_drive.rb +1 -1
- data/lib/badline/media/tune.rb +2 -2
- data/lib/badline/media.rb +3 -3
- data/lib/badline/memory.rb +3 -6
- data/lib/badline/model.rb +1 -1
- data/lib/badline/options/family.rb +5 -2
- data/lib/badline/options/help.rb +42 -16
- data/lib/badline/options/table.rb +2 -0
- data/lib/badline/options/validation.rb +2 -0
- data/lib/badline/options.rb +6 -1
- data/lib/badline/plus4/acia.rb +45 -0
- data/lib/badline/plus4/bus.rb +312 -0
- data/lib/badline/plus4/cpu.rb +10 -0
- data/lib/badline/plus4/cpu_port.rb +93 -0
- data/lib/badline/plus4/keyboard_port.rb +51 -0
- data/lib/badline/plus4/model.rb +38 -0
- data/lib/badline/plus4/user_port.rb +31 -0
- data/lib/badline/plus4.rb +164 -0
- data/lib/badline/roms/README +44 -6
- data/lib/badline/roms/plus4/basic.rom +0 -0
- data/lib/badline/roms/plus4/function-high.rom +0 -0
- data/lib/badline/roms/plus4/function-low.rom +0 -0
- data/lib/badline/roms/plus4/kernal-ntsc.rom +0 -0
- data/lib/badline/roms/plus4/kernal-pal.rom +0 -0
- 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 +32 -0
- data/lib/badline/snapshot/c64_setup.rb +83 -0
- data/lib/badline/snapshot/container.rb +4 -0
- data/lib/badline/snapshot/field_doc/markdown.rb +112 -0
- data/lib/badline/snapshot/field_doc.rb +109 -0
- data/lib/badline/snapshot/image.rb +132 -46
- data/lib/badline/snapshot/keyed/cursor.rb +40 -0
- data/lib/badline/snapshot/keyed/modules.rb +66 -0
- data/lib/badline/snapshot/keyed/reader.rb +188 -0
- data/lib/badline/snapshot/keyed/recorder.rb +88 -0
- data/lib/badline/snapshot/keyed/report.rb +26 -0
- data/lib/badline/snapshot/keyed/writer.rb +55 -0
- data/lib/badline/snapshot/keyed.rb +64 -0
- data/lib/badline/snapshot/machine_state.rb +17 -64
- data/lib/badline/snapshot/storage_setup.rb +63 -0
- data/lib/badline/snapshot/vic20_setup.rb +28 -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 +3 -3
- data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
- data/lib/badline/snapshot/vice.rb +13 -35
- data/lib/badline/snapshot.rb +44 -22
- data/lib/badline/storage/crt_file.rb +3 -1
- data/lib/badline/storage/d64_image.rb +0 -2
- data/lib/badline/storage/d71_image.rb +0 -2
- data/lib/badline/storage/d81_image.rb +0 -2
- data/lib/badline/storage/disk_image.rb +3 -6
- data/lib/badline/storage/g64_image.rb +10 -5
- data/lib/badline/storage/host_directory.rb +0 -5
- data/lib/badline/storage/t64.rb +2 -8
- data/lib/badline/storage/tap.rb +43 -15
- 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 +8 -5
- data/lib/badline/vic20/bus/keyed_state.rb +52 -0
- data/lib/badline/vic20/bus.rb +2 -25
- data/lib/badline/vic20/cpu.rb +1 -1
- data/lib/badline/vic20/keyed_modules.rb +73 -0
- data/lib/badline/vic20/keyed_state.rb +45 -0
- data/lib/badline/vic20/port_wiring.rb +4 -4
- data/lib/badline/vic20/user_via_ports.rb +2 -2
- data/lib/badline/vic20.rb +22 -17
- data/lib/badline.rb +1 -0
- metadata +271 -228
- 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 -66
- data/lib/badline/address_bus/sid_slots.rb +0 -42
- data/lib/badline/address_bus.rb +0 -216
- data/lib/badline/c128/bus_state.rb +0 -53
- data/lib/badline/c128/saved_state.rb +0 -143
- 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/chrout_trap.rb +0 -43
- 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/attachments.rb +0 -88
- data/lib/badline/computer/saved_state.rb +0 -117
- data/lib/badline/computer/true_drives.rb +0 -69
- 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/cpu_port.rb +0 -112
- data/lib/badline/datasette.rb +0 -161
- data/lib/badline/debug_register.rb +0 -28
- 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 -315
- data/lib/badline/drive1541/disk_state.rb +0 -86
- 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/keyboard_buffer.rb +0 -33
- 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/snapshot/setup.rb +0 -75
- data/lib/badline/snapshot/state.rb +0 -189
- 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 -853
- data/lib/badline/vic20/saved_state.rb +0 -124
- data/lib/badline/vic20/sound/output.rb +0 -83
- data/lib/badline/vic20/sound.rb +0 -233
- data/lib/badline/vic20/vic/saved_state.rb +0 -55
- 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
|
@@ -5,7 +5,7 @@ module Badline
|
|
|
5
5
|
# A .g64 image: a 1541 disk's flux as raw GCR, track by track, for the
|
|
6
6
|
# true drive to read the way it reads a real disk, copy protection and
|
|
7
7
|
# all. It has no file system of its own, so only the true drive
|
|
8
|
-
# (
|
|
8
|
+
# (Drives::Model1541::Disk.from_g64) can use it. A .g71 holds a 1571 disk the
|
|
9
9
|
# same way, with "GCR-1571" for its signature and 168 half tracks,
|
|
10
10
|
# the first side's 84 and then the second's.
|
|
11
11
|
#
|
|
@@ -21,7 +21,7 @@ module Badline
|
|
|
21
21
|
# A larger one is the offset of a speed map, two bits a byte, four
|
|
22
22
|
# track bytes to a map byte, the first byte's in the top two bits, for
|
|
23
23
|
# a track whose zone changes along it. The drive passes each byte
|
|
24
|
-
# under the head at its own zone's rate (
|
|
24
|
+
# under the head at its own zone's rate (Drives::Model1541::Track).
|
|
25
25
|
#
|
|
26
26
|
# The drive writes a track at one zone, so a track written back takes
|
|
27
27
|
# that zone as its speed entry. Writing it puts it in its own block,
|
|
@@ -66,15 +66,20 @@ module Badline
|
|
|
66
66
|
[bytes.length].pack("v") + bytes.pack("C*").ljust(size, "\x00".b)
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
-
attr_reader :half_tracks, :max_track_size
|
|
69
|
+
attr_reader :half_tracks, :max_track_size, :path
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
# `bytes` stands in for the host file's contents, as a snapshot
|
|
72
|
+
# restores the image as it was.
|
|
73
|
+
def initialize(path, read_only: false, bytes: nil)
|
|
72
74
|
@path = path
|
|
73
75
|
@read_only = read_only
|
|
74
|
-
@data = File.binread(path)
|
|
76
|
+
@data = bytes ? bytes.pack("C*") : File.binread(path)
|
|
75
77
|
parse
|
|
76
78
|
end
|
|
77
79
|
|
|
80
|
+
# The image as its file holds it.
|
|
81
|
+
def contents = @data.bytes
|
|
82
|
+
|
|
78
83
|
# Whether the image was opened write-protected.
|
|
79
84
|
def read_only? = @read_only
|
|
80
85
|
|
|
@@ -17,11 +17,6 @@ module Badline
|
|
|
17
17
|
@path = path
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
# What Storage.reopen needs to open the directory again.
|
|
21
|
-
def save_setup(out)
|
|
22
|
-
out.int(HOST_DIRECTORY).string(File.expand_path(@path))
|
|
23
|
-
end
|
|
24
|
-
|
|
25
20
|
def read_file(name, **)
|
|
26
21
|
entry = find(name)
|
|
27
22
|
return unless entry
|
data/lib/badline/storage/t64.rb
CHANGED
|
@@ -20,14 +20,8 @@ module Badline
|
|
|
20
20
|
raise FormatError, "Missing T64 signature" unless @bytes[0, 3] == SIGNATURE
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
# The host file's path, as it was opened.
|
|
24
|
-
attr_reader :path
|
|
25
|
-
|
|
26
|
-
# What Storage.reopen needs to open the archive again: its path and
|
|
27
|
-
# its bytes.
|
|
28
|
-
def save_setup(out)
|
|
29
|
-
out.int(T64_ARCHIVE).string(File.expand_path(@path)).blob(@bytes)
|
|
30
|
-
end
|
|
23
|
+
# The host file's path, as it was opened, and its bytes.
|
|
24
|
+
attr_reader :path, :bytes
|
|
31
25
|
|
|
32
26
|
def read_file(name, **)
|
|
33
27
|
pattern = Storage.matcher(name)
|
data/lib/badline/storage/tap.rb
CHANGED
|
@@ -5,11 +5,14 @@ module Badline
|
|
|
5
5
|
# Raw datasette pulse stream. The header holds the signature, the
|
|
6
6
|
# version at $0c, the platform at $0d (0 C64, 1 VIC-20, 2 C16) and the
|
|
7
7
|
# data size at $10; the data runs from $14, every byte the time to the
|
|
8
|
-
# next falling edge on the tape read line, in units of 8 cycles.
|
|
8
|
+
# next falling edge on the tape read line, in units of 8 cycles. A
|
|
9
|
+
# version 2 tape, the C16's and the Plus/4's, times half waves instead,
|
|
10
|
+
# so it takes two bytes to the next falling edge.
|
|
9
11
|
class TAP
|
|
10
12
|
class FormatError < StandardError; end
|
|
11
13
|
|
|
12
14
|
SIGNATURE = "C64-TAPE-RAW".bytes.freeze
|
|
15
|
+
C16_SIGNATURE = "C16-TAPE-RAW".bytes.freeze
|
|
13
16
|
HEADER_SIZE = 0x14
|
|
14
17
|
OVERFLOW = 0x100 * 8
|
|
15
18
|
|
|
@@ -28,10 +31,11 @@ module Badline
|
|
|
28
31
|
def initialize(path, bytes: nil)
|
|
29
32
|
@path = File.expand_path(path)
|
|
30
33
|
@bytes = bytes || File.binread(path).bytes
|
|
31
|
-
|
|
34
|
+
signature = @bytes[0, SIGNATURE.length]
|
|
35
|
+
raise FormatError, "Missing TAP signature" unless [SIGNATURE, C16_SIGNATURE].include?(signature)
|
|
32
36
|
|
|
33
37
|
@version = @bytes[0x0c].to_i
|
|
34
|
-
raise FormatError, "Unsupported TAP version #{@version}" if @version >
|
|
38
|
+
raise FormatError, "Unsupported TAP version #{@version}" if @version > 2
|
|
35
39
|
|
|
36
40
|
@platform = @bytes[0x0d].to_i
|
|
37
41
|
|
|
@@ -55,17 +59,16 @@ module Badline
|
|
|
55
59
|
# Records a pulse `cycles` long at the position, in place of the rest
|
|
56
60
|
# of the tape: a byte of units of 8 cycles, or a zero and the 24-bit
|
|
57
61
|
# cycle count for a long one (a lone zero, an overflow, on a version 0
|
|
58
|
-
# tape).
|
|
62
|
+
# tape). A version 2 tape records it as two equal halves.
|
|
59
63
|
def record_pulse(cycles)
|
|
60
|
-
units = (cycles + 4) / 8
|
|
61
|
-
encoded = if units.between?(1, 0xff) then [units]
|
|
62
|
-
elsif version.zero? then [0]
|
|
63
|
-
else
|
|
64
|
-
count = [cycles, 0xffffff].min
|
|
65
|
-
[0, count & 0xff, (count >> 8) & 0xff, count >> 16]
|
|
66
|
-
end
|
|
67
64
|
@bytes.slice!(@pos..)
|
|
68
|
-
|
|
65
|
+
if version == 2
|
|
66
|
+
half = cycles / 2
|
|
67
|
+
@bytes.concat(encode(cycles - half))
|
|
68
|
+
@bytes.concat(encode(half))
|
|
69
|
+
else
|
|
70
|
+
@bytes.concat(encode(cycles))
|
|
71
|
+
end
|
|
69
72
|
@pos = @end = @bytes.length
|
|
70
73
|
end
|
|
71
74
|
|
|
@@ -77,20 +80,45 @@ module Badline
|
|
|
77
80
|
File.binwrite(@path, @bytes.pack("C*"))
|
|
78
81
|
end
|
|
79
82
|
|
|
83
|
+
# Whether each byte times a half wave, as on a version 2 tape.
|
|
84
|
+
def half_waves? = version == 2
|
|
85
|
+
|
|
80
86
|
# Cycles until the next falling edge, or nil once the tape has run out.
|
|
87
|
+
# On a version 2 tape that is two half waves, or one left at the end.
|
|
81
88
|
def next_pulse
|
|
82
89
|
return if end?
|
|
90
|
+
return next_time unless half_waves?
|
|
91
|
+
|
|
92
|
+
first = next_time
|
|
93
|
+
end? ? first : first + next_time
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Cycles until the read line's next edge on a version 2 tape, or nil
|
|
97
|
+
# once the tape has run out.
|
|
98
|
+
def next_half_wave
|
|
99
|
+
next_time unless end?
|
|
100
|
+
end
|
|
83
101
|
|
|
102
|
+
private
|
|
103
|
+
|
|
104
|
+
def next_time
|
|
84
105
|
byte = @bytes[@pos]
|
|
85
106
|
@pos += 1
|
|
86
107
|
return byte * 8 unless byte.zero?
|
|
87
108
|
|
|
88
|
-
# $00 is an overflow in version 0 and a 24-bit cycle count
|
|
89
|
-
# version 1.
|
|
109
|
+
# $00 is an overflow in version 0 and a 24-bit cycle count from
|
|
110
|
+
# version 1 on.
|
|
90
111
|
version.zero? ? OVERFLOW : long_pulse
|
|
91
112
|
end
|
|
92
113
|
|
|
93
|
-
|
|
114
|
+
def encode(cycles)
|
|
115
|
+
units = (cycles + 4) / 8
|
|
116
|
+
return [units] if units.between?(1, 0xff)
|
|
117
|
+
return [0] if version.zero?
|
|
118
|
+
|
|
119
|
+
count = [cycles, 0xffffff].min
|
|
120
|
+
[0, count & 0xff, (count >> 8) & 0xff, count >> 16]
|
|
121
|
+
end
|
|
94
122
|
|
|
95
123
|
# The stated size disagrees with the file in the wild, and a few dumps
|
|
96
124
|
# leave it zeroed altogether.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module Badline
|
|
4
4
|
module Storage
|
|
5
5
|
# Stands in for a directory a detached restore leaves out
|
|
6
|
-
# (Snapshot::
|
|
6
|
+
# (Snapshot::StorageSetup): it finds no files and refuses every write
|
|
7
7
|
# as a write-protected disk does.
|
|
8
8
|
class Unavailable
|
|
9
9
|
def path = ""
|
data/lib/badline/storage.rb
CHANGED
|
@@ -11,10 +11,6 @@ require "badline/storage/g64_image"
|
|
|
11
11
|
require "badline/storage/t64"
|
|
12
12
|
require "badline/storage/tap"
|
|
13
13
|
require "badline/storage/crt_file"
|
|
14
|
-
require "badline/storage/sid_file"
|
|
15
|
-
require "badline/storage/hvsc"
|
|
16
|
-
require "badline/storage/song_lengths"
|
|
17
|
-
require "badline/storage/stil"
|
|
18
14
|
require "badline/storage/unavailable"
|
|
19
15
|
|
|
20
16
|
module Badline
|
|
@@ -36,29 +32,7 @@ module Badline
|
|
|
36
32
|
end
|
|
37
33
|
end
|
|
38
34
|
|
|
39
|
-
# The storage a snapshot's device 8 serves, by the number save_setup
|
|
40
|
-
# writes first.
|
|
41
|
-
HOST_DIRECTORY = 0
|
|
42
|
-
D64 = 1
|
|
43
|
-
D71 = 2
|
|
44
|
-
D81 = 3
|
|
45
|
-
T64_ARCHIVE = 4
|
|
46
|
-
|
|
47
35
|
class << self
|
|
48
|
-
# Opens the storage a save_setup wrote: the same directory by its
|
|
49
|
-
# path, an archive with the bytes it held, or a disk image with the
|
|
50
|
-
# bytes it held, writes and all. A detached reader gets the image
|
|
51
|
-
# write-protected, and Unavailable for a directory.
|
|
52
|
-
def reopen(input)
|
|
53
|
-
kind = input.int
|
|
54
|
-
path = input.string
|
|
55
|
-
case kind
|
|
56
|
-
when HOST_DIRECTORY then input.detached? ? Unavailable.new : HostDirectory.new(path)
|
|
57
|
-
when T64_ARCHIVE then T64.new(path, bytes: input.blob)
|
|
58
|
-
else reopen_image(kind, path, input)
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
|
|
62
36
|
# Folds shifted PETSCII letters to their ASCII equivalents.
|
|
63
37
|
def ascii(bytes)
|
|
64
38
|
bytes.map { |b| b.between?(0xc1, 0xda) ? b - 0x80 : b }.pack("C*")
|
|
@@ -83,17 +57,6 @@ module Badline
|
|
|
83
57
|
[base.to_s, FILE_TYPES[type.to_s.strip[0]&.upcase]]
|
|
84
58
|
end
|
|
85
59
|
|
|
86
|
-
def reopen_image(kind, path, input)
|
|
87
|
-
read_only = input.boolean? || input.detached?
|
|
88
|
-
bytes = input.blob
|
|
89
|
-
case kind
|
|
90
|
-
when D64 then D64Image.new(path, read_only:, bytes:)
|
|
91
|
-
when D71 then D71Image.new(path, read_only:, bytes:)
|
|
92
|
-
when D81 then D81Image.new(path, read_only:, bytes:)
|
|
93
|
-
else raise Snapshot::FormatError, "unknown storage #{kind} in the state"
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
|
|
97
60
|
# CBM-style filename pattern: "*" and "?" wildcards, case-insensitive.
|
|
98
61
|
# The DOS stops comparing at the first "*", so whatever follows it
|
|
99
62
|
# is ignored.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Support
|
|
5
|
+
# A Checkpoint of a C128, in either mode: a C64's components, with the
|
|
6
|
+
# whole 128K of RAM in place of bank 0 and the colour RAM bank the 8502
|
|
7
|
+
# sees, and besides them the VDC's registers and beam, the VDC's RAM, the
|
|
8
|
+
# MMU's registers and the Z80.
|
|
9
|
+
module C128Checkpoint
|
|
10
|
+
COMPONENTS = %w[cpu ram color_ram display vic cia1 cia2 sid vdc vdc_ram mmu z80].freeze
|
|
11
|
+
|
|
12
|
+
def self.take(machine)
|
|
13
|
+
Checkpoint.new(machine.cycles, [
|
|
14
|
+
Checkpoint.fnv1a(Checkpoint.cpu_state(machine.cpu)),
|
|
15
|
+
Checkpoint.fnv1a(Checkpoint.ram(machine.ram, 0x20000)),
|
|
16
|
+
Checkpoint.fnv1a(Checkpoint.color_ram(machine.address_bus.color_ram, 0xd800)),
|
|
17
|
+
Checkpoint.fnv1a(machine.vic.display),
|
|
18
|
+
Checkpoint.fnv1a(Checkpoint.vic_state(machine.vic)),
|
|
19
|
+
Checkpoint.fnv1a(Checkpoint.cia_state(machine.cia1)),
|
|
20
|
+
Checkpoint.fnv1a(Checkpoint.cia_state(machine.cia2)),
|
|
21
|
+
Checkpoint.fnv1a(Array.new(0x20) { |reg| machine.sid.register(reg) }),
|
|
22
|
+
Checkpoint.fnv1a(machine.vdc.registers + [machine.vdc.frame]),
|
|
23
|
+
Checkpoint.fnv1a(machine.vdc.ram),
|
|
24
|
+
Checkpoint.fnv1a(machine.mmu.registers),
|
|
25
|
+
Checkpoint.fnv1a(z80_state(machine.z80))
|
|
26
|
+
], COMPONENTS)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.parse(line) = Checkpoint.parse(line, COMPONENTS)
|
|
30
|
+
|
|
31
|
+
def self.z80_state(z80)
|
|
32
|
+
[z80.pc, z80.sp, z80.af, z80.bc, z80.de, z80.hl, z80.ix, z80.iy, z80.af_alt, z80.bc_alt, z80.de_alt,
|
|
33
|
+
z80.hl_alt, z80.i, z80.r, z80.im, flag(z80.iff1), flag(z80.iff2), flag(z80.halted), z80.cycles]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.flag(value) = value == true ? 1 : 0
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Support
|
|
5
|
+
# A digest of the machine's state at one cycle, for comparing two runs of
|
|
6
|
+
# the same scenario, on two builds or two revisions. Each component is
|
|
7
|
+
# hashed on its own with 32-bit FNV-1a, so a mismatch names the part of the
|
|
8
|
+
# machine that went its own way. Nothing is read through a chip's bus
|
|
9
|
+
# interface, so taking a checkpoint leaves the machine as it was.
|
|
10
|
+
#
|
|
11
|
+
# Checkpoint.take digests a C64's components, COMPONENTS.
|
|
12
|
+
# Vic20Checkpoint and C128Checkpoint digest the other families', each
|
|
13
|
+
# with a list of its own, which a checkpoint carries as +components+.
|
|
14
|
+
#
|
|
15
|
+
# Colour RAM is digested as the four bits each cell stores: the upper
|
|
16
|
+
# nibble a CPU read sees comes off the open bus.
|
|
17
|
+
class Checkpoint
|
|
18
|
+
COMPONENTS = %w[cpu ram color_ram display vic cia1 cia2 sid].freeze
|
|
19
|
+
|
|
20
|
+
FNV_OFFSET = 0x811c9dc5
|
|
21
|
+
FNV_PRIME = 0x01000193
|
|
22
|
+
|
|
23
|
+
attr_reader :cycle, :digests, :components
|
|
24
|
+
|
|
25
|
+
class << self
|
|
26
|
+
def take(computer)
|
|
27
|
+
new(computer.cycles, [
|
|
28
|
+
fnv1a(cpu_state(computer.cpu)),
|
|
29
|
+
fnv1a(ram(computer.ram, 0x10000)),
|
|
30
|
+
fnv1a(color_ram(computer.address_bus.color_ram, 0xd800)),
|
|
31
|
+
fnv1a(computer.vic.display),
|
|
32
|
+
fnv1a(vic_state(computer.vic)),
|
|
33
|
+
fnv1a(cia_state(computer.cia1)),
|
|
34
|
+
fnv1a(cia_state(computer.cia2)),
|
|
35
|
+
fnv1a(Array.new(0x20) { |reg| computer.sid.register(reg) })
|
|
36
|
+
])
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Reads a line written by #to_s, with a digest for each of
|
|
40
|
+
# `components`.
|
|
41
|
+
def parse(line, components = COMPONENTS)
|
|
42
|
+
fields = line.split
|
|
43
|
+
digests = components.map do |name|
|
|
44
|
+
field = fields.find { |f| f.start_with?("#{name}=") }
|
|
45
|
+
raise ArgumentError, "no #{name} digest in #{line.inspect}" unless field
|
|
46
|
+
|
|
47
|
+
field.split("=").last.to_i(16)
|
|
48
|
+
end
|
|
49
|
+
new(fields.first.to_i, digests, components)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def fnv1a(values)
|
|
53
|
+
hash = FNV_OFFSET
|
|
54
|
+
values.each { |value| hash = ((hash ^ (value & 0xffffffff)) * FNV_PRIME) & 0xffffffff }
|
|
55
|
+
hash
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# The registers and cycle count of a 6502 or an 8502.
|
|
59
|
+
def cpu_state(cpu)
|
|
60
|
+
[cpu.program_counter, cpu.a, cpu.x, cpu.y, cpu.stack_pointer, cpu.p, cpu.cycles]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# The first `length` bytes of `memory`.
|
|
64
|
+
def ram(memory, length)
|
|
65
|
+
Array.new(length) { |addr| memory.peek(addr) }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# The 1K of colour RAM at `start`.
|
|
69
|
+
def color_ram(memory, start)
|
|
70
|
+
Array.new(0x400) { |offset| memory.nibble(start + offset) }
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# A VIC-II's or a VIC-I's registers and beam position.
|
|
74
|
+
def vic_state(vic)
|
|
75
|
+
vic.register_file + [vic.rasterline, vic.column]
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def cia_state(cia)
|
|
79
|
+
start = cia.start
|
|
80
|
+
[cia.peek(start), cia.peek(start + 1), cia.peek(start + 2), cia.peek(start + 3),
|
|
81
|
+
cia.timer_a, cia.timer_a_latch, cia.timer_b, cia.timer_b_latch, cia.serial.data,
|
|
82
|
+
cia.control_a.value, cia.control_b.value, cia.interrupt_status.value,
|
|
83
|
+
cia.interrupt_control.value] + cia.time_of_day.registers
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def initialize(cycle, digests, components = COMPONENTS)
|
|
88
|
+
@cycle = cycle
|
|
89
|
+
@digests = digests
|
|
90
|
+
@components = components
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# The components whose digests differ from `other`'s.
|
|
94
|
+
def differences(other)
|
|
95
|
+
components.each_index.reject { |i| digests[i] == other.digests[i] }.map { |i| components[i] }
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def ==(other)
|
|
99
|
+
other.is_a?(Checkpoint) && cycle == other.cycle && components == other.components && digests == other.digests
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def to_s
|
|
103
|
+
fields = components.each_index.map { |i| "#{components[i]}=#{digests[i].to_s(16).rjust(8, '0')}" }
|
|
104
|
+
"#{cycle} #{fields.join(' ')}"
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Support
|
|
5
|
+
# A Checkpoint of a VIC-20: its CPU, the 48K of RAM the bus decodes, the
|
|
6
|
+
# colour RAM, the VIC-I's display and registers, both VIAs and the
|
|
7
|
+
# sound. The sound's shift registers and noise LFSR move only while it
|
|
8
|
+
# records, so a run that wants them digested records it.
|
|
9
|
+
module Vic20Checkpoint
|
|
10
|
+
COMPONENTS = %w[cpu ram color_ram display vic via1 via2 sound].freeze
|
|
11
|
+
|
|
12
|
+
def self.take(machine)
|
|
13
|
+
Checkpoint.new(machine.cycles, [
|
|
14
|
+
Checkpoint.fnv1a(Checkpoint.cpu_state(machine.cpu)),
|
|
15
|
+
Checkpoint.fnv1a(Checkpoint.ram(machine.ram, 0xc000)),
|
|
16
|
+
Checkpoint.fnv1a(Checkpoint.color_ram(machine.bus.color_ram, 0)),
|
|
17
|
+
Checkpoint.fnv1a(machine.vic.display),
|
|
18
|
+
Checkpoint.fnv1a(Checkpoint.vic_state(machine.vic)),
|
|
19
|
+
Checkpoint.fnv1a(via_state(machine.via1)),
|
|
20
|
+
Checkpoint.fnv1a(via_state(machine.via2)),
|
|
21
|
+
Checkpoint.fnv1a(sound_state(machine.sound))
|
|
22
|
+
], COMPONENTS)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.parse(line) = Checkpoint.parse(line, COMPONENTS)
|
|
26
|
+
|
|
27
|
+
def self.via_state(via)
|
|
28
|
+
[via.port_a_output, via.port_b_output, via.timer1, via.timer1_latch, via.timer2,
|
|
29
|
+
via.shift_register.data, via.acr, via.pcr, via.interrupt_flags, via.interrupt_enable]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.sound_state(sound)
|
|
33
|
+
[sound.volume, sound.shift_register(0), sound.shift_register(1), sound.shift_register(2),
|
|
34
|
+
sound.shift_register(3), sound.lfsr]
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
data/lib/badline/version.rb
CHANGED
|
@@ -4,11 +4,11 @@ module Badline
|
|
|
4
4
|
class Vic20
|
|
5
5
|
# What plugs into the VIC-20 besides its chips: cartridge ROM in the
|
|
6
6
|
# expansion blocks, the disk device 8 serves through the KERNAL traps
|
|
7
|
-
# (
|
|
8
|
-
# (
|
|
7
|
+
# (C64::KernalTraps), and a true 1541 or 1581 on the serial bus
|
|
8
|
+
# (C64::TrueDrives).
|
|
9
9
|
module Attachments
|
|
10
|
-
include
|
|
11
|
-
include
|
|
10
|
+
include C64::TrueDrives
|
|
11
|
+
include C64::KernalTraps
|
|
12
12
|
|
|
13
13
|
# The cycle by which a 1541 switched on with the machine has run its
|
|
14
14
|
# DOS's reset, the RAM test and the ROM checksum, and waits on the
|
|
@@ -34,6 +34,9 @@ module Badline
|
|
|
34
34
|
# The VIC-20's KERNAL, which the traps stand in for.
|
|
35
35
|
def trap_layout = KernalTrap::VIC20_LAYOUT
|
|
36
36
|
|
|
37
|
+
# The VIC-20's KERNAL keeps its keyboard buffer where the C64's does.
|
|
38
|
+
def keyboard_buffer = Machine::KeyboardBuffer::C64_LAYOUT
|
|
39
|
+
|
|
37
40
|
def trap_bus = @bus
|
|
38
41
|
|
|
39
42
|
# A drive that powers on with the machine takes longer to boot than
|
|
@@ -46,7 +49,7 @@ module Badline
|
|
|
46
49
|
# A 1581 plugged in, as a 1541 does, holds the machine's on_init
|
|
47
50
|
# handlers back until its DOS has booted.
|
|
48
51
|
def drive1581_attached
|
|
49
|
-
@init_threshold = [@init_threshold,
|
|
52
|
+
@init_threshold = [@init_threshold, Drives::Model1581::BOOT_CYCLES].max if @cycles < @init_threshold
|
|
50
53
|
end
|
|
51
54
|
end
|
|
52
55
|
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
class Vic20
|
|
5
|
+
class Bus
|
|
6
|
+
class ColorRAM
|
|
7
|
+
# The cells in a keyed snapshot module, under `key`.
|
|
8
|
+
def save_fields(out, key) = out.bytes(key, @cells)
|
|
9
|
+
|
|
10
|
+
def load_fields(input, key) = input.bytes_into(key, @cells)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# The bytes each side's data lines hold, under `prefix`, and a
|
|
14
|
+
# cartridge's ROM chips as rom<N>.start and rom<N>.bytes, in a keyed
|
|
15
|
+
# snapshot module (Snapshot::Keyed). The pages are mapped again once
|
|
16
|
+
# they are loaded.
|
|
17
|
+
module KeyedState
|
|
18
|
+
def save_fields(out, prefix)
|
|
19
|
+
out.int("#{prefix}data", @data).int("#{prefix}video_data", @video_data)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def load_fields(input, prefix)
|
|
23
|
+
@data = input.byte("#{prefix}data", @data)
|
|
24
|
+
@video_data = input.byte("#{prefix}video_data", @video_data)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Whether a cartridge's ROM chips are in the expansion blocks.
|
|
28
|
+
def cartridge? = !@roms.empty?
|
|
29
|
+
|
|
30
|
+
def save_rom_fields(out)
|
|
31
|
+
out.int("roms", @roms.length)
|
|
32
|
+
@roms.each_with_index do |rom, number|
|
|
33
|
+
out.int("rom#{number}.start", rom.start)
|
|
34
|
+
rom.save_fields(out, "rom#{number}.bytes")
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def load_rom_fields(input)
|
|
39
|
+
@roms = []
|
|
40
|
+
input.int("roms", 0).times do |number|
|
|
41
|
+
bytes = input.bytes("rom#{number}.bytes", "".b).bytes
|
|
42
|
+
@roms << ROM.new(bytes, length: bytes.length, start: input.word("rom#{number}.start", 0))
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def restored! = map_pages
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
include KeyedState
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
data/lib/badline/vic20/bus.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "badline/vic20/bus/keyed_state"
|
|
4
|
+
|
|
3
5
|
module Badline
|
|
4
6
|
class Vic20
|
|
5
7
|
# The CPU's bus:
|
|
@@ -215,31 +217,6 @@ module Badline
|
|
|
215
217
|
@ram.clear!(RAM_POWER_ON)
|
|
216
218
|
end
|
|
217
219
|
|
|
218
|
-
# The RAM, the colour RAM, the byte each side's data lines hold and the
|
|
219
|
-
# cartridge's ROM chips, for a snapshot. The expansion blocks are how
|
|
220
|
-
# the machine was built.
|
|
221
|
-
def save_state(out)
|
|
222
|
-
out.marker("VIC20 BUS")
|
|
223
|
-
@ram.save_state(out)
|
|
224
|
-
out.blob(@color_ram.cells).int(@data).int(@video_data).int(@roms.length)
|
|
225
|
-
@roms.each do |rom|
|
|
226
|
-
out.int(rom.start)
|
|
227
|
-
rom.save_state(out)
|
|
228
|
-
end
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
def load_state(input)
|
|
232
|
-
input.marker("VIC20 BUS")
|
|
233
|
-
@ram.load_state(input)
|
|
234
|
-
input.blob_into(@color_ram.cells)
|
|
235
|
-
@data = input.int
|
|
236
|
-
@video_data = input.int
|
|
237
|
-
chips = Array.new(input.int) { [input.int, input.blob] }
|
|
238
|
-
@roms = []
|
|
239
|
-
chips.each { |chip| @roms << ROM.new(chip[1], length: chip[1].length, start: chip[0]) }
|
|
240
|
-
map_pages
|
|
241
|
-
end
|
|
242
|
-
|
|
243
220
|
# Whether +block+ (BLOCKS) holds RAM.
|
|
244
221
|
def ram?(block) = @blocks.include?(block)
|
|
245
222
|
|
data/lib/badline/vic20/cpu.rb
CHANGED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
class Vic20
|
|
5
|
+
# The whole machine as keyed snapshot modules (Snapshot::Keyed), in the
|
|
6
|
+
# order a load applies them, as C64::KeyedModules: BL-MACHINE with the
|
|
7
|
+
# RAM expansion and the bytes each side's data lines hold under bus.*,
|
|
8
|
+
# the memories, a cartridge's ROM chips, the VIC with its sound, both
|
|
9
|
+
# VIAs, the CPU, the datasette, device 8 through the traps and the true
|
|
10
|
+
# drives.
|
|
11
|
+
module KeyedModules
|
|
12
|
+
def save_modules
|
|
13
|
+
bus = @bus
|
|
14
|
+
sections = [Snapshot::Keyed.section("BL-MACHINE") do |out|
|
|
15
|
+
save_machine_fields(out)
|
|
16
|
+
bus.save_fields(out, "bus.")
|
|
17
|
+
end]
|
|
18
|
+
sections << Snapshot::Keyed.section("BL-RAM") { |out| bus.ram.save_fields(out, "ram") }
|
|
19
|
+
sections << Snapshot::Keyed.section("BL-COLORRAM") { |out| bus.color_ram.save_fields(out, "ram") }
|
|
20
|
+
sections << Snapshot::Keyed.section("BL-CART") { |out| bus.save_rom_fields(out) } if bus.cartridge?
|
|
21
|
+
sections << Snapshot::Keyed.section("BL-CPU") { |out| @cpu.save_fields(out) }
|
|
22
|
+
sections << Snapshot::Keyed.section("BL-VICI") { |out| @vic.save_fields(out) }
|
|
23
|
+
sections << Snapshot::Keyed.section("BL-VIA1") { |out| @via1.save_fields(out) }
|
|
24
|
+
sections << Snapshot::Keyed.section("BL-VIA2") { |out| @via2.save_fields(out) }
|
|
25
|
+
sections << Snapshot::Keyed.section("BL-TAPE") { |out| @datasette.save_fields(out) }
|
|
26
|
+
sections << Snapshot::Keyed.section("BL-TRAPDOS") { |out| save_trap_dos_fields(out) } if mounted?
|
|
27
|
+
save_drive_modules(sections)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Raises Snapshot::FormatError for the modules of a VIC-20 with
|
|
31
|
+
# another RAM expansion.
|
|
32
|
+
def load_modules(modules)
|
|
33
|
+
machine = modules.machine
|
|
34
|
+
check_snapshot_setup(Snapshot::Vic20Setup.read_fields(machine))
|
|
35
|
+
load_machine_fields(machine)
|
|
36
|
+
bus = @bus
|
|
37
|
+
bus.load_fields(machine, "bus.")
|
|
38
|
+
bus.ram.load_fields(modules.required("BL-RAM"), "ram")
|
|
39
|
+
bus.color_ram.load_fields(modules.required("BL-COLORRAM"), "ram")
|
|
40
|
+
bus.load_rom_fields(modules.optional("BL-CART") || Snapshot::Keyed::Reader.new("BL-CART"))
|
|
41
|
+
bus.restored!
|
|
42
|
+
@vic.load_fields(modules.required("BL-VICI"))
|
|
43
|
+
@via1.load_fields(modules.required("BL-VIA1"))
|
|
44
|
+
@via2.load_fields(modules.required("BL-VIA2"))
|
|
45
|
+
@cpu.load_fields(modules.required("BL-CPU"))
|
|
46
|
+
@datasette.load_fields(modules.required("BL-TAPE"))
|
|
47
|
+
trap_dos = modules.optional("BL-TRAPDOS")
|
|
48
|
+
trap_dos ? load_trap_dos_fields(trap_dos, detached: modules.detached?) : unmount
|
|
49
|
+
load_drive_modules(modules)
|
|
50
|
+
modules_restored!
|
|
51
|
+
self
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def modules_restored!
|
|
57
|
+
@cpu.restored!
|
|
58
|
+
@vic.restored!
|
|
59
|
+
@via1.restored!
|
|
60
|
+
@via2.restored!
|
|
61
|
+
machine_restored!
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def check_snapshot_setup(setup)
|
|
65
|
+
return if setup.ram == @ram_configuration
|
|
66
|
+
|
|
67
|
+
raise Snapshot::FormatError, "the snapshot is of a VIC-20 with #{setup.ram} RAM, not #{@ram_configuration}"
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
include KeyedModules
|
|
72
|
+
end
|
|
73
|
+
end
|