badline 0.12.1 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -0
- data/CLAUDE.md +59 -31
- data/README.md +1 -1
- data/doc/library.md +9 -9
- data/doc/pinned-behaviour.md +105 -105
- data/doc/snapshots.md +1 -4
- data/lib/badline/audio/bare_player.rb +3 -3
- data/lib/badline/audio/cli.rb +6 -6
- data/lib/badline/audio/jukebox.rb +2 -2
- data/lib/badline/audio/machine_player.rb +2 -2
- data/lib/badline/{media → audio}/queue.rb +1 -1
- data/lib/badline/audio/queued_tune.rb +6 -6
- data/lib/badline/audio/renderer.rb +5 -5
- data/lib/badline/audio/stereo.rb +1 -1
- data/lib/badline/c128/{bus_state.rb → bus/saved_state.rb} +1 -1
- data/lib/badline/c128/bus.rb +18 -17
- data/lib/badline/c128/color_lines.rb +2 -2
- data/lib/badline/c128/cpu.rb +1 -1
- data/lib/badline/c128/drives.rb +10 -11
- data/lib/badline/c128/fast_serial.rb +5 -5
- data/lib/badline/c128/mmu_pages.rb +1 -1
- data/lib/badline/c128/modes.rb +2 -2
- data/lib/badline/c128/saved_state.rb +21 -47
- data/lib/badline/c128/z80.rb +2 -2
- data/lib/badline/c128.rb +14 -9
- data/lib/badline/{computer → c64}/attachments.rb +4 -6
- data/lib/badline/c64/banked_ram/banking.rb +32 -0
- data/lib/badline/c64/banked_ram/plus256k.rb +56 -0
- data/lib/badline/c64/banked_ram/plus60k.rb +45 -0
- data/lib/badline/c64/banked_ram/unexpanded.rb +30 -0
- data/lib/badline/c64/banked_ram.rb +23 -0
- data/lib/badline/c64/bus/extra_sids.rb +32 -0
- data/lib/badline/c64/bus/fittings.rb +40 -0
- data/lib/badline/c64/bus/pla.rb +149 -0
- data/lib/badline/c64/bus/roms.rb +41 -0
- data/lib/badline/c64/bus/saved_state.rb +68 -0
- data/lib/badline/c64/bus/sid_slots.rb +44 -0
- data/lib/badline/c64/bus.rb +218 -0
- data/lib/badline/c64/cartridge/action_replay.rb +128 -0
- data/lib/badline/c64/cartridge/atomic_power.rb +26 -0
- data/lib/badline/c64/cartridge/bank.rb +83 -0
- data/lib/badline/c64/cartridge/comal80.rb +52 -0
- data/lib/badline/c64/cartridge/dinamic.rb +36 -0
- data/lib/badline/c64/cartridge/easy_flash.rb +147 -0
- data/lib/badline/c64/cartridge/epyx_fastload.rb +81 -0
- data/lib/badline/c64/cartridge/final_cartridge3.rb +91 -0
- data/lib/badline/c64/cartridge/flash/saved_state.rb +40 -0
- data/lib/badline/c64/cartridge/flash.rb +279 -0
- data/lib/badline/c64/cartridge/freezer.rb +35 -0
- data/lib/badline/c64/cartridge/fun_play.rb +40 -0
- data/lib/badline/c64/cartridge/g_mod2.rb +76 -0
- data/lib/badline/c64/cartridge/game_system.rb +42 -0
- data/lib/badline/c64/cartridge/geo_ram.rb +81 -0
- data/lib/badline/c64/cartridge/kcs_power.rb +77 -0
- data/lib/badline/c64/cartridge/mach5.rb +34 -0
- data/lib/badline/c64/cartridge/magic_desk.rb +32 -0
- data/lib/badline/c64/cartridge/ocean.rb +37 -0
- data/lib/badline/c64/cartridge/pagefox.rb +70 -0
- data/lib/badline/c64/cartridge/retro_replay/saved_state.rb +47 -0
- data/lib/badline/c64/cartridge/retro_replay.rb +286 -0
- data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
- data/lib/badline/c64/cartridge/rgcd.rb +60 -0
- data/lib/badline/c64/cartridge/saved_state.rb +63 -0
- data/lib/badline/c64/cartridge/simons_basic.rb +37 -0
- data/lib/badline/c64/cartridge/standard.rb +17 -0
- data/lib/badline/c64/cartridge/super_games.rb +50 -0
- data/lib/badline/c64/cartridge/westermann.rb +32 -0
- data/lib/badline/c64/cartridge/zaxxon.rb +68 -0
- data/lib/badline/c64/cartridge.rb +258 -0
- data/lib/badline/c64/color_memory.rb +27 -0
- data/lib/badline/{computer → c64}/common.rb +2 -2
- data/lib/badline/{computer → c64}/kernal_traps.rb +18 -18
- data/lib/badline/c64/reu/dma/saved_state.rb +52 -0
- data/lib/badline/c64/reu/dma.rb +275 -0
- data/lib/badline/c64/reu/ram.rb +109 -0
- data/lib/badline/c64/reu/saved_state.rb +55 -0
- data/lib/badline/c64/reu/trigger.rb +34 -0
- data/lib/badline/c64/reu.rb +291 -0
- data/lib/badline/{computer → c64}/saved_state.rb +13 -18
- data/lib/badline/{computer → c64}/true_drives.rb +11 -11
- data/lib/badline/{computer.rb → c64.rb} +18 -13
- data/lib/badline/chips/cia/fast_forward.rb +62 -0
- data/lib/badline/chips/cia/interrupt_register.rb +145 -0
- data/lib/badline/chips/cia/saved_state.rb +49 -0
- data/lib/badline/chips/cia/serial/saved_state.rb +45 -0
- data/lib/badline/chips/cia/serial.rb +250 -0
- data/lib/badline/chips/cia/time_of_day.rb +232 -0
- data/lib/badline/chips/cia/timer.rb +208 -0
- data/lib/badline/chips/cia.rb +281 -0
- data/lib/badline/chips/cpu/addressing.rb +133 -0
- data/lib/badline/chips/cpu/boundary.rb +56 -0
- data/lib/badline/chips/cpu/core.rb +167 -0
- data/lib/badline/chips/cpu/instruction.rb +338 -0
- data/lib/badline/chips/cpu/instruction_set/arithmetic.rb +118 -0
- data/lib/badline/chips/cpu/instruction_set/bitwise.rb +130 -0
- data/lib/badline/chips/cpu/instruction_set/branch.rb +83 -0
- data/lib/badline/chips/cpu/instruction_set/flag.rb +67 -0
- data/lib/badline/chips/cpu/instruction_set/illegal.rb +274 -0
- data/lib/badline/chips/cpu/instruction_set/inc_dec.rb +73 -0
- data/lib/badline/chips/cpu/instruction_set/stack.rb +56 -0
- data/lib/badline/chips/cpu/instruction_set/transfer.rb +141 -0
- data/lib/badline/chips/cpu/instruction_set.rb +59 -0
- data/lib/badline/chips/cpu/interrupts.rb +108 -0
- data/lib/badline/chips/cpu/microcode.rb +179 -0
- data/lib/badline/chips/cpu/operations.rb +90 -0
- data/lib/badline/chips/cpu/port.rb +116 -0
- data/lib/badline/chips/cpu/saved_state.rb +117 -0
- data/lib/badline/chips/cpu/stack_operations.rb +84 -0
- data/lib/badline/chips/cpu/traps.rb +23 -0
- data/lib/badline/chips/cpu.rb +12 -0
- data/lib/badline/chips/sid/catch_up.rb +122 -0
- data/lib/badline/chips/sid/decimator.rb +66 -0
- data/lib/badline/chips/sid/envelope/saved_state.rb +70 -0
- data/lib/badline/chips/sid/envelope.rb +241 -0
- data/lib/badline/chips/sid/filter/saved_state.rb +42 -0
- data/lib/badline/chips/sid/filter.rb +241 -0
- data/lib/badline/chips/sid/saved_state.rb +52 -0
- data/lib/badline/chips/sid/voice.rb +79 -0
- data/lib/badline/chips/sid/waveform/combined.rb +128 -0
- data/lib/badline/chips/sid/waveform/fast_forward.rb +107 -0
- data/lib/badline/chips/sid/waveform/noise_writeback.rb +124 -0
- data/lib/badline/chips/sid/waveform/saved_state.rb +68 -0
- data/lib/badline/chips/sid/waveform.rb +307 -0
- data/lib/badline/chips/sid.rb +265 -0
- data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
- data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -1
- data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -1
- data/lib/badline/chips/vdc/saved_state.rb +36 -0
- data/lib/badline/{c128 → chips}/vdc/window.rb +1 -1
- data/lib/badline/{c128 → chips}/vdc.rb +7 -31
- data/lib/badline/chips/via/control_lines.rb +124 -0
- data/lib/badline/chips/via/fast_forward.rb +55 -0
- data/lib/badline/chips/via/interrupt_register.rb +69 -0
- data/lib/badline/chips/via/saved_state.rb +44 -0
- data/lib/badline/chips/via/shift_register.rb +182 -0
- data/lib/badline/chips/via/timer1.rb +133 -0
- data/lib/badline/chips/via/timer2.rb +135 -0
- data/lib/badline/chips/via.rb +268 -0
- data/lib/badline/chips/vic/bank.rb +135 -0
- data/lib/badline/chips/vic/border_mask.rb +88 -0
- data/lib/badline/chips/vic/collisions.rb +117 -0
- data/lib/badline/chips/vic/color_patches.rb +49 -0
- data/lib/badline/chips/vic/display_state.rb +187 -0
- data/lib/badline/chips/vic/graphics_mode.rb +166 -0
- data/lib/badline/chips/vic/graphics_shifter/saved_state.rb +40 -0
- data/lib/badline/chips/vic/graphics_shifter.rb +187 -0
- data/lib/badline/chips/vic/register_log.rb +83 -0
- data/lib/badline/chips/vic/registers.rb +197 -0
- data/lib/badline/chips/vic/saved_state.rb +82 -0
- data/lib/badline/chips/vic/sequencer/saved_state.rb +91 -0
- data/lib/badline/chips/vic/sequencer.rb +277 -0
- data/lib/badline/chips/vic/sequencer_output.rb +118 -0
- data/lib/badline/chips/vic/sprite/internal_bus.rb +70 -0
- data/lib/badline/chips/vic/sprite/saved_state.rb +66 -0
- data/lib/badline/chips/vic/sprite/shifter.rb +148 -0
- data/lib/badline/chips/vic/sprite/timing.rb +58 -0
- data/lib/badline/chips/vic/sprite.rb +339 -0
- data/lib/badline/chips/vic/sprites/saved_state.rb +59 -0
- data/lib/badline/chips/vic/sprites.rb +284 -0
- data/lib/badline/chips/vic.rb +783 -0
- data/lib/badline/chips/vic_i/painter/saved_state.rb +40 -0
- data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +6 -30
- data/lib/badline/{vic20/vic → chips/vic_i}/saved_state.rb +2 -2
- data/lib/badline/chips/vic_i/sound/output.rb +85 -0
- data/lib/badline/chips/vic_i/sound.rb +235 -0
- data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
- data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +5 -5
- data/lib/badline/chips/z80/arithmetic.rb +119 -0
- data/lib/badline/chips/z80/bit_page.rb +57 -0
- data/lib/badline/chips/z80/block_io.rb +60 -0
- data/lib/badline/chips/z80/block_transfers.rb +61 -0
- data/lib/badline/chips/z80/bus_cycles.rb +113 -0
- data/lib/badline/chips/z80/core.rb +115 -0
- data/lib/badline/chips/z80/exchanges.rb +52 -0
- data/lib/badline/chips/z80/extended_page.rb +91 -0
- data/lib/badline/chips/z80/flags.rb +39 -0
- data/lib/badline/chips/z80/interrupt_acceptance.rb +48 -0
- data/lib/badline/chips/z80/jumps.rb +84 -0
- data/lib/badline/chips/z80/loads.rb +100 -0
- data/lib/badline/chips/z80/main_page.rb +136 -0
- data/lib/badline/chips/z80/registers.rb +122 -0
- data/lib/badline/chips/z80/saved_state.rb +71 -0
- data/lib/badline/chips/z80/shifts.rb +66 -0
- data/lib/badline/chips/z80.rb +13 -0
- data/lib/badline/core.rb +26 -28
- data/lib/badline/drives/datasette/saved_state.rb +37 -0
- data/lib/badline/drives/datasette.rb +140 -0
- data/lib/badline/drives/engine/core.rb +149 -0
- data/lib/badline/drives/engine/fast_serial.rb +75 -0
- data/lib/badline/drives/engine/idle.rb +127 -0
- data/lib/badline/drives/engine/idle_cpu.rb +30 -0
- data/lib/badline/drives/engine/orbit.rb +81 -0
- data/lib/badline/drives/engine/serial_lines.rb +75 -0
- data/lib/badline/drives/engine/sleep.rb +114 -0
- data/lib/badline/drives/engine/vias.rb +86 -0
- data/lib/badline/drives/engine/watch.rb +152 -0
- data/lib/badline/drives/engine.rb +11 -0
- data/lib/badline/drives/model1541/bus.rb +88 -0
- data/lib/badline/drives/model1541/byte_ready.rb +50 -0
- data/lib/badline/drives/model1541/cpu.rb +13 -0
- data/lib/badline/drives/model1541/disk/saved_state.rb +88 -0
- data/lib/badline/drives/model1541/disk.rb +317 -0
- data/lib/badline/drives/model1541/disk_via.rb +38 -0
- data/lib/badline/drives/model1541/gcr.rb +59 -0
- data/lib/badline/drives/model1541/mechanism/saved_state.rb +72 -0
- data/lib/badline/drives/model1541/mechanism.rb +315 -0
- data/lib/badline/drives/model1541/rotation.rb +123 -0
- data/lib/badline/drives/model1541/saved_state.rb +44 -0
- data/lib/badline/drives/model1541/sector_reader.rb +78 -0
- data/lib/badline/drives/model1541/serial_port.rb +20 -0
- data/lib/badline/drives/model1541/track.rb +100 -0
- data/lib/badline/drives/model1541.rb +81 -0
- data/lib/badline/drives/model1571/bus.rb +113 -0
- data/lib/badline/drives/model1571/cpu.rb +13 -0
- data/lib/badline/drives/model1571/saved_state.rb +47 -0
- data/lib/badline/drives/model1571/serial_port.rb +39 -0
- data/lib/badline/drives/model1571/serial_via.rb +27 -0
- data/lib/badline/drives/model1571/wd1770.rb +122 -0
- data/lib/badline/drives/model1571.rb +142 -0
- data/lib/badline/drives/model1581/bus.rb +139 -0
- data/lib/badline/drives/model1581/cpu.rb +13 -0
- data/lib/badline/drives/model1581/disk/saved_state.rb +89 -0
- data/lib/badline/drives/model1581/disk.rb +137 -0
- data/lib/badline/drives/model1581/mechanism.rb +119 -0
- data/lib/badline/drives/model1581/saved_state.rb +42 -0
- data/lib/badline/drives/model1581/serial_port.rb +54 -0
- data/lib/badline/drives/model1581/slot.rb +79 -0
- data/lib/badline/drives/model1581/track.rb +102 -0
- data/lib/badline/drives/model1581/track_bytes.rb +77 -0
- data/lib/badline/drives/model1581/wd1772/registers.rb +91 -0
- data/lib/badline/drives/model1581/wd1772/saved_state.rb +68 -0
- data/lib/badline/drives/model1581/wd1772/sector_writes.rb +75 -0
- data/lib/badline/drives/model1581/wd1772/sectors.rb +152 -0
- data/lib/badline/drives/model1581/wd1772/stepping.rb +111 -0
- data/lib/badline/drives/model1581/wd1772/tracks.rb +127 -0
- data/lib/badline/drives/model1581/wd1772/turn.rb +75 -0
- data/lib/badline/drives/model1581/wd1772.rb +218 -0
- data/lib/badline/drives/model1581.rb +206 -0
- data/lib/badline/drives/serial_bus.rb +161 -0
- data/lib/badline/frontend/boot.rb +3 -3
- data/lib/badline/frontend/machine_window.rb +3 -1
- data/lib/badline/frontend/player/filter_view.rb +1 -1
- data/lib/badline/frontend/player/player_controller.rb +2 -2
- data/lib/badline/frontend/player/player_screen.rb +1 -0
- data/lib/badline/frontend/player/theme.rb +7 -7
- data/lib/badline/frontend/timeline.rb +3 -3
- data/lib/badline/input/control_ports.rb +78 -0
- data/lib/badline/input/joystick.rb +27 -0
- data/lib/badline/input/keyboard.rb +114 -0
- data/lib/badline/input.rb +3 -0
- data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
- data/lib/badline/kernal_trap/dos/channel.rb +183 -0
- data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
- data/lib/badline/kernal_trap/{drive.rb → dos.rb} +11 -10
- data/lib/badline/kernal_trap/load.rb +5 -5
- data/lib/badline/kernal_trap/save.rb +4 -4
- data/lib/badline/kernal_trap/serial.rb +7 -7
- data/lib/badline/kernal_trap.rb +1 -2
- data/lib/badline/machine/clocking.rb +1 -1
- data/lib/badline/machine.rb +5 -5
- data/lib/badline/media/true_drive.rb +1 -1
- data/lib/badline/media/tune.rb +2 -2
- data/lib/badline/media.rb +3 -3
- data/lib/badline/model.rb +1 -1
- data/lib/badline/roms/README +6 -6
- data/lib/badline/sdl.rb +1 -0
- data/lib/badline/{storage/sid_file.rb → sid_tune/file.rb} +3 -3
- data/lib/badline/{storage → sid_tune}/hvsc.rb +7 -7
- data/lib/badline/{storage → sid_tune}/song_lengths.rb +2 -2
- data/lib/badline/{storage → sid_tune}/stil/credit.rb +1 -1
- data/lib/badline/{storage → sid_tune}/stil.rb +3 -3
- data/lib/badline/sid_tune.rb +6 -0
- data/lib/badline/snapshot/c128_setup.rb +43 -0
- data/lib/badline/snapshot/c64_setup.rb +79 -0
- data/lib/badline/snapshot/image.rb +5 -25
- data/lib/badline/snapshot/machine_state.rb +1 -1
- data/lib/badline/snapshot/setup.rb +22 -66
- data/lib/badline/snapshot/state.rb +8 -18
- data/lib/badline/snapshot/storage_setup.rb +68 -0
- data/lib/badline/snapshot/vic20_setup.rb +37 -0
- data/lib/badline/snapshot/vice/c64_mem.rb +1 -1
- data/lib/badline/snapshot/vice/restore.rb +1 -1
- data/lib/badline/snapshot/vice/reu1764.rb +1 -1
- data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
- data/lib/badline/snapshot/vice.rb +7 -5
- data/lib/badline/snapshot.rb +3 -4
- data/lib/badline/storage/d64_image.rb +0 -2
- data/lib/badline/storage/d71_image.rb +0 -2
- data/lib/badline/storage/d81_image.rb +0 -2
- data/lib/badline/storage/disk_image.rb +3 -6
- data/lib/badline/storage/g64_image.rb +2 -2
- data/lib/badline/storage/host_directory.rb +0 -5
- data/lib/badline/storage/t64.rb +2 -8
- data/lib/badline/storage/unavailable.rb +1 -1
- data/lib/badline/storage.rb +0 -37
- data/lib/badline/support/c128_checkpoint.rb +39 -0
- data/lib/badline/support/checkpoint.rb +108 -0
- data/lib/badline/support/vic20_checkpoint.rb +38 -0
- data/lib/badline/support.rb +5 -0
- data/lib/badline/version.rb +1 -1
- data/lib/badline/vic20/attachments.rb +5 -5
- data/lib/badline/vic20/bus/saved_state.rb +35 -0
- data/lib/badline/vic20/bus.rb +3 -25
- data/lib/badline/vic20/cpu.rb +1 -1
- data/lib/badline/vic20/port_wiring.rb +4 -4
- data/lib/badline/vic20/saved_state.rb +16 -30
- data/lib/badline/vic20/user_via_ports.rb +2 -2
- data/lib/badline/vic20.rb +19 -14
- metadata +245 -221
- data/lib/badline/address_bus/extra_sids.rb +0 -30
- data/lib/badline/address_bus/fittings.rb +0 -38
- data/lib/badline/address_bus/pla.rb +0 -147
- data/lib/badline/address_bus/roms.rb +0 -39
- data/lib/badline/address_bus/saved_state.rb +0 -66
- data/lib/badline/address_bus/sid_slots.rb +0 -42
- data/lib/badline/address_bus.rb +0 -216
- data/lib/badline/cartridge/action_replay.rb +0 -126
- data/lib/badline/cartridge/atomic_power.rb +0 -24
- data/lib/badline/cartridge/bank.rb +0 -81
- data/lib/badline/cartridge/comal80.rb +0 -50
- data/lib/badline/cartridge/dinamic.rb +0 -34
- data/lib/badline/cartridge/easy_flash.rb +0 -145
- data/lib/badline/cartridge/epyx_fastload.rb +0 -79
- data/lib/badline/cartridge/final_cartridge3.rb +0 -89
- data/lib/badline/cartridge/flash.rb +0 -306
- data/lib/badline/cartridge/freezer.rb +0 -33
- data/lib/badline/cartridge/fun_play.rb +0 -38
- data/lib/badline/cartridge/g_mod2.rb +0 -74
- data/lib/badline/cartridge/game_system.rb +0 -40
- data/lib/badline/cartridge/geo_ram.rb +0 -79
- data/lib/badline/cartridge/kcs_power.rb +0 -75
- data/lib/badline/cartridge/mach5.rb +0 -32
- data/lib/badline/cartridge/magic_desk.rb +0 -30
- data/lib/badline/cartridge/ocean.rb +0 -35
- data/lib/badline/cartridge/pagefox.rb +0 -68
- data/lib/badline/cartridge/retro_replay.rb +0 -320
- data/lib/badline/cartridge/rex_utility.rb +0 -29
- data/lib/badline/cartridge/rgcd.rb +0 -58
- data/lib/badline/cartridge/simons_basic.rb +0 -35
- data/lib/badline/cartridge/standard.rb +0 -15
- data/lib/badline/cartridge/super_games.rb +0 -48
- data/lib/badline/cartridge/westermann.rb +0 -30
- data/lib/badline/cartridge/zaxxon.rb +0 -66
- data/lib/badline/cartridge.rb +0 -303
- data/lib/badline/checkpoint.rb +0 -98
- data/lib/badline/cia/fast_forward.rb +0 -60
- data/lib/badline/cia/interrupt_register.rb +0 -143
- data/lib/badline/cia/serial.rb +0 -275
- data/lib/badline/cia/state.rb +0 -47
- data/lib/badline/cia/timer.rb +0 -206
- data/lib/badline/cia.rb +0 -279
- data/lib/badline/color_memory.rb +0 -25
- data/lib/badline/control_ports.rb +0 -76
- data/lib/badline/cpu/addressing.rb +0 -131
- data/lib/badline/cpu/boundary.rb +0 -54
- data/lib/badline/cpu/core.rb +0 -165
- data/lib/badline/cpu/microcode.rb +0 -177
- data/lib/badline/cpu/operations.rb +0 -88
- data/lib/badline/cpu/saved_state.rb +0 -115
- data/lib/badline/cpu/stack_operations.rb +0 -82
- data/lib/badline/cpu.rb +0 -10
- data/lib/badline/cpu_port.rb +0 -112
- data/lib/badline/datasette.rb +0 -161
- data/lib/badline/drive/core.rb +0 -147
- data/lib/badline/drive/fast_serial.rb +0 -73
- data/lib/badline/drive/idle.rb +0 -125
- data/lib/badline/drive/idle_cpu.rb +0 -28
- data/lib/badline/drive/orbit.rb +0 -79
- data/lib/badline/drive/serial_lines.rb +0 -73
- data/lib/badline/drive/sleep.rb +0 -112
- data/lib/badline/drive/vias.rb +0 -84
- data/lib/badline/drive/watch.rb +0 -150
- data/lib/badline/drive.rb +0 -11
- data/lib/badline/drive1541/bus.rb +0 -86
- data/lib/badline/drive1541/byte_ready.rb +0 -48
- data/lib/badline/drive1541/cpu.rb +0 -11
- data/lib/badline/drive1541/disk.rb +0 -315
- data/lib/badline/drive1541/disk_state.rb +0 -86
- data/lib/badline/drive1541/disk_via.rb +0 -36
- data/lib/badline/drive1541/gcr.rb +0 -57
- data/lib/badline/drive1541/mechanism.rb +0 -313
- data/lib/badline/drive1541/mechanism_state.rb +0 -68
- data/lib/badline/drive1541/rotation.rb +0 -121
- data/lib/badline/drive1541/sector_reader.rb +0 -76
- data/lib/badline/drive1541/serial_port.rb +0 -18
- data/lib/badline/drive1541/track.rb +0 -98
- data/lib/badline/drive1541.rb +0 -111
- data/lib/badline/drive1571/bus.rb +0 -111
- data/lib/badline/drive1571/cpu.rb +0 -11
- data/lib/badline/drive1571/serial_port.rb +0 -37
- data/lib/badline/drive1571/serial_via.rb +0 -25
- data/lib/badline/drive1571/wd1770.rb +0 -120
- data/lib/badline/drive1571.rb +0 -175
- data/lib/badline/drive1581/bus.rb +0 -137
- data/lib/badline/drive1581/cpu.rb +0 -11
- data/lib/badline/drive1581/disk.rb +0 -135
- data/lib/badline/drive1581/disk_state.rb +0 -87
- data/lib/badline/drive1581/mechanism.rb +0 -117
- data/lib/badline/drive1581/serial_port.rb +0 -52
- data/lib/badline/drive1581/slot.rb +0 -78
- data/lib/badline/drive1581/track.rb +0 -100
- data/lib/badline/drive1581/track_bytes.rb +0 -75
- data/lib/badline/drive1581/wd1772/registers.rb +0 -89
- data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
- data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
- data/lib/badline/drive1581/wd1772/state.rb +0 -66
- data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
- data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
- data/lib/badline/drive1581/wd1772/turn.rb +0 -73
- data/lib/badline/drive1581/wd1772.rb +0 -216
- data/lib/badline/drive1581.rb +0 -233
- data/lib/badline/iec_bus.rb +0 -159
- data/lib/badline/instruction.rb +0 -334
- data/lib/badline/instruction_set/arithmetic.rb +0 -114
- data/lib/badline/instruction_set/bitwise.rb +0 -126
- data/lib/badline/instruction_set/branch.rb +0 -79
- data/lib/badline/instruction_set/flag.rb +0 -63
- data/lib/badline/instruction_set/illegal.rb +0 -270
- data/lib/badline/instruction_set/inc_dec.rb +0 -69
- data/lib/badline/instruction_set/stack.rb +0 -52
- data/lib/badline/instruction_set/transfer.rb +0 -137
- data/lib/badline/instruction_set.rb +0 -55
- data/lib/badline/interrupts.rb +0 -104
- data/lib/badline/joystick.rb +0 -25
- data/lib/badline/kernal_trap/channel.rb +0 -181
- data/lib/badline/keyboard.rb +0 -112
- data/lib/badline/ram_expansion/banking.rb +0 -30
- data/lib/badline/ram_expansion/plus256k.rb +0 -54
- data/lib/badline/ram_expansion/plus60k.rb +0 -43
- data/lib/badline/ram_expansion/unexpanded.rb +0 -28
- data/lib/badline/ram_expansion.rb +0 -21
- data/lib/badline/reu/dma/saved_state.rb +0 -50
- data/lib/badline/reu/dma.rb +0 -273
- data/lib/badline/reu/ram.rb +0 -107
- data/lib/badline/reu/saved_state.rb +0 -80
- data/lib/badline/reu/trigger.rb +0 -32
- data/lib/badline/reu.rb +0 -289
- data/lib/badline/sid/catch_up.rb +0 -120
- data/lib/badline/sid/decimator.rb +0 -64
- data/lib/badline/sid/envelope/state.rb +0 -68
- data/lib/badline/sid/envelope.rb +0 -239
- data/lib/badline/sid/filter.rb +0 -263
- data/lib/badline/sid/voice.rb +0 -77
- data/lib/badline/sid/waveform/combined.rb +0 -126
- data/lib/badline/sid/waveform/fast_forward.rb +0 -105
- data/lib/badline/sid/waveform/noise_writeback.rb +0 -122
- data/lib/badline/sid/waveform/state.rb +0 -66
- data/lib/badline/sid/waveform.rb +0 -305
- data/lib/badline/sid.rb +0 -303
- data/lib/badline/time_of_day.rb +0 -228
- data/lib/badline/traps.rb +0 -19
- data/lib/badline/via/control_lines.rb +0 -122
- data/lib/badline/via/fast_forward.rb +0 -53
- data/lib/badline/via/interrupt_register.rb +0 -67
- data/lib/badline/via/shift_register.rb +0 -180
- data/lib/badline/via/state.rb +0 -42
- data/lib/badline/via/timer1.rb +0 -131
- data/lib/badline/via/timer2.rb +0 -133
- data/lib/badline/via.rb +0 -266
- data/lib/badline/vic/bank.rb +0 -133
- data/lib/badline/vic/border_mask.rb +0 -86
- data/lib/badline/vic/collisions.rb +0 -115
- data/lib/badline/vic/color_patches.rb +0 -47
- data/lib/badline/vic/display_state.rb +0 -185
- data/lib/badline/vic/graphics_mode.rb +0 -164
- data/lib/badline/vic/graphics_shifter.rb +0 -207
- data/lib/badline/vic/register_log.rb +0 -81
- data/lib/badline/vic/registers.rb +0 -195
- data/lib/badline/vic/sequencer.rb +0 -275
- data/lib/badline/vic/sequencer_output.rb +0 -116
- data/lib/badline/vic/sequencer_state.rb +0 -89
- data/lib/badline/vic/sprite/internal_bus.rb +0 -68
- data/lib/badline/vic/sprite/saved_state.rb +0 -64
- data/lib/badline/vic/sprite/shifter.rb +0 -146
- data/lib/badline/vic/sprite/timing.rb +0 -56
- data/lib/badline/vic/sprite.rb +0 -337
- data/lib/badline/vic/sprites.rb +0 -282
- data/lib/badline/vic/sprites_state.rb +0 -57
- data/lib/badline/vic.rb +0 -853
- data/lib/badline/vic20/sound/output.rb +0 -83
- data/lib/badline/vic20/sound.rb +0 -233
- data/lib/badline/z80/arithmetic.rb +0 -117
- data/lib/badline/z80/bit_page.rb +0 -55
- data/lib/badline/z80/block_io.rb +0 -58
- data/lib/badline/z80/block_transfers.rb +0 -59
- data/lib/badline/z80/bus_cycles.rb +0 -111
- data/lib/badline/z80/core.rb +0 -113
- data/lib/badline/z80/exchanges.rb +0 -50
- data/lib/badline/z80/extended_page.rb +0 -89
- data/lib/badline/z80/flags.rb +0 -37
- data/lib/badline/z80/interrupt_acceptance.rb +0 -46
- data/lib/badline/z80/jumps.rb +0 -82
- data/lib/badline/z80/loads.rb +0 -98
- data/lib/badline/z80/main_page.rb +0 -134
- data/lib/badline/z80/registers.rb +0 -120
- data/lib/badline/z80/saved_state.rb +0 -69
- data/lib/badline/z80/shifts.rb +0 -64
- data/lib/badline/z80.rb +0 -11
- /data/lib/badline/snapshot/{fields.rb → vice/fields.rb} +0 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Drives
|
|
5
|
+
class Model1581
|
|
6
|
+
class WD1772
|
|
7
|
+
# The type III commands that take a whole turn, from one index pulse
|
|
8
|
+
# to the next:
|
|
9
|
+
#
|
|
10
|
+
# 11100hE00 read track every byte under the head (Track#raw)
|
|
11
|
+
# 11110hEP0 write track every byte the CPU sends, for a format
|
|
12
|
+
#
|
|
13
|
+
# Write track asks for its first byte at once and starts at the index
|
|
14
|
+
# pulse, giving up with LOST_DATA if the byte hasn't come three bytes
|
|
15
|
+
# later. $F5 writes a sync mark, an $A1, and the first of a run starts
|
|
16
|
+
# the CRC over; $F6 writes $C2; $F7 writes the CRC's two bytes. At
|
|
17
|
+
# the next index pulse the track under the head becomes the fields
|
|
18
|
+
# found in what went down (Track.parse).
|
|
19
|
+
module Tracks
|
|
20
|
+
LATE = 3
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def start_type3
|
|
25
|
+
@type1 = false
|
|
26
|
+
@status = 0
|
|
27
|
+
@drq = false
|
|
28
|
+
@mode = @command.anybits?(0x10) ? WRITE : READ
|
|
29
|
+
resume_track unless spinning_up?(TRACK_INDEX)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def resume_track
|
|
33
|
+
if @mode == WRITE
|
|
34
|
+
if @mechanism.write_protected?
|
|
35
|
+
@status |= PROTECTED
|
|
36
|
+
return finish
|
|
37
|
+
end
|
|
38
|
+
@drq = true
|
|
39
|
+
end
|
|
40
|
+
@phase = @mode == WRITE ? WRITE_TRACK_START : TRACK_INDEX
|
|
41
|
+
return wait_index(@phase) if @command.nobits?(SETTLE_DELAY)
|
|
42
|
+
|
|
43
|
+
@due = @now + SETTLE
|
|
44
|
+
@settling = true
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def wait_index(phase)
|
|
48
|
+
@settling = false
|
|
49
|
+
@phase = phase
|
|
50
|
+
@due = next_index
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def track_index
|
|
54
|
+
return wait_index(TRACK_INDEX) if @settling
|
|
55
|
+
|
|
56
|
+
@bytes = (@mechanism.track || Track.new([])).raw
|
|
57
|
+
@index = 0
|
|
58
|
+
@phase = READ_TRACK
|
|
59
|
+
@due = @now + BYTE
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def track_byte_read
|
|
63
|
+
@status |= LOST_DATA if @drq
|
|
64
|
+
@data = @bytes[@index]
|
|
65
|
+
@drq = true
|
|
66
|
+
@index += 1
|
|
67
|
+
@index == Track::LENGTH ? finish : @due += BYTE
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def write_track_start
|
|
71
|
+
return wait_index(WRITE_TRACK_START) if @settling
|
|
72
|
+
|
|
73
|
+
@bytes = []
|
|
74
|
+
@syncs = []
|
|
75
|
+
@crc = 0xffff
|
|
76
|
+
@phase = WRITE_TRACK
|
|
77
|
+
return track_byte_written unless @drq
|
|
78
|
+
|
|
79
|
+
@late = true
|
|
80
|
+
@due = @now + (LATE * BYTE)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# The next byte from the data register goes under the head, a 0
|
|
84
|
+
# where DRQ went unanswered.
|
|
85
|
+
def track_byte_written
|
|
86
|
+
return lost if @late && @drq
|
|
87
|
+
return track_written if @bytes.length >= Track::LENGTH
|
|
88
|
+
|
|
89
|
+
@late = false
|
|
90
|
+
value = @drq ? 0 : @data
|
|
91
|
+
@status |= LOST_DATA if @drq
|
|
92
|
+
@drq = true
|
|
93
|
+
before = @bytes.length
|
|
94
|
+
lay_byte(value)
|
|
95
|
+
@due = @now + ((@bytes.length - before) * BYTE)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def lay_byte(value)
|
|
99
|
+
case value
|
|
100
|
+
when 0xf5
|
|
101
|
+
@crc = 0xffff unless @syncs.last
|
|
102
|
+
push_byte(Track::SYNC, true)
|
|
103
|
+
when 0xf6 then push_byte(0xc2, false)
|
|
104
|
+
when 0xf7
|
|
105
|
+
crc = @crc
|
|
106
|
+
push_byte(crc >> 8, false)
|
|
107
|
+
push_byte(crc & 0xff, false)
|
|
108
|
+
else push_byte(value, false)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def push_byte(value, sync)
|
|
113
|
+
@bytes << value
|
|
114
|
+
@syncs << sync
|
|
115
|
+
@crc = Track.crc([value], @crc)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def track_written
|
|
119
|
+
@drq = false
|
|
120
|
+
@mechanism.write(Track.parse(@bytes.first(Track::LENGTH), @syncs))
|
|
121
|
+
finish
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Drives
|
|
5
|
+
class Model1581
|
|
6
|
+
class WD1772
|
|
7
|
+
# The disk turning under the head: the index pulses a phase waits
|
|
8
|
+
# for or counts, and the cycle the head comes to a place round the
|
|
9
|
+
# track.
|
|
10
|
+
module Turn
|
|
11
|
+
# The disk began or stopped turning: a phase waiting on the turn
|
|
12
|
+
# starts its wait again.
|
|
13
|
+
def spin_changed
|
|
14
|
+
case @phase
|
|
15
|
+
when SPIN_UP, MOTOR_IDLE, INDEX_INTERRUPT then count_index
|
|
16
|
+
when SEARCH then begin_search
|
|
17
|
+
when TRACK_INDEX, WRITE_TRACK_START then wait_index(@phase)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
# The motor starts: with h clear and the motor off, the command waits
|
|
24
|
+
# out six index pulses first, and the phase comes after them.
|
|
25
|
+
def spinning_up?(phase)
|
|
26
|
+
spin_up = !@motor_on && @command.nobits?(NO_SPIN_UP)
|
|
27
|
+
@motor_on = true
|
|
28
|
+
return false unless spin_up
|
|
29
|
+
|
|
30
|
+
@after_spin_up = phase
|
|
31
|
+
@phase = SPIN_UP
|
|
32
|
+
@count = 6
|
|
33
|
+
count_index
|
|
34
|
+
true
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Waits for @count index pulses, or for the disk to turn.
|
|
38
|
+
def count_index
|
|
39
|
+
@due = next_index
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def index_counted
|
|
43
|
+
@count -= 1
|
|
44
|
+
return @due += Mechanism::REVOLUTION if @count.positive?
|
|
45
|
+
|
|
46
|
+
case @phase
|
|
47
|
+
when SPIN_UP then spun_up
|
|
48
|
+
when MOTOR_IDLE
|
|
49
|
+
@motor_on = false
|
|
50
|
+
idle
|
|
51
|
+
else
|
|
52
|
+
@intrq = true
|
|
53
|
+
idle
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# The cycle the next index pulse starts, or NEVER while no disk turns.
|
|
58
|
+
def next_index = at_angle(0)
|
|
59
|
+
|
|
60
|
+
# The cycle the head next comes to +angle+, from the index.
|
|
61
|
+
def at_angle(angle)
|
|
62
|
+
return NEVER unless @mechanism.spinning?
|
|
63
|
+
|
|
64
|
+
delta = (angle - @mechanism.angle(@now)) % Mechanism::REVOLUTION
|
|
65
|
+
@now + (delta.zero? ? Mechanism::REVOLUTION : delta)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# The cycle the byte at +position+ round the track has passed under
|
|
69
|
+
# the head.
|
|
70
|
+
def byte_end(position) = at_angle(((position + 1) % Track::LENGTH) * BYTE)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "badline/drives/model1581/wd1772/registers"
|
|
4
|
+
require "badline/drives/model1581/wd1772/turn"
|
|
5
|
+
require "badline/drives/model1581/wd1772/stepping"
|
|
6
|
+
require "badline/drives/model1581/wd1772/sectors"
|
|
7
|
+
require "badline/drives/model1581/wd1772/sector_writes"
|
|
8
|
+
require "badline/drives/model1581/wd1772/tracks"
|
|
9
|
+
require "badline/drives/model1581/wd1772/saved_state"
|
|
10
|
+
|
|
11
|
+
module Badline
|
|
12
|
+
module Drives
|
|
13
|
+
class Model1581
|
|
14
|
+
# The WD1772 floppy disk controller at $6000, as the WD177x data sheet
|
|
15
|
+
# describes it, working on the Mechanism's Track at sector level: it
|
|
16
|
+
# finds ID and data fields where they lie round the turn and moves
|
|
17
|
+
# their bytes at the MFM double-density rate, a byte every 32 µs, but
|
|
18
|
+
# keeps no flux or bitstream.
|
|
19
|
+
#
|
|
20
|
+
# $6000 status (read), command (write)
|
|
21
|
+
# $6001 track
|
|
22
|
+
# $6002 sector
|
|
23
|
+
# $6003 data
|
|
24
|
+
#
|
|
25
|
+
# It runs on the drive's clock, 2 MHz here, so the data sheet's times,
|
|
26
|
+
# given for 8 MHz on the chip's clock pin, come out as BYTE cycles a
|
|
27
|
+
# byte, STEP_RATES between steps and SETTLE for the head to settle.
|
|
28
|
+
#
|
|
29
|
+
# A command runs as a chain of phases, each due at a cycle (@due): a
|
|
30
|
+
# step, an index pulse, the end of a byte under the head. Between them
|
|
31
|
+
# nothing happens, so cycle! only counts. BUSY sets as the command is
|
|
32
|
+
# written, and the chip takes it up START cycles later, 16 µs, so a
|
|
33
|
+
# command with nothing to do, such as a seek to the track the head is
|
|
34
|
+
# on, still shows BUSY to the DOS, which polls for it before waiting
|
|
35
|
+
# for it to clear.
|
|
36
|
+
#
|
|
37
|
+
# The 1581 leaves INTRQ and DRQ unconnected and polls the status
|
|
38
|
+
# register instead (schematic sheet 2), but both are here (intrq?,
|
|
39
|
+
# drq?). Its DOS sets h in every command, so the motor spin-up wait
|
|
40
|
+
# never runs; the spindle follows the 8520's /MOTOR line instead.
|
|
41
|
+
class WD1772
|
|
42
|
+
include Registers
|
|
43
|
+
include Turn
|
|
44
|
+
include Stepping
|
|
45
|
+
include Sectors
|
|
46
|
+
include SectorWrites
|
|
47
|
+
include Tracks
|
|
48
|
+
include SavedState
|
|
49
|
+
|
|
50
|
+
BYTE = 64
|
|
51
|
+
START = 32
|
|
52
|
+
STEP_RATES = [12_000, 24_000, 4_000, 6_000].freeze
|
|
53
|
+
SETTLE = 30_000
|
|
54
|
+
|
|
55
|
+
NEVER = 1 << 60
|
|
56
|
+
|
|
57
|
+
# Status bits. Bits 1 and 2 report the index pulse and track 0 after
|
|
58
|
+
# a type I command, and DRQ and lost data after the others; bit 5
|
|
59
|
+
# reports spin-up after a type I command and a deleted data mark
|
|
60
|
+
# after a read.
|
|
61
|
+
BUSY = 0x01
|
|
62
|
+
INDEX = 0x02
|
|
63
|
+
DATA_REQUEST = 0x02
|
|
64
|
+
TRACK0 = 0x04
|
|
65
|
+
LOST_DATA = 0x04
|
|
66
|
+
CRC_ERROR = 0x08
|
|
67
|
+
NOT_FOUND = 0x10
|
|
68
|
+
SPUN_UP = 0x20
|
|
69
|
+
DELETED = 0x20
|
|
70
|
+
PROTECTED = 0x40
|
|
71
|
+
MOTOR_ON = 0x80
|
|
72
|
+
|
|
73
|
+
# Command flags.
|
|
74
|
+
NO_SPIN_UP = 0x08
|
|
75
|
+
VERIFY = 0x04
|
|
76
|
+
SETTLE_DELAY = 0x04
|
|
77
|
+
MULTIPLE = 0x10
|
|
78
|
+
UPDATE = 0x10
|
|
79
|
+
DELETED_MARK = 0x01
|
|
80
|
+
|
|
81
|
+
# Phases.
|
|
82
|
+
IDLE = 0
|
|
83
|
+
SPIN_UP = 1
|
|
84
|
+
STEPPED = 2
|
|
85
|
+
SETTLED = 3
|
|
86
|
+
SEARCH = 4
|
|
87
|
+
READ_DATA = 5
|
|
88
|
+
WRITE_GATE = 6
|
|
89
|
+
WRITE_DATA = 7
|
|
90
|
+
READ_TRACK = 8
|
|
91
|
+
TRACK_INDEX = 9
|
|
92
|
+
WRITE_TRACK = 10
|
|
93
|
+
MOTOR_IDLE = 11
|
|
94
|
+
INDEX_INTERRUPT = 12
|
|
95
|
+
SETTLE_SEARCH = 13
|
|
96
|
+
READ_ADDRESS = 14
|
|
97
|
+
WRITE_TRACK_START = 15
|
|
98
|
+
STARTING = 16
|
|
99
|
+
|
|
100
|
+
# What a search for an ID field is for.
|
|
101
|
+
READ = 0
|
|
102
|
+
WRITE = 1
|
|
103
|
+
ADDRESS = 2
|
|
104
|
+
VERIFY_TRACK = 3
|
|
105
|
+
|
|
106
|
+
attr_reader :now, :track, :sector, :data, :command
|
|
107
|
+
|
|
108
|
+
def initialize(mechanism)
|
|
109
|
+
@mechanism = mechanism
|
|
110
|
+
@now = 0
|
|
111
|
+
@due = NEVER
|
|
112
|
+
@phase = IDLE
|
|
113
|
+
reset!
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# The MR line: the registers as the data sheet leaves them, $03 in
|
|
117
|
+
# the command register and 1 in the sector register, and no command
|
|
118
|
+
# running.
|
|
119
|
+
def reset!
|
|
120
|
+
@command = 0x03
|
|
121
|
+
@track = 0
|
|
122
|
+
@sector = 1
|
|
123
|
+
@data = 0
|
|
124
|
+
@status = 0
|
|
125
|
+
@type1 = true
|
|
126
|
+
@drq = false
|
|
127
|
+
@intrq = false
|
|
128
|
+
@motor_on = false
|
|
129
|
+
@inward = true
|
|
130
|
+
clear_command
|
|
131
|
+
idle
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def cycle!
|
|
135
|
+
@now += 1
|
|
136
|
+
advance if @now == @due
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# How many cycles can go by before the next phase is due.
|
|
140
|
+
def quiet_cycles = @due - @now - 1
|
|
141
|
+
|
|
142
|
+
# Runs +cycles+ cycles at once, as many as quiet_cycles allows.
|
|
143
|
+
def fast_forward(cycles)
|
|
144
|
+
@now += cycles
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def busy? = @phase != IDLE && @phase != MOTOR_IDLE && @phase != INDEX_INTERRUPT
|
|
148
|
+
|
|
149
|
+
def drq? = @drq
|
|
150
|
+
|
|
151
|
+
def intrq? = @intrq
|
|
152
|
+
|
|
153
|
+
def motor_on? = @motor_on
|
|
154
|
+
|
|
155
|
+
private
|
|
156
|
+
|
|
157
|
+
# A command ends: INTRQ, and the motor turns off after nine more
|
|
158
|
+
# index pulses unless a command comes first.
|
|
159
|
+
def finish
|
|
160
|
+
@intrq = true
|
|
161
|
+
@phase = MOTOR_IDLE
|
|
162
|
+
@count = 9
|
|
163
|
+
count_index
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# What a command keeps between its phases.
|
|
167
|
+
def clear_command
|
|
168
|
+
@steps = 0
|
|
169
|
+
@count = 0
|
|
170
|
+
@after_spin_up = IDLE
|
|
171
|
+
@mode = 0
|
|
172
|
+
@deadline = NEVER
|
|
173
|
+
@id_at = NEVER
|
|
174
|
+
@found = -1
|
|
175
|
+
@bytes = []
|
|
176
|
+
@syncs = []
|
|
177
|
+
@index = 0
|
|
178
|
+
@crc = 0xffff
|
|
179
|
+
@crc_good = true
|
|
180
|
+
@write_id = 0
|
|
181
|
+
@size = 0
|
|
182
|
+
@gate_open = false
|
|
183
|
+
@late = false
|
|
184
|
+
@settling = false
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def idle
|
|
188
|
+
@phase = IDLE
|
|
189
|
+
@due = NEVER
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def advance
|
|
193
|
+
case @phase
|
|
194
|
+
when STARTING then start_command
|
|
195
|
+
when SPIN_UP, MOTOR_IDLE, INDEX_INTERRUPT then index_counted
|
|
196
|
+
when STEPPED then step_done
|
|
197
|
+
when SETTLED then verify_track
|
|
198
|
+
when SETTLE_SEARCH then begin_search
|
|
199
|
+
when SEARCH then id_passed
|
|
200
|
+
when READ_DATA, READ_ADDRESS then byte_read
|
|
201
|
+
else advance_write
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def advance_write
|
|
206
|
+
case @phase
|
|
207
|
+
when WRITE_GATE then write_gate
|
|
208
|
+
when WRITE_DATA then byte_written
|
|
209
|
+
when READ_TRACK then track_byte_read
|
|
210
|
+
when TRACK_INDEX then track_index
|
|
211
|
+
when WRITE_TRACK_START then write_track_start
|
|
212
|
+
when WRITE_TRACK then track_byte_written
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "badline/drives/engine"
|
|
4
|
+
require "badline/drives/model1581/track"
|
|
5
|
+
require "badline/drives/model1581/track_bytes"
|
|
6
|
+
require "badline/drives/model1581/disk"
|
|
7
|
+
require "badline/drives/model1581/mechanism"
|
|
8
|
+
require "badline/drives/model1581/wd1772"
|
|
9
|
+
require "badline/drives/model1581/cpu"
|
|
10
|
+
require "badline/drives/model1581/serial_port"
|
|
11
|
+
require "badline/drives/model1581/bus"
|
|
12
|
+
require "badline/drives/model1581/saved_state"
|
|
13
|
+
|
|
14
|
+
module Badline
|
|
15
|
+
module Drives
|
|
16
|
+
# The 1581 3.5" disk drive: a 6502 at 2 MHz with 8 KB of RAM, an 8520
|
|
17
|
+
# for the serial bus and the mechanism's lines, a WD1772 for the MFM
|
|
18
|
+
# disk, and the DOS in 32 KB of ROM (1581 Service Manual). Drives::Engine::Core
|
|
19
|
+
# clocks it against the host.
|
|
20
|
+
#
|
|
21
|
+
# The 8520's port B faces the serial bus as VIA 1's does on the 1541,
|
|
22
|
+
# with the same bits, and ATN reaches its FLAG pin, so ATN going low
|
|
23
|
+
# interrupts the DOS. Its SP and CNT carry fast serial on DATA and SRQ,
|
|
24
|
+
# through buffers PB5 turns round (Drives::Engine::FastSerial), as the 1571's
|
|
25
|
+
# 6526 does. The ATN acknowledge differs: a NAND of ATN IN and
|
|
26
|
+
# ATN ACK pulls DATA, so DATA follows ATN only while ATN is asserted
|
|
27
|
+
# and PB4 is high, where the 1541's XOR pulls it whenever the two
|
|
28
|
+
# differ (Drives::SerialBus::DRIVE_ATN_GATED). Port A drives the motor, the side
|
|
29
|
+
# and the two LEDs, and reads the switches and the mechanism's /RDY and
|
|
30
|
+
# /DISK CHNG (SerialPort). Timer B interrupts every 10 ms for the
|
|
31
|
+
# controller code that runs the WD1772.
|
|
32
|
+
#
|
|
33
|
+
# The 8520 differs from the 6526 in its TOD, a 24-bit binary event
|
|
34
|
+
# counter where the 6526 keeps a BCD clock. The 1581 holds the TOD pin
|
|
35
|
+
# high when it carries a WD1772 (jumper J1 out), so the counter never
|
|
36
|
+
# counts, and the DOS's one use of it, writing $00 to the low byte and
|
|
37
|
+
# reading it back 20 µs later to tell a WD1770 from a WD1772, reads $00
|
|
38
|
+
# on either chip: the drive's CIA gets no TOD pulses (CIA's tod_hz).
|
|
39
|
+
class Model1581
|
|
40
|
+
include Engine::Core
|
|
41
|
+
include Engine::FastSerial
|
|
42
|
+
include SavedState
|
|
43
|
+
|
|
44
|
+
CLOCK_HZ = 2_000_000
|
|
45
|
+
|
|
46
|
+
# Where the DOS's idle loop starts over (see Drives::Engine::Idle).
|
|
47
|
+
IDLE_LOOP = 0xb105
|
|
48
|
+
|
|
49
|
+
# The host cycles, at about 1 MHz, by which a 1581 switched on with the
|
|
50
|
+
# machine has run its DOS's reset, the RAM test, the ROM checksum and
|
|
51
|
+
# the controller's half-second wait, and waits on the bus: 2.32 s,
|
|
52
|
+
# with a margin.
|
|
53
|
+
BOOT_CYCLES = 2_700_000
|
|
54
|
+
|
|
55
|
+
# The 8520's port A outputs.
|
|
56
|
+
SIDE = 0x01
|
|
57
|
+
MOTOR = 0x04
|
|
58
|
+
POWER_LED = 0x20
|
|
59
|
+
ACTIVITY_LED = 0x40
|
|
60
|
+
|
|
61
|
+
# Port B's ATN acknowledge, and the fast serial direction.
|
|
62
|
+
ATN_ACK = 0x10
|
|
63
|
+
FAST_SERIAL_OUT = 0x20
|
|
64
|
+
|
|
65
|
+
def cia
|
|
66
|
+
settle!
|
|
67
|
+
@cia
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def fdc
|
|
71
|
+
settle!
|
|
72
|
+
@fdc
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def model_name = "1581"
|
|
76
|
+
|
|
77
|
+
# +rom+ covers $8000-$FFFF, and defaults to the DOS image in the ROM
|
|
78
|
+
# path. +device+ is the number the switches on port A's PA3 and PA4
|
|
79
|
+
# set, 8 to 11.
|
|
80
|
+
def initialize(rom: nil, host_clock_hz: Model1541::CLOCK_HZ, device: 8, debug: false)
|
|
81
|
+
@device = device
|
|
82
|
+
@clock_hz = CLOCK_HZ
|
|
83
|
+
@mechanism = Mechanism.new
|
|
84
|
+
@fdc = WD1772.new(@mechanism)
|
|
85
|
+
@serial_port = SerialPort.new(@mechanism, device:)
|
|
86
|
+
@cia = Chips::CIA.new(start: 0x4000, peripheral: @serial_port, tod_hz: 0)
|
|
87
|
+
@bus = Bus.new(rom: rom || ROM.load("dos1581.rom", 0x8000), cia: @cia, fdc: @fdc, drive: self)
|
|
88
|
+
@cpu = CPU.new(@bus, debug:)
|
|
89
|
+
@idle_loop = IDLE_LOOP
|
|
90
|
+
@host_clock_hz = host_clock_hz
|
|
91
|
+
@phase = 0
|
|
92
|
+
@cycles = 0
|
|
93
|
+
@serial_bus = nil
|
|
94
|
+
@atn = false
|
|
95
|
+
@activity = false
|
|
96
|
+
@power = false
|
|
97
|
+
init_fast_serial
|
|
98
|
+
init_idle(debug)
|
|
99
|
+
ports_written
|
|
100
|
+
connect(SerialBus.new)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# The serial bus's RESET line reaches the CPU, the 8520 and the
|
|
104
|
+
# WD1772. RAM keeps its contents.
|
|
105
|
+
def reset!
|
|
106
|
+
settle!
|
|
107
|
+
@cia.reset!
|
|
108
|
+
@fdc.reset!
|
|
109
|
+
ports_written
|
|
110
|
+
@cpu.reset!
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def insert(disk)
|
|
114
|
+
settle!
|
|
115
|
+
@mechanism.insert(disk, @fdc.now)
|
|
116
|
+
@fdc.spin_changed
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Puts in a Disk from the .d81 image at +path+, write-protected with
|
|
120
|
+
# `read_only`.
|
|
121
|
+
def insert_image(path, read_only: false)
|
|
122
|
+
insert(Disk.open(path, read_only:))
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Whether the activity LED is lit. The power LED stays lit, and
|
|
126
|
+
# flashes on an error.
|
|
127
|
+
def led_on? = @activity
|
|
128
|
+
|
|
129
|
+
def power_led_on? = @power
|
|
130
|
+
|
|
131
|
+
# The 8520's port B as it drives the serial bus, in VIA 1's bits, the
|
|
132
|
+
# ATN acknowledge turned round for the NAND that gates it, with the
|
|
133
|
+
# fast serial pins above it. It holds still while the drive sleeps, so
|
|
134
|
+
# reading it leaves the drive asleep.
|
|
135
|
+
def serial_output
|
|
136
|
+
lines = @cia.port_b_lines
|
|
137
|
+
output = (lines & (SerialBus::DRIVE_DATA_OUT | SerialBus::DRIVE_CLK_OUT)) | SerialBus::DRIVE_ATN_GATED |
|
|
138
|
+
@fast_output
|
|
139
|
+
lines.anybits?(ATN_ACK) ? output : output | SerialBus::DRIVE_ATNA
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# The 8520's ports drive the motor, the side, the LEDs and the fast
|
|
143
|
+
# serial buffers: the drive follows them after every write to a port
|
|
144
|
+
# or direction register.
|
|
145
|
+
def ports_written
|
|
146
|
+
fast_serial_out = @cia.port_b_lines.anybits?(FAST_SERIAL_OUT)
|
|
147
|
+
turn_fast_serial(fast_serial_out) if fast_serial_out != @fast_serial_out
|
|
148
|
+
lines = @cia.port_a_lines
|
|
149
|
+
@mechanism.side = lines.anybits?(SIDE) ? 1 : 0
|
|
150
|
+
@activity = lines.anybits?(ACTIVITY_LED)
|
|
151
|
+
@power = lines.anybits?(POWER_LED)
|
|
152
|
+
motor = lines.nobits?(MOTOR)
|
|
153
|
+
return if motor == @mechanism.motor_on?
|
|
154
|
+
|
|
155
|
+
@mechanism.motor(motor, @fdc.now)
|
|
156
|
+
@fdc.spin_changed
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
private
|
|
160
|
+
|
|
161
|
+
# One drive cycle: ATN going low pulls FLAG, the WD1772 and the 8520
|
|
162
|
+
# clock ahead of the CPU, and the 8520 alone pulls IRQ.
|
|
163
|
+
def step
|
|
164
|
+
atn = @serial_port.atn_low?
|
|
165
|
+
if atn != @atn
|
|
166
|
+
@atn = atn
|
|
167
|
+
@cia.flag! if atn
|
|
168
|
+
end
|
|
169
|
+
@fdc.cycle!
|
|
170
|
+
@cia.cycle!
|
|
171
|
+
drive_fast_serial if @fast_serial_out
|
|
172
|
+
@cpu.irq = @cia.interrupted?
|
|
173
|
+
@cpu.cycle!
|
|
174
|
+
@cycles += 1
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def hear_atn
|
|
178
|
+
@atn = @serial_port.atn_low?
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# A pass of the idle loop reads and writes RAM alone, so it repeats
|
|
182
|
+
# while the 8520 pulls no IRQ, for as long as the 8520's counters and
|
|
183
|
+
# the WD1772's next phase leave room: until timer B's next interrupt
|
|
184
|
+
# for the controller code. Neither chip changes but by the clock, so
|
|
185
|
+
# only the CPU is compared.
|
|
186
|
+
def busy_for_pass? = @cia.interrupted?
|
|
187
|
+
|
|
188
|
+
def quiet_cycles = [@cia.quiet_cycles, @fdc.quiet_cycles].min
|
|
189
|
+
|
|
190
|
+
def idle_state = [*@cpu.idle_state, @bus.data, @atn]
|
|
191
|
+
|
|
192
|
+
def fast_forward_chips(cycles)
|
|
193
|
+
@cia.fast_forward(cycles)
|
|
194
|
+
@fdc.fast_forward(cycles)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Every timer B interrupt reads the 8520, so no orbit (Drives::Engine::Orbit)
|
|
198
|
+
# comes round, and the drive keeps no anchors.
|
|
199
|
+
def anchor = nil
|
|
200
|
+
|
|
201
|
+
def counter_state(_touched) = []
|
|
202
|
+
|
|
203
|
+
def skip_chip_orbits(_cycles, _touched) = nil
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|