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,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class CIA
|
|
6
|
+
# Running a CIA a stretch of cycles at once, for Drives::Engine::Idle.
|
|
7
|
+
module FastForward
|
|
8
|
+
# quiet_cycles for a CIA whose counters will never set a flag.
|
|
9
|
+
QUIET = 1 << 40
|
|
10
|
+
|
|
11
|
+
# Whether fast_forward can run the CIA: timer B stopped with nothing
|
|
12
|
+
# in its pipeline, no interrupt or acknowledge on its way, CNT where it
|
|
13
|
+
# was, the TOD clock stopped, and timer A either stopped, or free
|
|
14
|
+
# running (Timer#free_running?) with its interrupt masked and the
|
|
15
|
+
# serial port an idle input. Drives::Engine::Idle sleeps the 1571's CIA through
|
|
16
|
+
# such cycles, which its DOS leaves timer A running in.
|
|
17
|
+
def quiet?
|
|
18
|
+
return false unless @tb.idle? && @icr.quiet && @tod.quiet? && cnt_steady?
|
|
19
|
+
|
|
20
|
+
@ta.idle? ? @serial.idle : timer_a_free_running?
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# How many cycles the CIA can run with nothing but its counters
|
|
24
|
+
# moving: as quiet? allows, but with timer B free running too, up to
|
|
25
|
+
# the cycle before it underflows. The 1581's DOS leaves timer B
|
|
26
|
+
# interrupting every 10 ms.
|
|
27
|
+
def quiet_cycles
|
|
28
|
+
return 0 unless @icr.quiet && @tod.quiet? && cnt_steady? && timer_a_quiet?
|
|
29
|
+
return QUIET if @tb.idle?
|
|
30
|
+
return 0 unless @tb.free_running? && @control_b.value.nobits?(0x60)
|
|
31
|
+
|
|
32
|
+
@tb.counter - 1
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Runs +cycles+ cycles at once while quiet? or for quiet_cycles, as
|
|
36
|
+
# cycle! would: timer A's underflows flag in the ICR, and reach the
|
|
37
|
+
# serial port's underflow line.
|
|
38
|
+
def fast_forward(cycles)
|
|
39
|
+
@tod.fast_forward(cycles)
|
|
40
|
+
@tb.fast_forward(cycles) unless @tb.idle?
|
|
41
|
+
return if @ta.idle?
|
|
42
|
+
|
|
43
|
+
@icr.flag(:timer_a) if @ta.fast_forward(cycles).positive?
|
|
44
|
+
@serial.follow_underflow(@ta.underflowed)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def timer_a_quiet? = @ta.idle? ? @serial.idle : timer_a_free_running?
|
|
50
|
+
|
|
51
|
+
# Timer A free running with its interrupt masked, and the serial port
|
|
52
|
+
# an idle input it only clocks.
|
|
53
|
+
def timer_a_free_running?
|
|
54
|
+
@ta.free_running? && !@control_a.serial_mode? && @icr.mask.value.nobits?(0x01) && @serial.drained?
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Whether CNT holds the level the last cycle sampled.
|
|
58
|
+
def cnt_steady? = @serial.cnt == @cnt_high && !@cnt_rise
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class CIA
|
|
6
|
+
# The interrupt control register: the source flags, their mask and the
|
|
7
|
+
# IR bit that drives the interrupt line, with the 6526's acknowledge
|
|
8
|
+
# timing.
|
|
9
|
+
class InterruptRegister
|
|
10
|
+
attr_reader :status, :mask, :quiet
|
|
11
|
+
|
|
12
|
+
# The 6526A is the faster of the two: see the rules below.
|
|
13
|
+
def initialize(model = :mos6526)
|
|
14
|
+
@fast = model == :mos6526a
|
|
15
|
+
@mask = InterruptFlags.new([:timer_a, :timer_b, :alarm, :serial, :flag, 0, 0, 0])
|
|
16
|
+
@status = InterruptFlags.new([:timer_a, :timer_b, :alarm, :serial, :flag, 0, 0, :interrupt])
|
|
17
|
+
@pending = 0
|
|
18
|
+
@read = @read_last_cycle = @read_two_cycles_ago = nil
|
|
19
|
+
@timer_b_bug = false
|
|
20
|
+
@quiet = true
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# The CIA skips this while quiet: no read is recent enough to matter
|
|
24
|
+
# and no assert is due.
|
|
25
|
+
def cycle!
|
|
26
|
+
@read_two_cycles_ago = @read_last_cycle
|
|
27
|
+
@read_last_cycle = @read
|
|
28
|
+
@read = nil
|
|
29
|
+
if @pending.positive?
|
|
30
|
+
@pending -= 1
|
|
31
|
+
status.interrupt = true if @pending.zero?
|
|
32
|
+
end
|
|
33
|
+
@quiet = @pending.zero? && @read_last_cycle.nil? && @read_two_cycles_ago.nil?
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def interrupted? = status.value >= 0x80
|
|
37
|
+
|
|
38
|
+
def save_state(out)
|
|
39
|
+
out.int(@mask.value).int(@status.value).int(@pending)
|
|
40
|
+
[@read, @read_last_cycle, @read_two_cycles_ago].each { |read| out.optional_int(read) }
|
|
41
|
+
out.boolean(@timer_b_bug).boolean(@quiet)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def load_state(input)
|
|
45
|
+
@mask.value = input.int
|
|
46
|
+
@status.value = input.int
|
|
47
|
+
@pending = input.int
|
|
48
|
+
@read = input.optional_int
|
|
49
|
+
@read_last_cycle = input.optional_int
|
|
50
|
+
@read_two_cycles_ago = input.optional_int
|
|
51
|
+
@timer_b_bug = input.boolean?
|
|
52
|
+
@quiet = input.boolean?
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Raises IR on this cycle.
|
|
56
|
+
def assert_now
|
|
57
|
+
status.interrupt = true
|
|
58
|
+
@pending = 0
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Schedules IR to rise after delay cycles, keeping an earlier one.
|
|
62
|
+
def assert!(delay = 1)
|
|
63
|
+
@pending = @pending.positive? ? [@pending, delay].min : delay
|
|
64
|
+
@quiet = false
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Latch a source, pulling the interrupt line if it is armed. The 6526
|
|
68
|
+
# raises IR a cycle after the flag. The 6526A raises it on the flag's
|
|
69
|
+
# own cycle, unless the ICR was read on the cycle before.
|
|
70
|
+
def flag(source)
|
|
71
|
+
bit = source_bit(source)
|
|
72
|
+
@status.value |= bit
|
|
73
|
+
return unless mask.value.anybits?(bit)
|
|
74
|
+
|
|
75
|
+
@fast && @read_last_cycle.nil? ? assert_now : assert!
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# The 6526 timer B bug: an underflow on the cycle after a read still
|
|
79
|
+
# raises the flag, but the next read drops it unseen. The 6526A has
|
|
80
|
+
# no such bug.
|
|
81
|
+
def timer_b_underflow!
|
|
82
|
+
@timer_b_bug = !@fast && !@read_last_cycle.nil?
|
|
83
|
+
flag(:timer_b)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# A read releases the interrupt line at once, and cancels an assert
|
|
87
|
+
# due on the next cycle, but its acknowledge lands a cycle late. On
|
|
88
|
+
# the 6526 that holds only IR: the next cycle still reads IR set if it
|
|
89
|
+
# was set, or about to be. The 6526A reads an IR about to rise as set
|
|
90
|
+
# at once, and holds every bit it read: the next cycle reads them all
|
|
91
|
+
# again, along with anything flagged since.
|
|
92
|
+
def read
|
|
93
|
+
status.timer_b = false if @timer_b_bug
|
|
94
|
+
@timer_b_bug = false
|
|
95
|
+
value = status.value
|
|
96
|
+
value |= 0x80 if @fast && @pending == 1
|
|
97
|
+
@read = @pending == 1 ? value | 0x80 : value
|
|
98
|
+
@quiet = false
|
|
99
|
+
value |= held(@read_last_cycle) if @read_last_cycle
|
|
100
|
+
status.value = 0x0
|
|
101
|
+
@pending = 0
|
|
102
|
+
value
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Bit 7 picks between setting and clearing the mask bits given.
|
|
106
|
+
def write(value)
|
|
107
|
+
if value.nobits?(0x80)
|
|
108
|
+
@mask.value &= ~(value & 0x1f)
|
|
109
|
+
else
|
|
110
|
+
@mask.value |= (value & 0x1f)
|
|
111
|
+
end
|
|
112
|
+
if mask.value.anybits?(status.value & 0x1f)
|
|
113
|
+
assert!(arm_delay) unless interrupted?
|
|
114
|
+
elsif @pending == 1 && @read_two_cycles_ago
|
|
115
|
+
# On the 6526, masking the pending source cancels the assert due
|
|
116
|
+
# on the next cycle only while a read two cycles back is
|
|
117
|
+
# acknowledging.
|
|
118
|
+
@pending = 0
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
private
|
|
123
|
+
|
|
124
|
+
# Arming a pending source raises IR two cycles later on the 6526,
|
|
125
|
+
# and one cycle later on the 6526A.
|
|
126
|
+
def arm_delay = @fast ? 1 : 2
|
|
127
|
+
|
|
128
|
+
# What a read on the cycle before still holds: IR on the 6526, and
|
|
129
|
+
# every bit it read on the 6526A.
|
|
130
|
+
def held(last) = @fast ? last : last & 0x80
|
|
131
|
+
|
|
132
|
+
def source_bit(source)
|
|
133
|
+
case source
|
|
134
|
+
when :timer_a then 0x01
|
|
135
|
+
when :timer_b then 0x02
|
|
136
|
+
when :alarm then 0x04
|
|
137
|
+
when :serial then 0x08
|
|
138
|
+
when :flag then 0x10
|
|
139
|
+
else raise ArgumentError, "unknown interrupt source #{source}"
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class CIA
|
|
6
|
+
# A snapshot of the chip: everything it holds but its wiring, the ports,
|
|
7
|
+
# the PB4 and CNT levels, the timers, the interrupt register, the serial
|
|
8
|
+
# port and the TOD clock.
|
|
9
|
+
module SavedState
|
|
10
|
+
def save_state(out)
|
|
11
|
+
out.marker("CIA")
|
|
12
|
+
out.int(@data_port_a).int(@data_port_b).int(@data_dir_a).int(@data_dir_b)
|
|
13
|
+
out.boolean(@port_b4_high).boolean(@port_b4_driven_high).boolean(@cnt_high).boolean(@cnt_rise)
|
|
14
|
+
out.int(@control_a.value).int(@control_b.value)
|
|
15
|
+
@ta.save_state(out)
|
|
16
|
+
@tb.save_state(out)
|
|
17
|
+
@icr.save_state(out)
|
|
18
|
+
@serial.save_state(out)
|
|
19
|
+
@tod.save_state(out)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def load_state(input)
|
|
23
|
+
input.marker("CIA")
|
|
24
|
+
@data_port_a = input.int
|
|
25
|
+
@data_port_b = input.int
|
|
26
|
+
@data_dir_a = input.int
|
|
27
|
+
@data_dir_b = input.int
|
|
28
|
+
@port_b4_high = input.boolean?
|
|
29
|
+
@port_b4_driven_high = input.boolean?
|
|
30
|
+
@cnt_high = input.boolean?
|
|
31
|
+
@cnt_rise = input.boolean?
|
|
32
|
+
@control_a.value = input.int
|
|
33
|
+
@control_b.value = input.int
|
|
34
|
+
load_parts(input)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def load_parts(input)
|
|
40
|
+
@ta.load_state(input)
|
|
41
|
+
@tb.load_state(input)
|
|
42
|
+
@icr.load_state(input)
|
|
43
|
+
@serial.load_state(input)
|
|
44
|
+
@tod.load_state(input)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class CIA
|
|
6
|
+
class Serial
|
|
7
|
+
# The shift register's state for a snapshot.
|
|
8
|
+
module SavedState
|
|
9
|
+
def save_state(out)
|
|
10
|
+
out.int(@data).int(@shift).int(@steps).optional_int(@empty_in).optional_int(@busy_in)
|
|
11
|
+
out.boolean(@busy).boolean(@abandoned).optional_int(@pending).boolean(@underflow_high).boolean(@in_flight)
|
|
12
|
+
out.int(@flight_up).int(@flight_down).boolean(@idle)
|
|
13
|
+
[@cnt, @cnt_in, @sp_in, @sp_out].each { |level| out.boolean(level) }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def load_state(input)
|
|
17
|
+
@data = input.int
|
|
18
|
+
@shift = input.int
|
|
19
|
+
@steps = input.int
|
|
20
|
+
@empty_in = input.optional_int
|
|
21
|
+
@busy_in = input.optional_int
|
|
22
|
+
@busy = input.boolean?
|
|
23
|
+
@abandoned = input.boolean?
|
|
24
|
+
@pending = input.optional_int
|
|
25
|
+
load_lines(input)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def load_lines(input)
|
|
31
|
+
@underflow_high = input.boolean?
|
|
32
|
+
@in_flight = input.boolean?
|
|
33
|
+
@flight_up = input.int
|
|
34
|
+
@flight_down = input.int
|
|
35
|
+
@idle = input.boolean?
|
|
36
|
+
@cnt = input.boolean?
|
|
37
|
+
@cnt_in = input.boolean?
|
|
38
|
+
@sp_in = input.boolean?
|
|
39
|
+
@sp_out = input.boolean?
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "badline/chips/cia/serial/saved_state"
|
|
4
|
+
|
|
5
|
+
module Badline
|
|
6
|
+
module Chips
|
|
7
|
+
class CIA
|
|
8
|
+
# The serial shift register and the CNT line that clocks it.
|
|
9
|
+
#
|
|
10
|
+
# With CRA bit 6 clear the port is an input: SP is sampled on every
|
|
11
|
+
# rising CNT edge, and the byte reaches the data register after eight of
|
|
12
|
+
# them. With the bit set the CIA drives CNT itself, toggling it on every
|
|
13
|
+
# timer A underflow, so a byte takes sixteen underflows to go out. CNT falls
|
|
14
|
+
# as each bit is put on SP, and rises again to clock it in.
|
|
15
|
+
#
|
|
16
|
+
# The register counts itself empty as soon as the eighth bit is on SP,
|
|
17
|
+
# fifteen underflows in: the serial flag follows a few cycles later
|
|
18
|
+
# rather than waiting for the sixteenth underflow, and a byte written
|
|
19
|
+
# from that point on goes out on the next one.
|
|
20
|
+
class Serial
|
|
21
|
+
include SavedState
|
|
22
|
+
|
|
23
|
+
BITS = 8
|
|
24
|
+
|
|
25
|
+
# A byte written to the data register reaches the shift register one
|
|
26
|
+
# cycle later. The empty countdown starts on the underflow that puts
|
|
27
|
+
# the eighth bit on SP and is decremented on that same cycle, so the
|
|
28
|
+
# flag lands four cycles after it.
|
|
29
|
+
LOAD_DELAY = 1
|
|
30
|
+
EMPTY_DELAY = 5
|
|
31
|
+
BUSY_DELAY = 5
|
|
32
|
+
|
|
33
|
+
# The logic watching the shift register runs a few cycles behind it,
|
|
34
|
+
# so the level saying a bit is still on its way out is scheduled
|
|
35
|
+
# through a delay line: a bit set at position 7 - n takes effect n
|
|
36
|
+
# cycles later. Putting a bit on SP raises the level after one cycle
|
|
37
|
+
# and drops it again after two before raising it for good after
|
|
38
|
+
# three; the eighth bit skips straight to the last of those. CNT
|
|
39
|
+
# rising over a bit lowers the level four cycles later.
|
|
40
|
+
IN_FLIGHT = 0x50
|
|
41
|
+
LAST_IN_FLIGHT = 0x10
|
|
42
|
+
BOUNCE = 0x20
|
|
43
|
+
SETTLED = 0x08
|
|
44
|
+
|
|
45
|
+
attr_reader :data, :sp_out, :cnt, :cnt_in, :idle
|
|
46
|
+
attr_accessor :sp_in
|
|
47
|
+
|
|
48
|
+
def initialize(control)
|
|
49
|
+
@control = control
|
|
50
|
+
@data = 0x0
|
|
51
|
+
@shift = 0x0
|
|
52
|
+
@steps = 0
|
|
53
|
+
@empty_in = nil
|
|
54
|
+
@busy_in = nil
|
|
55
|
+
@busy = false
|
|
56
|
+
@abandoned = false
|
|
57
|
+
@pending = nil
|
|
58
|
+
@underflow_high = false
|
|
59
|
+
@in_flight = false
|
|
60
|
+
@flight_up = 0x0
|
|
61
|
+
@flight_down = 0x0
|
|
62
|
+
@idle = true
|
|
63
|
+
# Nothing drives the user port, so both lines float high.
|
|
64
|
+
@cnt = true
|
|
65
|
+
@cnt_in = true
|
|
66
|
+
@sp_in = true
|
|
67
|
+
@sp_out = true
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# The bits shifted so far, and the byte waiting to go out after the
|
|
71
|
+
# one shifting.
|
|
72
|
+
attr_reader :steps, :pending
|
|
73
|
+
|
|
74
|
+
def shift_register = @shift
|
|
75
|
+
|
|
76
|
+
# Sets the data register and the shift register, as a VICE snapshot
|
|
77
|
+
# gives them.
|
|
78
|
+
def restore_shift(data, shift)
|
|
79
|
+
@data = data
|
|
80
|
+
@shift = shift
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def output?
|
|
84
|
+
@control.serial_mode?
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Whether nothing is counting down or in the delay lines, so only
|
|
88
|
+
# timer A's underflows reach the register.
|
|
89
|
+
def drained? = idle?
|
|
90
|
+
|
|
91
|
+
# Takes timer A's underflow line as cycle! would have left it, with
|
|
92
|
+
# +underflowed+ its level on the last cycle, for a CIA run without
|
|
93
|
+
# the register in use (CIA#fast_forward).
|
|
94
|
+
def follow_underflow(underflowed)
|
|
95
|
+
@underflow_high = underflowed
|
|
96
|
+
@idle = !underflowed
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def cnt_in=(level)
|
|
100
|
+
@cnt_in = level
|
|
101
|
+
@cnt = level unless output?
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def write(value)
|
|
105
|
+
@data = value
|
|
106
|
+
@pending = LOAD_DELAY
|
|
107
|
+
@idle = false
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Clocked every cycle with timer A's underflow line. Yields once the
|
|
111
|
+
# shift register reports itself empty, which it does without waiting
|
|
112
|
+
# for the underflow that raises CNT over the eighth bit.
|
|
113
|
+
def cycle!(underflowed)
|
|
114
|
+
return if @idle && !underflowed
|
|
115
|
+
|
|
116
|
+
shift(underflowed)
|
|
117
|
+
@pending -= 1 if @pending&.positive?
|
|
118
|
+
drain_flight
|
|
119
|
+
count_busy
|
|
120
|
+
@idle = !underflowed && idle?
|
|
121
|
+
return if @empty_in.nil?
|
|
122
|
+
|
|
123
|
+
@empty_in -= 1
|
|
124
|
+
return unless @empty_in.zero?
|
|
125
|
+
|
|
126
|
+
@empty_in = nil
|
|
127
|
+
@busy = false
|
|
128
|
+
yield
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Clocked by rising CNT edges while receiving. Yields once a whole
|
|
132
|
+
# byte has arrived.
|
|
133
|
+
def rising_edge!
|
|
134
|
+
return if output?
|
|
135
|
+
|
|
136
|
+
@shift = ((@shift << 1) | (@sp_in ? 1 : 0)) & 0xff
|
|
137
|
+
@steps += 1
|
|
138
|
+
return unless @steps == BITS
|
|
139
|
+
|
|
140
|
+
@steps = 0
|
|
141
|
+
@data = @shift
|
|
142
|
+
yield if block_given?
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# A mode change drops the byte in flight and hands CNT back to
|
|
146
|
+
# whichever side drives it now, and yields: that byte counts as gone.
|
|
147
|
+
# Handing the port over as an input tears a transmission down, so a
|
|
148
|
+
# busy register reports it; the same change latches how far the bit
|
|
149
|
+
# in flight had got, and taking the port back reports that.
|
|
150
|
+
def reset!
|
|
151
|
+
abandoned = output? ? @abandoned : @busy
|
|
152
|
+
@abandoned = output? ? false : @in_flight
|
|
153
|
+
@in_flight = false
|
|
154
|
+
@steps = 0
|
|
155
|
+
@empty_in = nil
|
|
156
|
+
@busy_in = nil
|
|
157
|
+
@busy = false
|
|
158
|
+
@pending = nil
|
|
159
|
+
@cnt = output? || @cnt_in
|
|
160
|
+
yield if abandoned
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
private
|
|
164
|
+
|
|
165
|
+
# Without an underflow, a register with nothing counting down and
|
|
166
|
+
# nothing in the delay lines has nothing to do on a cycle.
|
|
167
|
+
def idle?
|
|
168
|
+
!@pending&.positive? && (@flight_up | @flight_down).zero? &&
|
|
169
|
+
@busy_in.nil? && @empty_in.nil?
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# The shift register picks up a waiting byte whenever the underflow
|
|
173
|
+
# line is asserted, but every half-step after that needs a fresh edge
|
|
174
|
+
# on it. A zero latch holds the line down for good rather than
|
|
175
|
+
# pulsing it, so such a byte stops after its first bit and never
|
|
176
|
+
# reaches the data register.
|
|
177
|
+
def shift(underflowed)
|
|
178
|
+
edge = underflowed && !@underflow_high
|
|
179
|
+
@underflow_high = underflowed
|
|
180
|
+
clock(edge) if underflowed && output?
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def clock(edge)
|
|
184
|
+
start if @steps <= 1
|
|
185
|
+
if @steps.zero?
|
|
186
|
+
@flight_down |= SETTLED
|
|
187
|
+
elsif edge || @steps == BITS * 2
|
|
188
|
+
half_step
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def half_step
|
|
193
|
+
@steps -= 1
|
|
194
|
+
@cnt = @steps.even?
|
|
195
|
+
if @cnt
|
|
196
|
+
@flight_down |= SETTLED
|
|
197
|
+
else
|
|
198
|
+
shift_out
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# The register reads as busy from a few cycles after the first bit
|
|
203
|
+
# reaches SP until it reports itself empty over the eighth.
|
|
204
|
+
def mark_busy
|
|
205
|
+
case @steps
|
|
206
|
+
when (BITS * 2) - 1 then @busy_in = BUSY_DELAY
|
|
207
|
+
when 1
|
|
208
|
+
@empty_in = EMPTY_DELAY
|
|
209
|
+
@busy_in = nil
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def count_busy
|
|
214
|
+
return if @busy_in.nil?
|
|
215
|
+
|
|
216
|
+
@busy_in -= 1
|
|
217
|
+
return unless @busy_in.zero?
|
|
218
|
+
|
|
219
|
+
@busy_in = nil
|
|
220
|
+
@busy = true
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def drain_flight
|
|
224
|
+
@in_flight = false if @flight_down.anybits?(0x80)
|
|
225
|
+
@flight_down = (@flight_down << 1) & 0xff
|
|
226
|
+
@in_flight = true if @flight_up.anybits?(0x80)
|
|
227
|
+
@flight_up = (@flight_up << 1) & 0xff
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# A byte only moves out of the data register once the one before it
|
|
231
|
+
# has put its last bit on SP.
|
|
232
|
+
def start
|
|
233
|
+
return unless @pending&.zero?
|
|
234
|
+
|
|
235
|
+
@pending = nil
|
|
236
|
+
@shift = @data
|
|
237
|
+
@steps = BITS * 2
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def shift_out
|
|
241
|
+
@sp_out = @shift.anybits?(0x80)
|
|
242
|
+
@shift = (@shift << 1) & 0xff
|
|
243
|
+
mark_busy
|
|
244
|
+
@flight_up |= @steps == 1 ? LAST_IN_FLIGHT : IN_FLIGHT
|
|
245
|
+
@flight_down |= BOUNCE
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
end
|