badline 0.12.1 → 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 +17 -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 +3 -3
- 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} +1 -1
- data/lib/badline/c128/bus.rb +18 -17
- 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 +14 -9
- data/lib/badline/{computer → c64}/attachments.rb +4 -6
- 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/{computer → c64}/common.rb +2 -2
- data/lib/badline/{computer → c64}/kernal_traps.rb +18 -18
- 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 +11 -11
- data/lib/badline/{computer.rb → c64.rb} +18 -13
- 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 +26 -28
- 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 +3 -3
- 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/load.rb +5 -5
- data/lib/badline/kernal_trap/save.rb +4 -4
- data/lib/badline/kernal_trap/serial.rb +7 -7
- data/lib/badline/kernal_trap.rb +1 -2
- data/lib/badline/machine/clocking.rb +1 -1
- data/lib/badline/machine.rb +5 -5
- data/lib/badline/media/true_drive.rb +1 -1
- data/lib/badline/media/tune.rb +2 -2
- data/lib/badline/media.rb +3 -3
- data/lib/badline/model.rb +1 -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 +1 -1
- data/lib/badline/snapshot/setup.rb +22 -66
- data/lib/badline/snapshot/state.rb +8 -18
- 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 +3 -4
- data/lib/badline/storage/d64_image.rb +0 -2
- data/lib/badline/storage/d71_image.rb +0 -2
- data/lib/badline/storage/d81_image.rb +0 -2
- data/lib/badline/storage/disk_image.rb +3 -6
- data/lib/badline/storage/g64_image.rb +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 +5 -5
- 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 -30
- data/lib/badline/vic20/user_via_ports.rb +2 -2
- data/lib/badline/vic20.rb +19 -14
- metadata +245 -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 -66
- data/lib/badline/address_bus/sid_slots.rb +0 -42
- data/lib/badline/address_bus.rb +0 -216
- 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/control_ports.rb +0 -76
- data/lib/badline/cpu/addressing.rb +0 -131
- data/lib/badline/cpu/boundary.rb +0 -54
- data/lib/badline/cpu/core.rb +0 -165
- data/lib/badline/cpu/microcode.rb +0 -177
- data/lib/badline/cpu/operations.rb +0 -88
- data/lib/badline/cpu/saved_state.rb +0 -115
- data/lib/badline/cpu/stack_operations.rb +0 -82
- data/lib/badline/cpu.rb +0 -10
- data/lib/badline/cpu_port.rb +0 -112
- data/lib/badline/datasette.rb +0 -161
- data/lib/badline/drive/core.rb +0 -147
- data/lib/badline/drive/fast_serial.rb +0 -73
- data/lib/badline/drive/idle.rb +0 -125
- data/lib/badline/drive/idle_cpu.rb +0 -28
- data/lib/badline/drive/orbit.rb +0 -79
- data/lib/badline/drive/serial_lines.rb +0 -73
- data/lib/badline/drive/sleep.rb +0 -112
- data/lib/badline/drive/vias.rb +0 -84
- data/lib/badline/drive/watch.rb +0 -150
- data/lib/badline/drive.rb +0 -11
- data/lib/badline/drive1541/bus.rb +0 -86
- data/lib/badline/drive1541/byte_ready.rb +0 -48
- data/lib/badline/drive1541/cpu.rb +0 -11
- data/lib/badline/drive1541/disk.rb +0 -315
- data/lib/badline/drive1541/disk_state.rb +0 -86
- data/lib/badline/drive1541/disk_via.rb +0 -36
- data/lib/badline/drive1541/gcr.rb +0 -57
- data/lib/badline/drive1541/mechanism.rb +0 -313
- data/lib/badline/drive1541/mechanism_state.rb +0 -68
- data/lib/badline/drive1541/rotation.rb +0 -121
- data/lib/badline/drive1541/sector_reader.rb +0 -76
- data/lib/badline/drive1541/serial_port.rb +0 -18
- data/lib/badline/drive1541/track.rb +0 -98
- data/lib/badline/drive1541.rb +0 -111
- data/lib/badline/drive1571/bus.rb +0 -111
- data/lib/badline/drive1571/cpu.rb +0 -11
- data/lib/badline/drive1571/serial_port.rb +0 -37
- data/lib/badline/drive1571/serial_via.rb +0 -25
- data/lib/badline/drive1571/wd1770.rb +0 -120
- data/lib/badline/drive1571.rb +0 -175
- data/lib/badline/drive1581/bus.rb +0 -137
- data/lib/badline/drive1581/cpu.rb +0 -11
- data/lib/badline/drive1581/disk.rb +0 -135
- data/lib/badline/drive1581/disk_state.rb +0 -87
- data/lib/badline/drive1581/mechanism.rb +0 -117
- data/lib/badline/drive1581/serial_port.rb +0 -52
- data/lib/badline/drive1581/slot.rb +0 -78
- data/lib/badline/drive1581/track.rb +0 -100
- data/lib/badline/drive1581/track_bytes.rb +0 -75
- data/lib/badline/drive1581/wd1772/registers.rb +0 -89
- data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
- data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
- data/lib/badline/drive1581/wd1772/state.rb +0 -66
- data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
- data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
- data/lib/badline/drive1581/wd1772/turn.rb +0 -73
- data/lib/badline/drive1581/wd1772.rb +0 -216
- data/lib/badline/drive1581.rb +0 -233
- data/lib/badline/iec_bus.rb +0 -159
- data/lib/badline/instruction.rb +0 -334
- data/lib/badline/instruction_set/arithmetic.rb +0 -114
- data/lib/badline/instruction_set/bitwise.rb +0 -126
- data/lib/badline/instruction_set/branch.rb +0 -79
- data/lib/badline/instruction_set/flag.rb +0 -63
- data/lib/badline/instruction_set/illegal.rb +0 -270
- data/lib/badline/instruction_set/inc_dec.rb +0 -69
- data/lib/badline/instruction_set/stack.rb +0 -52
- data/lib/badline/instruction_set/transfer.rb +0 -137
- data/lib/badline/instruction_set.rb +0 -55
- data/lib/badline/interrupts.rb +0 -104
- data/lib/badline/joystick.rb +0 -25
- data/lib/badline/kernal_trap/channel.rb +0 -181
- data/lib/badline/keyboard.rb +0 -112
- data/lib/badline/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 -853
- 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
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
module InstructionSet
|
|
5
|
-
module Transfer
|
|
6
|
-
# +begin_src ruby
|
|
7
|
-
# Load accumulator with memory.
|
|
8
|
-
#
|
|
9
|
-
# Opcodes:
|
|
10
|
-
# $A1 - indirect_x - 6 cycles
|
|
11
|
-
# $A5 - zeropage - 3 cycles
|
|
12
|
-
# $A9 - immediate - 2 cycles
|
|
13
|
-
# $AD - absolute - 4 cycles
|
|
14
|
-
# $B1 - indirect_y - 5+ cycles
|
|
15
|
-
# $B5 - zeropage_x - 4 cycles
|
|
16
|
-
# $B9 - absolute_y - 4+ cycles
|
|
17
|
-
# $BD - absolute_x - 4+ cycles
|
|
18
|
-
def lda(_addr, value)
|
|
19
|
-
@a = value
|
|
20
|
-
update_number_flags(@a)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
# Load X register with memory.
|
|
24
|
-
#
|
|
25
|
-
# Opcodes:
|
|
26
|
-
# $A2 - immediate - 2 cycles
|
|
27
|
-
# $A6 - zeropage - 3 cycles
|
|
28
|
-
# $AE - absolute - 4 cycles
|
|
29
|
-
# $B6 - zeropage_y - 4 cycles
|
|
30
|
-
# $BE - absolute_y - 4+ cycles
|
|
31
|
-
def ldx(_addr, value)
|
|
32
|
-
@x = value
|
|
33
|
-
update_number_flags(@x)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Load Y register with memory.
|
|
37
|
-
#
|
|
38
|
-
# Opcodes:
|
|
39
|
-
# $A0 - immediate - 2 cycles
|
|
40
|
-
# $A4 - zeropage - 3 cycles
|
|
41
|
-
# $AC - absolute - 4 cycles
|
|
42
|
-
# $B4 - zeropage_x - 4 cycles
|
|
43
|
-
# $BC - absolute_x - 4+ cycles
|
|
44
|
-
def ldy(_addr, value)
|
|
45
|
-
@y = value
|
|
46
|
-
update_number_flags(@y)
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
# Store accumulator in memory.
|
|
50
|
-
#
|
|
51
|
-
# Opcodes:
|
|
52
|
-
# $81 - indirect_x - 6 cycles
|
|
53
|
-
# $85 - zeropage - 3 cycles
|
|
54
|
-
# $8D - absolute - 4 cycles
|
|
55
|
-
# $91 - indirect_y - 6 cycles
|
|
56
|
-
# $95 - zeropage_x - 4 cycles
|
|
57
|
-
# $99 - absolute_y - 5 cycles
|
|
58
|
-
# $9D - absolute_x - 5 cycles
|
|
59
|
-
def sta(addr, _value)
|
|
60
|
-
write_byte(addr, @a)
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
# Store X register in memory.
|
|
64
|
-
#
|
|
65
|
-
# Opcodes:
|
|
66
|
-
# $86 - zeropage - 3 cycles
|
|
67
|
-
# $8E - absolute - 4 cycles
|
|
68
|
-
# $96 - zeropage_y - 4 cycles
|
|
69
|
-
def stx(addr, _value)
|
|
70
|
-
write_byte(addr, @x)
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
# Store Y register in memory.
|
|
74
|
-
#
|
|
75
|
-
# Opcodes:
|
|
76
|
-
# $84 - zeropage - 3 cycles
|
|
77
|
-
# $8C - absolute - 4 cycles
|
|
78
|
-
# $94 - zeropage_x - 4 cycles
|
|
79
|
-
def sty(addr, _value)
|
|
80
|
-
write_byte(addr, @y)
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
# Transfer accumulator to X register.
|
|
84
|
-
#
|
|
85
|
-
# Opcodes:
|
|
86
|
-
# $AA - implied - 2 cycles
|
|
87
|
-
def tax(_addr, _value)
|
|
88
|
-
@x = a
|
|
89
|
-
update_number_flags(@x)
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
# Transfer accumulator to Y register.
|
|
93
|
-
#
|
|
94
|
-
# Opcodes:
|
|
95
|
-
# $A8 - implied - 2 cycles
|
|
96
|
-
def tay(_addr, _value)
|
|
97
|
-
@y = a
|
|
98
|
-
update_number_flags(@y)
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
# Transfer stack pointer to X register.
|
|
102
|
-
#
|
|
103
|
-
# Opcodes:
|
|
104
|
-
# $BA - implied - 2 cycles
|
|
105
|
-
def tsx(_addr, _value)
|
|
106
|
-
@x = stack_pointer
|
|
107
|
-
update_number_flags(@x)
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
# Transfer X register to accumulator.
|
|
111
|
-
#
|
|
112
|
-
# Opcodes:
|
|
113
|
-
# $8A - implied - 2 cycles
|
|
114
|
-
def txa(_addr, _operand)
|
|
115
|
-
@a = x
|
|
116
|
-
update_number_flags(@a)
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
# Transfer X register to stack pointer.
|
|
120
|
-
#
|
|
121
|
-
# Opcodes:
|
|
122
|
-
# $9A - implied - 2 cycles
|
|
123
|
-
def txs(_addr, _operand)
|
|
124
|
-
@stack_pointer = x
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
# Transfer Y register to accumulator.
|
|
128
|
-
#
|
|
129
|
-
# Opcodes:
|
|
130
|
-
# $98 - implied - 2 cycles
|
|
131
|
-
def tya(_addr, _operand)
|
|
132
|
-
@a = y
|
|
133
|
-
update_number_flags(@a)
|
|
134
|
-
end
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
|
-
end
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "badline/instruction_set/arithmetic"
|
|
4
|
-
require "badline/instruction_set/bitwise"
|
|
5
|
-
require "badline/instruction_set/branch"
|
|
6
|
-
require "badline/instruction_set/inc_dec"
|
|
7
|
-
require "badline/instruction_set/flag"
|
|
8
|
-
require "badline/instruction_set/illegal"
|
|
9
|
-
require "badline/instruction_set/stack"
|
|
10
|
-
require "badline/instruction_set/transfer"
|
|
11
|
-
|
|
12
|
-
module Badline
|
|
13
|
-
# http://www.6502.org/tutorials/6502opcodes.html
|
|
14
|
-
# http://www.e-tradition.net/bytes/6502/6502_instruction_set.html
|
|
15
|
-
module InstructionSet
|
|
16
|
-
include InstructionSet::Arithmetic
|
|
17
|
-
include InstructionSet::Bitwise
|
|
18
|
-
include InstructionSet::Branch
|
|
19
|
-
include InstructionSet::IncDec
|
|
20
|
-
include InstructionSet::Flag
|
|
21
|
-
include InstructionSet::Illegal
|
|
22
|
-
include InstructionSet::Stack
|
|
23
|
-
include InstructionSet::Transfer
|
|
24
|
-
|
|
25
|
-
# No operation. The illegal forms with an operand still read it, in
|
|
26
|
-
# the steps before this is called.
|
|
27
|
-
#
|
|
28
|
-
# Opcodes:
|
|
29
|
-
# $EA - implied - 2 cycles
|
|
30
|
-
# $04, $44, $64 - zeropage - 3 cycles (illegal)
|
|
31
|
-
# $14, $34, $54, $74, $D4, $F4 - zeropage_x - 4 cycles (illegal)
|
|
32
|
-
# $0C - absolute - 4 cycles (illegal)
|
|
33
|
-
# $1C, $3C, $5C, $7C, $DC, $FC - absolute_x - 4+ cycles (illegal)
|
|
34
|
-
# $1A, $3A, $5A, $7A, $DA, $FA - implied - 2 cycles (illegal)
|
|
35
|
-
def nop(_addr, _value); end
|
|
36
|
-
|
|
37
|
-
private
|
|
38
|
-
|
|
39
|
-
def update_number_flags(value)
|
|
40
|
-
status.zero = value.zero?
|
|
41
|
-
status.negative = value & 0x80 != 0
|
|
42
|
-
value
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# Stores a read-modify-write result. For memory, the write happens in
|
|
46
|
-
# the steps that follow (see Operations#op_rmw_read).
|
|
47
|
-
def write_modified(addr, result)
|
|
48
|
-
if addr == :accumulator
|
|
49
|
-
@a = result
|
|
50
|
-
else
|
|
51
|
-
@rmw_result = result
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
data/lib/badline/interrupts.rb
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
module Interrupts
|
|
5
|
-
BREAK_MASK = 0x10
|
|
6
|
-
|
|
7
|
-
private
|
|
8
|
-
|
|
9
|
-
# Samples the IRQ line and the NMI latch once per cycle. An instruction
|
|
10
|
-
# boundary commits the sample taken on its second-to-last cycle.
|
|
11
|
-
def poll
|
|
12
|
-
if @skip_poll
|
|
13
|
-
@skip_poll = false
|
|
14
|
-
return
|
|
15
|
-
end
|
|
16
|
-
@irq_pending = @irq_sample
|
|
17
|
-
@nmi_pending = @nmi_sample
|
|
18
|
-
@irq_sample = @irq && !@status.interrupt?
|
|
19
|
-
@nmi_sample = @nmi
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
# A cycle the VIC stalls through BA keeps sampling the lines, OR-ed with
|
|
23
|
-
# the sample it already holds, but the boundary pipeline doesn't advance
|
|
24
|
-
# and a skipped poll stays owed to the next real cycle.
|
|
25
|
-
def sample_while_stalled
|
|
26
|
-
@irq_sample ||= @irq && !interrupt_disabled_after_stall?
|
|
27
|
-
@nmi_sample = true if @nmi
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# A stalled CLI or SEI execute cycle masks with the I it is about to
|
|
31
|
-
# set. Every other step masks with the current I, PLP included: its
|
|
32
|
-
# pulled I only arrives with the stalled stack read.
|
|
33
|
-
def interrupt_disabled_after_stall?
|
|
34
|
-
return @status.interrupt? unless @plan.equal?(CPU::IMPLIED_PLAN)
|
|
35
|
-
|
|
36
|
-
case @operation
|
|
37
|
-
when :cli then false
|
|
38
|
-
when :sei then true
|
|
39
|
-
else @status.interrupt?
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# Runs in the opcode fetch cycle in place of the fetch, with no bus
|
|
44
|
-
# access, and switches to the interrupt plan.
|
|
45
|
-
def start_interrupt
|
|
46
|
-
@interrupt = @boundary_nmi ? 0xfffa : 0xfffe
|
|
47
|
-
@brk = false
|
|
48
|
-
@plan = CPU::INTERRUPT_PLAN
|
|
49
|
-
@writes = CPU::INTERRUPT_WRITES
|
|
50
|
-
@index = 1
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
# BRK reads the byte after its opcode and ignores it, and selects the
|
|
54
|
-
# IRQ vector.
|
|
55
|
-
def op_brk_dummy
|
|
56
|
-
@memory.peek(@program_counter)
|
|
57
|
-
@interrupt = 0xfffe
|
|
58
|
-
@brk = true
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def op_int_push_pch
|
|
62
|
-
@address = @brk ? (@program_counter + 1) & 0xffff : @program_counter
|
|
63
|
-
@memory.poke(stack_address, high_byte(@address))
|
|
64
|
-
@stack_pointer = (@stack_pointer - 1) & 0xff
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def op_int_push_pcl
|
|
68
|
-
@memory.poke(stack_address, low_byte(@address))
|
|
69
|
-
@stack_pointer = (@stack_pointer - 1) & 0xff
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def op_int_push_status
|
|
73
|
-
value = @brk ? @status.value | BREAK_MASK : @status.value & ~BREAK_MASK
|
|
74
|
-
@memory.poke(stack_address, value)
|
|
75
|
-
@stack_pointer = (@stack_pointer - 1) & 0xff
|
|
76
|
-
@status.interrupt = true
|
|
77
|
-
# An NMI that arrives before cycle 4 of a BRK or IRQ takes it over:
|
|
78
|
-
# the sequence finishes with the NMI vector.
|
|
79
|
-
@interrupt = 0xfffa if @interrupt == 0xfffe && @nmi_pending
|
|
80
|
-
@nmi = false if @interrupt == 0xfffa
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def op_int_vector_low
|
|
84
|
-
@address = @memory.peek(@interrupt)
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
# Clears any interrupt that is pending, so the handler's first
|
|
88
|
-
# instruction always runs before the next interrupt. This applies to
|
|
89
|
-
# BRK too.
|
|
90
|
-
def op_int_vector_high
|
|
91
|
-
high = @memory.peek((@interrupt + 1) & 0xffff)
|
|
92
|
-
@program_counter = @address | (high << 8)
|
|
93
|
-
@irq_sample = @irq_pending = false
|
|
94
|
-
@nmi_sample = @nmi_pending = false
|
|
95
|
-
@interrupt = nil
|
|
96
|
-
if @brk
|
|
97
|
-
@status.break = false
|
|
98
|
-
end_instruction
|
|
99
|
-
else
|
|
100
|
-
end_sequence
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
end
|
data/lib/badline/joystick.rb
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Joystick
|
|
5
|
-
DIRECTIONS = { up: 0, down: 1, left: 2, right: 3, fire: 4 }.freeze
|
|
6
|
-
|
|
7
|
-
# Kept up to date as switches move, since the CIA samples the fire line
|
|
8
|
-
# every cycle to drive the light pen input.
|
|
9
|
-
attr_reader :port_bits
|
|
10
|
-
|
|
11
|
-
def initialize
|
|
12
|
-
@port_bits = 0xff
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def press(direction)
|
|
16
|
-
bit = DIRECTIONS[direction]
|
|
17
|
-
@port_bits &= ~(1 << bit) if bit
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def release(direction)
|
|
21
|
-
bit = DIRECTIONS[direction]
|
|
22
|
-
@port_bits |= 1 << bit if bit
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
module KernalTrap
|
|
5
|
-
# One open channel on the virtual drive, holding a file, a block buffer
|
|
6
|
-
# or the command channel's status message. It gives out one byte at a
|
|
7
|
-
# time and flags the last one, so the bus can raise EOI with it. A
|
|
8
|
-
# channel cut short by a read error never flags one, and holds the
|
|
9
|
-
# error for the drive to report once its bytes run out.
|
|
10
|
-
class Channel
|
|
11
|
-
attr_accessor :buffer
|
|
12
|
-
attr_reader :error, :pointer
|
|
13
|
-
attr_writer :lead
|
|
14
|
-
|
|
15
|
-
def initialize(bytes = [], error: nil, writable: false, base: 0)
|
|
16
|
-
@base = base
|
|
17
|
-
replace(bytes)
|
|
18
|
-
@error = error
|
|
19
|
-
@writable = writable
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
# A block buffer opened with "#", which reads and writes one of the
|
|
23
|
-
# drive's buffers in its RAM, so M-R and M-W reach the same bytes. It
|
|
24
|
-
# hands out the whole block unless a B-R sets a shorter end, and
|
|
25
|
-
# flags that byte as the last. The DOS opens it with the pointer at 1
|
|
26
|
-
# and the buffer's number as the byte to send, so the first read
|
|
27
|
-
# answers with the number and the next one moves on to the third
|
|
28
|
-
# byte.
|
|
29
|
-
def self.buffer(memory, number)
|
|
30
|
-
new(memory.ram, writable: true, base: Drive::Memory.buffer_address(number)).tap do |channel|
|
|
31
|
-
channel.buffer = number
|
|
32
|
-
channel.rewind(Drive::BLOCK_SIZE)
|
|
33
|
-
channel.pointer = 1
|
|
34
|
-
channel.lead = number
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
# A file's bytes, up to the first block its chain can't read. The
|
|
39
|
-
# drive reads a block ahead before sending the last byte of the one
|
|
40
|
-
# before, so a bad block holds that byte back too, and a bad first
|
|
41
|
-
# block or a missing file leaves nothing to send.
|
|
42
|
-
def self.for_file(storage, name, type)
|
|
43
|
-
data = storage.read_file(name, type:)
|
|
44
|
-
return new([], error: [Drive::FILE_NOT_FOUND]) unless data
|
|
45
|
-
|
|
46
|
-
failure = storage.respond_to?(:read_error) && storage.read_error(name, type:)
|
|
47
|
-
return new(data) unless failure
|
|
48
|
-
|
|
49
|
-
new(data[0, failure[:offset] - 1] || [], error: failure.values_at(:error, :track, :sector))
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# The file an open names. The drive keeps the first block of the file
|
|
53
|
-
# a LOAD (secondary address 0) opens at $7E and $026F of its memory,
|
|
54
|
-
# and a LOAD of a name starting with "*" reopens that file rather than
|
|
55
|
-
# the first one on the disk. Loaders write the block there with M-W
|
|
56
|
-
# to load a file the directory doesn't list. A LOAD of "$" reads the
|
|
57
|
-
# directory as a BASIC program, which a pattern after a colon narrows
|
|
58
|
-
# to the files it names.
|
|
59
|
-
def self.for_name(storage, memory, secondary, name, type)
|
|
60
|
-
return new(storage.directory.bytes(name)) if listing?(storage, secondary, name)
|
|
61
|
-
|
|
62
|
-
file = Storage.parse_name(name).first
|
|
63
|
-
return for_file(storage, file, type) unless secondary.zero? && storage.respond_to?(:first_block)
|
|
64
|
-
|
|
65
|
-
last = memory.last_program if name.start_with?("*")
|
|
66
|
-
return at_block(storage, *last) if last
|
|
67
|
-
|
|
68
|
-
block = storage.first_block(file, type:)
|
|
69
|
-
memory.last_program = block if block
|
|
70
|
-
for_file(storage, file, type)
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def self.listing?(storage, secondary, name)
|
|
74
|
-
secondary.zero? && name.start_with?("$") && storage.respond_to?(:directory)
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
# The file whose chain starts at the block.
|
|
78
|
-
def self.at_block(storage, track, sector)
|
|
79
|
-
data = storage.read_file_at(track, sector)
|
|
80
|
-
data ? new(data) : new([], error: [Drive::ILLEGAL_TRACK_OR_SECTOR, track, sector])
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
# Reads what save_state wrote after the flag that marks a file open
|
|
84
|
-
# for writing (Drive::Channels.channel_from_state). A buffer channel
|
|
85
|
-
# takes its block in `ram`, the drive's RAM, again.
|
|
86
|
-
def self.from_state(input, ram)
|
|
87
|
-
new.tap { |channel| channel.load_state(input, ram) }
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
# A buffer channel's bytes are the drive's RAM, which the drive
|
|
91
|
-
# writes itself.
|
|
92
|
-
def save_state(out)
|
|
93
|
-
out.boolean(false).boolean(@writable).int(@base).int(@length).int(@pointer)
|
|
94
|
-
out.optional_int(@lead).optional_int(@buffer).boolean(!@error.nil?)
|
|
95
|
-
out.ints(@error) if @error
|
|
96
|
-
out.blob(@bytes) unless @writable
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
def load_state(input, ram)
|
|
100
|
-
@writable = input.boolean?
|
|
101
|
-
@base = input.int
|
|
102
|
-
@length = input.int
|
|
103
|
-
@pointer = input.int
|
|
104
|
-
@lead = input.optional_int
|
|
105
|
-
@buffer = input.optional_int
|
|
106
|
-
@error = input.boolean? ? input.ints : nil
|
|
107
|
-
@bytes = @writable ? ram : input.blob
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def replace(bytes, length = bytes.length)
|
|
111
|
-
@bytes = bytes
|
|
112
|
-
rewind(length)
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def rewind(length)
|
|
116
|
-
@length = length
|
|
117
|
-
self.pointer = 0
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
def pointer=(position)
|
|
121
|
-
@pointer = position
|
|
122
|
-
@lead = nil
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
# A block read into the channel. A buffer channel takes it into its
|
|
126
|
-
# buffer, a file channel hands it out in place of the file.
|
|
127
|
-
def load(block, length)
|
|
128
|
-
return replace(block.dup, length) unless @writable
|
|
129
|
-
|
|
130
|
-
@bytes[@base, block.length] = block
|
|
131
|
-
rewind(length)
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
def writable? = @writable
|
|
135
|
-
|
|
136
|
-
# A buffer channel's block, as a block write puts it on the disk.
|
|
137
|
-
def block = @bytes[@base, Drive::BLOCK_SIZE]
|
|
138
|
-
|
|
139
|
-
def exhausted?
|
|
140
|
-
@pointer >= @length
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
# A file that holds nothing but its error never opened.
|
|
144
|
-
def failed?
|
|
145
|
-
exhausted? && !@error.nil?
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
# Each byte lands at the pointer, which wraps within the block.
|
|
149
|
-
def write(bytes)
|
|
150
|
-
@lead = nil
|
|
151
|
-
bytes.each do |byte|
|
|
152
|
-
@bytes[@base + @pointer] = byte
|
|
153
|
-
@pointer = (@pointer + 1) & 0xff
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
def read
|
|
158
|
-
return read_buffer if @writable
|
|
159
|
-
return if exhausted?
|
|
160
|
-
|
|
161
|
-
byte = @lead || @bytes[@base + @pointer]
|
|
162
|
-
@lead = nil
|
|
163
|
-
@pointer += 1
|
|
164
|
-
[byte, exhausted? && !@error]
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
private
|
|
168
|
-
|
|
169
|
-
# A buffer never runs out. Past its last byte, which goes out with
|
|
170
|
-
# EOI, the pointer wraps back to the second, and a pointer set past
|
|
171
|
-
# the end runs on around the block to it.
|
|
172
|
-
def read_buffer
|
|
173
|
-
byte = @lead || @bytes[@base + @pointer]
|
|
174
|
-
@lead = nil
|
|
175
|
-
last = @pointer == @length - 1
|
|
176
|
-
@pointer = last ? 1 : (@pointer + 1) & 0xff
|
|
177
|
-
[byte, last]
|
|
178
|
-
end
|
|
179
|
-
end
|
|
180
|
-
end
|
|
181
|
-
end
|
data/lib/badline/keyboard.rb
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
# The key matrix spanning CIA 1's two ports: rows on port A, columns on
|
|
5
|
-
# port B. Row lines beyond the eighth sit above port A's bits in +rows+.
|
|
6
|
-
#
|
|
7
|
-
# A pressed key shorts its row line to its column line, so whichever side is
|
|
8
|
-
# pulled low drags the other down with it. Scanning works in either
|
|
9
|
-
# direction, and chains of keys sharing a line propagate the pulldown -- the
|
|
10
|
-
# ghost keys real hardware reports.
|
|
11
|
-
class Keyboard
|
|
12
|
-
include IntegerHelper
|
|
13
|
-
|
|
14
|
-
# Keys the C64 types as a combination: cursor up and cursor left are the
|
|
15
|
-
# shifted cursor keys. Pressing one holds both of its matrix keys, while
|
|
16
|
-
# a shift key held on its own stays down when it is released.
|
|
17
|
-
COMBINATIONS = {
|
|
18
|
-
cursor_up: %i[lshift cursor_v],
|
|
19
|
-
cursor_left: %i[lshift cursor_h]
|
|
20
|
-
}.freeze
|
|
21
|
-
|
|
22
|
-
# The C64's wiring: one row of keys per port A line, in port B column
|
|
23
|
-
# order.
|
|
24
|
-
C64_MATRIX = [
|
|
25
|
-
%i[delete return cursor_h f7 f1 f3 f5 cursor_v],
|
|
26
|
-
%i[3 w a 4 z s e lshift],
|
|
27
|
-
%i[5 r d 6 c f t x],
|
|
28
|
-
%i[7 y g 8 b h u v],
|
|
29
|
-
%i[9 i j 0 m k o n],
|
|
30
|
-
%i[+ p l - . : @ ,],
|
|
31
|
-
%i[£ * ; clr_home rshift = up /],
|
|
32
|
-
%i[1 left control 2 space cbm q run_stop]
|
|
33
|
-
].freeze
|
|
34
|
-
|
|
35
|
-
attr_reader :keys, :matrix
|
|
36
|
-
|
|
37
|
-
def initialize(matrix: C64_MATRIX)
|
|
38
|
-
@keys = []
|
|
39
|
-
@row_masks = nil
|
|
40
|
-
@matrix = matrix
|
|
41
|
-
@connected = true
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# Whether the machine has a keyboard. The C64GS has none: no key goes
|
|
45
|
-
# down on it.
|
|
46
|
-
def connected? = @connected
|
|
47
|
-
|
|
48
|
-
def connected=(connected)
|
|
49
|
-
@connected = connected
|
|
50
|
-
@keys.clear unless connected
|
|
51
|
-
@row_masks = nil
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def press(key)
|
|
55
|
-
return unless @connected && valid_key?(key)
|
|
56
|
-
|
|
57
|
-
@keys << key
|
|
58
|
-
@row_masks = nil
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def release(key)
|
|
62
|
-
@keys.reject! { |k| k == key }
|
|
63
|
-
@row_masks = nil
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
# Settles the row (port A) and column (port B) lines against each other
|
|
67
|
-
# until no key contact pulls a line low any more, and returns both.
|
|
68
|
-
def scan(rows, cols)
|
|
69
|
-
return [rows, cols] if keys.empty?
|
|
70
|
-
|
|
71
|
-
loop do
|
|
72
|
-
settled_rows = rows
|
|
73
|
-
settled_cols = cols
|
|
74
|
-
|
|
75
|
-
row_masks.each_with_index do |mask, row|
|
|
76
|
-
bit = 1 << row
|
|
77
|
-
next if mask.zero? || (rows.allbits?(bit) && cols.allbits?(mask))
|
|
78
|
-
|
|
79
|
-
rows &= ~bit
|
|
80
|
-
cols &= ~mask
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
return [rows, cols] if rows == settled_rows && cols == settled_cols
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
def read_a(port_a, port_b) = scan(port_a, port_b).first
|
|
88
|
-
|
|
89
|
-
def read_b(port_a, port_b) = scan(port_a, port_b).last
|
|
90
|
-
|
|
91
|
-
private
|
|
92
|
-
|
|
93
|
-
# Columns held down per row, as a bit mask of port B lines.
|
|
94
|
-
def row_masks
|
|
95
|
-
@row_masks ||= begin
|
|
96
|
-
pressed = held
|
|
97
|
-
matrix.map do |row|
|
|
98
|
-
row.each_with_index.sum { |key, column| pressed.include?(key) ? 1 << column : 0 }
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
# The matrix keys held down, with each combination expanded.
|
|
104
|
-
def held
|
|
105
|
-
keys.flat_map { |key| COMBINATIONS[key] || [key] }
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
def valid_key?(key)
|
|
109
|
-
COMBINATIONS.key?(key) || matrix.flatten.include?(key)
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
|
-
end
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
module RAMExpansion
|
|
5
|
-
# The register and page mapping the expansions share. #map lays the
|
|
6
|
-
# selected banks out in the address bus's page tables, and #map_io puts
|
|
7
|
-
# the register over the VIC's I/O page at $D100.
|
|
8
|
-
module Banking
|
|
9
|
-
attr_reader :low_ram, :high_ram, :video_ram
|
|
10
|
-
|
|
11
|
-
# The block runs whenever the register moves a bank.
|
|
12
|
-
def on_change(&block)
|
|
13
|
-
@on_change = block
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def peek(_addr) = 0xff
|
|
17
|
-
|
|
18
|
-
def map(read_pages, write_pages)
|
|
19
|
-
[read_pages, write_pages].each do |pages|
|
|
20
|
-
pages.fill(@low_ram, 0x00, 0x10)
|
|
21
|
-
pages.fill(@high_ram, 0x10, 0xf0)
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def map_io(read_pages, write_pages)
|
|
26
|
-
read_pages[0xd1] = write_pages[0xd1] = self
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
module RAMExpansion
|
|
5
|
-
# The +256K: four 64K banks, the first of them the machine's own RAM.
|
|
6
|
-
# $D100 picks one for $0000-$0FFF (bits 0-1), one for the VIC (bits 2-3)
|
|
7
|
-
# and one for $1000-$FFFF (bits 6-7). Setting bit 4 locks the register
|
|
8
|
-
# until the next reset.
|
|
9
|
-
class Plus256k
|
|
10
|
-
include Banking
|
|
11
|
-
|
|
12
|
-
def initialize(ram)
|
|
13
|
-
@banks = [ram, Memory.new, Memory.new, Memory.new]
|
|
14
|
-
@on_change = nil
|
|
15
|
-
reset!
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def poke(_addr, value)
|
|
19
|
-
return if @locked
|
|
20
|
-
|
|
21
|
-
@low_ram = @banks[value & 0b11]
|
|
22
|
-
@video_ram = @banks[(value >> 2) & 0b11]
|
|
23
|
-
@high_ram = @banks[value >> 6]
|
|
24
|
-
@locked = value.anybits?(0x10)
|
|
25
|
-
@on_change&.call
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def reset!
|
|
29
|
-
@low_ram = @video_ram = @high_ram = @banks[0]
|
|
30
|
-
@locked = false
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def type = :plus256k
|
|
34
|
-
|
|
35
|
-
def save_state(out)
|
|
36
|
-
[@low_ram, @video_ram, @high_ram].each { |bank| out.int(@banks.index(bank)) }
|
|
37
|
-
out.boolean(@locked)
|
|
38
|
-
@banks.drop(1).each { |bank| bank.save_state(out) }
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def load_state(input)
|
|
42
|
-
@low_ram = @banks.fetch(input.int)
|
|
43
|
-
@video_ram = @banks.fetch(input.int)
|
|
44
|
-
@high_ram = @banks.fetch(input.int)
|
|
45
|
-
@locked = input.boolean?
|
|
46
|
-
@banks.drop(1).each { |bank| bank.load_state(input) }
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def power_on!
|
|
50
|
-
@banks.drop(1).each(&:clear!)
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|