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
data/lib/badline/cia.rb
DELETED
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "badline/cia/interrupt_register"
|
|
4
|
-
require "badline/cia/serial"
|
|
5
|
-
require "badline/cia/timer"
|
|
6
|
-
require "badline/cia/state"
|
|
7
|
-
require "badline/cia/fast_forward"
|
|
8
|
-
|
|
9
|
-
module Badline
|
|
10
|
-
# CIA (Complex Interface Adapter) chip
|
|
11
|
-
class CIA
|
|
12
|
-
include Addressable
|
|
13
|
-
include State
|
|
14
|
-
include FastForward
|
|
15
|
-
|
|
16
|
-
# The original NMOS 6526 of the breadbin C64, and the HMOS 6526A of the
|
|
17
|
-
# C64C, which differs from it only in its interrupt control register.
|
|
18
|
-
MODELS = %i[mos6526 mos6526a].freeze
|
|
19
|
-
|
|
20
|
-
attr_reader :start, :control_a, :control_b, :serial, :model
|
|
21
|
-
|
|
22
|
-
# What's on the ports outside the chip. It pulls port lines low through
|
|
23
|
-
# read_a and read_b, and on CIA 1 drives PB4 through port_b4_high?.
|
|
24
|
-
attr_accessor :peripheral
|
|
25
|
-
|
|
26
|
-
# Timer A and timer B.
|
|
27
|
-
def timers = [@ta, @tb]
|
|
28
|
-
|
|
29
|
-
# Port A and B's data and direction registers.
|
|
30
|
-
def port_registers = [@data_port_a, @data_port_b, @data_dir_a, @data_dir_b]
|
|
31
|
-
|
|
32
|
-
def interrupt_status = @icr.status
|
|
33
|
-
|
|
34
|
-
def interrupt_control = @icr.mask
|
|
35
|
-
|
|
36
|
-
def interrupt!(delay = 1) = @icr.assert!(delay)
|
|
37
|
-
|
|
38
|
-
def time_of_day = @tod
|
|
39
|
-
|
|
40
|
-
def timer_a = @ta.counter
|
|
41
|
-
|
|
42
|
-
def timer_a=(value)
|
|
43
|
-
@ta.counter = value
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def timer_a_latch = @ta.latch
|
|
47
|
-
|
|
48
|
-
def timer_a_latch=(value)
|
|
49
|
-
@ta.latch = value
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def timer_b = @tb.counter
|
|
53
|
-
|
|
54
|
-
def timer_b=(value)
|
|
55
|
-
@tb.counter = value
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def timer_b_latch = @tb.latch
|
|
59
|
-
|
|
60
|
-
def timer_b_latch=(value)
|
|
61
|
-
@tb.latch = value
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
# +tod_hz+ is the rate of the pulses on the TOD pin, the region's mains
|
|
65
|
-
# unless a machine feeds it otherwise, and 0 for a pin held still.
|
|
66
|
-
def initialize(start: 0, peripheral: nil, model: :mos6526, region: Region::PAL, tod_hz: nil)
|
|
67
|
-
raise ArgumentError, "unknown CIA model #{model}" unless MODELS.include?(model)
|
|
68
|
-
|
|
69
|
-
addressable_at(start, length: 2**8)
|
|
70
|
-
|
|
71
|
-
@model = model
|
|
72
|
-
@clock_hz = region.clock_hz
|
|
73
|
-
@mains_hz = tod_hz || region.mains_hz
|
|
74
|
-
|
|
75
|
-
@peripheral = peripheral
|
|
76
|
-
@port_b4_handler = nil
|
|
77
|
-
@port_a_handler = nil
|
|
78
|
-
@port_b4_high = true
|
|
79
|
-
reset!
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
# The RES line: ports back to inputs, timers stopped with their latches
|
|
83
|
-
# full, interrupts masked and the TOD clock stopped at 1:00:00.0. The
|
|
84
|
-
# PB4 level carries over and is resampled on the next cycle.
|
|
85
|
-
def reset!
|
|
86
|
-
@data_port_a = 0x00
|
|
87
|
-
@data_port_b = 0x00
|
|
88
|
-
@data_dir_a = 0x00
|
|
89
|
-
@data_dir_b = 0x00
|
|
90
|
-
@port_b4_driven_high = true
|
|
91
|
-
@cnt_high = true
|
|
92
|
-
@cnt_rise = false
|
|
93
|
-
@tod = TimeOfDay.new(clock_hz: @clock_hz, mains_hz: @mains_hz)
|
|
94
|
-
@icr = InterruptRegister.new(@model)
|
|
95
|
-
@icr_status = @icr.status
|
|
96
|
-
@control_a = ControlRegister.new(%i[start output out_mode run_mode load
|
|
97
|
-
in_mode serial_mode clock_frequency])
|
|
98
|
-
@control_b = ControlRegister.new(%i[start output out_mode run_mode load
|
|
99
|
-
in_cnt in_timer_a alarm])
|
|
100
|
-
@ta = Timer.new(@control_a)
|
|
101
|
-
@tb = Timer.new(@control_b)
|
|
102
|
-
@serial = Serial.new(@control_a)
|
|
103
|
-
@port_a_handler&.call
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
# Register a change handler on the PB4 line. On CIA 1, this feeds the
|
|
107
|
-
# light pen input.
|
|
108
|
-
def on_port_b4_change(&handler)
|
|
109
|
-
@port_b4_handler = handler
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
# Register a handler for writes that can move port A's lines: to the
|
|
113
|
-
# data register or DDR, and the reset. On CIA 2, this tells the drives
|
|
114
|
-
# on the serial bus that the C64 may have moved a line.
|
|
115
|
-
def on_port_a_write(&handler)
|
|
116
|
-
@port_a_handler = handler
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
# A falling edge on the FLAG pin. On CIA 1 the datasette's tape read
|
|
120
|
-
# line drives it, on CIA 2 the serial bus SRQ.
|
|
121
|
-
def flag! = raise_interrupt(:flag)
|
|
122
|
-
|
|
123
|
-
def interrupted? = @icr_status.value >= 0x80
|
|
124
|
-
|
|
125
|
-
def cycle!
|
|
126
|
-
@icr.cycle! unless @icr.quiet
|
|
127
|
-
refresh_port_b4 if @port_b4_handler
|
|
128
|
-
level = @serial.cnt
|
|
129
|
-
level == @cnt_high ? @cnt_rise = false : cnt_edge(level)
|
|
130
|
-
underflowed = update_timers
|
|
131
|
-
@serial.cycle!(underflowed) { trigger_serial } if underflowed || !@serial.idle
|
|
132
|
-
@tod.cycle! { trigger_alarm }
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
def read_port_a
|
|
136
|
-
lines = driven_lines(@data_port_a, @data_dir_a)
|
|
137
|
-
return lines unless peripheral
|
|
138
|
-
|
|
139
|
-
lines & peripheral.read_a(lines, driven_lines(@data_port_b, @data_dir_b))
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
# Port A as driven by the data/direction registers alone, without
|
|
143
|
-
# peripheral pulldown. Cheap path for the VIC bank lookup.
|
|
144
|
-
def port_a_lines = driven_lines(@data_port_a, @data_dir_a)
|
|
145
|
-
|
|
146
|
-
# Port B as driven by the data/direction registers alone.
|
|
147
|
-
def port_b_lines = driven_lines(@data_port_b, @data_dir_b)
|
|
148
|
-
|
|
149
|
-
def read_port_b
|
|
150
|
-
lines = driven_lines(@data_port_b, @data_dir_b)
|
|
151
|
-
lines &= peripheral.read_b(driven_lines(@data_port_a, @data_dir_a), lines) if peripheral
|
|
152
|
-
apply_timer_output(lines)
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
def peek(addr)
|
|
156
|
-
case offset_of(addr) & 0x0f
|
|
157
|
-
when 0x00 then read_port_a
|
|
158
|
-
when 0x01 then read_port_b
|
|
159
|
-
when 0x02 then @data_dir_a
|
|
160
|
-
when 0x03 then @data_dir_b
|
|
161
|
-
when 0x04 then low_byte(@ta.counter)
|
|
162
|
-
when 0x05 then high_byte(@ta.counter)
|
|
163
|
-
when 0x06 then low_byte(@tb.counter)
|
|
164
|
-
when 0x07 then high_byte(@tb.counter)
|
|
165
|
-
when 0x08 then @tod.tenths
|
|
166
|
-
when 0x09 then @tod.seconds
|
|
167
|
-
when 0x0a then @tod.minutes
|
|
168
|
-
when 0x0b then @tod.hours
|
|
169
|
-
when 0x0c then @serial.data
|
|
170
|
-
when 0x0d then @icr.read
|
|
171
|
-
when 0x0e then control_a.value
|
|
172
|
-
when 0x0f then control_b.value
|
|
173
|
-
end
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
def poke(addr, value)
|
|
177
|
-
case offset_of(addr) & 0x0f
|
|
178
|
-
when 0x00 then update_port_a { @data_port_a = value }
|
|
179
|
-
when 0x01 then update_port_b { @data_port_b = value }
|
|
180
|
-
when 0x02 then update_port_a { @data_dir_a = value }
|
|
181
|
-
when 0x03 then update_port_b { @data_dir_b = value }
|
|
182
|
-
when 0x04 then @ta.write_latch_low(value)
|
|
183
|
-
when 0x05 then @ta.write_latch_high(value)
|
|
184
|
-
when 0x06 then @tb.write_latch_low(value)
|
|
185
|
-
when 0x07 then @tb.write_latch_high(value)
|
|
186
|
-
when 0x08 then @tod.write(:tenths, value, alarm: control_b.alarm?)
|
|
187
|
-
when 0x09 then @tod.write(:seconds, value, alarm: control_b.alarm?)
|
|
188
|
-
when 0x0a then @tod.write(:minutes, value, alarm: control_b.alarm?)
|
|
189
|
-
when 0x0b then @tod.write_hours(value, alarm: control_b.alarm?)
|
|
190
|
-
when 0x0c then @serial.write(value)
|
|
191
|
-
when 0x0d then @icr.write(value)
|
|
192
|
-
when 0x0e then write_control_a(value)
|
|
193
|
-
when 0x0f then @tb.write_control(value)
|
|
194
|
-
end
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
private
|
|
198
|
-
|
|
199
|
-
def update_port_a
|
|
200
|
-
yield
|
|
201
|
-
@port_a_handler&.call
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
def update_port_b
|
|
205
|
-
yield
|
|
206
|
-
@port_b4_driven_high = driven_lines(@data_port_b, @data_dir_b).anybits?(0x10)
|
|
207
|
-
refresh_port_b4 if @port_b4_handler
|
|
208
|
-
end
|
|
209
|
-
|
|
210
|
-
# PB4 is also control port 1's fire line, and a peripheral pulls it low
|
|
211
|
-
# without any register write, so the level is resampled every cycle rather
|
|
212
|
-
# than only after a poke.
|
|
213
|
-
def refresh_port_b4
|
|
214
|
-
high = @port_b4_driven_high && (peripheral.nil? || peripheral.port_b4_high?)
|
|
215
|
-
return if high == @port_b4_high
|
|
216
|
-
|
|
217
|
-
@port_b4_high = high
|
|
218
|
-
@port_b4_handler.call(high)
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
def driven_lines(register, direction)
|
|
222
|
-
# Output bits are driven from the data register; input bits float high.
|
|
223
|
-
# External peripherals can still pull any line low (wired-AND).
|
|
224
|
-
(register & direction) | (~direction & 0xff)
|
|
225
|
-
end
|
|
226
|
-
|
|
227
|
-
def apply_timer_output(value)
|
|
228
|
-
value = with_bit(value, 6, @ta.output?) if control_a.output?
|
|
229
|
-
value = with_bit(value, 7, @tb.output?) if control_b.output?
|
|
230
|
-
value
|
|
231
|
-
end
|
|
232
|
-
|
|
233
|
-
def with_bit(value, bit, set)
|
|
234
|
-
set ? value | (1 << bit) : value & ~(1 << bit)
|
|
235
|
-
end
|
|
236
|
-
|
|
237
|
-
def trigger_alarm = raise_interrupt(:alarm)
|
|
238
|
-
def trigger_serial = raise_interrupt(:serial)
|
|
239
|
-
|
|
240
|
-
def raise_interrupt(source) = @icr.flag(source)
|
|
241
|
-
|
|
242
|
-
# CNT is sampled once a cycle. When the serial port drives it from this
|
|
243
|
-
# cycle's timer A underflow, the new level is picked up on the next one.
|
|
244
|
-
def cnt_edge(level)
|
|
245
|
-
@cnt_high = level
|
|
246
|
-
@cnt_rise = level
|
|
247
|
-
@serial.rising_edge! { trigger_serial } if level
|
|
248
|
-
end
|
|
249
|
-
|
|
250
|
-
# Returns whether timer A underflowed, which clocks the serial port.
|
|
251
|
-
#
|
|
252
|
-
# CRB bits 6-5 pick timer B's source: ø2, CNT edges, timer A
|
|
253
|
-
# underflows, or timer A underflows gated by the CNT level. Every source
|
|
254
|
-
# drives the same count-enable line, so a cascaded underflow goes through
|
|
255
|
-
# the input pipeline exactly as a CNT edge does.
|
|
256
|
-
def update_timers
|
|
257
|
-
@ta.cycle!(@control_a.value & 0x20 == 0x20 ? @cnt_rise : true)
|
|
258
|
-
underflowed = @ta.underflowed
|
|
259
|
-
@tb.cycle!(
|
|
260
|
-
case @control_b.value & 0x60
|
|
261
|
-
when 0x00 then true
|
|
262
|
-
when 0x20 then @cnt_rise
|
|
263
|
-
when 0x40 then underflowed
|
|
264
|
-
else underflowed && @cnt_high
|
|
265
|
-
end
|
|
266
|
-
)
|
|
267
|
-
@icr.flag(:timer_a) if underflowed
|
|
268
|
-
@icr.timer_b_underflow! if @tb.underflowed
|
|
269
|
-
underflowed
|
|
270
|
-
end
|
|
271
|
-
|
|
272
|
-
def write_control_a(value)
|
|
273
|
-
was_output = control_a.serial_mode?
|
|
274
|
-
@ta.write_control(value)
|
|
275
|
-
@serial.reset! { trigger_serial } if control_a.serial_mode? != was_output
|
|
276
|
-
@tod.fifty_hz = control_a.clock_frequency?
|
|
277
|
-
end
|
|
278
|
-
end
|
|
279
|
-
end
|
data/lib/badline/color_memory.rb
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
# Colour RAM is four bits wide. A CPU read takes the upper nibble off the
|
|
5
|
-
# open data bus, which still holds the byte the VIC fetched in phi1.
|
|
6
|
-
class ColorMemory < Memory
|
|
7
|
-
def initialize(vic, start: 0xd800, length: 2**10)
|
|
8
|
-
super(start:, length:)
|
|
9
|
-
@vic = vic
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def peek(addr)
|
|
13
|
-
(@vic.phi1_data & 0xf0) | @storage[offset_of(addr)]
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def poke(addr, value)
|
|
17
|
-
super(addr, value & 0x0f)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
# The four bits the cell stores, as the VIC's c-access sees them.
|
|
21
|
-
def nibble(addr)
|
|
22
|
-
@storage[offset_of(addr)]
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Computer
|
|
5
|
-
# What plugs into the machine besides its chips, the cartridge, its
|
|
6
|
-
# true drives (TrueDrives) and an REU, and their state for a snapshot.
|
|
7
|
-
# The disk device 8 serves through the traps is KernalTraps'.
|
|
8
|
-
module Attachments
|
|
9
|
-
include TrueDrives
|
|
10
|
-
|
|
11
|
-
# Puts the cartridge in the expansion port and wires its clock and NMI
|
|
12
|
-
# line to the machine, leaving the machine's state as it is. A
|
|
13
|
-
# restored snapshot's cartridge comes back through here.
|
|
14
|
-
def connect_cartridge(cartridge)
|
|
15
|
-
cartridge.clock = -> { @cycles }
|
|
16
|
-
cartridge.on_nmi_change { |level| @cartridge_nmi = level }
|
|
17
|
-
address_bus.attach_cartridge(cartridge)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
# The serial bus, which CIA 2's port A drives through the C64's own
|
|
21
|
-
# inverters and reads back on PA6 and PA7, with or without a drive on
|
|
22
|
-
# it.
|
|
23
|
-
attr_reader :iec_bus
|
|
24
|
-
|
|
25
|
-
private
|
|
26
|
-
|
|
27
|
-
# CIA 2's port A drives the serial bus, which reads CLK and DATA back
|
|
28
|
-
# into it.
|
|
29
|
-
def plug_serial_bus
|
|
30
|
-
@iec_bus = IECBus.new
|
|
31
|
-
@cia2.peripheral = @iec_bus
|
|
32
|
-
@cia2.on_port_a_write { push_serial_lines }
|
|
33
|
-
push_serial_lines
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Pushes the lines CIA 2's port A pulls into the serial bus.
|
|
37
|
-
def push_serial_lines
|
|
38
|
-
@iec_bus.host_lines = @cia2.port_a_lines
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def save_cartridge(out)
|
|
42
|
-
cartridge = address_bus.cartridge
|
|
43
|
-
out.boolean(!cartridge.nil?)
|
|
44
|
-
cartridge&.save_setup(out)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
# A cartridge comes back built afresh from the setup it was built
|
|
48
|
-
# with, before the address bus puts its state into it.
|
|
49
|
-
def load_cartridge(input)
|
|
50
|
-
if input.boolean?
|
|
51
|
-
connect_cartridge(Cartridge.from_setup(input))
|
|
52
|
-
elsif address_bus.cartridge
|
|
53
|
-
address_bus.detach_cartridge
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# A true 1541 on the serial bus, then a 1581. The leading flag is the
|
|
58
|
-
# bus itself, which every machine now has.
|
|
59
|
-
def save_serial_bus(out)
|
|
60
|
-
out.boolean(true).boolean(!@drive1541.nil?)
|
|
61
|
-
if @drive1541
|
|
62
|
-
out.int(@drive1541.device)
|
|
63
|
-
@drive1541.save_state(out)
|
|
64
|
-
end
|
|
65
|
-
save_drive1581(out)
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def load_serial_bus(input)
|
|
69
|
-
input.boolean?
|
|
70
|
-
load_drive1541(input)
|
|
71
|
-
load_drive1581(input)
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
# The REU, which the setup says the machine has, and whether it has
|
|
75
|
-
# asked for the bus. Its IRQ line reaches the CPU as it was.
|
|
76
|
-
def save_reu(out)
|
|
77
|
-
@reu&.save_state(out)
|
|
78
|
-
out.boolean(@dma)
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def load_reu(input)
|
|
82
|
-
@reu&.load_state(input)
|
|
83
|
-
@reu_irq = @reu ? @reu.irq? : false
|
|
84
|
-
@dma = input.boolean?
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
end
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Computer
|
|
5
|
-
# The keyword arguments Computer.new takes to build the machine a
|
|
6
|
-
# State from #snapshot was taken of.
|
|
7
|
-
def self.setup(state)
|
|
8
|
-
input = Snapshot::StateReader.new(state)
|
|
9
|
-
input.marker("COMPUTER")
|
|
10
|
-
input.check_stamp
|
|
11
|
-
Snapshot::Setup.read(input)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# A new machine, built as the one a State from #snapshot was taken of,
|
|
15
|
-
# at that state. `detached` builds it without the host's files
|
|
16
|
-
# (Snapshot::StateReader).
|
|
17
|
-
def self.restored(state, detached: false) = setup(state).build.apply_state(state, detached:)
|
|
18
|
-
|
|
19
|
-
# The whole machine's state for a snapshot: the machine's own latches,
|
|
20
|
-
# the bus and its chips, the CPU, and what is attached to it
|
|
21
|
-
# (Attachments).
|
|
22
|
-
module SavedState
|
|
23
|
-
# How many more on_init handlers the machine a State was taken of had
|
|
24
|
-
# yet to run than this one has: they are the host's blocks, which a
|
|
25
|
-
# State can't hold. Nil until the machine is restored.
|
|
26
|
-
attr_reader :init_handlers_lost
|
|
27
|
-
|
|
28
|
-
# The machine's whole state, in memory. #restore takes the machine, or
|
|
29
|
-
# another built with the same chip models, region and RAM expansion,
|
|
30
|
-
# back to it. The cartridge, the disk in device 8, a true 1541 and its
|
|
31
|
-
# disk and the tape go in the state too. What the host holds stays
|
|
32
|
-
# out: the keyboard, the joysticks and the pot devices, the traps and
|
|
33
|
-
# callbacks, whether the display renders and whether the SID records.
|
|
34
|
-
def snapshot
|
|
35
|
-
out = Snapshot::StateWriter.new
|
|
36
|
-
save_state(out)
|
|
37
|
-
out.state
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# Takes the machine back to a State from #snapshot. The machine keeps
|
|
41
|
-
# its chips, its traps and its callbacks, and puts in the cartridge,
|
|
42
|
-
# drives and tape the state has, taking out any it hasn't. Raises
|
|
43
|
-
# Snapshot::FormatError for a state of a machine built another way.
|
|
44
|
-
# The state goes into a new machine first, so one that fails leaves
|
|
45
|
-
# this machine as it was.
|
|
46
|
-
def restore(state)
|
|
47
|
-
check_setup(Computer.setup(state))
|
|
48
|
-
Computer.restored(state)
|
|
49
|
-
apply_state(state)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# Puts a State into the machine without trying it on a new one
|
|
53
|
-
# first, for a machine built for it (Computer.restored): a state that
|
|
54
|
-
# fails leaves the machine part restored. `detached` restores it
|
|
55
|
-
# without the host's files (Snapshot::StateReader).
|
|
56
|
-
def apply_state(state, detached: false)
|
|
57
|
-
input = Snapshot::StateReader.new(state, detached:)
|
|
58
|
-
load_state(input)
|
|
59
|
-
raise Snapshot::FormatError, "the state goes on past the machine" unless input.finished?
|
|
60
|
-
|
|
61
|
-
self
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
# Sets the machine's cycle count, for a snapshot from VICE, which
|
|
65
|
-
# counts from its own clock.
|
|
66
|
-
def resume_at(cycles)
|
|
67
|
-
@cycles = cycles
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def save_state(out)
|
|
71
|
-
out.marker("COMPUTER").stamp
|
|
72
|
-
Snapshot::Setup.of(address_bus).write(out)
|
|
73
|
-
out.int(@cycles).boolean(@nmi_asserted).boolean(@cartridge_nmi).boolean(@restore_pulse).boolean(@freezing)
|
|
74
|
-
out.int(@freeze_writes).boolean(!@pending_keys.nil?)
|
|
75
|
-
out.ints(@pending_keys) if @pending_keys
|
|
76
|
-
out.int(booting? ? @init_handlers.length : 0)
|
|
77
|
-
save_cartridge(out)
|
|
78
|
-
address_bus.save_state(out)
|
|
79
|
-
@cpu.save_state(out)
|
|
80
|
-
save_trap_drive(out)
|
|
81
|
-
save_serial_bus(out)
|
|
82
|
-
save_reu(out)
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def load_state(input)
|
|
86
|
-
input.marker("COMPUTER")
|
|
87
|
-
input.check_stamp
|
|
88
|
-
check_setup(Snapshot::Setup.read(input))
|
|
89
|
-
@cycles = input.int
|
|
90
|
-
@nmi_asserted = input.boolean?
|
|
91
|
-
@cartridge_nmi = input.boolean?
|
|
92
|
-
@restore_pulse = input.boolean?
|
|
93
|
-
@freezing = input.boolean?
|
|
94
|
-
@freeze_writes = input.int
|
|
95
|
-
@pending_keys = nil
|
|
96
|
-
@pending_keys = input.ints if input.boolean?
|
|
97
|
-
@init_handlers_lost = [input.int - @init_handlers.length, 0].max
|
|
98
|
-
load_cartridge(input)
|
|
99
|
-
address_bus.load_state(input)
|
|
100
|
-
push_serial_lines
|
|
101
|
-
@cpu.load_state(input)
|
|
102
|
-
load_trap_drive(input)
|
|
103
|
-
load_serial_bus(input)
|
|
104
|
-
load_reu(input)
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
private
|
|
108
|
-
|
|
109
|
-
def check_setup(setup)
|
|
110
|
-
ours = Snapshot::Setup.of(address_bus)
|
|
111
|
-
return if setup == ours
|
|
112
|
-
|
|
113
|
-
raise Snapshot::FormatError, "the state is of a machine with #{setup}, not #{ours}"
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
end
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Computer
|
|
5
|
-
# The true drives on the machine's serial bus: a Drive1541, and a
|
|
6
|
-
# Drive1581 (Drive1581::Slot), each in a field of its own. Computer,
|
|
7
|
-
# Vic20 and C128 each include it.
|
|
8
|
-
module TrueDrives
|
|
9
|
-
include Drive1581::Slot
|
|
10
|
-
|
|
11
|
-
# Plugs in a Drive1541, which then runs alongside the machine on its
|
|
12
|
-
# own clock and talks to it over the serial bus. The serial traps stop
|
|
13
|
-
# answering the drive's device number, so the KERNAL's TALK, LISTEN and
|
|
14
|
-
# byte transfers reach the drive. The LOAD and SAVE traps stay, and
|
|
15
|
-
# still serve a mounted image.
|
|
16
|
-
def attach_drive1541(drive)
|
|
17
|
-
@iec_bus.detach(@drive1541) if @drive1541
|
|
18
|
-
drive.host_clock_hz = timing.clock_hz
|
|
19
|
-
@drive1541 = drive
|
|
20
|
-
drive.connect(@iec_bus)
|
|
21
|
-
@serial_trap&.device = serial_trap_device
|
|
22
|
-
drive1541_attached
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# The true drive on the serial bus: the Drive1581 ahead of the
|
|
26
|
-
# Drive1541, or nil.
|
|
27
|
-
def true_drive = @drive1581 || @drive1541
|
|
28
|
-
|
|
29
|
-
# Plugs a Drive1541 in as device 8, in place of a 1581 there, and
|
|
30
|
-
# returns it.
|
|
31
|
-
def plug_true_drive
|
|
32
|
-
detach_drive1581 if drive1581_on_device8?
|
|
33
|
-
Drive1541.new.tap { |drive| attach_drive1541(drive) }
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Unplugs the Drive1541, leaving the serial bus with nothing on it.
|
|
37
|
-
def detach_drive1541
|
|
38
|
-
return unless @drive1541
|
|
39
|
-
|
|
40
|
-
@iec_bus.detach(@drive1541)
|
|
41
|
-
@drive1541 = nil
|
|
42
|
-
@serial_trap&.device = serial_trap_device
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
private
|
|
46
|
-
|
|
47
|
-
# The device number the serial traps answer: device 8, unless a true
|
|
48
|
-
# drive is on the bus as device 8.
|
|
49
|
-
def serial_trap_device
|
|
50
|
-
device = KernalTrap::Routine::DEVICE
|
|
51
|
-
@drive1541&.device == device || drive1581_on_device8? ? nil : device
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# What the machine does as a 1541 goes on its bus. The VIC-20 waits
|
|
55
|
-
# for its DOS to boot before typing.
|
|
56
|
-
def drive1541_attached = nil
|
|
57
|
-
|
|
58
|
-
# A true 1541 on the serial bus, with its device number.
|
|
59
|
-
def load_drive1541(input)
|
|
60
|
-
return detach_drive1541 unless input.boolean?
|
|
61
|
-
|
|
62
|
-
device = input.int
|
|
63
|
-
detach_drive1541 if @drive1541 && @drive1541.device != device
|
|
64
|
-
attach_drive1541(Drive1541.new(device:)) unless @drive1541
|
|
65
|
-
@drive1541.load_state(input)
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
end
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
# CIA 1's control ports and the keyboard matrix that spans them.
|
|
5
|
-
#
|
|
6
|
-
# Port A carries the matrix rows together with joystick 2, port B the matrix
|
|
7
|
-
# columns together with joystick 1. Every switch is active low, so the
|
|
8
|
-
# joysticks are wired-AND onto the lines *before* the matrix settles: a stick
|
|
9
|
-
# held in a direction selects rows and columns of its own, which is where
|
|
10
|
-
# hardware's phantom keypresses come from. Paddles and a 1351 mouse have
|
|
11
|
-
# buttons on those same lines.
|
|
12
|
-
#
|
|
13
|
-
# The ports also carry SID's POTX/POTY lines, which reach them through analog
|
|
14
|
-
# switches closed by CIA 1 PA6 (port 1) and PA7 (port 2). Close both and the
|
|
15
|
-
# pots sit in parallel, so SID charges through the lower of the two
|
|
16
|
-
# resistances; close neither and the lines float high. Reading a pot asks the
|
|
17
|
-
# CIA for the current select lines, since a program sets them and then goes
|
|
18
|
-
# straight to SID without touching the ports again.
|
|
19
|
-
#
|
|
20
|
-
# A matrix may have rows beyond port A's eight. Their select lines come from
|
|
21
|
-
# outside the CIA and are pushed into +extra_rows+, bit 0 for the ninth row
|
|
22
|
-
# upwards, active low like port A; idle, every line is high and none of
|
|
23
|
-
# those rows is selected. They settle with port A's lines as rows 8 and up,
|
|
24
|
-
# so their keys reach port B, but port A reads only its own eight.
|
|
25
|
-
class ControlPorts
|
|
26
|
-
PORT1_POTS = 0x40
|
|
27
|
-
PORT2_POTS = 0x80
|
|
28
|
-
FIRE = 0x10
|
|
29
|
-
|
|
30
|
-
attr_reader :keyboard, :joystick1, :joystick2
|
|
31
|
-
attr_accessor :device1, :device2, :port_a_source, :extra_rows
|
|
32
|
-
|
|
33
|
-
def initialize(keyboard:, joystick1:, joystick2:)
|
|
34
|
-
@keyboard = keyboard
|
|
35
|
-
@joystick1 = joystick1
|
|
36
|
-
@joystick2 = joystick2
|
|
37
|
-
@device1 = nil
|
|
38
|
-
@device2 = nil
|
|
39
|
-
@port_a_source = nil
|
|
40
|
-
@extra_rows = 0xff
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def read_a(port_a, port_b) = scan(port_a, port_b).first & 0xff
|
|
44
|
-
|
|
45
|
-
def read_b(port_a, port_b) = scan(port_a, port_b).last
|
|
46
|
-
|
|
47
|
-
# Control port 1 pin 6 is both the port B fire line and the VIC's light
|
|
48
|
-
# pen input, so joystick 1's button and a 1351's left button latch
|
|
49
|
-
# $D013/$D014. The CIA samples this every cycle, so it skips the matrix and
|
|
50
|
-
# asks only what the port's own devices drive.
|
|
51
|
-
def port_b4_high? = port_bits(@joystick1, @device1).anybits?(FIRE)
|
|
52
|
-
|
|
53
|
-
def pot_x = selected_devices.map(&:pot_x).min || 0xff
|
|
54
|
-
|
|
55
|
-
def pot_y = selected_devices.map(&:pot_y).min || 0xff
|
|
56
|
-
|
|
57
|
-
private
|
|
58
|
-
|
|
59
|
-
def selected_devices
|
|
60
|
-
lines = @port_a_source&.port_a_lines || 0x00
|
|
61
|
-
devices = []
|
|
62
|
-
devices << @device1 if @device1 && lines.anybits?(PORT1_POTS)
|
|
63
|
-
devices << @device2 if @device2 && lines.anybits?(PORT2_POTS)
|
|
64
|
-
devices
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def scan(port_a, port_b)
|
|
68
|
-
keyboard.scan((port_a & port_bits(@joystick2, @device2)) | (@extra_rows << 8),
|
|
69
|
-
port_b & port_bits(@joystick1, @device1))
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def port_bits(joystick, device)
|
|
73
|
-
device ? joystick.port_bits & device.port_bits : joystick.port_bits
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
end
|