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
data/lib/badline/snapshot.rb
CHANGED
|
@@ -4,7 +4,6 @@ require "zlib"
|
|
|
4
4
|
require "badline/snapshot/state"
|
|
5
5
|
require "badline/snapshot/setup"
|
|
6
6
|
require "badline/snapshot/container"
|
|
7
|
-
require "badline/snapshot/fields"
|
|
8
7
|
require "badline/snapshot/machine_state"
|
|
9
8
|
require "badline/snapshot/vice"
|
|
10
9
|
require "badline/snapshot/image"
|
|
@@ -14,7 +13,7 @@ module Badline
|
|
|
14
13
|
#
|
|
15
14
|
# A snapshot badline writes carries VICE's modules for what both
|
|
16
15
|
# emulators model, and a BADLINE module holding the State
|
|
17
|
-
#
|
|
16
|
+
# C64#snapshot takes, with everything badline needs to carry on
|
|
18
17
|
# exactly where it stopped. VICE skips modules it doesn't know. Restoring
|
|
19
18
|
# a badline snapshot uses the BADLINE module alone; a snapshot from VICE
|
|
20
19
|
# restores through its modules, as far as they map, and reports the
|
|
@@ -47,23 +46,25 @@ module Badline
|
|
|
47
46
|
# applied and left out, yielding a line for each thing left out. A
|
|
48
47
|
# snapshot that fails leaves the machine as it was.
|
|
49
48
|
def restore(computer, path, &) = read(path).restore(computer, &)
|
|
50
|
-
end
|
|
51
49
|
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
# A machine's snapshots as .vsf files. C64, Vic20 and C128 each
|
|
51
|
+
# include it.
|
|
52
|
+
module Files
|
|
53
|
+
def save_snapshot(path) = Snapshot.save(self, path)
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
def restore_snapshot(path, &) = Snapshot.restore(self, path, &)
|
|
56
|
+
end
|
|
56
57
|
end
|
|
57
58
|
|
|
58
|
-
class
|
|
59
|
-
|
|
59
|
+
class C64
|
|
60
|
+
include Snapshot::Files
|
|
61
|
+
end
|
|
60
62
|
|
|
61
|
-
|
|
63
|
+
class Vic20
|
|
64
|
+
include Snapshot::Files
|
|
62
65
|
end
|
|
63
66
|
|
|
64
67
|
class C128
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def restore_snapshot(path, &) = Snapshot.restore(self, path, &)
|
|
68
|
+
include Snapshot::Files
|
|
68
69
|
end
|
|
69
70
|
end
|
|
@@ -15,20 +15,26 @@ module Badline
|
|
|
15
15
|
count
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
def storage_kind = D64
|
|
19
|
-
|
|
20
18
|
# The sides of a disk the image's tracks fill.
|
|
21
19
|
def sides = 1
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
21
|
+
# The last track of each of the 1541's speed zones but the innermost,
|
|
22
|
+
# from the outermost, zone 3, in: tracks 1-17, 18-24 and 25-30, and
|
|
23
|
+
# zone 0 from 31 on.
|
|
24
|
+
ZONE_LAST_TRACKS = [17, 24, 30].freeze
|
|
25
|
+
|
|
26
|
+
# The sectors a track holds in each zone, by its number.
|
|
27
|
+
ZONE_SECTORS = [17, 18, 19, 21].freeze
|
|
28
|
+
|
|
29
|
+
# The speed zone a track is written in, 3 for the outermost.
|
|
30
|
+
def self.zone(track)
|
|
31
|
+
zone = 3
|
|
32
|
+
zone -= 1 while zone.positive? && track > ZONE_LAST_TRACKS[3 - zone]
|
|
33
|
+
zone
|
|
30
34
|
end
|
|
31
35
|
|
|
36
|
+
def sectors_in(track) = ZONE_SECTORS[D64Image.zone(track)]
|
|
37
|
+
|
|
32
38
|
private
|
|
33
39
|
|
|
34
40
|
def error_tables = ERROR_TABLES
|
|
@@ -11,7 +11,7 @@ module Badline
|
|
|
11
11
|
module Writing
|
|
12
12
|
# Whether the disk takes writes: the image wasn't opened read-only
|
|
13
13
|
# and the host file takes them.
|
|
14
|
-
def writable? = !read_only? &&
|
|
14
|
+
def writable? = !read_only? && File.writable?(@path)
|
|
15
15
|
|
|
16
16
|
# Writes a new file, or with `replace` writes over the one of the
|
|
17
17
|
# same name in its directory entry. A name already on the disk
|
|
@@ -87,7 +87,7 @@ module Badline
|
|
|
87
87
|
saved = [@bytes.dup, @errors&.dup]
|
|
88
88
|
begin
|
|
89
89
|
yield
|
|
90
|
-
|
|
90
|
+
File.binwrite(@path, (@bytes + @errors.to_a).pack("C*"))
|
|
91
91
|
rescue WriteError, SystemCallError => e
|
|
92
92
|
@bytes, @errors = saved
|
|
93
93
|
raise e.is_a?(WriteError) ? e : WriteError.new(WriteError::WRITE_PROTECT_ON)
|
|
@@ -42,12 +42,9 @@ module Badline
|
|
|
42
42
|
# Whether the image was opened write-protected.
|
|
43
43
|
def read_only? = @read_only
|
|
44
44
|
|
|
45
|
-
#
|
|
46
|
-
#
|
|
47
|
-
|
|
48
|
-
def save_setup(out)
|
|
49
|
-
out.int(storage_kind).string(::File.expand_path(@path)).boolean(@read_only).blob(@bytes + @errors.to_a)
|
|
50
|
-
end
|
|
45
|
+
# The image as its file holds it, with its error table after the
|
|
46
|
+
# blocks.
|
|
47
|
+
def contents = @bytes + @errors.to_a
|
|
51
48
|
|
|
52
49
|
# A LOAD reads only PRG files. An OPEN names the type it wants, or
|
|
53
50
|
# takes the first file of any type with a nil `type`.
|
|
@@ -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,
|
|
@@ -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)
|
|
@@ -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
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
module Badline
|
|
4
4
|
class Vic20
|
|
5
5
|
# What plugs into the VIC-20 besides its chips: cartridge ROM in the
|
|
6
|
-
# expansion blocks, the disk device 8 serves through the KERNAL traps
|
|
7
|
-
# and a true 1541 or 1581 on the serial bus
|
|
6
|
+
# expansion blocks, the disk device 8 serves through the KERNAL traps
|
|
7
|
+
# (C64::KernalTraps), and a true 1541 or 1581 on the serial bus
|
|
8
|
+
# (C64::TrueDrives).
|
|
8
9
|
module Attachments
|
|
9
|
-
include
|
|
10
|
+
include C64::TrueDrives
|
|
11
|
+
include C64::KernalTraps
|
|
10
12
|
|
|
11
13
|
# The cycle by which a 1541 switched on with the machine has run its
|
|
12
14
|
# DOS's reset, the RAM test and the ROM checksum, and waits on the
|
|
@@ -27,96 +29,24 @@ module Badline
|
|
|
27
29
|
power_cycle!
|
|
28
30
|
end
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
# point while the machine runs: the drive keeps its RAM and its
|
|
32
|
-
# status.
|
|
33
|
-
def mount(storage)
|
|
34
|
-
return @drive.insert(storage) if @drive
|
|
35
|
-
|
|
36
|
-
@drive = KernalTrap::Drive.new(storage)
|
|
37
|
-
layout = KernalTrap::VIC20_LAYOUT
|
|
38
|
-
load_trap = KernalTrap::Load.new(cpu:, bus:, layout:, drive: @drive)
|
|
39
|
-
cpu.install_trap(layout.load) { load_trap.call }
|
|
40
|
-
@serial_trap = KernalTrap::Serial.new(cpu:, bus:, layout:, drive: @drive, device: serial_trap_device).install
|
|
41
|
-
save_trap = @save_trap = KernalTrap::Save.new(cpu:, bus:, layout:, drive: @drive)
|
|
42
|
-
cpu.install_trap(layout.save) { save_trap.call }
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# Takes device 8's mounted storage out, and with it the LOAD, SAVE and
|
|
46
|
-
# serial traps, so the KERNAL's routines go out over the serial bus.
|
|
47
|
-
# Mounting again starts a new drive, with its RAM cleared.
|
|
48
|
-
def unmount
|
|
49
|
-
return unless @drive
|
|
32
|
+
private
|
|
50
33
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
@serial_trap.uninstall
|
|
54
|
-
@serial_trap = nil
|
|
55
|
-
@save_trap = nil
|
|
56
|
-
@drive = nil
|
|
57
|
-
end
|
|
34
|
+
# The VIC-20's KERNAL, which the traps stand in for.
|
|
35
|
+
def trap_layout = KernalTrap::VIC20_LAYOUT
|
|
58
36
|
|
|
59
|
-
|
|
60
|
-
def mounted? = !@drive.nil?
|
|
37
|
+
def trap_bus = @bus
|
|
61
38
|
|
|
62
|
-
# Plugs in a Drive1541, which then runs alongside the VIC-20 on its own
|
|
63
|
-
# clock and talks to it over the serial bus. The serial traps stop
|
|
64
|
-
# answering the drive's device number, so the KERNAL's TALK, LISTEN
|
|
65
|
-
# and byte transfers reach the drive. The LOAD and SAVE traps stay,
|
|
66
|
-
# and still serve a mounted image.
|
|
67
|
-
#
|
|
68
39
|
# A drive that powers on with the machine takes longer to boot than
|
|
69
40
|
# the KERNAL, and doesn't answer the bus until it has, so the
|
|
70
41
|
# machine's on_init handlers wait for it too.
|
|
71
|
-
def
|
|
42
|
+
def drive1541_attached
|
|
72
43
|
@init_threshold = [@init_threshold, DRIVE_BOOT_CYCLES].max if @cycles < @init_threshold
|
|
73
|
-
@iec_bus.detach(@drive1541) if @drive1541
|
|
74
|
-
drive.host_clock_hz = timing.clock_hz
|
|
75
|
-
@drive1541 = drive
|
|
76
|
-
drive.connect(@iec_bus)
|
|
77
|
-
@serial_trap&.device = serial_trap_device
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
# The true drive on the serial bus: the Drive1581 ahead of the
|
|
81
|
-
# Drive1541, or nil.
|
|
82
|
-
def true_drive = @drive1581 || @drive1541
|
|
83
|
-
|
|
84
|
-
# Plugs a Drive1541 in as device 8, in place of a 1581 there, and
|
|
85
|
-
# returns it.
|
|
86
|
-
def plug_true_drive
|
|
87
|
-
detach_drive1581 if drive1581_on_device8?
|
|
88
|
-
Drive1541.new.tap { |drive| attach_drive1541(drive) }
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
# Unplugs the Drive1541, leaving the serial bus with nothing on it.
|
|
92
|
-
def detach_drive1541
|
|
93
|
-
return unless @drive1541
|
|
94
|
-
|
|
95
|
-
@iec_bus.detach(@drive1541)
|
|
96
|
-
@drive1541 = nil
|
|
97
|
-
@serial_trap&.device = serial_trap_device
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
# Records what the KERNAL prints through CHROUT (ChroutTrap).
|
|
101
|
-
def capture_output
|
|
102
|
-
@capture_output ||= ChroutTrap.new(cpu:, bus:, layout: KernalTrap::VIC20_LAYOUT).tap do |trap|
|
|
103
|
-
cpu.install_trap(ChroutTrap::ADDRESS) { trap.call }
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
private
|
|
108
|
-
|
|
109
|
-
# The device number the serial traps answer: device 8, unless a true
|
|
110
|
-
# drive is on the bus as device 8.
|
|
111
|
-
def serial_trap_device
|
|
112
|
-
device = KernalTrap::Routine::DEVICE
|
|
113
|
-
@drive1541&.device == device || drive1581_on_device8? ? nil : device
|
|
114
44
|
end
|
|
115
45
|
|
|
116
46
|
# A 1581 plugged in, as a 1541 does, holds the machine's on_init
|
|
117
47
|
# handlers back until its DOS has booted.
|
|
118
48
|
def drive1581_attached
|
|
119
|
-
@init_threshold = [@init_threshold,
|
|
49
|
+
@init_threshold = [@init_threshold, Drives::Model1581::BOOT_CYCLES].max if @cycles < @init_threshold
|
|
120
50
|
end
|
|
121
51
|
end
|
|
122
52
|
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
class Vic20
|
|
5
|
+
class Bus
|
|
6
|
+
# The bus's state for a snapshot.
|
|
7
|
+
module SavedState
|
|
8
|
+
# The RAM, the colour RAM, the byte each side's data lines hold and the
|
|
9
|
+
# cartridge's ROM chips, for a snapshot. The expansion blocks are how
|
|
10
|
+
# the machine was built.
|
|
11
|
+
def save_state(out)
|
|
12
|
+
out.marker("VIC20 BUS")
|
|
13
|
+
@ram.save_state(out)
|
|
14
|
+
out.blob(@color_ram.cells).int(@data).int(@video_data).int(@roms.length)
|
|
15
|
+
@roms.each do |rom|
|
|
16
|
+
out.int(rom.start)
|
|
17
|
+
rom.save_state(out)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def load_state(input)
|
|
22
|
+
input.marker("VIC20 BUS")
|
|
23
|
+
@ram.load_state(input)
|
|
24
|
+
input.blob_into(@color_ram.cells)
|
|
25
|
+
@data = input.int
|
|
26
|
+
@video_data = input.int
|
|
27
|
+
chips = Array.new(input.int) { [input.int, input.blob] }
|
|
28
|
+
@roms = []
|
|
29
|
+
chips.each { |chip| @roms << ROM.new(chip[1], length: chip[1].length, start: chip[0]) }
|
|
30
|
+
map_pages
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
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/saved_state"
|
|
4
|
+
|
|
3
5
|
module Badline
|
|
4
6
|
class Vic20
|
|
5
7
|
# The CPU's bus:
|
|
@@ -27,6 +29,7 @@ module Badline
|
|
|
27
29
|
# Writes to ROM and to empty spots go nowhere.
|
|
28
30
|
class Bus
|
|
29
31
|
include Addressable
|
|
32
|
+
include SavedState
|
|
30
33
|
|
|
31
34
|
# The pages each expansion block covers, as [first page, count].
|
|
32
35
|
BLOCKS = {
|
|
@@ -215,31 +218,6 @@ module Badline
|
|
|
215
218
|
@ram.clear!(RAM_POWER_ON)
|
|
216
219
|
end
|
|
217
220
|
|
|
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
221
|
# Whether +block+ (BLOCKS) holds RAM.
|
|
244
222
|
def ram?(block) = @blocks.include?(block)
|
|
245
223
|
|