badline 0.12.0 → 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 +25 -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 +4 -4
- 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} +6 -6
- data/lib/badline/c128/bus.rb +30 -51
- 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 +18 -72
- data/lib/badline/{computer → c64}/attachments.rb +16 -47
- 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/c64/common.rb +34 -0
- data/lib/badline/c64/kernal_traps.rb +89 -0
- 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 +20 -31
- data/lib/badline/{computer.rb → c64.rb} +22 -80
- 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 +27 -29
- 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 +10 -61
- 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/{file.rb → file_routine.rb} +1 -1
- data/lib/badline/kernal_trap/load.rb +6 -6
- data/lib/badline/kernal_trap/save.rb +5 -5
- data/lib/badline/kernal_trap/serial.rb +7 -7
- data/lib/badline/kernal_trap.rb +2 -3
- data/lib/badline/machine/clocking.rb +50 -0
- data/lib/badline/machine.rb +63 -7
- data/lib/badline/media/boot_disk.rb +2 -2
- data/lib/badline/media/disk_list.rb +3 -3
- data/lib/badline/media/disk_set.rb +1 -1
- data/lib/badline/media/extensions.rb +33 -0
- data/lib/badline/media/program.rb +28 -0
- data/lib/badline/media/true_drive.rb +4 -3
- data/lib/badline/media/tune.rb +35 -0
- data/lib/badline/media/vic20_cartridge.rb +1 -7
- data/lib/badline/media/vic20_media.rb +38 -80
- data/lib/badline/media.rb +84 -81
- data/lib/badline/model.rb +1 -1
- data/lib/badline/options/event.rb +3 -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 +10 -2
- data/lib/badline/snapshot/setup.rb +22 -66
- data/lib/badline/snapshot/state.rb +8 -17
- 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 +13 -12
- data/lib/badline/storage/d64_image.rb +15 -9
- data/lib/badline/storage/d71_image.rb +0 -2
- data/lib/badline/storage/d81_image.rb +0 -2
- data/lib/badline/storage/disk_image/writing.rb +2 -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 +11 -81
- 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 -60
- data/lib/badline/vic20/user_via_ports.rb +2 -2
- data/lib/badline/vic20.rb +20 -51
- metadata +250 -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 -72
- data/lib/badline/address_bus/sid_slots.rb +0 -42
- data/lib/badline/address_bus.rb +0 -235
- 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/computer/kernal_traps.rb +0 -29
- 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/cycleable.rb +0 -38
- 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 -318
- data/lib/badline/drive1541/disk_state.rb +0 -94
- 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 -852
- 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,102 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Drives
|
|
5
|
+
class Model1581
|
|
6
|
+
# One side of a cylinder as the WD1772 finds it: its sectors, each an
|
|
7
|
+
# ID field and a data field at a place round the turn, counted in
|
|
8
|
+
# bytes from the index pulse. The disk turns at 300 rpm and the bits
|
|
9
|
+
# pass at 250 kbit/s, so a turn is LENGTH bytes of 32 µs. The bytes
|
|
10
|
+
# between the fields, the gaps and the sync marks, are not kept: a
|
|
11
|
+
# read track lays them out again (raw).
|
|
12
|
+
#
|
|
13
|
+
# A standard track is the one the 1581 DOS formats (its format routine,
|
|
14
|
+
# and the 1581 Service Manual's per-sector organization): 32 bytes of
|
|
15
|
+
# $4E after the index, then ten 512-byte sectors numbered from 1, each
|
|
16
|
+
#
|
|
17
|
+
# 12 x $00, 3 x $A1, $FE, track, side, sector, size code, CRC,
|
|
18
|
+
# 22 x $4E, 12 x $00, 3 x $A1, $FB, 512 data bytes, CRC,
|
|
19
|
+
# 35 x $4E
|
|
20
|
+
#
|
|
21
|
+
# and $4E to the index. A write track lays down whatever the CPU sends,
|
|
22
|
+
# and parse finds its fields again.
|
|
23
|
+
class Track
|
|
24
|
+
LENGTH = 6250
|
|
25
|
+
GAP = 0x4e
|
|
26
|
+
SYNC = 0xa1
|
|
27
|
+
ID_MARK = 0xfe
|
|
28
|
+
DATA_MARK = 0xfb
|
|
29
|
+
DELETED_MARK = 0xf8
|
|
30
|
+
|
|
31
|
+
SECTORS = 10
|
|
32
|
+
SECTOR_SIZE = 512
|
|
33
|
+
SIZE_CODE = 2
|
|
34
|
+
|
|
35
|
+
# Where the first sector's ID mark lies, and how far apart the
|
|
36
|
+
# sectors are.
|
|
37
|
+
FIRST_ID = 32 + 15
|
|
38
|
+
SECTOR_SPACING = 574 + 35
|
|
39
|
+
|
|
40
|
+
# From an ID mark to its data mark.
|
|
41
|
+
DATA_OFFSET = 44
|
|
42
|
+
|
|
43
|
+
# How far after an ID field's CRC a data mark still belongs to it
|
|
44
|
+
# (WD177x data sheet).
|
|
45
|
+
DATA_MARK_WINDOW = 43
|
|
46
|
+
|
|
47
|
+
# An ID or data field: its mark's place, its bytes, whether its CRC
|
|
48
|
+
# reads back, and for a data field whether its mark is the deleted
|
|
49
|
+
# one.
|
|
50
|
+
Field = Struct.new(:mark, :bytes, :good, :deleted)
|
|
51
|
+
|
|
52
|
+
# A sector: its ID field and its data field, or nil where none
|
|
53
|
+
# follows the ID.
|
|
54
|
+
Sector = Struct.new(:id, :data)
|
|
55
|
+
|
|
56
|
+
# The CRC-CCITT the WD1772 writes after each field, over the field
|
|
57
|
+
# from its first $A1: x^16 + x^12 + x^5 + 1 from $FFFF.
|
|
58
|
+
def self.crc(bytes, crc = 0xffff)
|
|
59
|
+
bytes.each do |byte|
|
|
60
|
+
crc ^= byte << 8
|
|
61
|
+
8.times { crc = crc.anybits?(0x8000) ? ((crc << 1) ^ 0x1021) & 0xffff : (crc << 1) & 0xffff }
|
|
62
|
+
end
|
|
63
|
+
crc
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# A field's CRC as the two bytes written after it: the mark and
|
|
67
|
+
# +bytes+, behind three $A1s.
|
|
68
|
+
def self.field_crc(mark, bytes)
|
|
69
|
+
crc = crc([SYNC, SYNC, SYNC, mark] + bytes)
|
|
70
|
+
[crc >> 8, crc & 0xff]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# A standard track for +cylinder+ and +side+, each sector's data the
|
|
74
|
+
# block yields for its number, 1 to 10.
|
|
75
|
+
def self.standard(cylinder, side)
|
|
76
|
+
sectors = Array.new(SECTORS) do |index|
|
|
77
|
+
mark = FIRST_ID + (index * SECTOR_SPACING)
|
|
78
|
+
id = Field.new(mark, [cylinder, side, index + 1, SIZE_CODE], true, false)
|
|
79
|
+
Sector.new(id, Field.new(mark + DATA_OFFSET, yield(index + 1), true, false))
|
|
80
|
+
end
|
|
81
|
+
new(sectors)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
attr_reader :sectors
|
|
85
|
+
|
|
86
|
+
def initialize(sectors)
|
|
87
|
+
@sectors = sectors
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# The first sector whose ID mark lies at or after +position+, round
|
|
91
|
+
# from the index if none does, or nil on a track without IDs.
|
|
92
|
+
def next_id(position)
|
|
93
|
+
@sectors.find { |sector| sector.id.mark >= position } || @sectors.first
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# The sector with the ID field +id+, track, side, sector and size
|
|
97
|
+
# code, or nil.
|
|
98
|
+
def sector(id) = @sectors.find { |sector| sector.id.bytes == id }
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Drives
|
|
5
|
+
class Model1581
|
|
6
|
+
class Track
|
|
7
|
+
# A Track as the bytes going round under the head, for the WD1772's
|
|
8
|
+
# read track: its fields with their gaps and sync marks.
|
|
9
|
+
module Bytes
|
|
10
|
+
# The track's LENGTH bytes from the index: $4E gaps, and before each
|
|
11
|
+
# field 12 x $00 and three $A1 sync marks, its mark, its bytes and
|
|
12
|
+
# its CRC, spoiled where the field's CRC doesn't read back.
|
|
13
|
+
def raw
|
|
14
|
+
bytes = Array.new(LENGTH, GAP)
|
|
15
|
+
@sectors.each do |sector|
|
|
16
|
+
lay(bytes, sector.id, ID_MARK)
|
|
17
|
+
data = sector.data
|
|
18
|
+
lay(bytes, data, data.deleted ? DELETED_MARK : DATA_MARK) if data
|
|
19
|
+
end
|
|
20
|
+
bytes
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def lay(bytes, field, mark)
|
|
26
|
+
start = field.mark - 15
|
|
27
|
+
crc = Track.field_crc(mark, field.bytes)
|
|
28
|
+
crc[1] ^= 0xff unless field.good
|
|
29
|
+
[*Array.new(12, 0), SYNC, SYNC, SYNC, mark, *field.bytes, *crc].each_with_index do |byte, i|
|
|
30
|
+
bytes[start + i] = byte if start + i < LENGTH
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Finding the fields in the bytes a write track laid down.
|
|
36
|
+
module Parse
|
|
37
|
+
# Every sector in +bytes+, a turn as a write track laid it down,
|
|
38
|
+
# where +syncs+ marks the $A1s written as sync marks: an ID mark
|
|
39
|
+
# behind three of them, its four bytes and CRC, and the data field
|
|
40
|
+
# that follows it within DATA_MARK_WINDOW bytes, its length from
|
|
41
|
+
# the ID's size code.
|
|
42
|
+
def parse(bytes, syncs)
|
|
43
|
+
sectors = []
|
|
44
|
+
position = 0
|
|
45
|
+
while (mark = find_mark(bytes, syncs, position...bytes.length, ID_MARK..ID_MARK))
|
|
46
|
+
id = read_field(bytes, mark, 4)
|
|
47
|
+
position = mark + 7
|
|
48
|
+
data_mark = find_mark(bytes, syncs, position...(position + DATA_MARK_WINDOW), DELETED_MARK..DATA_MARK)
|
|
49
|
+
sectors << Sector.new(id, data_mark && read_field(bytes, data_mark, 128 << (id.bytes[3] & 3)))
|
|
50
|
+
end
|
|
51
|
+
new(sectors)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
# The first place in +range+ that holds one of +marks+ behind three
|
|
57
|
+
# sync marks.
|
|
58
|
+
def find_mark(bytes, syncs, range, marks)
|
|
59
|
+
([range.first, 3].max...[range.end, bytes.length].min).find do |at|
|
|
60
|
+
marks.cover?(bytes[at]) && syncs[at - 1] && syncs[at - 2] && syncs[at - 3]
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def read_field(bytes, mark, length)
|
|
65
|
+
field = bytes[mark + 1, length] || []
|
|
66
|
+
field += Array.new(length - field.length, 0)
|
|
67
|
+
crc = bytes[mark + 1 + length, 2] || []
|
|
68
|
+
Field.new(mark, field, crc == Track.field_crc(bytes[mark], field), bytes[mark] < 0xfa)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
include Bytes
|
|
73
|
+
extend Parse
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Drives
|
|
5
|
+
class Model1581
|
|
6
|
+
class WD1772
|
|
7
|
+
# The four registers as the CPU reaches them, and a command written
|
|
8
|
+
# to the command register.
|
|
9
|
+
module Registers
|
|
10
|
+
# Register +offset+, 0 to 3.
|
|
11
|
+
def peek(offset)
|
|
12
|
+
case offset
|
|
13
|
+
when 0 then status
|
|
14
|
+
when 1 then @track
|
|
15
|
+
when 2 then @sector
|
|
16
|
+
else read_data
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def poke(offset, value)
|
|
21
|
+
case offset
|
|
22
|
+
when 0 then write_command(value)
|
|
23
|
+
when 1 then @track = value unless busy?
|
|
24
|
+
when 2 then @sector = value unless busy?
|
|
25
|
+
else write_data(value)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# The status register, which clears INTRQ: after a type I command
|
|
30
|
+
# bits 1, 2, 5 and 6 follow the index sensor, the track 0 sensor, the
|
|
31
|
+
# spin-up and the write-protect line as they are now.
|
|
32
|
+
def status
|
|
33
|
+
@intrq = false
|
|
34
|
+
value = @status | (@motor_on ? MOTOR_ON : 0) | (busy? ? BUSY : 0)
|
|
35
|
+
return value | (@drq ? DATA_REQUEST : 0) unless @type1
|
|
36
|
+
|
|
37
|
+
value |= PROTECTED if @mechanism.write_protected?
|
|
38
|
+
value |= TRACK0 if @mechanism.track0?
|
|
39
|
+
value | (@mechanism.index?(@now) ? INDEX : 0)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def read_data
|
|
45
|
+
@drq = false
|
|
46
|
+
@data
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def write_data(value)
|
|
50
|
+
@drq = false
|
|
51
|
+
@data = value
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# A command while busy goes nowhere, but for a force interrupt.
|
|
55
|
+
def write_command(value)
|
|
56
|
+
@intrq = false
|
|
57
|
+
return force_interrupt(value) if value & 0xf0 == 0xd0
|
|
58
|
+
return if busy?
|
|
59
|
+
|
|
60
|
+
@command = value
|
|
61
|
+
@phase = STARTING
|
|
62
|
+
@due = @now + START
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def start_command
|
|
66
|
+
if @command < 0x80 then start_type1
|
|
67
|
+
elsif @command < 0xc0 then start_type2
|
|
68
|
+
elsif @command & 0xf0 == 0xc0 then start_read_address
|
|
69
|
+
else start_type3
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Stops a command where it is, leaving its status but for BUSY, or
|
|
74
|
+
# with none running switches the status to type I. I3 interrupts at
|
|
75
|
+
# once and I2 at the next index pulse.
|
|
76
|
+
def force_interrupt(value)
|
|
77
|
+
@type1 = true unless busy?
|
|
78
|
+
@drq = false
|
|
79
|
+
idle
|
|
80
|
+
@intrq = true if value.anybits?(0x08)
|
|
81
|
+
return unless value.anybits?(0x04)
|
|
82
|
+
|
|
83
|
+
@phase = INDEX_INTERRUPT
|
|
84
|
+
@count = 1
|
|
85
|
+
count_index
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Drives
|
|
5
|
+
class Model1581
|
|
6
|
+
class WD1772
|
|
7
|
+
# Saving and restoring the WD1772 for a snapshot: its registers and
|
|
8
|
+
# lines, and the command running, down to the byte it is at.
|
|
9
|
+
module SavedState
|
|
10
|
+
def save_state(out)
|
|
11
|
+
[@now, @due, @phase, @command, @track, @sector, @data, @status, @steps, @count, @after_spin_up, @mode,
|
|
12
|
+
@deadline, @id_at, @found, @index, @crc, @write_id, @size].each { |value| out.int(value) }
|
|
13
|
+
[@type1, @drq, @intrq, @motor_on, @inward, @crc_good, @gate_open, @late,
|
|
14
|
+
@settling].each { |flag| out.boolean(flag) }
|
|
15
|
+
out.ints(@bytes).ints(@syncs.map { |sync| sync ? 1 : 0 })
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def load_state(input)
|
|
19
|
+
load_registers(input)
|
|
20
|
+
load_command(input)
|
|
21
|
+
load_flags(input)
|
|
22
|
+
@bytes = input.ints
|
|
23
|
+
@syncs = input.ints.map { |sync| sync == 1 }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def load_registers(input)
|
|
29
|
+
@now = input.int
|
|
30
|
+
@due = input.int
|
|
31
|
+
@phase = input.int
|
|
32
|
+
@command = input.int
|
|
33
|
+
@track = input.int
|
|
34
|
+
@sector = input.int
|
|
35
|
+
@data = input.int
|
|
36
|
+
@status = input.int
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def load_command(input)
|
|
40
|
+
@steps = input.int
|
|
41
|
+
@count = input.int
|
|
42
|
+
@after_spin_up = input.int
|
|
43
|
+
@mode = input.int
|
|
44
|
+
@deadline = input.int
|
|
45
|
+
@id_at = input.int
|
|
46
|
+
@found = input.int
|
|
47
|
+
@index = input.int
|
|
48
|
+
@crc = input.int
|
|
49
|
+
@write_id = input.int
|
|
50
|
+
@size = input.int
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def load_flags(input)
|
|
54
|
+
@type1 = input.boolean?
|
|
55
|
+
@drq = input.boolean?
|
|
56
|
+
@intrq = input.boolean?
|
|
57
|
+
@motor_on = input.boolean?
|
|
58
|
+
@inward = input.boolean?
|
|
59
|
+
@crc_good = input.boolean?
|
|
60
|
+
@gate_open = input.boolean?
|
|
61
|
+
@late = input.boolean?
|
|
62
|
+
@settling = input.boolean?
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Drives
|
|
5
|
+
class Model1581
|
|
6
|
+
class WD1772
|
|
7
|
+
# Write sector, once Sectors has found the ID: it asks for the first
|
|
8
|
+
# byte 2 bytes after the ID's CRC and gives up at 22 with LOST_DATA,
|
|
9
|
+
# then writes the data field where a format puts it, behind 12 x $00
|
|
10
|
+
# and three $A1s, its mark deleted with a, a byte of 0 for each one
|
|
11
|
+
# the CPU missed, and the CRC and a $FF after the last.
|
|
12
|
+
module SectorWrites
|
|
13
|
+
WRITE_REQUEST = 2
|
|
14
|
+
WRITE_DEADLINE = 22
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def write_sector(sector)
|
|
19
|
+
@write_id = sector.id.mark
|
|
20
|
+
@size = 128 << (sector.id.bytes[3] & 0x03)
|
|
21
|
+
@gate_open = false
|
|
22
|
+
@phase = WRITE_GATE
|
|
23
|
+
@due = byte_end(@write_id + 6 + WRITE_REQUEST)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Two bytes after the ID's CRC, DRQ asks for the first byte, and
|
|
27
|
+
# twenty bytes on it has to be there.
|
|
28
|
+
def write_gate
|
|
29
|
+
unless @gate_open
|
|
30
|
+
@gate_open = true
|
|
31
|
+
@drq = true
|
|
32
|
+
return @due += (WRITE_DEADLINE - WRITE_REQUEST) * BYTE
|
|
33
|
+
end
|
|
34
|
+
return lost if @drq
|
|
35
|
+
|
|
36
|
+
@bytes = []
|
|
37
|
+
@phase = WRITE_DATA
|
|
38
|
+
@due = byte_end(@write_id + Track::DATA_OFFSET)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# The next byte goes under the head from the data register, a 0
|
|
42
|
+
# where DRQ went unanswered, and DRQ asks for the one after it.
|
|
43
|
+
# After the last come the CRC and a $FF.
|
|
44
|
+
def byte_written
|
|
45
|
+
return sector_written if @bytes.length == @size
|
|
46
|
+
|
|
47
|
+
@status |= LOST_DATA if @drq && !@bytes.empty?
|
|
48
|
+
@bytes << (@drq && !@bytes.empty? ? 0 : @data)
|
|
49
|
+
@drq = @bytes.length < @size
|
|
50
|
+
@due += @bytes.length == @size ? 3 * BYTE : BYTE
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def sector_written
|
|
54
|
+
sector = found
|
|
55
|
+
if sector
|
|
56
|
+
sector.data = Track::Field.new(@write_id + Track::DATA_OFFSET, @bytes, true,
|
|
57
|
+
@command.anybits?(DELETED_MARK))
|
|
58
|
+
@mechanism.write(@mechanism.track)
|
|
59
|
+
end
|
|
60
|
+
return finish if @command.nobits?(MULTIPLE)
|
|
61
|
+
|
|
62
|
+
@sector = (@sector + 1) & 0xff
|
|
63
|
+
begin_search
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def lost
|
|
67
|
+
@status |= LOST_DATA
|
|
68
|
+
@drq = false
|
|
69
|
+
finish
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Drives
|
|
5
|
+
class Model1581
|
|
6
|
+
class WD1772
|
|
7
|
+
# The type II commands and read address, which find an ID field on
|
|
8
|
+
# the track under the head:
|
|
9
|
+
#
|
|
10
|
+
# 100mhE00 read sector the data field after the ID that carries
|
|
11
|
+
# the track and sector registers
|
|
12
|
+
# 101mhEPa write sector a data field after that ID, deleted with a
|
|
13
|
+
# 11000hE00 read address the next ID field's six bytes, the track
|
|
14
|
+
# going into the sector register
|
|
15
|
+
#
|
|
16
|
+
# The search reads each ID field as it passes. One that matches but
|
|
17
|
+
# whose CRC doesn't read back sets CRC_ERROR and the search goes on;
|
|
18
|
+
# after five index pulses it gives up with NOT_FOUND. Each byte of a
|
|
19
|
+
# field passes in BYTE cycles and sets DRQ as it lands in the data
|
|
20
|
+
# register, and LOST_DATA where the last one was still unread. With m
|
|
21
|
+
# the command goes on to the next sector until one isn't found. E
|
|
22
|
+
# lets the head settle first. SectorWrites writes the data field.
|
|
23
|
+
module Sectors
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def start_type2
|
|
27
|
+
start_search(@command < 0xa0 ? READ : WRITE)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def start_read_address
|
|
31
|
+
start_search(ADDRESS)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def start_search(mode)
|
|
35
|
+
@type1 = false
|
|
36
|
+
@status = 0
|
|
37
|
+
@drq = false
|
|
38
|
+
@mode = mode
|
|
39
|
+
resume_type2 unless spinning_up?(SEARCH)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def resume_type2
|
|
43
|
+
if @mode == WRITE && @mechanism.write_protected?
|
|
44
|
+
@status |= PROTECTED
|
|
45
|
+
return finish
|
|
46
|
+
end
|
|
47
|
+
return begin_search if @command.nobits?(SETTLE_DELAY)
|
|
48
|
+
|
|
49
|
+
@phase = SETTLE_SEARCH
|
|
50
|
+
@due = @now + SETTLE
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Searches for five index pulses from now.
|
|
54
|
+
def begin_search
|
|
55
|
+
index = next_index
|
|
56
|
+
@deadline = index == NEVER ? NEVER : index + (4 * Mechanism::REVOLUTION)
|
|
57
|
+
search
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Waits for the next ID field to pass under the head.
|
|
61
|
+
def search
|
|
62
|
+
@phase = SEARCH
|
|
63
|
+
track = @mechanism.track
|
|
64
|
+
sector = track&.next_id((@mechanism.angle(@now) / BYTE) + 1)
|
|
65
|
+
@found = sector ? track.sectors.index(sector) : -1
|
|
66
|
+
@id_at = sector ? byte_end(sector.id.mark) : NEVER
|
|
67
|
+
@due = [@id_at, @deadline].min
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def found = @mechanism.track&.sectors&.[](@found)
|
|
71
|
+
|
|
72
|
+
def id_passed
|
|
73
|
+
return not_found unless @now == @id_at
|
|
74
|
+
|
|
75
|
+
sector = found
|
|
76
|
+
return search if sector.nil?
|
|
77
|
+
|
|
78
|
+
id = sector.id
|
|
79
|
+
return id_read(id) if @mode == ADDRESS
|
|
80
|
+
return search unless matches?(id.bytes)
|
|
81
|
+
return crc_mismatch unless id.good
|
|
82
|
+
|
|
83
|
+
@status &= ~CRC_ERROR
|
|
84
|
+
@mode == VERIFY_TRACK ? finish : sector_found(sector)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def matches?(id)
|
|
88
|
+
id[0] == @track && (@mode == VERIFY_TRACK || id[2] == @sector)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def crc_mismatch
|
|
92
|
+
@status |= CRC_ERROR
|
|
93
|
+
search
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def not_found
|
|
97
|
+
@status |= NOT_FOUND
|
|
98
|
+
finish
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def sector_found(sector)
|
|
102
|
+
return write_sector(sector) if @mode == WRITE
|
|
103
|
+
|
|
104
|
+
data = sector.data
|
|
105
|
+
return search if data.nil? || data.mark > sector.id.mark + 7 + Track::DATA_MARK_WINDOW
|
|
106
|
+
|
|
107
|
+
@status |= DELETED if data.deleted
|
|
108
|
+
transfer(data.bytes, data.mark, READ_DATA)
|
|
109
|
+
@crc_good = data.good
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Read address: the ID's bytes and its CRC.
|
|
113
|
+
def id_read(id)
|
|
114
|
+
@status |= CRC_ERROR unless id.good
|
|
115
|
+
transfer(id.bytes + Track.field_crc(Track::ID_MARK, id.bytes), id.mark, READ_ADDRESS)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def transfer(bytes, mark, phase)
|
|
119
|
+
@bytes = bytes
|
|
120
|
+
@index = 0
|
|
121
|
+
@phase = phase
|
|
122
|
+
@due = byte_end(mark + 1)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# A byte of the field lands in the data register. After the last,
|
|
126
|
+
# the CRC passes.
|
|
127
|
+
def byte_read
|
|
128
|
+
return field_read if @index == @bytes.length
|
|
129
|
+
|
|
130
|
+
@status |= LOST_DATA if @drq
|
|
131
|
+
@data = @bytes[@index]
|
|
132
|
+
@drq = true
|
|
133
|
+
@index += 1
|
|
134
|
+
@due += @index == @bytes.length && @phase == READ_DATA ? 2 * BYTE : BYTE
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def field_read
|
|
138
|
+
if @phase == READ_ADDRESS
|
|
139
|
+
@sector = @bytes[0]
|
|
140
|
+
elsif !@crc_good
|
|
141
|
+
@status |= CRC_ERROR
|
|
142
|
+
elsif @command.anybits?(MULTIPLE)
|
|
143
|
+
@sector = (@sector + 1) & 0xff
|
|
144
|
+
return begin_search
|
|
145
|
+
end
|
|
146
|
+
finish
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Drives
|
|
5
|
+
class Model1581
|
|
6
|
+
class WD1772
|
|
7
|
+
# The type I commands, which move the head:
|
|
8
|
+
#
|
|
9
|
+
# 0000hVrr restore step out to track 0, the track register to 0
|
|
10
|
+
# 0001hVrr seek step until the track register holds the data
|
|
11
|
+
# register's track
|
|
12
|
+
# 001uhVrr step one step the way the last one went
|
|
13
|
+
# 010uhVrr step in one step towards the hub
|
|
14
|
+
# 011uhVrr step out one step towards the rim
|
|
15
|
+
#
|
|
16
|
+
# Each step waits out the step rate rr picks (STEP_RATES), and u has
|
|
17
|
+
# a step update the track register, as restore and seek always do.
|
|
18
|
+
# With V the head settles and the command reads IDs until one carries
|
|
19
|
+
# the track register's track, or sets NOT_FOUND after five turns.
|
|
20
|
+
module Stepping
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def start_type1
|
|
24
|
+
@type1 = true
|
|
25
|
+
@status = 0
|
|
26
|
+
@drq = false
|
|
27
|
+
@phase = STEPPED
|
|
28
|
+
@steps = 0
|
|
29
|
+
if @command < 0x10
|
|
30
|
+
@track = 0xff
|
|
31
|
+
@data = 0
|
|
32
|
+
elsif @command >= 0x40
|
|
33
|
+
@inward = @command < 0x60
|
|
34
|
+
end
|
|
35
|
+
step_done unless spinning_up?(STEPPED)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def spun_up
|
|
39
|
+
@status |= SPUN_UP
|
|
40
|
+
@phase = @after_spin_up
|
|
41
|
+
case @after_spin_up
|
|
42
|
+
when STEPPED then step_done
|
|
43
|
+
when SEARCH then resume_type2
|
|
44
|
+
else resume_track
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# The step rate has passed: the next step, or the end of the moves.
|
|
49
|
+
def step_done
|
|
50
|
+
return next_step if @steps.zero? || @command < 0x20
|
|
51
|
+
|
|
52
|
+
moved
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Restore and seek step until the track register matches, restore
|
|
56
|
+
# also stopping at track 0. The others step once.
|
|
57
|
+
def next_step
|
|
58
|
+
return single_step if @command >= 0x20
|
|
59
|
+
return seek_restore if @command < 0x10 && restored?
|
|
60
|
+
|
|
61
|
+
if @track == @data
|
|
62
|
+
moved
|
|
63
|
+
else
|
|
64
|
+
@inward = @data > @track
|
|
65
|
+
@track = (@track + (@inward ? 1 : -1)) & 0xff
|
|
66
|
+
pulse
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def restored?
|
|
71
|
+
return false unless @mechanism.track0? || @steps >= 255
|
|
72
|
+
|
|
73
|
+
@status |= NOT_FOUND if !@mechanism.track0? && @command.anybits?(VERIFY)
|
|
74
|
+
true
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def seek_restore
|
|
78
|
+
@track = 0 if @mechanism.track0?
|
|
79
|
+
moved
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def single_step
|
|
83
|
+
@track = (@track + (@inward ? 1 : -1)) & 0xff if @command.anybits?(UPDATE)
|
|
84
|
+
pulse
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def pulse
|
|
88
|
+
@steps += 1
|
|
89
|
+
@mechanism.step(@inward)
|
|
90
|
+
@phase = STEPPED
|
|
91
|
+
@due = @now + STEP_RATES[@command & 0x03]
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# The head is there: with V it settles, and the command ends
|
|
95
|
+
# otherwise.
|
|
96
|
+
def moved
|
|
97
|
+
return finish unless @command.anybits?(VERIFY) && @status.nobits?(NOT_FOUND)
|
|
98
|
+
|
|
99
|
+
@phase = SETTLED
|
|
100
|
+
@due = @now + SETTLE
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def verify_track
|
|
104
|
+
@mode = VERIFY_TRACK
|
|
105
|
+
begin_search
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|