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/cartridge.rb
DELETED
|
@@ -1,303 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "badline/cartridge/bank"
|
|
4
|
-
require "badline/cartridge/flash"
|
|
5
|
-
require "badline/cartridge/standard"
|
|
6
|
-
require "badline/cartridge/simons_basic"
|
|
7
|
-
require "badline/cartridge/ocean"
|
|
8
|
-
require "badline/cartridge/fun_play"
|
|
9
|
-
require "badline/cartridge/super_games"
|
|
10
|
-
require "badline/cartridge/epyx_fastload"
|
|
11
|
-
require "badline/cartridge/westermann"
|
|
12
|
-
require "badline/cartridge/rex_utility"
|
|
13
|
-
require "badline/cartridge/game_system"
|
|
14
|
-
require "badline/cartridge/dinamic"
|
|
15
|
-
require "badline/cartridge/zaxxon"
|
|
16
|
-
require "badline/cartridge/magic_desk"
|
|
17
|
-
require "badline/cartridge/comal80"
|
|
18
|
-
require "badline/cartridge/easy_flash"
|
|
19
|
-
require "badline/cartridge/mach5"
|
|
20
|
-
require "badline/cartridge/pagefox"
|
|
21
|
-
require "badline/cartridge/rgcd"
|
|
22
|
-
require "badline/cartridge/g_mod2"
|
|
23
|
-
require "badline/cartridge/freezer"
|
|
24
|
-
require "badline/cartridge/action_replay"
|
|
25
|
-
require "badline/cartridge/atomic_power"
|
|
26
|
-
require "badline/cartridge/final_cartridge3"
|
|
27
|
-
require "badline/cartridge/retro_replay"
|
|
28
|
-
require "badline/cartridge/kcs_power"
|
|
29
|
-
require "badline/cartridge/geo_ram"
|
|
30
|
-
|
|
31
|
-
module Badline
|
|
32
|
-
class Cartridge
|
|
33
|
-
class UnsupportedTypeError < StandardError; end
|
|
34
|
-
|
|
35
|
-
ROMH_START = 0xa000
|
|
36
|
-
BANK_SIZE = 0x2000
|
|
37
|
-
|
|
38
|
-
HARDWARE_TYPES = {
|
|
39
|
-
0 => Standard, 1 => ActionReplay, 2 => KCSPower, 3 => FinalCartridge3,
|
|
40
|
-
4 => SimonsBasic, 5 => Ocean, 7 => FunPlay, 8 => SuperGames,
|
|
41
|
-
9 => AtomicPower, 10 => EpyxFastload, 11 => Westermann,
|
|
42
|
-
12 => RexUtility, 15 => GameSystem, 17 => Dinamic, 18 => Zaxxon,
|
|
43
|
-
19 => MagicDesk, 21 => Comal80, 32 => EasyFlash, 36 => RetroReplay,
|
|
44
|
-
51 => Mach5, 53 => Pagefox, 57 => RGCD, 60 => GMod2
|
|
45
|
-
}.freeze
|
|
46
|
-
|
|
47
|
-
# The EXROM and GAME line levels of each memory configuration. The lines
|
|
48
|
-
# are active low.
|
|
49
|
-
MODES = {
|
|
50
|
-
rom8k: [0, 1].freeze, rom16k: [0, 0].freeze,
|
|
51
|
-
ultimax: [1, 0].freeze, off: [1, 1].freeze
|
|
52
|
-
}.freeze
|
|
53
|
-
|
|
54
|
-
attr_reader :name, :exrom, :game, :roml, :romh
|
|
55
|
-
|
|
56
|
-
# A callable returning the current cycle, for mappers with timed state.
|
|
57
|
-
attr_writer :clock
|
|
58
|
-
|
|
59
|
-
class << self
|
|
60
|
-
# Options set the cartridge's jumpers, for the mappers that have them.
|
|
61
|
-
def from_file(path, **)
|
|
62
|
-
from_crt(Storage::CRTFile.new(path), **)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def from_crt(crt, **)
|
|
66
|
-
mapper_for(crt).new(crt, **)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
# A cartridge built afresh from what save_setup wrote, before
|
|
70
|
-
# load_state puts its state in.
|
|
71
|
-
def from_setup(input)
|
|
72
|
-
return GeoRAM.new(size: input.int) if input.int == GEO_RAM_SETUP
|
|
73
|
-
|
|
74
|
-
crt = Storage::CRTFile.new(bytes: input.string)
|
|
75
|
-
mapper_for(crt).from_jumpers(crt, input)
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
# A cartridge from its image and what save_jumpers wrote: whether
|
|
79
|
-
# there are jumpers, then their settings on a mapper that has them.
|
|
80
|
-
def from_jumpers(crt, input)
|
|
81
|
-
input.boolean?
|
|
82
|
-
new(crt)
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def mapper_for(crt)
|
|
86
|
-
HARDWARE_TYPES.fetch(crt.hardware_type) do
|
|
87
|
-
raise UnsupportedTypeError,
|
|
88
|
-
"Unsupported cartridge hardware type #{crt.hardware_type}"
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# What save_setup writes first: a cartridge from a CRT image, or a
|
|
94
|
-
# GEO-RAM.
|
|
95
|
-
CRT_SETUP = 0
|
|
96
|
-
GEO_RAM_SETUP = 1
|
|
97
|
-
|
|
98
|
-
# Keeps the image it was built from, so a snapshot's machine can build
|
|
99
|
-
# the same cartridge before the snapshot's state goes into it.
|
|
100
|
-
def initialize(crt)
|
|
101
|
-
@crt = crt
|
|
102
|
-
@name = crt.name
|
|
103
|
-
@exrom = crt.exrom
|
|
104
|
-
@game = crt.game
|
|
105
|
-
@roml = @romh = nil
|
|
106
|
-
@banks = nil
|
|
107
|
-
@on_change = nil
|
|
108
|
-
@on_nmi_change = nil
|
|
109
|
-
@nmi = false
|
|
110
|
-
@open_bus = nil
|
|
111
|
-
@clock = nil
|
|
112
|
-
install_chips(crt.chips)
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def on_change(&block)
|
|
116
|
-
@on_change = block
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
# What builds the same cartridge afresh (Cartridge.from_setup): the CRT
|
|
120
|
-
# image it was built from, and the jumpers of a mapper that has them.
|
|
121
|
-
def save_setup(out)
|
|
122
|
-
out.int(CRT_SETUP).string(Storage::CRTFile.encode(@crt))
|
|
123
|
-
save_jumpers(out)
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
# The lines, the pull on NMI, the button and the mapper's own state.
|
|
127
|
-
# Loading sets them without calling back into the machine, which maps
|
|
128
|
-
# the cartridge again afterwards.
|
|
129
|
-
def save_state(out)
|
|
130
|
-
out.marker("CARTRIDGE")
|
|
131
|
-
out.int(@exrom).int(@game).boolean(@nmi).boolean(@button == true)
|
|
132
|
-
save_mapper(out)
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
def load_state(input)
|
|
136
|
-
input.marker("CARTRIDGE")
|
|
137
|
-
@exrom = input.int
|
|
138
|
-
@game = input.int
|
|
139
|
-
@nmi = input.boolean?
|
|
140
|
-
@button = input.boolean?
|
|
141
|
-
load_mapper(input)
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
# Called with the level of the cartridge's pull on the NMI line when it
|
|
145
|
-
# changes. The line is wired-OR with CIA 2's.
|
|
146
|
-
def on_nmi_change(&block)
|
|
147
|
-
@on_nmi_change = block
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
def nmi?
|
|
151
|
-
@nmi
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
# The address bus hands over the C64's RAM, for mappers that write
|
|
155
|
-
# through to it, and the open bus, for I/O reads the cartridge doesn't
|
|
156
|
-
# drive.
|
|
157
|
-
def connect(ram:, open_bus:)
|
|
158
|
-
@ram = ram
|
|
159
|
-
@open_bus = open_bus
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
def ultimax?
|
|
163
|
-
@game.zero? && @exrom == 1
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
# Whether the first half of the cycle, where the VIC does most of its
|
|
167
|
-
# fetching, sees Ultimax mode. Some cartridges drive GAME and EXROM
|
|
168
|
-
# differently in the two halves; #ultimax? is the second, the CPU's.
|
|
169
|
-
def phi1_ultimax?
|
|
170
|
-
ultimax?
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
# The I/O pages ($de, $df) whose reads the mapper drives. Reads of the
|
|
174
|
-
# others are open bus.
|
|
175
|
-
def readable_io_pages
|
|
176
|
-
[]
|
|
177
|
-
end
|
|
178
|
-
|
|
179
|
-
def poke(_addr, _value); end
|
|
180
|
-
|
|
181
|
-
# A window taking writes to $E000-$FFFF while reads there see the C64's
|
|
182
|
-
# memory, for a cartridge that asserts Ultimax on write cycles only.
|
|
183
|
-
def romh_writes; end
|
|
184
|
-
|
|
185
|
-
# A window at $A000-$BFFF in Ultimax mode, where the C64 maps nothing.
|
|
186
|
-
def ultimax_a000; end
|
|
187
|
-
|
|
188
|
-
# The RES line on the expansion port.
|
|
189
|
-
def reset; end
|
|
190
|
-
|
|
191
|
-
# Whether the cartridge has a freeze button.
|
|
192
|
-
def freezer? = false
|
|
193
|
-
|
|
194
|
-
# The freeze button, which cartridges without one ignore.
|
|
195
|
-
def press_button; end
|
|
196
|
-
|
|
197
|
-
def release_button; end
|
|
198
|
-
|
|
199
|
-
private
|
|
200
|
-
|
|
201
|
-
def save_jumpers(out)
|
|
202
|
-
out.boolean(false)
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
# The mapper's own state: where its windows point, for a mapper that
|
|
206
|
-
# moves them, and whatever a mapper adds after calling super.
|
|
207
|
-
def save_mapper(out)
|
|
208
|
-
save_windows(out, windows) if windows
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
def load_mapper(input)
|
|
212
|
-
load_windows(input, windows) if windows
|
|
213
|
-
end
|
|
214
|
-
|
|
215
|
-
# The banks and views ROML and ROMH can point at, which a snapshot
|
|
216
|
-
# names them by: the mapper's banks, or nothing for a mapper whose
|
|
217
|
-
# windows stay where install_chips put them.
|
|
218
|
-
def windows
|
|
219
|
-
[*@banks, EMPTY_BANK] if @banks
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
# Where the ROML and ROMH windows point, as their places in `windows`,
|
|
223
|
-
# the banks and views the mapper picks them from, or -1 for none.
|
|
224
|
-
def save_windows(out, windows)
|
|
225
|
-
out.int(window_index(@roml, windows)).int(window_index(@romh, windows))
|
|
226
|
-
end
|
|
227
|
-
|
|
228
|
-
def load_windows(input, windows)
|
|
229
|
-
@roml = window_at(input.int, windows)
|
|
230
|
-
@romh = window_at(input.int, windows)
|
|
231
|
-
end
|
|
232
|
-
|
|
233
|
-
def window_index(window, windows)
|
|
234
|
-
return -1 if window.nil?
|
|
235
|
-
|
|
236
|
-
windows.index { |candidate| candidate.equal?(window) } ||
|
|
237
|
-
raise(ArgumentError, "#{self.class.name}: a window that isn't among its banks")
|
|
238
|
-
end
|
|
239
|
-
|
|
240
|
-
def window_at(index, windows) = index.negative? ? nil : windows.fetch(index)
|
|
241
|
-
|
|
242
|
-
def nmi=(level)
|
|
243
|
-
return if @nmi == level
|
|
244
|
-
|
|
245
|
-
@nmi = level
|
|
246
|
-
@on_nmi_change&.call(level)
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
def changed!
|
|
250
|
-
@on_change&.call
|
|
251
|
-
end
|
|
252
|
-
|
|
253
|
-
def mode=(mode)
|
|
254
|
-
@exrom, @game = MODES.fetch(mode)
|
|
255
|
-
end
|
|
256
|
-
|
|
257
|
-
# Sets the lines and tells the machine to map the cartridge again.
|
|
258
|
-
def select_mode(mode)
|
|
259
|
-
self.mode = mode
|
|
260
|
-
changed!
|
|
261
|
-
end
|
|
262
|
-
|
|
263
|
-
def open_bus(addr)
|
|
264
|
-
@open_bus ? @open_bus.peek(addr) : 0xff
|
|
265
|
-
end
|
|
266
|
-
|
|
267
|
-
def install_chips(_chips)
|
|
268
|
-
raise NotImplementedError
|
|
269
|
-
end
|
|
270
|
-
|
|
271
|
-
def rom_bank(data)
|
|
272
|
-
Bank.new(data)
|
|
273
|
-
end
|
|
274
|
-
|
|
275
|
-
# A bank the image leaves out reads as erased ROM.
|
|
276
|
-
def bank(banks, number)
|
|
277
|
-
banks[number] || EMPTY_BANK
|
|
278
|
-
end
|
|
279
|
-
|
|
280
|
-
# The bank register bits a ROM decodes. The ROM holds the highest bank
|
|
281
|
-
# in the image, and has address lines for the power of two that covers
|
|
282
|
-
# it; the register bits above those lines are ignored.
|
|
283
|
-
def bank_mask(banks)
|
|
284
|
-
(1 << (banks.length - 1).bit_length) - 1
|
|
285
|
-
end
|
|
286
|
-
|
|
287
|
-
# Sorts the CHIP packets into ROML and ROMH banks by load address. A 16K
|
|
288
|
-
# chip at $8000 spans both.
|
|
289
|
-
def banks_from(chips)
|
|
290
|
-
roml = []
|
|
291
|
-
romh = []
|
|
292
|
-
chips.each do |chip|
|
|
293
|
-
if chip.address >= ROMH_START
|
|
294
|
-
romh[chip.bank] = rom_bank(chip.data)
|
|
295
|
-
else
|
|
296
|
-
roml[chip.bank] = rom_bank(chip.data[0, BANK_SIZE])
|
|
297
|
-
romh[chip.bank] = rom_bank(chip.data[BANK_SIZE, BANK_SIZE]) if chip.data.length > BANK_SIZE
|
|
298
|
-
end
|
|
299
|
-
end
|
|
300
|
-
[roml, romh]
|
|
301
|
-
end
|
|
302
|
-
end
|
|
303
|
-
end
|
data/lib/badline/checkpoint.rb
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
# A digest of the machine's state at one cycle, for comparing two runs of
|
|
5
|
-
# the same scenario, on two builds or two revisions. Each component is
|
|
6
|
-
# hashed on its own with 32-bit FNV-1a, so a mismatch names the part of the
|
|
7
|
-
# machine that went its own way. Nothing is read through a chip's bus
|
|
8
|
-
# interface, so taking a checkpoint leaves the machine as it was.
|
|
9
|
-
#
|
|
10
|
-
# Colour RAM is digested as the four bits each cell stores: the upper
|
|
11
|
-
# nibble a CPU read sees comes off the open bus.
|
|
12
|
-
class Checkpoint
|
|
13
|
-
COMPONENTS = %w[cpu ram color_ram display vic cia1 cia2 sid].freeze
|
|
14
|
-
|
|
15
|
-
FNV_OFFSET = 0x811c9dc5
|
|
16
|
-
FNV_PRIME = 0x01000193
|
|
17
|
-
|
|
18
|
-
attr_reader :cycle, :digests
|
|
19
|
-
|
|
20
|
-
class << self
|
|
21
|
-
def take(computer)
|
|
22
|
-
new(computer.cycles, [
|
|
23
|
-
fnv1a(cpu_state(computer.cpu)),
|
|
24
|
-
fnv1a(ram(computer.ram)),
|
|
25
|
-
fnv1a(color_ram(computer.address_bus.color_ram)),
|
|
26
|
-
fnv1a(computer.vic.display),
|
|
27
|
-
fnv1a(vic_state(computer.vic)),
|
|
28
|
-
fnv1a(cia_state(computer.cia1)),
|
|
29
|
-
fnv1a(cia_state(computer.cia2)),
|
|
30
|
-
fnv1a(Array.new(0x20) { |reg| computer.sid.register(reg) })
|
|
31
|
-
])
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# Reads a line written by #to_s.
|
|
35
|
-
def parse(line)
|
|
36
|
-
fields = line.split
|
|
37
|
-
digests = COMPONENTS.map do |name|
|
|
38
|
-
field = fields.find { |f| f.start_with?("#{name}=") }
|
|
39
|
-
raise ArgumentError, "no #{name} digest in #{line.inspect}" unless field
|
|
40
|
-
|
|
41
|
-
field.split("=").last.to_i(16)
|
|
42
|
-
end
|
|
43
|
-
new(fields.first.to_i, digests)
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def fnv1a(values)
|
|
47
|
-
hash = FNV_OFFSET
|
|
48
|
-
values.each { |value| hash = ((hash ^ (value & 0xffffffff)) * FNV_PRIME) & 0xffffffff }
|
|
49
|
-
hash
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
private
|
|
53
|
-
|
|
54
|
-
def cpu_state(cpu)
|
|
55
|
-
[cpu.program_counter, cpu.a, cpu.x, cpu.y, cpu.stack_pointer, cpu.p, cpu.cycles]
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def ram(memory)
|
|
59
|
-
Array.new(0x10000) { |addr| memory.peek(addr) }
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def color_ram(memory)
|
|
63
|
-
Array.new(0x400) { |offset| memory.nibble(0xd800 + offset) }
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def vic_state(vic)
|
|
67
|
-
vic.register_file + [vic.rasterline, vic.column]
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def cia_state(cia)
|
|
71
|
-
start = cia.start
|
|
72
|
-
[cia.peek(start), cia.peek(start + 1), cia.peek(start + 2), cia.peek(start + 3),
|
|
73
|
-
cia.timer_a, cia.timer_a_latch, cia.timer_b, cia.timer_b_latch, cia.serial.data,
|
|
74
|
-
cia.control_a.value, cia.control_b.value, cia.interrupt_status.value,
|
|
75
|
-
cia.interrupt_control.value] + cia.time_of_day.registers
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def initialize(cycle, digests)
|
|
80
|
-
@cycle = cycle
|
|
81
|
-
@digests = digests
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# The components whose digests differ from `other`'s.
|
|
85
|
-
def differences(other)
|
|
86
|
-
COMPONENTS.each_index.reject { |i| digests[i] == other.digests[i] }.map { |i| COMPONENTS[i] }
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def ==(other)
|
|
90
|
-
other.is_a?(Checkpoint) && cycle == other.cycle && digests == other.digests
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def to_s
|
|
94
|
-
fields = COMPONENTS.each_index.map { |i| "#{COMPONENTS[i]}=#{digests[i].to_s(16).rjust(8, '0')}" }
|
|
95
|
-
"#{cycle} #{fields.join(' ')}"
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
end
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class CIA
|
|
5
|
-
# Running a CIA a stretch of cycles at once, for Drive::Idle.
|
|
6
|
-
module FastForward
|
|
7
|
-
# quiet_cycles for a CIA whose counters will never set a flag.
|
|
8
|
-
QUIET = 1 << 40
|
|
9
|
-
|
|
10
|
-
# Whether fast_forward can run the CIA: timer B stopped with nothing
|
|
11
|
-
# in its pipeline, no interrupt or acknowledge on its way, CNT where it
|
|
12
|
-
# was, the TOD clock stopped, and timer A either stopped, or free
|
|
13
|
-
# running (Timer#free_running?) with its interrupt masked and the
|
|
14
|
-
# serial port an idle input. Drive::Idle sleeps the 1571's CIA through
|
|
15
|
-
# such cycles, which its DOS leaves timer A running in.
|
|
16
|
-
def quiet?
|
|
17
|
-
return false unless @tb.idle? && @icr.quiet && @tod.quiet? && cnt_steady?
|
|
18
|
-
|
|
19
|
-
@ta.idle? ? @serial.idle : timer_a_free_running?
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
# How many cycles the CIA can run with nothing but its counters
|
|
23
|
-
# moving: as quiet? allows, but with timer B free running too, up to
|
|
24
|
-
# the cycle before it underflows. The 1581's DOS leaves timer B
|
|
25
|
-
# interrupting every 10 ms.
|
|
26
|
-
def quiet_cycles
|
|
27
|
-
return 0 unless @icr.quiet && @tod.quiet? && cnt_steady? && timer_a_quiet?
|
|
28
|
-
return QUIET if @tb.idle?
|
|
29
|
-
return 0 unless @tb.free_running? && @control_b.value.nobits?(0x60)
|
|
30
|
-
|
|
31
|
-
@tb.counter - 1
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# Runs +cycles+ cycles at once while quiet? or for quiet_cycles, as
|
|
35
|
-
# cycle! would: timer A's underflows flag in the ICR, and reach the
|
|
36
|
-
# serial port's underflow line.
|
|
37
|
-
def fast_forward(cycles)
|
|
38
|
-
@tod.fast_forward(cycles)
|
|
39
|
-
@tb.fast_forward(cycles) unless @tb.idle?
|
|
40
|
-
return if @ta.idle?
|
|
41
|
-
|
|
42
|
-
@icr.flag(:timer_a) if @ta.fast_forward(cycles).positive?
|
|
43
|
-
@serial.follow_underflow(@ta.underflowed)
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
private
|
|
47
|
-
|
|
48
|
-
def timer_a_quiet? = @ta.idle? ? @serial.idle : timer_a_free_running?
|
|
49
|
-
|
|
50
|
-
# Timer A free running with its interrupt masked, and the serial port
|
|
51
|
-
# an idle input it only clocks.
|
|
52
|
-
def timer_a_free_running?
|
|
53
|
-
@ta.free_running? && !@control_a.serial_mode? && @icr.mask.value.nobits?(0x01) && @serial.drained?
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
# Whether CNT holds the level the last cycle sampled.
|
|
57
|
-
def cnt_steady? = @serial.cnt == @cnt_high && !@cnt_rise
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class CIA
|
|
5
|
-
# The interrupt control register: the source flags, their mask and the
|
|
6
|
-
# IR bit that drives the interrupt line, with the 6526's acknowledge
|
|
7
|
-
# timing.
|
|
8
|
-
class InterruptRegister
|
|
9
|
-
attr_reader :status, :mask, :quiet
|
|
10
|
-
|
|
11
|
-
# The 6526A is the faster of the two: see the rules below.
|
|
12
|
-
def initialize(model = :mos6526)
|
|
13
|
-
@fast = model == :mos6526a
|
|
14
|
-
@mask = InterruptFlags.new([:timer_a, :timer_b, :alarm, :serial, :flag, 0, 0, 0])
|
|
15
|
-
@status = InterruptFlags.new([:timer_a, :timer_b, :alarm, :serial, :flag, 0, 0, :interrupt])
|
|
16
|
-
@pending = 0
|
|
17
|
-
@read = @read_last_cycle = @read_two_cycles_ago = nil
|
|
18
|
-
@timer_b_bug = false
|
|
19
|
-
@quiet = true
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
# The CIA skips this while quiet: no read is recent enough to matter
|
|
23
|
-
# and no assert is due.
|
|
24
|
-
def cycle!
|
|
25
|
-
@read_two_cycles_ago = @read_last_cycle
|
|
26
|
-
@read_last_cycle = @read
|
|
27
|
-
@read = nil
|
|
28
|
-
if @pending.positive?
|
|
29
|
-
@pending -= 1
|
|
30
|
-
status.interrupt = true if @pending.zero?
|
|
31
|
-
end
|
|
32
|
-
@quiet = @pending.zero? && @read_last_cycle.nil? && @read_two_cycles_ago.nil?
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def interrupted? = status.value >= 0x80
|
|
36
|
-
|
|
37
|
-
def save_state(out)
|
|
38
|
-
out.int(@mask.value).int(@status.value).int(@pending)
|
|
39
|
-
[@read, @read_last_cycle, @read_two_cycles_ago].each { |read| out.optional_int(read) }
|
|
40
|
-
out.boolean(@timer_b_bug).boolean(@quiet)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def load_state(input)
|
|
44
|
-
@mask.value = input.int
|
|
45
|
-
@status.value = input.int
|
|
46
|
-
@pending = input.int
|
|
47
|
-
@read = input.optional_int
|
|
48
|
-
@read_last_cycle = input.optional_int
|
|
49
|
-
@read_two_cycles_ago = input.optional_int
|
|
50
|
-
@timer_b_bug = input.boolean?
|
|
51
|
-
@quiet = input.boolean?
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# Raises IR on this cycle.
|
|
55
|
-
def assert_now
|
|
56
|
-
status.interrupt = true
|
|
57
|
-
@pending = 0
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
# Schedules IR to rise after delay cycles, keeping an earlier one.
|
|
61
|
-
def assert!(delay = 1)
|
|
62
|
-
@pending = @pending.positive? ? [@pending, delay].min : delay
|
|
63
|
-
@quiet = false
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
# Latch a source, pulling the interrupt line if it is armed. The 6526
|
|
67
|
-
# raises IR a cycle after the flag. The 6526A raises it on the flag's
|
|
68
|
-
# own cycle, unless the ICR was read on the cycle before.
|
|
69
|
-
def flag(source)
|
|
70
|
-
bit = source_bit(source)
|
|
71
|
-
@status.value |= bit
|
|
72
|
-
return unless mask.value.anybits?(bit)
|
|
73
|
-
|
|
74
|
-
@fast && @read_last_cycle.nil? ? assert_now : assert!
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
# The 6526 timer B bug: an underflow on the cycle after a read still
|
|
78
|
-
# raises the flag, but the next read drops it unseen. The 6526A has
|
|
79
|
-
# no such bug.
|
|
80
|
-
def timer_b_underflow!
|
|
81
|
-
@timer_b_bug = !@fast && !@read_last_cycle.nil?
|
|
82
|
-
flag(:timer_b)
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
# A read releases the interrupt line at once, and cancels an assert
|
|
86
|
-
# due on the next cycle, but its acknowledge lands a cycle late. On
|
|
87
|
-
# the 6526 that holds only IR: the next cycle still reads IR set if it
|
|
88
|
-
# was set, or about to be. The 6526A reads an IR about to rise as set
|
|
89
|
-
# at once, and holds every bit it read: the next cycle reads them all
|
|
90
|
-
# again, along with anything flagged since.
|
|
91
|
-
def read
|
|
92
|
-
status.timer_b = false if @timer_b_bug
|
|
93
|
-
@timer_b_bug = false
|
|
94
|
-
value = status.value
|
|
95
|
-
value |= 0x80 if @fast && @pending == 1
|
|
96
|
-
@read = @pending == 1 ? value | 0x80 : value
|
|
97
|
-
@quiet = false
|
|
98
|
-
value |= held(@read_last_cycle) if @read_last_cycle
|
|
99
|
-
status.value = 0x0
|
|
100
|
-
@pending = 0
|
|
101
|
-
value
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
# Bit 7 picks between setting and clearing the mask bits given.
|
|
105
|
-
def write(value)
|
|
106
|
-
if value.nobits?(0x80)
|
|
107
|
-
@mask.value &= ~(value & 0x1f)
|
|
108
|
-
else
|
|
109
|
-
@mask.value |= (value & 0x1f)
|
|
110
|
-
end
|
|
111
|
-
if mask.value.anybits?(status.value & 0x1f)
|
|
112
|
-
assert!(arm_delay) unless interrupted?
|
|
113
|
-
elsif @pending == 1 && @read_two_cycles_ago
|
|
114
|
-
# On the 6526, masking the pending source cancels the assert due
|
|
115
|
-
# on the next cycle only while a read two cycles back is
|
|
116
|
-
# acknowledging.
|
|
117
|
-
@pending = 0
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
private
|
|
122
|
-
|
|
123
|
-
# Arming a pending source raises IR two cycles later on the 6526,
|
|
124
|
-
# and one cycle later on the 6526A.
|
|
125
|
-
def arm_delay = @fast ? 1 : 2
|
|
126
|
-
|
|
127
|
-
# What a read on the cycle before still holds: IR on the 6526, and
|
|
128
|
-
# every bit it read on the 6526A.
|
|
129
|
-
def held(last) = @fast ? last : last & 0x80
|
|
130
|
-
|
|
131
|
-
def source_bit(source)
|
|
132
|
-
case source
|
|
133
|
-
when :timer_a then 0x01
|
|
134
|
-
when :timer_b then 0x02
|
|
135
|
-
when :alarm then 0x04
|
|
136
|
-
when :serial then 0x08
|
|
137
|
-
when :flag then 0x10
|
|
138
|
-
else raise ArgumentError, "unknown interrupt source #{source}"
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
end
|