badline 0.12.1 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +66 -1
- data/CLAUDE.md +86 -38
- data/CONTRIBUTING.md +4 -3
- data/README.md +9 -6
- data/doc/library.md +9 -9
- data/doc/media.md +2 -1
- data/doc/pinned-behaviour.md +134 -105
- data/doc/snapshot-format.md +1047 -0
- data/doc/snapshots.md +73 -43
- data/lib/badline/audio/bare_player.rb +53 -20
- data/lib/badline/audio/cli.rb +6 -6
- data/lib/badline/audio/jukebox.rb +2 -2
- data/lib/badline/audio/machine_player.rb +16 -10
- data/lib/badline/{media → audio}/queue.rb +1 -1
- data/lib/badline/audio/queued_tune.rb +6 -6
- data/lib/badline/audio/renderer.rb +33 -22
- data/lib/badline/audio/stereo.rb +1 -1
- data/lib/badline/c128/banks.rb +6 -3
- data/lib/badline/c128/bus/keyed_state.rb +45 -0
- data/lib/badline/c128/bus.rb +35 -20
- data/lib/badline/c128/color_lines.rb +2 -2
- data/lib/badline/c128/cpu.rb +1 -1
- data/lib/badline/c128/drives.rb +14 -34
- data/lib/badline/c128/fast_serial.rb +5 -5
- data/lib/badline/c128/keyed_modules.rb +117 -0
- data/lib/badline/c128/keyed_state.rb +91 -0
- data/lib/badline/c128/keys.rb +9 -0
- data/lib/badline/c128/mmu.rb +9 -8
- data/lib/badline/c128/mmu_pages.rb +21 -1
- data/lib/badline/c128/modes.rb +21 -11
- data/lib/badline/c128/z80.rb +2 -2
- data/lib/badline/c128/z80_turns.rb +1 -1
- data/lib/badline/c128.rb +21 -16
- data/lib/badline/c64/attachments.rb +42 -0
- data/lib/badline/c64/banked_ram/banking.rb +32 -0
- data/lib/badline/c64/banked_ram/plus256k.rb +64 -0
- data/lib/badline/c64/banked_ram/plus60k.rb +47 -0
- data/lib/badline/c64/banked_ram/unexpanded.rb +30 -0
- data/lib/badline/c64/banked_ram.rb +23 -0
- data/lib/badline/c64/bus/debug_register.rb +32 -0
- data/lib/badline/c64/bus/extra_sids.rb +32 -0
- data/lib/badline/c64/bus/fittings.rb +40 -0
- data/lib/badline/c64/bus/keyed_state.rb +41 -0
- data/lib/badline/c64/bus/pla.rb +149 -0
- data/lib/badline/c64/bus/roms.rb +41 -0
- data/lib/badline/c64/bus/sid_slots.rb +44 -0
- data/lib/badline/c64/bus.rb +219 -0
- data/lib/badline/c64/cartridge/action_replay.rb +115 -0
- data/lib/badline/c64/cartridge/atomic_power.rb +26 -0
- data/lib/badline/c64/cartridge/bank.rb +83 -0
- data/lib/badline/c64/cartridge/comal80.rb +52 -0
- data/lib/badline/c64/cartridge/dinamic.rb +36 -0
- data/lib/badline/c64/cartridge/easy_flash.rb +132 -0
- data/lib/badline/c64/cartridge/epyx_fastload.rb +73 -0
- data/lib/badline/c64/cartridge/final_cartridge3.rb +79 -0
- data/lib/badline/c64/cartridge/flash.rb +279 -0
- data/lib/badline/c64/cartridge/freezer.rb +35 -0
- data/lib/badline/c64/cartridge/fun_play.rb +40 -0
- data/lib/badline/c64/cartridge/g_mod2.rb +64 -0
- data/lib/badline/c64/cartridge/game_system.rb +42 -0
- data/lib/badline/c64/cartridge/geo_ram.rb +65 -0
- data/lib/badline/c64/cartridge/kcs_power.rb +69 -0
- data/lib/badline/c64/cartridge/keyed_state.rb +393 -0
- data/lib/badline/c64/cartridge/mach5.rb +34 -0
- data/lib/badline/c64/cartridge/magic_desk.rb +32 -0
- data/lib/badline/c64/cartridge/ocean.rb +37 -0
- data/lib/badline/c64/cartridge/pagefox.rb +60 -0
- data/lib/badline/c64/cartridge/retro_replay.rb +278 -0
- data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
- data/lib/badline/c64/cartridge/rgcd.rb +50 -0
- data/lib/badline/c64/cartridge/simons_basic.rb +37 -0
- data/lib/badline/c64/cartridge/standard.rb +17 -0
- data/lib/badline/c64/cartridge/super_games.rb +40 -0
- data/lib/badline/c64/cartridge/westermann.rb +32 -0
- data/lib/badline/c64/cartridge/zaxxon.rb +52 -0
- data/lib/badline/c64/cartridge.rb +232 -0
- data/lib/badline/c64/color_memory.rb +27 -0
- data/lib/badline/{computer → c64}/common.rb +2 -2
- data/lib/badline/{computer → c64}/kernal_traps.rb +39 -36
- data/lib/badline/c64/keyed_modules.rb +111 -0
- data/lib/badline/c64/keyed_state.rb +68 -0
- data/lib/badline/c64/reu/dma.rb +271 -0
- data/lib/badline/c64/reu/keyed_state.rb +140 -0
- data/lib/badline/c64/reu/ram.rb +94 -0
- data/lib/badline/c64/reu/trigger.rb +34 -0
- data/lib/badline/c64/reu.rb +289 -0
- data/lib/badline/c64/true_drives.rb +120 -0
- data/lib/badline/{computer.rb → c64.rb} +24 -15
- data/lib/badline/chips/cia/fast_forward.rb +62 -0
- data/lib/badline/chips/cia/interrupt_register.rb +128 -0
- data/lib/badline/chips/cia/keyed_parts.rb +213 -0
- data/lib/badline/chips/cia/serial.rb +246 -0
- data/lib/badline/chips/cia/time_of_day.rb +210 -0
- data/lib/badline/chips/cia/timer.rb +188 -0
- data/lib/badline/chips/cia.rb +281 -0
- data/lib/badline/chips/cpu/addressing.rb +133 -0
- data/lib/badline/chips/cpu/boundary.rb +56 -0
- data/lib/badline/chips/cpu/core.rb +183 -0
- data/lib/badline/chips/cpu/instruction.rb +338 -0
- data/lib/badline/chips/cpu/instruction_set/arithmetic.rb +118 -0
- data/lib/badline/chips/cpu/instruction_set/bitwise.rb +130 -0
- data/lib/badline/chips/cpu/instruction_set/branch.rb +83 -0
- data/lib/badline/chips/cpu/instruction_set/flag.rb +67 -0
- data/lib/badline/chips/cpu/instruction_set/illegal.rb +274 -0
- data/lib/badline/chips/cpu/instruction_set/inc_dec.rb +73 -0
- data/lib/badline/chips/cpu/instruction_set/stack.rb +56 -0
- data/lib/badline/chips/cpu/instruction_set/transfer.rb +141 -0
- data/lib/badline/chips/cpu/instruction_set.rb +59 -0
- data/lib/badline/chips/cpu/interrupts.rb +108 -0
- data/lib/badline/chips/cpu/keyed_state.rb +177 -0
- data/lib/badline/chips/cpu/microcode.rb +195 -0
- data/lib/badline/chips/cpu/operations.rb +90 -0
- data/lib/badline/chips/cpu/port.rb +133 -0
- data/lib/badline/chips/cpu/stack_operations.rb +84 -0
- data/lib/badline/chips/cpu/traps.rb +23 -0
- data/lib/badline/chips/cpu.rb +17 -0
- data/lib/badline/chips/sid/catch_up.rb +122 -0
- data/lib/badline/chips/sid/decimator.rb +68 -0
- data/lib/badline/chips/sid/envelope.rb +236 -0
- data/lib/badline/chips/sid/filter.rb +227 -0
- data/lib/badline/chips/sid/keyed_parts.rb +286 -0
- data/lib/badline/chips/sid/voice.rb +69 -0
- data/lib/badline/chips/sid/waveform/combined.rb +128 -0
- data/lib/badline/chips/sid/waveform/fast_forward.rb +107 -0
- data/lib/badline/chips/sid/waveform/noise_writeback.rb +124 -0
- data/lib/badline/chips/sid/waveform.rb +305 -0
- data/lib/badline/chips/sid.rb +264 -0
- data/lib/badline/chips/ted/beam.rb +119 -0
- data/lib/badline/chips/ted/timers.rb +66 -0
- data/lib/badline/chips/ted.rb +143 -0
- data/lib/badline/chips/tia.rb +49 -0
- data/lib/badline/chips/vdc/keyed_parts.rb +105 -0
- data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
- data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -13
- data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -17
- data/lib/badline/{c128 → chips}/vdc/window.rb +1 -10
- data/lib/badline/{c128 → chips}/vdc.rb +6 -31
- data/lib/badline/chips/via/control_lines.rb +109 -0
- data/lib/badline/chips/via/fast_forward.rb +55 -0
- data/lib/badline/chips/via/interrupt_register.rb +60 -0
- data/lib/badline/chips/via/keyed_parts.rb +163 -0
- data/lib/badline/chips/via/shift_register.rb +168 -0
- data/lib/badline/chips/via/timer1.rb +120 -0
- data/lib/badline/chips/via/timer2.rb +117 -0
- data/lib/badline/chips/via.rb +267 -0
- data/lib/badline/chips/vic/bank.rb +135 -0
- data/lib/badline/chips/vic/border_mask.rb +78 -0
- data/lib/badline/chips/vic/collisions.rb +106 -0
- data/lib/badline/chips/vic/color_patches.rb +38 -0
- data/lib/badline/chips/vic/display_state.rb +168 -0
- data/lib/badline/chips/vic/graphics_mode.rb +166 -0
- data/lib/badline/chips/vic/graphics_shifter.rb +183 -0
- data/lib/badline/chips/vic/keyed_parts.rb +228 -0
- data/lib/badline/chips/vic/keyed_sprites.rb +225 -0
- data/lib/badline/chips/vic/keyed_state.rb +102 -0
- data/lib/badline/chips/vic/register_log.rb +65 -0
- data/lib/badline/chips/vic/registers.rb +188 -0
- data/lib/badline/chips/vic/sequencer.rb +275 -0
- data/lib/badline/chips/vic/sequencer_output.rb +118 -0
- data/lib/badline/chips/vic/sprite/internal_bus.rb +59 -0
- data/lib/badline/chips/vic/sprite/shifter.rb +148 -0
- data/lib/badline/chips/vic/sprite/timing.rb +58 -0
- data/lib/badline/chips/vic/sprite.rb +337 -0
- data/lib/badline/chips/vic/sprites.rb +281 -0
- data/lib/badline/chips/vic.rb +787 -0
- data/lib/badline/chips/vic_i/keyed_parts.rb +142 -0
- data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +2 -30
- data/lib/badline/chips/vic_i/sound/output.rb +85 -0
- data/lib/badline/chips/vic_i/sound.rb +227 -0
- data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
- data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +6 -6
- data/lib/badline/chips/z80/arithmetic.rb +119 -0
- data/lib/badline/chips/z80/bit_page.rb +57 -0
- data/lib/badline/chips/z80/block_io.rb +60 -0
- data/lib/badline/chips/z80/block_transfers.rb +61 -0
- data/lib/badline/chips/z80/bus_cycles.rb +113 -0
- data/lib/badline/chips/z80/core.rb +115 -0
- data/lib/badline/chips/z80/exchanges.rb +52 -0
- data/lib/badline/chips/z80/extended_page.rb +91 -0
- data/lib/badline/chips/z80/flags.rb +39 -0
- data/lib/badline/chips/z80/interrupt_acceptance.rb +48 -0
- data/lib/badline/chips/z80/jumps.rb +84 -0
- data/lib/badline/chips/z80/keyed_state.rb +73 -0
- data/lib/badline/chips/z80/loads.rb +100 -0
- data/lib/badline/chips/z80/main_page.rb +136 -0
- data/lib/badline/chips/z80/registers.rb +122 -0
- data/lib/badline/chips/z80/shifts.rb +66 -0
- data/lib/badline/chips/z80.rb +13 -0
- data/lib/badline/chips.rb +10 -0
- data/lib/badline/core.rb +13 -32
- data/lib/badline/drives/datasette/keyed_state.rb +38 -0
- data/lib/badline/drives/datasette.rb +173 -0
- data/lib/badline/drives/engine/core.rb +152 -0
- data/lib/badline/drives/engine/fast_serial.rb +75 -0
- data/lib/badline/drives/engine/idle.rb +127 -0
- data/lib/badline/drives/engine/idle_cpu.rb +30 -0
- data/lib/badline/drives/engine/orbit.rb +81 -0
- data/lib/badline/drives/engine/serial_lines.rb +72 -0
- data/lib/badline/drives/engine/sleep.rb +114 -0
- data/lib/badline/drives/engine/vias.rb +86 -0
- data/lib/badline/drives/engine/watch.rb +152 -0
- data/lib/badline/drives/engine.rb +11 -0
- data/lib/badline/drives/model1541/bus.rb +75 -0
- data/lib/badline/drives/model1541/byte_ready.rb +50 -0
- data/lib/badline/drives/model1541/cpu.rb +13 -0
- data/lib/badline/drives/model1541/disk.rb +318 -0
- data/lib/badline/drives/model1541/disk_via.rb +38 -0
- data/lib/badline/drives/model1541/gcr.rb +59 -0
- data/lib/badline/drives/model1541/keyed_state.rb +251 -0
- data/lib/badline/drives/model1541/mechanism.rb +313 -0
- data/lib/badline/drives/model1541/rotation.rb +123 -0
- data/lib/badline/drives/model1541/sector_reader.rb +78 -0
- data/lib/badline/drives/model1541/serial_port.rb +20 -0
- data/lib/badline/drives/model1541/track.rb +100 -0
- data/lib/badline/drives/model1541.rb +80 -0
- data/lib/badline/drives/model1571/bus.rb +100 -0
- data/lib/badline/drives/model1571/cpu.rb +13 -0
- data/lib/badline/drives/model1571/keyed_state.rb +108 -0
- data/lib/badline/drives/model1571/serial_port.rb +39 -0
- data/lib/badline/drives/model1571/serial_via.rb +27 -0
- data/lib/badline/drives/model1571/wd1770.rb +108 -0
- data/lib/badline/drives/model1571.rb +141 -0
- data/lib/badline/drives/model1581/bus.rb +126 -0
- data/lib/badline/drives/model1581/cpu.rb +13 -0
- data/lib/badline/drives/model1581/disk.rb +133 -0
- data/lib/badline/drives/model1581/keyed_state.rb +280 -0
- data/lib/badline/drives/model1581/mechanism.rb +98 -0
- data/lib/badline/drives/model1581/serial_port.rb +54 -0
- data/lib/badline/drives/model1581/slot.rb +61 -0
- data/lib/badline/drives/model1581/track.rb +102 -0
- data/lib/badline/drives/model1581/track_bytes.rb +77 -0
- data/lib/badline/drives/model1581/wd1772/registers.rb +91 -0
- data/lib/badline/drives/model1581/wd1772/sector_writes.rb +75 -0
- data/lib/badline/drives/model1581/wd1772/sectors.rb +152 -0
- data/lib/badline/drives/model1581/wd1772/stepping.rb +111 -0
- data/lib/badline/drives/model1581/wd1772/tracks.rb +127 -0
- data/lib/badline/drives/model1581/wd1772/turn.rb +75 -0
- data/lib/badline/drives/model1581/wd1772.rb +216 -0
- data/lib/badline/drives/model1581.rb +206 -0
- data/lib/badline/drives/serial_bus.rb +161 -0
- data/lib/badline/drives.rb +8 -0
- data/lib/badline/frontend/app.rb +3 -3
- data/lib/badline/frontend/boot.rb +4 -4
- data/lib/badline/frontend/controls.rb +19 -3
- data/lib/badline/frontend/drive_led.rb +44 -21
- data/lib/badline/frontend/machine_window.rb +3 -1
- data/lib/badline/frontend/menu/menu_dialogs.rb +2 -2
- data/lib/badline/frontend/player/filter_view.rb +1 -1
- data/lib/badline/frontend/player/player_controller.rb +2 -2
- data/lib/badline/frontend/player/player_screen.rb +1 -0
- data/lib/badline/frontend/player/theme.rb +7 -7
- data/lib/badline/frontend/snapshots.rb +12 -1
- data/lib/badline/frontend/timeline.rb +30 -12
- data/lib/badline/input/control_ports.rb +78 -0
- data/lib/badline/input/joystick.rb +27 -0
- data/lib/badline/input/keyboard.rb +114 -0
- data/lib/badline/input/matrix_typist.rb +98 -0
- data/lib/badline/input.rb +4 -0
- data/lib/badline/kernal_trap/chrout.rb +45 -0
- data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
- data/lib/badline/kernal_trap/dos/channel.rb +156 -0
- data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -26
- data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -10
- data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -9
- data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -19
- data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
- data/lib/badline/kernal_trap/{drive.rb → dos.rb} +9 -27
- data/lib/badline/kernal_trap/file_routine.rb +4 -4
- data/lib/badline/kernal_trap/keyed_state.rb +150 -0
- data/lib/badline/kernal_trap/layout.rb +75 -11
- data/lib/badline/kernal_trap/load.rb +19 -21
- data/lib/badline/kernal_trap/routine.rb +12 -0
- data/lib/badline/kernal_trap/save.rb +12 -22
- data/lib/badline/kernal_trap/serial.rb +8 -24
- data/lib/badline/kernal_trap.rb +3 -2
- data/lib/badline/machine/clocking.rb +1 -1
- data/lib/badline/machine/keyboard_buffer.rb +49 -0
- data/lib/badline/machine/settling.rb +29 -0
- data/lib/badline/machine.rb +10 -7
- data/lib/badline/media/boot_disk.rb +14 -2
- data/lib/badline/media/extensions.rb +10 -0
- data/lib/badline/media/true_drive.rb +1 -1
- data/lib/badline/media/tune.rb +2 -2
- data/lib/badline/media.rb +3 -3
- data/lib/badline/memory.rb +3 -6
- data/lib/badline/model.rb +1 -1
- data/lib/badline/options/family.rb +5 -2
- data/lib/badline/options/help.rb +42 -16
- data/lib/badline/options/table.rb +2 -0
- data/lib/badline/options/validation.rb +2 -0
- data/lib/badline/options.rb +6 -1
- data/lib/badline/plus4/acia.rb +45 -0
- data/lib/badline/plus4/bus.rb +312 -0
- data/lib/badline/plus4/cpu.rb +10 -0
- data/lib/badline/plus4/cpu_port.rb +93 -0
- data/lib/badline/plus4/keyboard_port.rb +51 -0
- data/lib/badline/plus4/model.rb +38 -0
- data/lib/badline/plus4/user_port.rb +31 -0
- data/lib/badline/plus4.rb +164 -0
- data/lib/badline/roms/README +44 -6
- data/lib/badline/roms/plus4/basic.rom +0 -0
- data/lib/badline/roms/plus4/function-high.rom +0 -0
- data/lib/badline/roms/plus4/function-low.rom +0 -0
- data/lib/badline/roms/plus4/kernal-ntsc.rom +0 -0
- data/lib/badline/roms/plus4/kernal-pal.rom +0 -0
- data/lib/badline/sdl.rb +1 -0
- data/lib/badline/{storage/sid_file.rb → sid_tune/file.rb} +3 -3
- data/lib/badline/{storage → sid_tune}/hvsc.rb +7 -7
- data/lib/badline/{storage → sid_tune}/song_lengths.rb +2 -2
- data/lib/badline/{storage → sid_tune}/stil/credit.rb +1 -1
- data/lib/badline/{storage → sid_tune}/stil.rb +3 -3
- data/lib/badline/sid_tune.rb +6 -0
- data/lib/badline/snapshot/c128_setup.rb +32 -0
- data/lib/badline/snapshot/c64_setup.rb +83 -0
- data/lib/badline/snapshot/container.rb +4 -0
- data/lib/badline/snapshot/field_doc/markdown.rb +112 -0
- data/lib/badline/snapshot/field_doc.rb +109 -0
- data/lib/badline/snapshot/image.rb +132 -46
- data/lib/badline/snapshot/keyed/cursor.rb +40 -0
- data/lib/badline/snapshot/keyed/modules.rb +66 -0
- data/lib/badline/snapshot/keyed/reader.rb +188 -0
- data/lib/badline/snapshot/keyed/recorder.rb +88 -0
- data/lib/badline/snapshot/keyed/report.rb +26 -0
- data/lib/badline/snapshot/keyed/writer.rb +55 -0
- data/lib/badline/snapshot/keyed.rb +64 -0
- data/lib/badline/snapshot/machine_state.rb +17 -64
- data/lib/badline/snapshot/storage_setup.rb +63 -0
- data/lib/badline/snapshot/vic20_setup.rb +28 -0
- data/lib/badline/snapshot/vice/c64_mem.rb +1 -1
- data/lib/badline/snapshot/vice/restore.rb +1 -1
- data/lib/badline/snapshot/vice/reu1764.rb +3 -3
- data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
- data/lib/badline/snapshot/vice.rb +13 -35
- data/lib/badline/snapshot.rb +44 -22
- data/lib/badline/storage/crt_file.rb +3 -1
- data/lib/badline/storage/d64_image.rb +0 -2
- data/lib/badline/storage/d71_image.rb +0 -2
- data/lib/badline/storage/d81_image.rb +0 -2
- data/lib/badline/storage/disk_image.rb +3 -6
- data/lib/badline/storage/g64_image.rb +10 -5
- data/lib/badline/storage/host_directory.rb +0 -5
- data/lib/badline/storage/t64.rb +2 -8
- data/lib/badline/storage/tap.rb +43 -15
- data/lib/badline/storage/unavailable.rb +1 -1
- data/lib/badline/storage.rb +0 -37
- data/lib/badline/support/c128_checkpoint.rb +39 -0
- data/lib/badline/support/checkpoint.rb +108 -0
- data/lib/badline/support/vic20_checkpoint.rb +38 -0
- data/lib/badline/support.rb +5 -0
- data/lib/badline/version.rb +1 -1
- data/lib/badline/vic20/attachments.rb +8 -5
- data/lib/badline/vic20/bus/keyed_state.rb +52 -0
- data/lib/badline/vic20/bus.rb +2 -25
- data/lib/badline/vic20/cpu.rb +1 -1
- data/lib/badline/vic20/keyed_modules.rb +73 -0
- data/lib/badline/vic20/keyed_state.rb +45 -0
- data/lib/badline/vic20/port_wiring.rb +4 -4
- data/lib/badline/vic20/user_via_ports.rb +2 -2
- data/lib/badline/vic20.rb +22 -17
- data/lib/badline.rb +1 -0
- metadata +271 -228
- data/lib/badline/address_bus/extra_sids.rb +0 -30
- data/lib/badline/address_bus/fittings.rb +0 -38
- data/lib/badline/address_bus/pla.rb +0 -147
- data/lib/badline/address_bus/roms.rb +0 -39
- data/lib/badline/address_bus/saved_state.rb +0 -66
- data/lib/badline/address_bus/sid_slots.rb +0 -42
- data/lib/badline/address_bus.rb +0 -216
- data/lib/badline/c128/bus_state.rb +0 -53
- data/lib/badline/c128/saved_state.rb +0 -143
- data/lib/badline/cartridge/action_replay.rb +0 -126
- data/lib/badline/cartridge/atomic_power.rb +0 -24
- data/lib/badline/cartridge/bank.rb +0 -81
- data/lib/badline/cartridge/comal80.rb +0 -50
- data/lib/badline/cartridge/dinamic.rb +0 -34
- data/lib/badline/cartridge/easy_flash.rb +0 -145
- data/lib/badline/cartridge/epyx_fastload.rb +0 -79
- data/lib/badline/cartridge/final_cartridge3.rb +0 -89
- data/lib/badline/cartridge/flash.rb +0 -306
- data/lib/badline/cartridge/freezer.rb +0 -33
- data/lib/badline/cartridge/fun_play.rb +0 -38
- data/lib/badline/cartridge/g_mod2.rb +0 -74
- data/lib/badline/cartridge/game_system.rb +0 -40
- data/lib/badline/cartridge/geo_ram.rb +0 -79
- data/lib/badline/cartridge/kcs_power.rb +0 -75
- data/lib/badline/cartridge/mach5.rb +0 -32
- data/lib/badline/cartridge/magic_desk.rb +0 -30
- data/lib/badline/cartridge/ocean.rb +0 -35
- data/lib/badline/cartridge/pagefox.rb +0 -68
- data/lib/badline/cartridge/retro_replay.rb +0 -320
- data/lib/badline/cartridge/rex_utility.rb +0 -29
- data/lib/badline/cartridge/rgcd.rb +0 -58
- data/lib/badline/cartridge/simons_basic.rb +0 -35
- data/lib/badline/cartridge/standard.rb +0 -15
- data/lib/badline/cartridge/super_games.rb +0 -48
- data/lib/badline/cartridge/westermann.rb +0 -30
- data/lib/badline/cartridge/zaxxon.rb +0 -66
- data/lib/badline/cartridge.rb +0 -303
- data/lib/badline/checkpoint.rb +0 -98
- data/lib/badline/chrout_trap.rb +0 -43
- data/lib/badline/cia/fast_forward.rb +0 -60
- data/lib/badline/cia/interrupt_register.rb +0 -143
- data/lib/badline/cia/serial.rb +0 -275
- data/lib/badline/cia/state.rb +0 -47
- data/lib/badline/cia/timer.rb +0 -206
- data/lib/badline/cia.rb +0 -279
- data/lib/badline/color_memory.rb +0 -25
- data/lib/badline/computer/attachments.rb +0 -88
- data/lib/badline/computer/saved_state.rb +0 -117
- data/lib/badline/computer/true_drives.rb +0 -69
- data/lib/badline/control_ports.rb +0 -76
- data/lib/badline/cpu/addressing.rb +0 -131
- data/lib/badline/cpu/boundary.rb +0 -54
- data/lib/badline/cpu/core.rb +0 -165
- data/lib/badline/cpu/microcode.rb +0 -177
- data/lib/badline/cpu/operations.rb +0 -88
- data/lib/badline/cpu/saved_state.rb +0 -115
- data/lib/badline/cpu/stack_operations.rb +0 -82
- data/lib/badline/cpu.rb +0 -10
- data/lib/badline/cpu_port.rb +0 -112
- data/lib/badline/datasette.rb +0 -161
- data/lib/badline/debug_register.rb +0 -28
- data/lib/badline/drive/core.rb +0 -147
- data/lib/badline/drive/fast_serial.rb +0 -73
- data/lib/badline/drive/idle.rb +0 -125
- data/lib/badline/drive/idle_cpu.rb +0 -28
- data/lib/badline/drive/orbit.rb +0 -79
- data/lib/badline/drive/serial_lines.rb +0 -73
- data/lib/badline/drive/sleep.rb +0 -112
- data/lib/badline/drive/vias.rb +0 -84
- data/lib/badline/drive/watch.rb +0 -150
- data/lib/badline/drive.rb +0 -11
- data/lib/badline/drive1541/bus.rb +0 -86
- data/lib/badline/drive1541/byte_ready.rb +0 -48
- data/lib/badline/drive1541/cpu.rb +0 -11
- data/lib/badline/drive1541/disk.rb +0 -315
- data/lib/badline/drive1541/disk_state.rb +0 -86
- data/lib/badline/drive1541/disk_via.rb +0 -36
- data/lib/badline/drive1541/gcr.rb +0 -57
- data/lib/badline/drive1541/mechanism.rb +0 -313
- data/lib/badline/drive1541/mechanism_state.rb +0 -68
- data/lib/badline/drive1541/rotation.rb +0 -121
- data/lib/badline/drive1541/sector_reader.rb +0 -76
- data/lib/badline/drive1541/serial_port.rb +0 -18
- data/lib/badline/drive1541/track.rb +0 -98
- data/lib/badline/drive1541.rb +0 -111
- data/lib/badline/drive1571/bus.rb +0 -111
- data/lib/badline/drive1571/cpu.rb +0 -11
- data/lib/badline/drive1571/serial_port.rb +0 -37
- data/lib/badline/drive1571/serial_via.rb +0 -25
- data/lib/badline/drive1571/wd1770.rb +0 -120
- data/lib/badline/drive1571.rb +0 -175
- data/lib/badline/drive1581/bus.rb +0 -137
- data/lib/badline/drive1581/cpu.rb +0 -11
- data/lib/badline/drive1581/disk.rb +0 -135
- data/lib/badline/drive1581/disk_state.rb +0 -87
- data/lib/badline/drive1581/mechanism.rb +0 -117
- data/lib/badline/drive1581/serial_port.rb +0 -52
- data/lib/badline/drive1581/slot.rb +0 -78
- data/lib/badline/drive1581/track.rb +0 -100
- data/lib/badline/drive1581/track_bytes.rb +0 -75
- data/lib/badline/drive1581/wd1772/registers.rb +0 -89
- data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
- data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
- data/lib/badline/drive1581/wd1772/state.rb +0 -66
- data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
- data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
- data/lib/badline/drive1581/wd1772/turn.rb +0 -73
- data/lib/badline/drive1581/wd1772.rb +0 -216
- data/lib/badline/drive1581.rb +0 -233
- data/lib/badline/iec_bus.rb +0 -159
- data/lib/badline/instruction.rb +0 -334
- data/lib/badline/instruction_set/arithmetic.rb +0 -114
- data/lib/badline/instruction_set/bitwise.rb +0 -126
- data/lib/badline/instruction_set/branch.rb +0 -79
- data/lib/badline/instruction_set/flag.rb +0 -63
- data/lib/badline/instruction_set/illegal.rb +0 -270
- data/lib/badline/instruction_set/inc_dec.rb +0 -69
- data/lib/badline/instruction_set/stack.rb +0 -52
- data/lib/badline/instruction_set/transfer.rb +0 -137
- data/lib/badline/instruction_set.rb +0 -55
- data/lib/badline/interrupts.rb +0 -104
- data/lib/badline/joystick.rb +0 -25
- data/lib/badline/kernal_trap/channel.rb +0 -181
- data/lib/badline/keyboard.rb +0 -112
- data/lib/badline/keyboard_buffer.rb +0 -33
- data/lib/badline/ram_expansion/banking.rb +0 -30
- data/lib/badline/ram_expansion/plus256k.rb +0 -54
- data/lib/badline/ram_expansion/plus60k.rb +0 -43
- data/lib/badline/ram_expansion/unexpanded.rb +0 -28
- data/lib/badline/ram_expansion.rb +0 -21
- data/lib/badline/reu/dma/saved_state.rb +0 -50
- data/lib/badline/reu/dma.rb +0 -273
- data/lib/badline/reu/ram.rb +0 -107
- data/lib/badline/reu/saved_state.rb +0 -80
- data/lib/badline/reu/trigger.rb +0 -32
- data/lib/badline/reu.rb +0 -289
- data/lib/badline/sid/catch_up.rb +0 -120
- data/lib/badline/sid/decimator.rb +0 -64
- data/lib/badline/sid/envelope/state.rb +0 -68
- data/lib/badline/sid/envelope.rb +0 -239
- data/lib/badline/sid/filter.rb +0 -263
- data/lib/badline/sid/voice.rb +0 -77
- data/lib/badline/sid/waveform/combined.rb +0 -126
- data/lib/badline/sid/waveform/fast_forward.rb +0 -105
- data/lib/badline/sid/waveform/noise_writeback.rb +0 -122
- data/lib/badline/sid/waveform/state.rb +0 -66
- data/lib/badline/sid/waveform.rb +0 -305
- data/lib/badline/sid.rb +0 -303
- data/lib/badline/snapshot/setup.rb +0 -75
- data/lib/badline/snapshot/state.rb +0 -189
- data/lib/badline/time_of_day.rb +0 -228
- data/lib/badline/traps.rb +0 -19
- data/lib/badline/via/control_lines.rb +0 -122
- data/lib/badline/via/fast_forward.rb +0 -53
- data/lib/badline/via/interrupt_register.rb +0 -67
- data/lib/badline/via/shift_register.rb +0 -180
- data/lib/badline/via/state.rb +0 -42
- data/lib/badline/via/timer1.rb +0 -131
- data/lib/badline/via/timer2.rb +0 -133
- data/lib/badline/via.rb +0 -266
- data/lib/badline/vic/bank.rb +0 -133
- data/lib/badline/vic/border_mask.rb +0 -86
- data/lib/badline/vic/collisions.rb +0 -115
- data/lib/badline/vic/color_patches.rb +0 -47
- data/lib/badline/vic/display_state.rb +0 -185
- data/lib/badline/vic/graphics_mode.rb +0 -164
- data/lib/badline/vic/graphics_shifter.rb +0 -207
- data/lib/badline/vic/register_log.rb +0 -81
- data/lib/badline/vic/registers.rb +0 -195
- data/lib/badline/vic/sequencer.rb +0 -275
- data/lib/badline/vic/sequencer_output.rb +0 -116
- data/lib/badline/vic/sequencer_state.rb +0 -89
- data/lib/badline/vic/sprite/internal_bus.rb +0 -68
- data/lib/badline/vic/sprite/saved_state.rb +0 -64
- data/lib/badline/vic/sprite/shifter.rb +0 -146
- data/lib/badline/vic/sprite/timing.rb +0 -56
- data/lib/badline/vic/sprite.rb +0 -337
- data/lib/badline/vic/sprites.rb +0 -282
- data/lib/badline/vic/sprites_state.rb +0 -57
- data/lib/badline/vic.rb +0 -853
- data/lib/badline/vic20/saved_state.rb +0 -124
- data/lib/badline/vic20/sound/output.rb +0 -83
- data/lib/badline/vic20/sound.rb +0 -233
- data/lib/badline/vic20/vic/saved_state.rb +0 -55
- data/lib/badline/z80/arithmetic.rb +0 -117
- data/lib/badline/z80/bit_page.rb +0 -55
- data/lib/badline/z80/block_io.rb +0 -58
- data/lib/badline/z80/block_transfers.rb +0 -59
- data/lib/badline/z80/bus_cycles.rb +0 -111
- data/lib/badline/z80/core.rb +0 -113
- data/lib/badline/z80/exchanges.rb +0 -50
- data/lib/badline/z80/extended_page.rb +0 -89
- data/lib/badline/z80/flags.rb +0 -37
- data/lib/badline/z80/interrupt_acceptance.rb +0 -46
- data/lib/badline/z80/jumps.rb +0 -82
- data/lib/badline/z80/loads.rb +0 -98
- data/lib/badline/z80/main_page.rb +0 -134
- data/lib/badline/z80/registers.rb +0 -120
- data/lib/badline/z80/saved_state.rb +0 -69
- data/lib/badline/z80/shifts.rb +0 -64
- data/lib/badline/z80.rb +0 -11
- /data/lib/badline/snapshot/{fields.rb → vice/fields.rb} +0 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class VIA
|
|
6
|
+
# One port's pair of control lines, CA1 and CA2 or CB1 and CB2, set up
|
|
7
|
+
# by a nibble of the peripheral control register, and their two
|
|
8
|
+
# interrupt flags. Bit 0 picks the active edge of C1, rising when set.
|
|
9
|
+
# Bits 3-1 pick the C2 mode:
|
|
10
|
+
#
|
|
11
|
+
# 000 input, falling edge 100 handshake output
|
|
12
|
+
# 001 independent, falling 101 pulse output
|
|
13
|
+
# 010 input, rising edge 110 low output
|
|
14
|
+
# 011 independent, rising 111 high output
|
|
15
|
+
#
|
|
16
|
+
# A port access clears both flags, but an independent input keeps C2's.
|
|
17
|
+
# In handshake mode C2 goes low on a port access and back high on the
|
|
18
|
+
# next active C1 edge. In pulse mode it goes low for the cycle after the
|
|
19
|
+
# access. Port A handshakes on reads and writes, port B on writes only.
|
|
20
|
+
class ControlLines
|
|
21
|
+
attr_reader :control, :c1_high, :c2_high
|
|
22
|
+
|
|
23
|
+
# The level driven on C2, high while it is an input.
|
|
24
|
+
attr_reader :c2_output
|
|
25
|
+
|
|
26
|
+
def initialize(interrupts, c1_flag:, c2_flag:, handshake_on_read:)
|
|
27
|
+
@interrupts = interrupts
|
|
28
|
+
@c1_flag = c1_flag
|
|
29
|
+
@c2_flag = c2_flag
|
|
30
|
+
@handshake_on_read = handshake_on_read
|
|
31
|
+
@c1_high = @c2_high = true
|
|
32
|
+
reset!
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Back to input mode with both handshake outputs released. The input
|
|
36
|
+
# levels carry over.
|
|
37
|
+
def reset!
|
|
38
|
+
@control = 0
|
|
39
|
+
@handshake_low = false
|
|
40
|
+
@pulse = 0
|
|
41
|
+
drive
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def control=(nibble)
|
|
45
|
+
@control = nibble & 0x0f
|
|
46
|
+
drive
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Only the pulse output needs the clock.
|
|
50
|
+
def pulsing? = @pulse.positive?
|
|
51
|
+
|
|
52
|
+
def cycle!
|
|
53
|
+
@pulse -= 1
|
|
54
|
+
drive if @pulse.zero?
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def active_c1_edge?(high) = high == @control.anybits?(0x01)
|
|
58
|
+
|
|
59
|
+
# Everything the lines hold, for comparing them at two points.
|
|
60
|
+
def state = [@control, @c1_high, @c2_high, @handshake_low, @pulse, @c2_output]
|
|
61
|
+
|
|
62
|
+
# A new C1 level. An active edge sets the flag and ends a handshake.
|
|
63
|
+
def c1=(high)
|
|
64
|
+
return if high == @c1_high
|
|
65
|
+
|
|
66
|
+
@c1_high = high
|
|
67
|
+
return unless active_c1_edge?(high)
|
|
68
|
+
|
|
69
|
+
@handshake_low = false
|
|
70
|
+
drive
|
|
71
|
+
@interrupts.set(@c1_flag)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# A new C2 level. An active edge sets the flag while C2 is an input.
|
|
75
|
+
def c2=(high)
|
|
76
|
+
return if high == @c2_high
|
|
77
|
+
|
|
78
|
+
@c2_high = high
|
|
79
|
+
@interrupts.set(@c2_flag) if @control.nobits?(0x08) && high == @control.anybits?(0x04)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# A read or write of the handshaking port register.
|
|
83
|
+
def access!(write)
|
|
84
|
+
@interrupts.clear(independent? ? @c1_flag : @c1_flag | @c2_flag)
|
|
85
|
+
return unless write || @handshake_on_read
|
|
86
|
+
|
|
87
|
+
case @control >> 1
|
|
88
|
+
when 4 then @handshake_low = true
|
|
89
|
+
when 5 then @pulse = 2
|
|
90
|
+
end
|
|
91
|
+
drive
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
private
|
|
95
|
+
|
|
96
|
+
def independent? = @control & 0x0a == 0x02
|
|
97
|
+
|
|
98
|
+
def drive
|
|
99
|
+
@c2_output = case @control >> 1
|
|
100
|
+
when 4 then !@handshake_low
|
|
101
|
+
when 5 then @pulse.zero?
|
|
102
|
+
when 6 then false
|
|
103
|
+
else true
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class VIA
|
|
6
|
+
# Running a VIA a stretch of cycles at once while nothing but its
|
|
7
|
+
# counters would change, for Drives::Engine::Idle.
|
|
8
|
+
module FastForward
|
|
9
|
+
# quiet_cycles for a VIA that will never set a flag of its own.
|
|
10
|
+
QUIET = 1 << 40
|
|
11
|
+
|
|
12
|
+
# How many cycles the VIA can run with nothing but its counters
|
|
13
|
+
# changing: no flag set, no pulse on a control line and no bit
|
|
14
|
+
# shifted. See Drives::Engine::Idle.
|
|
15
|
+
def quiet_cycles
|
|
16
|
+
return 0 if @sr_uses_t2 || @shift_register.clocking? || @ca.pulsing? || @cb.pulsing?
|
|
17
|
+
|
|
18
|
+
[@t1.quiet_cycles, @t2.quiet_cycles].min
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Runs +cycles+ cycles at once, as many as quiet_cycles allows, which
|
|
22
|
+
# moves only the counters.
|
|
23
|
+
def fast_forward(cycles)
|
|
24
|
+
return if cycles.zero?
|
|
25
|
+
|
|
26
|
+
@t1.fast_forward(cycles)
|
|
27
|
+
@t2.fast_forward(cycles)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# The counters an orbit (see Drives::Engine::Idle) has to bring back: those
|
|
31
|
+
# of the armed timers, and of the timers +touched+ names (bit 0 for
|
|
32
|
+
# timer 1, bit 1 for timer 2). The others only count.
|
|
33
|
+
def counter_state(touched)
|
|
34
|
+
[(@t1.count_state if @t1.armed? || touched.anybits?(1)),
|
|
35
|
+
(@t2.count_state if @t2.armed? || touched.anybits?(2))]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Runs +cycles+ cycles of whole orbits at once: the counters
|
|
39
|
+
# counter_state leaves out move on, and the rest come back round.
|
|
40
|
+
def skip_orbits(cycles, touched)
|
|
41
|
+
@t1.fast_forward(cycles) unless @t1.armed? || touched.anybits?(1)
|
|
42
|
+
@t2.fast_forward(cycles) unless @t2.armed? || touched.anybits?(2)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Everything the VIA holds but its counters, for comparing it at two
|
|
46
|
+
# points. Timer 1's PB7 level counts only while ACR bit 7 puts it on
|
|
47
|
+
# the pin: nothing reads it otherwise.
|
|
48
|
+
def idle_state
|
|
49
|
+
[@ora, @orb, @ddra, @ddrb, @latch_a, @latch_b, @acr, @pcr, @pb6_high, @ifr.flags, @ifr.enable,
|
|
50
|
+
@acr.anybits?(0x80) && @t1.pb7, *@t1.state, *@t2.state, *@ca.state, *@cb.state, *@shift_register.state]
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class VIA
|
|
6
|
+
# The interrupt flag and enable registers. Each source has a flag bit,
|
|
7
|
+
# and IRQ is pulled low while any flag is set with its enable bit.
|
|
8
|
+
class InterruptRegister
|
|
9
|
+
CA2 = 0x01
|
|
10
|
+
CA1 = 0x02
|
|
11
|
+
SR = 0x04
|
|
12
|
+
CB2 = 0x08
|
|
13
|
+
CB1 = 0x10
|
|
14
|
+
TIMER2 = 0x20
|
|
15
|
+
TIMER1 = 0x40
|
|
16
|
+
|
|
17
|
+
attr_reader :flags, :enable
|
|
18
|
+
|
|
19
|
+
def initialize
|
|
20
|
+
reset!
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def reset!
|
|
24
|
+
@flags = 0x00
|
|
25
|
+
@enable = 0x00
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def set(bits)
|
|
29
|
+
@flags |= bits
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def clear(bits)
|
|
33
|
+
@flags &= ~bits
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def irq? = @flags.anybits?(@enable)
|
|
37
|
+
|
|
38
|
+
# Bit 7 reads the IRQ output.
|
|
39
|
+
def read = irq? ? @flags | 0x80 : @flags
|
|
40
|
+
|
|
41
|
+
# Writing 1s clears the flags; bit 7 is ignored.
|
|
42
|
+
def write(value)
|
|
43
|
+
clear(value & 0x7f)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Bit 7 reads as 1.
|
|
47
|
+
def read_enable = @enable | 0x80
|
|
48
|
+
|
|
49
|
+
# Bit 7 picks between setting and clearing the enable bits given.
|
|
50
|
+
def write_enable(value)
|
|
51
|
+
if value.anybits?(0x80)
|
|
52
|
+
@enable |= value & 0x7f
|
|
53
|
+
else
|
|
54
|
+
@enable &= ~value & 0x7f
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class VIA
|
|
6
|
+
class Timer1
|
|
7
|
+
# Timer 1's fields in a keyed snapshot module, under `prefix`.
|
|
8
|
+
module KeyedState
|
|
9
|
+
def save_fields(out, prefix)
|
|
10
|
+
out.int("#{prefix}counter", @counter).int("#{prefix}latch", @latch).bool("#{prefix}hold", @hold)
|
|
11
|
+
out.bool("#{prefix}reload", @reload).bool("#{prefix}armed", @armed).bool("#{prefix}pb7", @pb7)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def load_fields(input, prefix)
|
|
15
|
+
@counter = input.word("#{prefix}counter", @counter)
|
|
16
|
+
@latch = input.word("#{prefix}latch", @latch)
|
|
17
|
+
@hold = input.bool("#{prefix}hold", @hold)
|
|
18
|
+
@reload = input.bool("#{prefix}reload", @reload)
|
|
19
|
+
@armed = input.bool("#{prefix}armed", @armed)
|
|
20
|
+
@pb7 = input.bool("#{prefix}pb7", @pb7)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
include KeyedState
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class Timer2
|
|
28
|
+
# Timer 2's fields in a keyed snapshot module, under `prefix`.
|
|
29
|
+
module KeyedState
|
|
30
|
+
def save_fields(out, prefix)
|
|
31
|
+
out.int("#{prefix}counter", @counter).int("#{prefix}latch_low", @latch_low).bool("#{prefix}hold", @hold)
|
|
32
|
+
out.bool("#{prefix}low_reload", @low_reload).bool("#{prefix}armed", @armed)
|
|
33
|
+
out.bool("#{prefix}low_underflowed", @low_underflowed).bool("#{prefix}count_pulses", @count_pulses)
|
|
34
|
+
out.bool("#{prefix}counting_pulses", @counting_pulses)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def load_fields(input, prefix)
|
|
38
|
+
@counter = input.word("#{prefix}counter", @counter)
|
|
39
|
+
@latch_low = input.byte("#{prefix}latch_low", @latch_low)
|
|
40
|
+
@hold = input.bool("#{prefix}hold", @hold)
|
|
41
|
+
@low_reload = input.bool("#{prefix}low_reload", @low_reload)
|
|
42
|
+
@armed = input.bool("#{prefix}armed", @armed)
|
|
43
|
+
@low_underflowed = input.bool("#{prefix}low_underflowed", @low_underflowed)
|
|
44
|
+
@count_pulses = input.bool("#{prefix}count_pulses", @count_pulses)
|
|
45
|
+
@counting_pulses = input.bool("#{prefix}counting_pulses", @counting_pulses)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
include KeyedState
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
class ShiftRegister
|
|
53
|
+
# The shift register's fields in a keyed snapshot module, under
|
|
54
|
+
# `prefix`.
|
|
55
|
+
module KeyedState
|
|
56
|
+
def save_fields(out, prefix)
|
|
57
|
+
out.int("#{prefix}mode", @mode).int("#{prefix}data", @data).int("#{prefix}bits", @bits)
|
|
58
|
+
out.int("#{prefix}delay", @delay).bool("#{prefix}clock", @clock).bool("#{prefix}cb2", @cb2)
|
|
59
|
+
out.bool("#{prefix}cb2_input", @cb2_input)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def load_fields(input, prefix)
|
|
63
|
+
@mode = input.masked("#{prefix}mode", @mode, 0x07)
|
|
64
|
+
@data = input.byte("#{prefix}data", @data)
|
|
65
|
+
@bits = input.int("#{prefix}bits", @bits)
|
|
66
|
+
@delay = input.int("#{prefix}delay", @delay)
|
|
67
|
+
@clock = input.bool("#{prefix}clock", @clock)
|
|
68
|
+
@cb2 = input.bool("#{prefix}cb2", @cb2)
|
|
69
|
+
@cb2_input = input.bool("#{prefix}cb2_input", @cb2_input)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
include KeyedState
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
class InterruptRegister
|
|
77
|
+
# The flags and the enable mask, under `prefix`.
|
|
78
|
+
module KeyedState
|
|
79
|
+
def save_fields(out, prefix)
|
|
80
|
+
out.int("#{prefix}flags", @flags).int("#{prefix}enable", @enable)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def load_fields(input, prefix)
|
|
84
|
+
@flags = input.masked("#{prefix}flags", @flags, 0x7f)
|
|
85
|
+
@enable = input.masked("#{prefix}enable", @enable, 0x7f)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
include KeyedState
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
class ControlLines
|
|
93
|
+
# A pair of control lines' fields, under `prefix`.
|
|
94
|
+
module KeyedState
|
|
95
|
+
def save_fields(out, prefix)
|
|
96
|
+
out.int("#{prefix}control", @control).bool("#{prefix}c1_high", @c1_high).bool("#{prefix}c2_high", @c2_high)
|
|
97
|
+
out.bool("#{prefix}handshake_low", @handshake_low).int("#{prefix}pulse", @pulse)
|
|
98
|
+
out.bool("#{prefix}c2_output", @c2_output)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def load_fields(input, prefix)
|
|
102
|
+
@control = input.masked("#{prefix}control", @control, 0x0f)
|
|
103
|
+
@c1_high = input.bool("#{prefix}c1_high", @c1_high)
|
|
104
|
+
@c2_high = input.bool("#{prefix}c2_high", @c2_high)
|
|
105
|
+
@handshake_low = input.bool("#{prefix}handshake_low", @handshake_low)
|
|
106
|
+
@pulse = input.int("#{prefix}pulse", @pulse)
|
|
107
|
+
@c2_output = input.bool("#{prefix}c2_output", @c2_output)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
include KeyedState
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# The VIA's fields in a keyed snapshot module (Snapshot::Keyed): the
|
|
115
|
+
# registers and PB6, and its parts under t1., t2., sr., ifr., ca. and
|
|
116
|
+
# cb. Whether the shift register clocks off timer 2 comes from the
|
|
117
|
+
# ACR on load. The peripheral restores its own state.
|
|
118
|
+
module KeyedState
|
|
119
|
+
def save_fields(out)
|
|
120
|
+
out.int("ora", @ora).int("orb", @orb).int("ddra", @ddra).int("ddrb", @ddrb).int("latch_a", @latch_a)
|
|
121
|
+
out.int("latch_b", @latch_b).int("acr", @acr).int("pcr", @pcr).bool("pb6_high", @pb6_high)
|
|
122
|
+
@t1.save_fields(out, "t1.")
|
|
123
|
+
@t2.save_fields(out, "t2.")
|
|
124
|
+
@shift_register.save_fields(out, "sr.")
|
|
125
|
+
@ifr.save_fields(out, "ifr.")
|
|
126
|
+
@ca.save_fields(out, "ca.")
|
|
127
|
+
@cb.save_fields(out, "cb.")
|
|
128
|
+
out
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def load_fields(input)
|
|
132
|
+
@ora = input.byte("ora", @ora)
|
|
133
|
+
@orb = input.byte("orb", @orb)
|
|
134
|
+
@ddra = input.byte("ddra", @ddra)
|
|
135
|
+
@ddrb = input.byte("ddrb", @ddrb)
|
|
136
|
+
@latch_a = input.byte("latch_a", @latch_a)
|
|
137
|
+
@latch_b = input.byte("latch_b", @latch_b)
|
|
138
|
+
@acr = input.byte("acr", @acr)
|
|
139
|
+
@pcr = input.byte("pcr", @pcr)
|
|
140
|
+
@pb6_high = input.bool("pb6_high", @pb6_high)
|
|
141
|
+
load_part_fields(input)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def restored!
|
|
145
|
+
@sr_uses_t2 = [1, 4, 5].include?((@acr >> 2) & 0x07)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
private
|
|
149
|
+
|
|
150
|
+
def load_part_fields(input)
|
|
151
|
+
@t1.load_fields(input, "t1.")
|
|
152
|
+
@t2.load_fields(input, "t2.")
|
|
153
|
+
@shift_register.load_fields(input, "sr.")
|
|
154
|
+
@ifr.load_fields(input, "ifr.")
|
|
155
|
+
@ca.load_fields(input, "ca.")
|
|
156
|
+
@cb.load_fields(input, "cb.")
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
include KeyedState
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class VIA
|
|
6
|
+
# The 6522's shift register, with the CB1 clock and CB2 data lines it
|
|
7
|
+
# takes over in every mode but the first.
|
|
8
|
+
#
|
|
9
|
+
# ACR bits 4-2 pick the mode. Modes 1 to 3 shift in, left, with the new
|
|
10
|
+
# bit taken from CB2 into bit 0 on each rising CB1 edge. Modes 4 to 7
|
|
11
|
+
# shift out: each falling CB1 edge puts bit 7 on CB2 and rotates it back
|
|
12
|
+
# round into bit 0, so after eight bits the byte is back where it
|
|
13
|
+
# started. Modes 1, 4 and 5 clock off timer 2, modes 2 and 6 off φ2, and
|
|
14
|
+
# modes 3 and 7 off whatever drives CB1 from outside.
|
|
15
|
+
#
|
|
16
|
+
# Under its own clock the register drives CB1, idling high. Reading or
|
|
17
|
+
# writing the data register starts a byte, but only while the register
|
|
18
|
+
# is idle and enabled: an access in mode 0, or one before the eighth bit
|
|
19
|
+
# is in, leaves the count alone. CB1 falls on the first clock tick of
|
|
20
|
+
# the byte and rises on the second, and so on, so a byte is eight pulses
|
|
21
|
+
# over sixteen ticks. The interrupt flag is set on the tick that raises
|
|
22
|
+
# CB1 over the eighth bit, and CB1 then stays high until the next
|
|
23
|
+
# access.
|
|
24
|
+
#
|
|
25
|
+
# In modes 2 and 6 a tick is a φ2 cycle, from the second cycle after
|
|
26
|
+
# the access on, which makes a byte sixteen cycles. In modes 1, 4 and 5
|
|
27
|
+
# it comes two cycles after each timer 2 low byte underflow, on the
|
|
28
|
+
# cycle after the low byte reloads, which makes a byte sixteen
|
|
29
|
+
# underflows. Mode 4 never stops and never interrupts: its counter is
|
|
30
|
+
# disabled, and the byte goes round and round.
|
|
31
|
+
#
|
|
32
|
+
# Under an external clock the register shifts on every CB1 edge, access
|
|
33
|
+
# or not. The access only arms the counter: the flag is set on the eighth
|
|
34
|
+
# rising edge after it, and the counter then waits for the next access.
|
|
35
|
+
class ShiftRegister
|
|
36
|
+
DISABLED = 0
|
|
37
|
+
IN_T2 = 1
|
|
38
|
+
IN_PHI2 = 2
|
|
39
|
+
IN_EXTERNAL = 3
|
|
40
|
+
OUT_FREE_RUNNING = 4
|
|
41
|
+
OUT_T2 = 5
|
|
42
|
+
OUT_PHI2 = 6
|
|
43
|
+
OUT_EXTERNAL = 7
|
|
44
|
+
|
|
45
|
+
attr_reader :mode, :data
|
|
46
|
+
attr_accessor :cb2_input
|
|
47
|
+
|
|
48
|
+
def initialize
|
|
49
|
+
@mode = DISABLED
|
|
50
|
+
@data = 0x00
|
|
51
|
+
# Bits still to count before the flag, zero when the counter is idle.
|
|
52
|
+
@bits = 0
|
|
53
|
+
# The clock's last two cycles, newest in bit 0: timer 2 low byte
|
|
54
|
+
# underflows in modes 1, 4 and 5, and whether the byte has started
|
|
55
|
+
# in modes 2 and 6.
|
|
56
|
+
@delay = 0
|
|
57
|
+
@clock = true
|
|
58
|
+
@cb2 = true
|
|
59
|
+
# Nothing drives CB2 from outside, so it floats high.
|
|
60
|
+
@cb2_input = true
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def mode=(value)
|
|
64
|
+
@mode = value & 0x07
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def data=(value)
|
|
68
|
+
@data = value & 0xff
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# A read or write of the data register, which starts a byte if the
|
|
72
|
+
# register is idle and enabled.
|
|
73
|
+
def access!
|
|
74
|
+
return if @mode == DISABLED || @bits.nonzero?
|
|
75
|
+
|
|
76
|
+
@bits = 8
|
|
77
|
+
@delay = 0 if @mode == IN_PHI2 || @mode == OUT_PHI2
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Whether the register is counting bits off its own clock, which
|
|
81
|
+
# changes it from cycle to cycle.
|
|
82
|
+
def clocking? = @bits.nonzero? && internal_clock?
|
|
83
|
+
|
|
84
|
+
# Everything the register holds, for comparing it at two points.
|
|
85
|
+
def state = [@mode, @data, @bits, @delay, @clock, @cb2, @cb2_input]
|
|
86
|
+
|
|
87
|
+
# The CB1 level the register drives, or nil when CB1 is an input.
|
|
88
|
+
def cb1_output
|
|
89
|
+
internal_clock? ? @clock : nil
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# The CB2 level the register drives, or nil when it doesn't.
|
|
93
|
+
def cb2_output
|
|
94
|
+
@mode >= OUT_FREE_RUNNING ? @cb2 : nil
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Clocked once per φ2 cycle, with whether timer 2's low byte underflowed
|
|
98
|
+
# on it. Returns true on the cycle that sets the interrupt flag.
|
|
99
|
+
def cycle!(t2_low_underflow)
|
|
100
|
+
case @mode
|
|
101
|
+
when IN_PHI2, OUT_PHI2 then @bits.nonzero? && phi2_tick
|
|
102
|
+
when IN_T2, OUT_T2, OUT_FREE_RUNNING then t2_tick(t2_low_underflow)
|
|
103
|
+
else false
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# A level change on CB1 from outside. Only the external clock modes
|
|
108
|
+
# listen: shifting in samples CB2 as CB1 rises, and shifting out puts
|
|
109
|
+
# the next bit on CB2 as it falls. Returns true when the edge sets the
|
|
110
|
+
# interrupt flag.
|
|
111
|
+
def cb1_edge!(rising)
|
|
112
|
+
return false unless @mode == IN_EXTERNAL || @mode == OUT_EXTERNAL
|
|
113
|
+
|
|
114
|
+
shift_in if rising && @mode == IN_EXTERNAL
|
|
115
|
+
shift_out if !rising && @mode == OUT_EXTERNAL
|
|
116
|
+
rising && eighth_bit?
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
private
|
|
120
|
+
|
|
121
|
+
def internal_clock?
|
|
122
|
+
@mode != DISABLED && @mode != IN_EXTERNAL && @mode != OUT_EXTERNAL
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# A φ2 cycle of a byte: every one but the first ticks.
|
|
126
|
+
def phi2_tick
|
|
127
|
+
started = @delay.nonzero?
|
|
128
|
+
@delay = 1
|
|
129
|
+
started && tick
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Ticks on the underflow from two cycles back, while a byte is under
|
|
133
|
+
# way.
|
|
134
|
+
def t2_tick(underflow)
|
|
135
|
+
due = @delay.anybits?(2)
|
|
136
|
+
@delay = ((@delay << 1) & 2) | (underflow ? 1 : 0)
|
|
137
|
+
due && @bits.nonzero? && tick
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# One half period of the register's own clock: a falling edge puts a
|
|
141
|
+
# bit out, and a rising one takes a bit in and counts it.
|
|
142
|
+
def tick
|
|
143
|
+
@clock = !@clock
|
|
144
|
+
shift_out if !@clock && @mode >= OUT_FREE_RUNNING
|
|
145
|
+
shift_in if @clock && @mode < IN_EXTERNAL
|
|
146
|
+
@clock && @mode != OUT_FREE_RUNNING && eighth_bit?
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Counts a bit, and says whether it was the eighth since the access.
|
|
150
|
+
def eighth_bit?
|
|
151
|
+
return false if @bits.zero?
|
|
152
|
+
|
|
153
|
+
@bits -= 1
|
|
154
|
+
@bits.zero?
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def shift_in
|
|
158
|
+
@data = ((@data << 1) | (@cb2_input ? 1 : 0)) & 0xff
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def shift_out
|
|
162
|
+
@cb2 = @data.anybits?(0x80)
|
|
163
|
+
@data = ((@data << 1) | (@cb2 ? 1 : 0)) & 0xff
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class VIA
|
|
6
|
+
# Timer 1: a 16-bit counter that decrements on every φ2 cycle, with a
|
|
7
|
+
# latch it reloads from on every timeout and the PB7 output.
|
|
8
|
+
#
|
|
9
|
+
# Writing the high counter byte loads the counter on the cycle after,
|
|
10
|
+
# so a timer loaded with N reads N, N-1, ... 0 and then $FFFF, which is
|
|
11
|
+
# the cycle its interrupt flag sets: N + 1.5 cycles after the write in
|
|
12
|
+
# the datasheet's terms. The counter then reloads from the latch on the
|
|
13
|
+
# next cycle, which makes the period N + 2 cycles. It does so in one-shot
|
|
14
|
+
# mode too, unlike timer 2.
|
|
15
|
+
#
|
|
16
|
+
# Only a write of the high counter byte arms the timer. An armed timeout
|
|
17
|
+
# sets the flag and inverts PB7, and in one-shot mode disarms it, so the
|
|
18
|
+
# first timeout after the load alone does. Free-running keeps it armed,
|
|
19
|
+
# but switching to free-running doesn't arm it: an unarmed timer counts
|
|
20
|
+
# and reloads without touching the flag or PB7. The load pulls PB7 low,
|
|
21
|
+
# and ACR bit 7 turning on drives it high, so a timer loaded before its
|
|
22
|
+
# PB7 output is enabled reads high until the timeout pulls it low.
|
|
23
|
+
class Timer1
|
|
24
|
+
attr_accessor :counter, :latch
|
|
25
|
+
|
|
26
|
+
# The level the timer drives on PB7 when ACR bit 7 hands it the pin.
|
|
27
|
+
attr_reader :pb7
|
|
28
|
+
|
|
29
|
+
# ACR bit 7 turning on hands PB7 to the timer high.
|
|
30
|
+
def pb7_enabled!
|
|
31
|
+
@pb7 = true
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def initialize
|
|
35
|
+
@counter = @latch = 0xffff
|
|
36
|
+
@reload = @hold = false
|
|
37
|
+
@armed = false
|
|
38
|
+
@pb7 = true
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def write_latch_low(value)
|
|
42
|
+
@latch = (@latch & 0xff00) | value
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def write_latch_high(value)
|
|
46
|
+
@latch = (value << 8) | (@latch & 0xff)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# The high counter byte write: load from the latch, hold the count
|
|
50
|
+
# for a cycle, arm the interrupt and pull PB7 low.
|
|
51
|
+
def start!
|
|
52
|
+
@counter = @latch
|
|
53
|
+
@hold = true
|
|
54
|
+
@reload = false
|
|
55
|
+
@armed = true
|
|
56
|
+
@pb7 = false
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# One φ2 cycle. Returns true on the cycle that sets the interrupt flag.
|
|
60
|
+
def cycle!(free_run)
|
|
61
|
+
if @hold || @reload
|
|
62
|
+
@counter = @latch if @reload
|
|
63
|
+
@hold = @reload = false
|
|
64
|
+
return false
|
|
65
|
+
end
|
|
66
|
+
@counter = (@counter - 1) & 0xffff
|
|
67
|
+
@counter == 0xffff && timeout(free_run)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# How many cycles the timer can run without setting its flag: until
|
|
71
|
+
# an armed timer's timeout, and forever for an unarmed one, whose
|
|
72
|
+
# timeouts only reload the counter. None while an armed timer loads
|
|
73
|
+
# or reloads.
|
|
74
|
+
def quiet_cycles
|
|
75
|
+
return FastForward::QUIET unless @armed
|
|
76
|
+
return 0 if @hold || @reload
|
|
77
|
+
|
|
78
|
+
@counter
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Runs +cycles+ cycles at once, as many as quiet_cycles allows. An
|
|
82
|
+
# unarmed timer goes round its period of latch + 2 cycles: the
|
|
83
|
+
# timeout at $FFFF, the reload, and latch down to 0.
|
|
84
|
+
def fast_forward(cycles)
|
|
85
|
+
if @hold || @reload
|
|
86
|
+
cycle!(false)
|
|
87
|
+
cycles -= 1
|
|
88
|
+
end
|
|
89
|
+
return @counter -= cycles if cycles <= @counter
|
|
90
|
+
|
|
91
|
+
phase = (cycles - @counter - 1) % (@latch + 2)
|
|
92
|
+
@reload = phase.zero?
|
|
93
|
+
@counter = @reload ? 0xffff : @latch - phase + 1
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# What the counter and PB7 don't hold, for comparing the timer at two
|
|
97
|
+
# points.
|
|
98
|
+
def state = [@latch, @armed]
|
|
99
|
+
|
|
100
|
+
# Whether a timeout sets the flag.
|
|
101
|
+
def armed? = @armed
|
|
102
|
+
|
|
103
|
+
# The count, for comparing the timer at two points where it matters.
|
|
104
|
+
def count_state = [@counter, @hold, @reload]
|
|
105
|
+
|
|
106
|
+
private
|
|
107
|
+
|
|
108
|
+
# The counter reloads either way. Armed, PB7 inverts and the flag
|
|
109
|
+
# sets, and one-shot mode disarms. Returns whether the flag sets.
|
|
110
|
+
def timeout(free_run)
|
|
111
|
+
interrupt = @armed
|
|
112
|
+
@reload = true
|
|
113
|
+
@pb7 = !@pb7 if @armed
|
|
114
|
+
@armed &&= free_run
|
|
115
|
+
interrupt
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|