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
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Drive1541
|
|
5
|
-
# Reads a track's blocks back out of its GCR, as the DOS finds them:
|
|
6
|
-
# each SYNC mark is ten or more 1 bits, and the block after it starts
|
|
7
|
-
# at the first 0 bit. Writes land wherever the head was, so a block
|
|
8
|
-
# can start at any bit of the stored bytes, and the reader works on
|
|
9
|
-
# the bits.
|
|
10
|
-
#
|
|
11
|
-
# A header block starts with $08, and the next block after a header is
|
|
12
|
-
# that sector's data block, whatever it holds.
|
|
13
|
-
module SectorReader
|
|
14
|
-
HEADER_BITS = 10 * 8
|
|
15
|
-
DATA_BITS = 325 * 8
|
|
16
|
-
SYNC = /1{10,}/
|
|
17
|
-
|
|
18
|
-
# A sector as read: its decoded header, [ID, checksum, sector, track,
|
|
19
|
-
# the second ID byte, the first, ...], and its decoded data block,
|
|
20
|
-
# [ID, 256 data bytes, checksum, ...], nil when there isn't one that
|
|
21
|
-
# decodes.
|
|
22
|
-
Sector = Struct.new(:header, :data)
|
|
23
|
-
|
|
24
|
-
module_function
|
|
25
|
-
|
|
26
|
-
# The sectors found on the track's bytes, by sector number. Headers
|
|
27
|
-
# for another track are left out.
|
|
28
|
-
def read(bytes, track)
|
|
29
|
-
ring = ring(bytes)
|
|
30
|
-
return {} unless ring
|
|
31
|
-
|
|
32
|
-
sectors = {}
|
|
33
|
-
each_block(ring) do |header, data|
|
|
34
|
-
next unless header[3] == track
|
|
35
|
-
|
|
36
|
-
sectors[header[2]] ||= Sector.new(header, data)
|
|
37
|
-
end
|
|
38
|
-
sectors
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
# The track's bits, starting at a 0 bit so no SYNC mark straddles the
|
|
42
|
-
# start, twice over so a block can run on past the end. Nil for a
|
|
43
|
-
# track without a 0 bit.
|
|
44
|
-
def ring(bytes)
|
|
45
|
-
bits = bytes.pack("C*").unpack1("B*")
|
|
46
|
-
zero = bits.index("0")
|
|
47
|
-
return unless zero
|
|
48
|
-
|
|
49
|
-
bits = bits[zero..] + bits[0, zero]
|
|
50
|
-
[bits * 2, bits.length]
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
# Yields each header whose SYNC mark starts in the first turn, with
|
|
54
|
-
# the data block after it.
|
|
55
|
-
def each_block(ring)
|
|
56
|
-
bits, length = ring
|
|
57
|
-
pos = 0
|
|
58
|
-
while (sync = SYNC.match(bits, pos)) && sync.begin(0) < length
|
|
59
|
-
pos = sync.end(0)
|
|
60
|
-
header = decode(bits, pos, HEADER_BITS)
|
|
61
|
-
next unless header && header[0] == Disk::HEADER_ID
|
|
62
|
-
|
|
63
|
-
data_sync = SYNC.match(bits, pos + HEADER_BITS)
|
|
64
|
-
yield header, data_sync && decode(bits, data_sync.end(0), DATA_BITS)
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def decode(bits, pos, count)
|
|
69
|
-
slice = bits[pos, count]
|
|
70
|
-
return unless slice.length == count
|
|
71
|
-
|
|
72
|
-
GCR.decode([slice].pack("B*").bytes)
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
end
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Drive1541
|
|
5
|
-
# What VIA 1's ports read from outside the chip. Port B carries the
|
|
6
|
-
# serial bus inputs and the device number jumpers (Drive::SerialLines);
|
|
7
|
-
# port A goes to the unused parallel header and floats high.
|
|
8
|
-
class SerialPort
|
|
9
|
-
include Drive::SerialLines
|
|
10
|
-
|
|
11
|
-
def initialize(device: 8, bus: IECBus.new)
|
|
12
|
-
init_serial_lines(device, bus)
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def read_a(_lines) = 0xff
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Drive1541
|
|
5
|
-
# One ring of flux on the disk, as the GCR bytes the head reads from it,
|
|
6
|
-
# most significant bit first, and the speed zone it was written in
|
|
7
|
-
# (0-3). The bytes wrap around: the last one's bits run into the
|
|
8
|
-
# first's. A track is as long as its bytes, which is what a .g64 image
|
|
9
|
-
# stores for each half track.
|
|
10
|
-
#
|
|
11
|
-
# The disk turns at 300 rpm, so every track passes under the head in
|
|
12
|
-
# the same 200 ms, and its bits pass at the rate they were written at.
|
|
13
|
-
# Each bit is a cell of time, starting at the track's index angle with
|
|
14
|
-
# the first byte's top bit, and a 1 bit is a flux transition at the
|
|
15
|
-
# start of its cell. The cells are spread evenly over the turn, so a
|
|
16
|
-
# track as long as a turn holds at its zone's rate
|
|
17
|
-
# (Disk::TRACK_LENGTHS) passes at that rate, within the part of a byte
|
|
18
|
-
# the length rounds off, and a longer or shorter one faster or slower.
|
|
19
|
-
# A .g64 speed map gives each byte the zone it was written in, and the
|
|
20
|
-
# cells of each byte are as wide as their zone's, scaled together to
|
|
21
|
-
# fill the turn.
|
|
22
|
-
#
|
|
23
|
-
# Times are in TICKs, 1/65536 of a tick of the drive's 16 MHz crystal,
|
|
24
|
-
# so the cells add up to a turn within a tick.
|
|
25
|
-
class Track
|
|
26
|
-
TICK = 1 << 16
|
|
27
|
-
TURN = 200_000 * 16 * TICK
|
|
28
|
-
|
|
29
|
-
# A bit cell at the zone's rate, in TICKs.
|
|
30
|
-
def self.cell(zone) = 4 * (16 - zone) * TICK
|
|
31
|
-
|
|
32
|
-
attr_reader :bytes, :zone, :speeds, :width, :widths
|
|
33
|
-
|
|
34
|
-
# +speeds+ holds each byte's zone, where the track's rate changes
|
|
35
|
-
# along it.
|
|
36
|
-
def initialize(bytes, zone, speeds = nil)
|
|
37
|
-
@bytes = bytes
|
|
38
|
-
@zone = zone
|
|
39
|
-
@speeds = speeds
|
|
40
|
-
@widths = speeds && scaled_widths(speeds)
|
|
41
|
-
@width = speeds ? @widths[0] : TURN / (bytes.length * 8)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def length = @bytes.length
|
|
45
|
-
|
|
46
|
-
# Whether the whole track was written at the +zone+'s rate.
|
|
47
|
-
def written_at?(zone) = @widths.nil? && @zone == zone
|
|
48
|
-
|
|
49
|
-
# The bit cell under the head +time+ TICKs into the turn, as
|
|
50
|
-
# [byte, mask, the time the cell ends].
|
|
51
|
-
def cell_at(time)
|
|
52
|
-
start = 0
|
|
53
|
-
index = 0
|
|
54
|
-
if @widths
|
|
55
|
-
while index < length - 1 && time >= start + (@widths[index] * 8)
|
|
56
|
-
start += @widths[index] * 8
|
|
57
|
-
index += 1
|
|
58
|
-
end
|
|
59
|
-
else
|
|
60
|
-
index = [time / (@width * 8), length - 1].min
|
|
61
|
-
start = index * @width * 8
|
|
62
|
-
end
|
|
63
|
-
width = @widths ? @widths[index] : @width
|
|
64
|
-
bit = [(time - start) / width, 7].min
|
|
65
|
-
cell_end = index == length - 1 && bit == 7 ? TURN : start + ((bit + 1) * width)
|
|
66
|
-
[index, 0x80 >> bit, cell_end]
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
# The track laid out again as one turn at the +zone+'s rate, each
|
|
70
|
-
# flux transition in the cell under it.
|
|
71
|
-
def relaid(zone)
|
|
72
|
-
bits = Disk::TRACK_LENGTHS[zone] * 8
|
|
73
|
-
cell = TURN / bits
|
|
74
|
-
relaid = Array.new(bits / 8, 0)
|
|
75
|
-
time = 0
|
|
76
|
-
@bytes.each_with_index do |byte, index|
|
|
77
|
-
width = @widths ? @widths[index] : @width
|
|
78
|
-
8.times do |bit|
|
|
79
|
-
if byte.anybits?(0x80 >> bit)
|
|
80
|
-
cell_index = [time / cell, bits - 1].min
|
|
81
|
-
relaid[cell_index >> 3] |= 0x80 >> (cell_index & 7)
|
|
82
|
-
end
|
|
83
|
-
time += width
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
Track.new(relaid, zone)
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
private
|
|
90
|
-
|
|
91
|
-
def scaled_widths(speeds)
|
|
92
|
-
units = 0
|
|
93
|
-
speeds.each { |zone| units += 16 - zone }
|
|
94
|
-
speeds.map { |zone| TURN * (16 - zone) / (units * 8) }
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
end
|
data/lib/badline/drive1541.rb
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "badline/drive"
|
|
4
|
-
require "badline/drive1541/bus"
|
|
5
|
-
require "badline/drive1541/cpu"
|
|
6
|
-
require "badline/drive1541/serial_port"
|
|
7
|
-
require "badline/drive1541/gcr"
|
|
8
|
-
require "badline/drive1541/track"
|
|
9
|
-
require "badline/drive1541/disk"
|
|
10
|
-
require "badline/drive1541/mechanism"
|
|
11
|
-
require "badline/drive1541/disk_via"
|
|
12
|
-
|
|
13
|
-
module Badline
|
|
14
|
-
# The 1541 disk drive as a machine of its own: a 6502 running the DOS
|
|
15
|
-
# ROM at 1 MHz, with 2 KB of RAM and two VIAs on its bus. Drive::Core
|
|
16
|
-
# clocks it against the host and sleeps through the DOS's idle loop.
|
|
17
|
-
class Drive1541
|
|
18
|
-
include Drive::Core
|
|
19
|
-
include Drive::VIAs
|
|
20
|
-
|
|
21
|
-
CLOCK_HZ = 1_000_000
|
|
22
|
-
|
|
23
|
-
# Where the DOS 2.6 idle loop starts over (see Drive::Idle).
|
|
24
|
-
IDLE_LOOP = 0xebff
|
|
25
|
-
|
|
26
|
-
def model_name = "1541"
|
|
27
|
-
|
|
28
|
-
# +rom+ covers $C000-$FFFF, and defaults to the DOS image in the ROM
|
|
29
|
-
# path. +device+ is the number the jumpers on VIA 1's PB5 and PB6 set,
|
|
30
|
-
# 8 to 11.
|
|
31
|
-
def initialize(rom: nil, host_clock_hz: CLOCK_HZ, device: 8, debug: false)
|
|
32
|
-
@device = device
|
|
33
|
-
@serial_port = SerialPort.new(device:)
|
|
34
|
-
@via1 = VIA.new(start: 0x1800, peripheral: @serial_port)
|
|
35
|
-
@mechanism = Mechanism.new
|
|
36
|
-
@via2 = DiskVIA.new(start: 0x1c00, mechanism: @mechanism)
|
|
37
|
-
@bus = Bus.new(rom: rom || ROM.load("dos1541.rom", 0xc000), via1: @via1, via2: @via2)
|
|
38
|
-
@cpu = CPU.new(@bus, debug:)
|
|
39
|
-
@clock_hz = CLOCK_HZ
|
|
40
|
-
@idle_loop = IDLE_LOOP
|
|
41
|
-
@host_clock_hz = host_clock_hz
|
|
42
|
-
@phase = 0
|
|
43
|
-
@cycles = 0
|
|
44
|
-
@serial_bus = nil
|
|
45
|
-
init_idle(debug)
|
|
46
|
-
# CA1 powers up at the level of a released ATN, without an edge.
|
|
47
|
-
@via1.ca1 = false
|
|
48
|
-
@via1.reset!
|
|
49
|
-
connect(IECBus.new)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# The drive's whole state: its clock phase, the CPU, RAM, both VIAs,
|
|
53
|
-
# the serial port's latch of the C64's lines and the mechanism with its
|
|
54
|
-
# disk. The drive settles first, so it is awake and not recording a
|
|
55
|
-
# pass, and a restored drive starts the same way, its orbits forgotten
|
|
56
|
-
# from the state it takes: Idle's and Orbit's bookkeeping
|
|
57
|
-
# isn't stored. The device number, the host's clock rate and whether
|
|
58
|
-
# the drive may sleep are the machine's wiring.
|
|
59
|
-
def save_state(out)
|
|
60
|
-
settle!
|
|
61
|
-
out.marker("DRIVE1541")
|
|
62
|
-
out.int(@phase).int(@cycles).boolean(@mechanism.so_pending)
|
|
63
|
-
@serial_port.save_state(out)
|
|
64
|
-
@via1.save_state(out)
|
|
65
|
-
@via2.save_state(out)
|
|
66
|
-
@bus.save_state(out)
|
|
67
|
-
@cpu.save_state(out)
|
|
68
|
-
@mechanism.save_state(out)
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def load_state(input)
|
|
72
|
-
settle!
|
|
73
|
-
input.marker("DRIVE1541")
|
|
74
|
-
@phase = input.int
|
|
75
|
-
@cycles = input.int
|
|
76
|
-
@mechanism.so_pending = input.boolean?
|
|
77
|
-
@serial_port.load_state(input)
|
|
78
|
-
@via1.load_state(input)
|
|
79
|
-
@via2.load_state(input)
|
|
80
|
-
@bus.load_state(input)
|
|
81
|
-
@cpu.load_state(input)
|
|
82
|
-
@mechanism.load_state(input)
|
|
83
|
-
forget_orbits
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
private
|
|
87
|
-
|
|
88
|
-
# One drive cycle. The VIAs clock ahead of the CPU, as the C64's chips
|
|
89
|
-
# do, and either one pulls IRQ. Nothing drives NMI on the 1541. The CPU
|
|
90
|
-
# runs whether or not the motor turns, since it answers ATN.
|
|
91
|
-
#
|
|
92
|
-
# The disk mechanism runs first, so BYTE READY lands on the VIA ahead
|
|
93
|
-
# of the CPU's cycle. The CPU samples SO a cycle late: BYTE READY sets
|
|
94
|
-
# V for the next cycle's instruction step.
|
|
95
|
-
#
|
|
96
|
-
# ATN reaches VIA 1's CA1 through the same inverter as PB7, so CA1 goes
|
|
97
|
-
# high as the C64 asserts ATN, as the serial port sees it: from the
|
|
98
|
-
# host cycle after the one that asserts it.
|
|
99
|
-
def step
|
|
100
|
-
so = @mechanism.take_so
|
|
101
|
-
@mechanism.cycle!
|
|
102
|
-
@via1.ca1 = @serial_port.atn_low?
|
|
103
|
-
@via1.cycle!
|
|
104
|
-
@via2.cycle!
|
|
105
|
-
@cpu.irq = @via1.irq? || @via2.irq?
|
|
106
|
-
@cpu.so! if so
|
|
107
|
-
@cpu.cycle!
|
|
108
|
-
@cycles += 1
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
end
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Drive1571
|
|
5
|
-
# The drive CPU's bus:
|
|
6
|
-
#
|
|
7
|
-
# $0000-$07FF - 2 KB of RAM
|
|
8
|
-
# $0800-$17FF - nothing: open bus
|
|
9
|
-
# $1800-$1BFF - VIA 1, its sixteen registers mirrored
|
|
10
|
-
# $1C00-$1FFF - VIA 2, its sixteen registers mirrored
|
|
11
|
-
# $2000-$3FFF - the WD1770, its four registers mirrored
|
|
12
|
-
# $4000-$7FFF - the CIA, its sixteen registers mirrored
|
|
13
|
-
# $8000-$FFFF - the DOS ROM
|
|
14
|
-
#
|
|
15
|
-
# Writes to the ROM and to open bus go nowhere, and a read from open
|
|
16
|
-
# bus finds the last byte on the data bus, as on the 1541. Any access
|
|
17
|
-
# to VIA 2 clears the BYTE READY latch VIA 1's PA7 reads (SerialPort).
|
|
18
|
-
#
|
|
19
|
-
# While Idle records a pass of the DOS's idle loop, the bus watches it,
|
|
20
|
-
# and while Idle looks for an orbit, it guards the drive (see
|
|
21
|
-
# Drive::Watch). Any access to the CIA or the WD1770 makes the pass
|
|
22
|
-
# volatile and taints the drive.
|
|
23
|
-
class Bus
|
|
24
|
-
include Addressable
|
|
25
|
-
include Drive::Watch
|
|
26
|
-
|
|
27
|
-
attr_reader :ram, :rom, :via1, :via2, :cia, :fdc, :data
|
|
28
|
-
|
|
29
|
-
def initialize(rom:, via1:, via2:, cia:, fdc:)
|
|
30
|
-
addressable_at(0, length: 2**16)
|
|
31
|
-
@ram = Memory.new([], length: 0x0800, start: 0)
|
|
32
|
-
@rom = rom
|
|
33
|
-
@via1 = via1
|
|
34
|
-
@via2 = via2
|
|
35
|
-
@cia = cia
|
|
36
|
-
@fdc = fdc
|
|
37
|
-
@mechanism = via2.mechanism
|
|
38
|
-
@data = 0
|
|
39
|
-
init_watch
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
# The last byte on the data bus and the RAM. What a watched stretch
|
|
43
|
-
# touched is Idle's, and a restored bus isn't watching.
|
|
44
|
-
def save_state(out)
|
|
45
|
-
out.int(@data)
|
|
46
|
-
@ram.save_state(out)
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def load_state(input)
|
|
50
|
-
@data = input.int
|
|
51
|
-
@ram.load_state(input)
|
|
52
|
-
@watching = false
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def peek(addr)
|
|
56
|
-
return @data = @rom.peek(addr) if addr >= 0x8000
|
|
57
|
-
return @data = chip_peek(addr) if addr >= 0x2000
|
|
58
|
-
|
|
59
|
-
watch_read(addr) if @watching
|
|
60
|
-
@data = if addr < 0x0800
|
|
61
|
-
@ram.peek(addr)
|
|
62
|
-
elsif addr < 0x1800
|
|
63
|
-
@data
|
|
64
|
-
elsif addr < 0x1c00
|
|
65
|
-
@via1.peek(addr)
|
|
66
|
-
else
|
|
67
|
-
@mechanism.release_byte_latch
|
|
68
|
-
@via2.peek(addr)
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def poke(addr, value)
|
|
73
|
-
@data = value
|
|
74
|
-
return if addr >= 0x8000
|
|
75
|
-
return chip_poke(addr, value) if addr >= 0x2000
|
|
76
|
-
|
|
77
|
-
low_poke(addr, value)
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
private
|
|
81
|
-
|
|
82
|
-
# A write below $2000: RAM or a VIA.
|
|
83
|
-
def low_poke(addr, value)
|
|
84
|
-
if addr < 0x0800
|
|
85
|
-
touch(addr) if @recording
|
|
86
|
-
@ram.poke(addr, value)
|
|
87
|
-
elsif addr >= 0x1c00
|
|
88
|
-
@mechanism.release_byte_latch
|
|
89
|
-
@via2.poke(addr, value)
|
|
90
|
-
elsif addr >= 0x1800
|
|
91
|
-
@via1.poke(addr, value)
|
|
92
|
-
end
|
|
93
|
-
watch_write(addr) if @watching
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def chip_peek(addr)
|
|
97
|
-
watch_chip if @watching
|
|
98
|
-
addr >= 0x4000 ? @cia.peek(0x4000 | (addr & 0x0f)) : @fdc.peek(addr & 0x03)
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def chip_poke(addr, value)
|
|
102
|
-
if addr >= 0x4000
|
|
103
|
-
@cia.poke(0x4000 | (addr & 0x0f), value)
|
|
104
|
-
else
|
|
105
|
-
@fdc.poke(addr & 0x03, value)
|
|
106
|
-
end
|
|
107
|
-
watch_chip if @watching
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
end
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Drive1571
|
|
5
|
-
# What VIA 1's ports read from outside the chip. Port B carries the
|
|
6
|
-
# serial bus inputs and the device number jumpers, as on the 1541
|
|
7
|
-
# (Drive::SerialLines). Port A reads the mechanism on two inputs:
|
|
8
|
-
#
|
|
9
|
-
# PA0 track 0 sensor, low while the head sits on track 1
|
|
10
|
-
# PA7 BYTE READY, latched low from a whole byte until the CPU next
|
|
11
|
-
# reads or writes VIA 2
|
|
12
|
-
#
|
|
13
|
-
# The DOS steps the head out until PA0 reads low with the stepper on
|
|
14
|
-
# phase 0, and polls PA7 for each byte at 2 MHz, taking the byte from
|
|
15
|
-
# VIA 2's port A or putting the next one there after each. PA1 (fast serial
|
|
16
|
-
# direction), PA2 (side) and PA5 (1 or 2 MHz) are outputs, which
|
|
17
|
-
# Drive1571 follows (SerialVIA).
|
|
18
|
-
class SerialPort
|
|
19
|
-
include Drive::SerialLines
|
|
20
|
-
|
|
21
|
-
TRACK0 = 0x01
|
|
22
|
-
BYTE_READY = 0x80
|
|
23
|
-
|
|
24
|
-
def initialize(mechanism, device: 8, bus: IECBus.new)
|
|
25
|
-
@mechanism = mechanism
|
|
26
|
-
init_serial_lines(device, bus)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def read_a(_lines)
|
|
30
|
-
value = 0xff
|
|
31
|
-
value &= ~TRACK0 if @mechanism.half_track == Drive1541::Mechanism::MIN_HALF_TRACK
|
|
32
|
-
value &= ~BYTE_READY if @mechanism.byte_latched?
|
|
33
|
-
value
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Drive1571
|
|
5
|
-
# VIA 1, the one facing the serial bus. Its port A also selects the
|
|
6
|
-
# side, the clock rate and the fast serial direction, so the drive
|
|
7
|
-
# hears port A after every write and reset (Drive1571#port_a_written).
|
|
8
|
-
class SerialVIA < VIA
|
|
9
|
-
def initialize(start:, peripheral:, drive:)
|
|
10
|
-
@drive = drive
|
|
11
|
-
super(start:, peripheral:)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def reset!
|
|
15
|
-
super
|
|
16
|
-
@drive.port_a_written(port_a_output)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def poke(addr, value)
|
|
20
|
-
super
|
|
21
|
-
@drive.port_a_written(port_a_output)
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Drive1571
|
|
5
|
-
# The WD1770 floppy controller at $2000, which DOS 3.0 drives for MFM
|
|
6
|
-
# disks. The 1571 here only ever holds GCR disks, so the controller
|
|
7
|
-
# never finds an MFM sector: it runs each command for its time and ends
|
|
8
|
-
# it as the WD177x data sheet does on a disk without one.
|
|
9
|
-
#
|
|
10
|
-
# $2000 status (read), command (write)
|
|
11
|
-
# $2001 track
|
|
12
|
-
# $2002 sector
|
|
13
|
-
# $2003 data
|
|
14
|
-
#
|
|
15
|
-
# BUSY sets as a command is written. A restore, seek or step (type I)
|
|
16
|
-
# moves the track register and ends a few milliseconds later, with
|
|
17
|
-
# TRACK 0 reported at track 0. A sector read or write, a read address
|
|
18
|
-
# or a read track ends with RECORD NOT FOUND after five turns of the
|
|
19
|
-
# disk, and a write track after one, with nothing written. A force
|
|
20
|
-
# interrupt ends the command at once. Time is the drive CPU's cycles.
|
|
21
|
-
class WD1770
|
|
22
|
-
BUSY = 0x01
|
|
23
|
-
TRACK0 = 0x04
|
|
24
|
-
NOT_FOUND = 0x10
|
|
25
|
-
MOTOR_ON = 0x80
|
|
26
|
-
|
|
27
|
-
# Cycles at 2 MHz, the 1571's clock in 1571 mode: a turn of the disk
|
|
28
|
-
# at 300 rpm, and a step with the head settling.
|
|
29
|
-
TURN = 400_000
|
|
30
|
-
STEP = 12_000
|
|
31
|
-
|
|
32
|
-
# The CPU whose cycles time the commands.
|
|
33
|
-
attr_writer :cpu
|
|
34
|
-
|
|
35
|
-
def initialize
|
|
36
|
-
@registers = [0, 0, 0, 0]
|
|
37
|
-
@status = 0
|
|
38
|
-
@due = 0
|
|
39
|
-
@result = 0
|
|
40
|
-
@cpu = nil
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# Register +offset+, 0 to 3: the status, settled to the command's end
|
|
44
|
-
# once its time has run out.
|
|
45
|
-
def peek(offset)
|
|
46
|
-
return @registers[offset] unless offset.zero?
|
|
47
|
-
|
|
48
|
-
finish if @status.anybits?(BUSY) && @cpu.cycles >= @due
|
|
49
|
-
@status
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def poke(offset, value)
|
|
53
|
-
offset.zero? ? command(value) : @registers[offset] = value
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def save_state(out)
|
|
57
|
-
out.ints([*@registers, @status, @due, @result])
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
# A state from before the controller ran commands holds the four
|
|
61
|
-
# registers alone.
|
|
62
|
-
def load_state(input)
|
|
63
|
-
values = input.ints
|
|
64
|
-
@registers = values[0, 4]
|
|
65
|
-
@status = values[4] || 0
|
|
66
|
-
@due = values[5] || 0
|
|
67
|
-
@result = values[6] || 0
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
private
|
|
71
|
-
|
|
72
|
-
def command(value)
|
|
73
|
-
return interrupt if (value & 0xf0) == 0xd0
|
|
74
|
-
|
|
75
|
-
@registers[0] = value
|
|
76
|
-
value < 0x80 ? step(value) : search(value)
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
# A restore ($0x), seek ($1x) or step ($2x to $7x), its track register
|
|
80
|
-
# moved at once.
|
|
81
|
-
def step(value)
|
|
82
|
-
track = @registers[1]
|
|
83
|
-
target = case value >> 4
|
|
84
|
-
when 0 then 0
|
|
85
|
-
when 1 then @registers[3]
|
|
86
|
-
else track + step_direction(value)
|
|
87
|
-
end
|
|
88
|
-
@registers[1] = target.clamp(0, 255) if value < 0x20 || value.anybits?(0x10)
|
|
89
|
-
start(STEP * [(target - track).abs, 1].max, @registers[1].zero? ? TRACK0 : 0)
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
# Step in ($4x) moves toward higher tracks, step out ($6x) toward
|
|
93
|
-
# track 0, and step ($2x) the way the last one went.
|
|
94
|
-
def step_direction(value)
|
|
95
|
-
@direction = 1 if (value >> 5) == 2
|
|
96
|
-
@direction = -1 if (value >> 5) == 3
|
|
97
|
-
@direction || 1
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
# A sector or track command that finds no MFM sector.
|
|
101
|
-
def search(value)
|
|
102
|
-
value >= 0xf0 ? start(TURN, 0) : start(TURN * 5, NOT_FOUND)
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def start(cycles, result)
|
|
106
|
-
@status = BUSY | MOTOR_ON
|
|
107
|
-
@due = @cpu.cycles + cycles
|
|
108
|
-
@result = result
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def finish
|
|
112
|
-
@status = @result
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def interrupt
|
|
116
|
-
@status &= ~BUSY & 0xff
|
|
117
|
-
end
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
end
|