badline 0.12.1 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -0
- data/CLAUDE.md +59 -31
- data/README.md +1 -1
- data/doc/library.md +9 -9
- data/doc/pinned-behaviour.md +105 -105
- data/doc/snapshots.md +1 -4
- data/lib/badline/audio/bare_player.rb +3 -3
- data/lib/badline/audio/cli.rb +6 -6
- data/lib/badline/audio/jukebox.rb +2 -2
- data/lib/badline/audio/machine_player.rb +2 -2
- data/lib/badline/{media → audio}/queue.rb +1 -1
- data/lib/badline/audio/queued_tune.rb +6 -6
- data/lib/badline/audio/renderer.rb +5 -5
- data/lib/badline/audio/stereo.rb +1 -1
- data/lib/badline/c128/{bus_state.rb → bus/saved_state.rb} +1 -1
- data/lib/badline/c128/bus.rb +18 -17
- data/lib/badline/c128/color_lines.rb +2 -2
- data/lib/badline/c128/cpu.rb +1 -1
- data/lib/badline/c128/drives.rb +10 -11
- data/lib/badline/c128/fast_serial.rb +5 -5
- data/lib/badline/c128/mmu_pages.rb +1 -1
- data/lib/badline/c128/modes.rb +2 -2
- data/lib/badline/c128/saved_state.rb +21 -47
- data/lib/badline/c128/z80.rb +2 -2
- data/lib/badline/c128.rb +14 -9
- data/lib/badline/{computer → c64}/attachments.rb +4 -6
- data/lib/badline/c64/banked_ram/banking.rb +32 -0
- data/lib/badline/c64/banked_ram/plus256k.rb +56 -0
- data/lib/badline/c64/banked_ram/plus60k.rb +45 -0
- data/lib/badline/c64/banked_ram/unexpanded.rb +30 -0
- data/lib/badline/c64/banked_ram.rb +23 -0
- data/lib/badline/c64/bus/extra_sids.rb +32 -0
- data/lib/badline/c64/bus/fittings.rb +40 -0
- data/lib/badline/c64/bus/pla.rb +149 -0
- data/lib/badline/c64/bus/roms.rb +41 -0
- data/lib/badline/c64/bus/saved_state.rb +68 -0
- data/lib/badline/c64/bus/sid_slots.rb +44 -0
- data/lib/badline/c64/bus.rb +218 -0
- data/lib/badline/c64/cartridge/action_replay.rb +128 -0
- data/lib/badline/c64/cartridge/atomic_power.rb +26 -0
- data/lib/badline/c64/cartridge/bank.rb +83 -0
- data/lib/badline/c64/cartridge/comal80.rb +52 -0
- data/lib/badline/c64/cartridge/dinamic.rb +36 -0
- data/lib/badline/c64/cartridge/easy_flash.rb +147 -0
- data/lib/badline/c64/cartridge/epyx_fastload.rb +81 -0
- data/lib/badline/c64/cartridge/final_cartridge3.rb +91 -0
- data/lib/badline/c64/cartridge/flash/saved_state.rb +40 -0
- data/lib/badline/c64/cartridge/flash.rb +279 -0
- data/lib/badline/c64/cartridge/freezer.rb +35 -0
- data/lib/badline/c64/cartridge/fun_play.rb +40 -0
- data/lib/badline/c64/cartridge/g_mod2.rb +76 -0
- data/lib/badline/c64/cartridge/game_system.rb +42 -0
- data/lib/badline/c64/cartridge/geo_ram.rb +81 -0
- data/lib/badline/c64/cartridge/kcs_power.rb +77 -0
- data/lib/badline/c64/cartridge/mach5.rb +34 -0
- data/lib/badline/c64/cartridge/magic_desk.rb +32 -0
- data/lib/badline/c64/cartridge/ocean.rb +37 -0
- data/lib/badline/c64/cartridge/pagefox.rb +70 -0
- data/lib/badline/c64/cartridge/retro_replay/saved_state.rb +47 -0
- data/lib/badline/c64/cartridge/retro_replay.rb +286 -0
- data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
- data/lib/badline/c64/cartridge/rgcd.rb +60 -0
- data/lib/badline/c64/cartridge/saved_state.rb +63 -0
- data/lib/badline/c64/cartridge/simons_basic.rb +37 -0
- data/lib/badline/c64/cartridge/standard.rb +17 -0
- data/lib/badline/c64/cartridge/super_games.rb +50 -0
- data/lib/badline/c64/cartridge/westermann.rb +32 -0
- data/lib/badline/c64/cartridge/zaxxon.rb +68 -0
- data/lib/badline/c64/cartridge.rb +258 -0
- data/lib/badline/c64/color_memory.rb +27 -0
- data/lib/badline/{computer → c64}/common.rb +2 -2
- data/lib/badline/{computer → c64}/kernal_traps.rb +18 -18
- data/lib/badline/c64/reu/dma/saved_state.rb +52 -0
- data/lib/badline/c64/reu/dma.rb +275 -0
- data/lib/badline/c64/reu/ram.rb +109 -0
- data/lib/badline/c64/reu/saved_state.rb +55 -0
- data/lib/badline/c64/reu/trigger.rb +34 -0
- data/lib/badline/c64/reu.rb +291 -0
- data/lib/badline/{computer → c64}/saved_state.rb +13 -18
- data/lib/badline/{computer → c64}/true_drives.rb +11 -11
- data/lib/badline/{computer.rb → c64.rb} +18 -13
- data/lib/badline/chips/cia/fast_forward.rb +62 -0
- data/lib/badline/chips/cia/interrupt_register.rb +145 -0
- data/lib/badline/chips/cia/saved_state.rb +49 -0
- data/lib/badline/chips/cia/serial/saved_state.rb +45 -0
- data/lib/badline/chips/cia/serial.rb +250 -0
- data/lib/badline/chips/cia/time_of_day.rb +232 -0
- data/lib/badline/chips/cia/timer.rb +208 -0
- data/lib/badline/chips/cia.rb +281 -0
- data/lib/badline/chips/cpu/addressing.rb +133 -0
- data/lib/badline/chips/cpu/boundary.rb +56 -0
- data/lib/badline/chips/cpu/core.rb +167 -0
- data/lib/badline/chips/cpu/instruction.rb +338 -0
- data/lib/badline/chips/cpu/instruction_set/arithmetic.rb +118 -0
- data/lib/badline/chips/cpu/instruction_set/bitwise.rb +130 -0
- data/lib/badline/chips/cpu/instruction_set/branch.rb +83 -0
- data/lib/badline/chips/cpu/instruction_set/flag.rb +67 -0
- data/lib/badline/chips/cpu/instruction_set/illegal.rb +274 -0
- data/lib/badline/chips/cpu/instruction_set/inc_dec.rb +73 -0
- data/lib/badline/chips/cpu/instruction_set/stack.rb +56 -0
- data/lib/badline/chips/cpu/instruction_set/transfer.rb +141 -0
- data/lib/badline/chips/cpu/instruction_set.rb +59 -0
- data/lib/badline/chips/cpu/interrupts.rb +108 -0
- data/lib/badline/chips/cpu/microcode.rb +179 -0
- data/lib/badline/chips/cpu/operations.rb +90 -0
- data/lib/badline/chips/cpu/port.rb +116 -0
- data/lib/badline/chips/cpu/saved_state.rb +117 -0
- data/lib/badline/chips/cpu/stack_operations.rb +84 -0
- data/lib/badline/chips/cpu/traps.rb +23 -0
- data/lib/badline/chips/cpu.rb +12 -0
- data/lib/badline/chips/sid/catch_up.rb +122 -0
- data/lib/badline/chips/sid/decimator.rb +66 -0
- data/lib/badline/chips/sid/envelope/saved_state.rb +70 -0
- data/lib/badline/chips/sid/envelope.rb +241 -0
- data/lib/badline/chips/sid/filter/saved_state.rb +42 -0
- data/lib/badline/chips/sid/filter.rb +241 -0
- data/lib/badline/chips/sid/saved_state.rb +52 -0
- data/lib/badline/chips/sid/voice.rb +79 -0
- data/lib/badline/chips/sid/waveform/combined.rb +128 -0
- data/lib/badline/chips/sid/waveform/fast_forward.rb +107 -0
- data/lib/badline/chips/sid/waveform/noise_writeback.rb +124 -0
- data/lib/badline/chips/sid/waveform/saved_state.rb +68 -0
- data/lib/badline/chips/sid/waveform.rb +307 -0
- data/lib/badline/chips/sid.rb +265 -0
- data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
- data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -1
- data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -1
- data/lib/badline/chips/vdc/saved_state.rb +36 -0
- data/lib/badline/{c128 → chips}/vdc/window.rb +1 -1
- data/lib/badline/{c128 → chips}/vdc.rb +7 -31
- data/lib/badline/chips/via/control_lines.rb +124 -0
- data/lib/badline/chips/via/fast_forward.rb +55 -0
- data/lib/badline/chips/via/interrupt_register.rb +69 -0
- data/lib/badline/chips/via/saved_state.rb +44 -0
- data/lib/badline/chips/via/shift_register.rb +182 -0
- data/lib/badline/chips/via/timer1.rb +133 -0
- data/lib/badline/chips/via/timer2.rb +135 -0
- data/lib/badline/chips/via.rb +268 -0
- data/lib/badline/chips/vic/bank.rb +135 -0
- data/lib/badline/chips/vic/border_mask.rb +88 -0
- data/lib/badline/chips/vic/collisions.rb +117 -0
- data/lib/badline/chips/vic/color_patches.rb +49 -0
- data/lib/badline/chips/vic/display_state.rb +187 -0
- data/lib/badline/chips/vic/graphics_mode.rb +166 -0
- data/lib/badline/chips/vic/graphics_shifter/saved_state.rb +40 -0
- data/lib/badline/chips/vic/graphics_shifter.rb +187 -0
- data/lib/badline/chips/vic/register_log.rb +83 -0
- data/lib/badline/chips/vic/registers.rb +197 -0
- data/lib/badline/chips/vic/saved_state.rb +82 -0
- data/lib/badline/chips/vic/sequencer/saved_state.rb +91 -0
- data/lib/badline/chips/vic/sequencer.rb +277 -0
- data/lib/badline/chips/vic/sequencer_output.rb +118 -0
- data/lib/badline/chips/vic/sprite/internal_bus.rb +70 -0
- data/lib/badline/chips/vic/sprite/saved_state.rb +66 -0
- data/lib/badline/chips/vic/sprite/shifter.rb +148 -0
- data/lib/badline/chips/vic/sprite/timing.rb +58 -0
- data/lib/badline/chips/vic/sprite.rb +339 -0
- data/lib/badline/chips/vic/sprites/saved_state.rb +59 -0
- data/lib/badline/chips/vic/sprites.rb +284 -0
- data/lib/badline/chips/vic.rb +783 -0
- data/lib/badline/chips/vic_i/painter/saved_state.rb +40 -0
- data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +6 -30
- data/lib/badline/{vic20/vic → chips/vic_i}/saved_state.rb +2 -2
- data/lib/badline/chips/vic_i/sound/output.rb +85 -0
- data/lib/badline/chips/vic_i/sound.rb +235 -0
- data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
- data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +5 -5
- data/lib/badline/chips/z80/arithmetic.rb +119 -0
- data/lib/badline/chips/z80/bit_page.rb +57 -0
- data/lib/badline/chips/z80/block_io.rb +60 -0
- data/lib/badline/chips/z80/block_transfers.rb +61 -0
- data/lib/badline/chips/z80/bus_cycles.rb +113 -0
- data/lib/badline/chips/z80/core.rb +115 -0
- data/lib/badline/chips/z80/exchanges.rb +52 -0
- data/lib/badline/chips/z80/extended_page.rb +91 -0
- data/lib/badline/chips/z80/flags.rb +39 -0
- data/lib/badline/chips/z80/interrupt_acceptance.rb +48 -0
- data/lib/badline/chips/z80/jumps.rb +84 -0
- data/lib/badline/chips/z80/loads.rb +100 -0
- data/lib/badline/chips/z80/main_page.rb +136 -0
- data/lib/badline/chips/z80/registers.rb +122 -0
- data/lib/badline/chips/z80/saved_state.rb +71 -0
- data/lib/badline/chips/z80/shifts.rb +66 -0
- data/lib/badline/chips/z80.rb +13 -0
- data/lib/badline/core.rb +26 -28
- data/lib/badline/drives/datasette/saved_state.rb +37 -0
- data/lib/badline/drives/datasette.rb +140 -0
- data/lib/badline/drives/engine/core.rb +149 -0
- data/lib/badline/drives/engine/fast_serial.rb +75 -0
- data/lib/badline/drives/engine/idle.rb +127 -0
- data/lib/badline/drives/engine/idle_cpu.rb +30 -0
- data/lib/badline/drives/engine/orbit.rb +81 -0
- data/lib/badline/drives/engine/serial_lines.rb +75 -0
- data/lib/badline/drives/engine/sleep.rb +114 -0
- data/lib/badline/drives/engine/vias.rb +86 -0
- data/lib/badline/drives/engine/watch.rb +152 -0
- data/lib/badline/drives/engine.rb +11 -0
- data/lib/badline/drives/model1541/bus.rb +88 -0
- data/lib/badline/drives/model1541/byte_ready.rb +50 -0
- data/lib/badline/drives/model1541/cpu.rb +13 -0
- data/lib/badline/drives/model1541/disk/saved_state.rb +88 -0
- data/lib/badline/drives/model1541/disk.rb +317 -0
- data/lib/badline/drives/model1541/disk_via.rb +38 -0
- data/lib/badline/drives/model1541/gcr.rb +59 -0
- data/lib/badline/drives/model1541/mechanism/saved_state.rb +72 -0
- data/lib/badline/drives/model1541/mechanism.rb +315 -0
- data/lib/badline/drives/model1541/rotation.rb +123 -0
- data/lib/badline/drives/model1541/saved_state.rb +44 -0
- data/lib/badline/drives/model1541/sector_reader.rb +78 -0
- data/lib/badline/drives/model1541/serial_port.rb +20 -0
- data/lib/badline/drives/model1541/track.rb +100 -0
- data/lib/badline/drives/model1541.rb +81 -0
- data/lib/badline/drives/model1571/bus.rb +113 -0
- data/lib/badline/drives/model1571/cpu.rb +13 -0
- data/lib/badline/drives/model1571/saved_state.rb +47 -0
- data/lib/badline/drives/model1571/serial_port.rb +39 -0
- data/lib/badline/drives/model1571/serial_via.rb +27 -0
- data/lib/badline/drives/model1571/wd1770.rb +122 -0
- data/lib/badline/drives/model1571.rb +142 -0
- data/lib/badline/drives/model1581/bus.rb +139 -0
- data/lib/badline/drives/model1581/cpu.rb +13 -0
- data/lib/badline/drives/model1581/disk/saved_state.rb +89 -0
- data/lib/badline/drives/model1581/disk.rb +137 -0
- data/lib/badline/drives/model1581/mechanism.rb +119 -0
- data/lib/badline/drives/model1581/saved_state.rb +42 -0
- data/lib/badline/drives/model1581/serial_port.rb +54 -0
- data/lib/badline/drives/model1581/slot.rb +79 -0
- data/lib/badline/drives/model1581/track.rb +102 -0
- data/lib/badline/drives/model1581/track_bytes.rb +77 -0
- data/lib/badline/drives/model1581/wd1772/registers.rb +91 -0
- data/lib/badline/drives/model1581/wd1772/saved_state.rb +68 -0
- data/lib/badline/drives/model1581/wd1772/sector_writes.rb +75 -0
- data/lib/badline/drives/model1581/wd1772/sectors.rb +152 -0
- data/lib/badline/drives/model1581/wd1772/stepping.rb +111 -0
- data/lib/badline/drives/model1581/wd1772/tracks.rb +127 -0
- data/lib/badline/drives/model1581/wd1772/turn.rb +75 -0
- data/lib/badline/drives/model1581/wd1772.rb +218 -0
- data/lib/badline/drives/model1581.rb +206 -0
- data/lib/badline/drives/serial_bus.rb +161 -0
- data/lib/badline/frontend/boot.rb +3 -3
- data/lib/badline/frontend/machine_window.rb +3 -1
- data/lib/badline/frontend/player/filter_view.rb +1 -1
- data/lib/badline/frontend/player/player_controller.rb +2 -2
- data/lib/badline/frontend/player/player_screen.rb +1 -0
- data/lib/badline/frontend/player/theme.rb +7 -7
- data/lib/badline/frontend/timeline.rb +3 -3
- data/lib/badline/input/control_ports.rb +78 -0
- data/lib/badline/input/joystick.rb +27 -0
- data/lib/badline/input/keyboard.rb +114 -0
- data/lib/badline/input.rb +3 -0
- data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
- data/lib/badline/kernal_trap/dos/channel.rb +183 -0
- data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
- data/lib/badline/kernal_trap/{drive.rb → dos.rb} +11 -10
- data/lib/badline/kernal_trap/load.rb +5 -5
- data/lib/badline/kernal_trap/save.rb +4 -4
- data/lib/badline/kernal_trap/serial.rb +7 -7
- data/lib/badline/kernal_trap.rb +1 -2
- data/lib/badline/machine/clocking.rb +1 -1
- data/lib/badline/machine.rb +5 -5
- data/lib/badline/media/true_drive.rb +1 -1
- data/lib/badline/media/tune.rb +2 -2
- data/lib/badline/media.rb +3 -3
- data/lib/badline/model.rb +1 -1
- data/lib/badline/roms/README +6 -6
- data/lib/badline/sdl.rb +1 -0
- data/lib/badline/{storage/sid_file.rb → sid_tune/file.rb} +3 -3
- data/lib/badline/{storage → sid_tune}/hvsc.rb +7 -7
- data/lib/badline/{storage → sid_tune}/song_lengths.rb +2 -2
- data/lib/badline/{storage → sid_tune}/stil/credit.rb +1 -1
- data/lib/badline/{storage → sid_tune}/stil.rb +3 -3
- data/lib/badline/sid_tune.rb +6 -0
- data/lib/badline/snapshot/c128_setup.rb +43 -0
- data/lib/badline/snapshot/c64_setup.rb +79 -0
- data/lib/badline/snapshot/image.rb +5 -25
- data/lib/badline/snapshot/machine_state.rb +1 -1
- data/lib/badline/snapshot/setup.rb +22 -66
- data/lib/badline/snapshot/state.rb +8 -18
- data/lib/badline/snapshot/storage_setup.rb +68 -0
- data/lib/badline/snapshot/vic20_setup.rb +37 -0
- data/lib/badline/snapshot/vice/c64_mem.rb +1 -1
- data/lib/badline/snapshot/vice/restore.rb +1 -1
- data/lib/badline/snapshot/vice/reu1764.rb +1 -1
- data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
- data/lib/badline/snapshot/vice.rb +7 -5
- data/lib/badline/snapshot.rb +3 -4
- data/lib/badline/storage/d64_image.rb +0 -2
- data/lib/badline/storage/d71_image.rb +0 -2
- data/lib/badline/storage/d81_image.rb +0 -2
- data/lib/badline/storage/disk_image.rb +3 -6
- data/lib/badline/storage/g64_image.rb +2 -2
- data/lib/badline/storage/host_directory.rb +0 -5
- data/lib/badline/storage/t64.rb +2 -8
- data/lib/badline/storage/unavailable.rb +1 -1
- data/lib/badline/storage.rb +0 -37
- data/lib/badline/support/c128_checkpoint.rb +39 -0
- data/lib/badline/support/checkpoint.rb +108 -0
- data/lib/badline/support/vic20_checkpoint.rb +38 -0
- data/lib/badline/support.rb +5 -0
- data/lib/badline/version.rb +1 -1
- data/lib/badline/vic20/attachments.rb +5 -5
- data/lib/badline/vic20/bus/saved_state.rb +35 -0
- data/lib/badline/vic20/bus.rb +3 -25
- data/lib/badline/vic20/cpu.rb +1 -1
- data/lib/badline/vic20/port_wiring.rb +4 -4
- data/lib/badline/vic20/saved_state.rb +16 -30
- data/lib/badline/vic20/user_via_ports.rb +2 -2
- data/lib/badline/vic20.rb +19 -14
- metadata +245 -221
- data/lib/badline/address_bus/extra_sids.rb +0 -30
- data/lib/badline/address_bus/fittings.rb +0 -38
- data/lib/badline/address_bus/pla.rb +0 -147
- data/lib/badline/address_bus/roms.rb +0 -39
- data/lib/badline/address_bus/saved_state.rb +0 -66
- data/lib/badline/address_bus/sid_slots.rb +0 -42
- data/lib/badline/address_bus.rb +0 -216
- data/lib/badline/cartridge/action_replay.rb +0 -126
- data/lib/badline/cartridge/atomic_power.rb +0 -24
- data/lib/badline/cartridge/bank.rb +0 -81
- data/lib/badline/cartridge/comal80.rb +0 -50
- data/lib/badline/cartridge/dinamic.rb +0 -34
- data/lib/badline/cartridge/easy_flash.rb +0 -145
- data/lib/badline/cartridge/epyx_fastload.rb +0 -79
- data/lib/badline/cartridge/final_cartridge3.rb +0 -89
- data/lib/badline/cartridge/flash.rb +0 -306
- data/lib/badline/cartridge/freezer.rb +0 -33
- data/lib/badline/cartridge/fun_play.rb +0 -38
- data/lib/badline/cartridge/g_mod2.rb +0 -74
- data/lib/badline/cartridge/game_system.rb +0 -40
- data/lib/badline/cartridge/geo_ram.rb +0 -79
- data/lib/badline/cartridge/kcs_power.rb +0 -75
- data/lib/badline/cartridge/mach5.rb +0 -32
- data/lib/badline/cartridge/magic_desk.rb +0 -30
- data/lib/badline/cartridge/ocean.rb +0 -35
- data/lib/badline/cartridge/pagefox.rb +0 -68
- data/lib/badline/cartridge/retro_replay.rb +0 -320
- data/lib/badline/cartridge/rex_utility.rb +0 -29
- data/lib/badline/cartridge/rgcd.rb +0 -58
- data/lib/badline/cartridge/simons_basic.rb +0 -35
- data/lib/badline/cartridge/standard.rb +0 -15
- data/lib/badline/cartridge/super_games.rb +0 -48
- data/lib/badline/cartridge/westermann.rb +0 -30
- data/lib/badline/cartridge/zaxxon.rb +0 -66
- data/lib/badline/cartridge.rb +0 -303
- data/lib/badline/checkpoint.rb +0 -98
- data/lib/badline/cia/fast_forward.rb +0 -60
- data/lib/badline/cia/interrupt_register.rb +0 -143
- data/lib/badline/cia/serial.rb +0 -275
- data/lib/badline/cia/state.rb +0 -47
- data/lib/badline/cia/timer.rb +0 -206
- data/lib/badline/cia.rb +0 -279
- data/lib/badline/color_memory.rb +0 -25
- data/lib/badline/control_ports.rb +0 -76
- data/lib/badline/cpu/addressing.rb +0 -131
- data/lib/badline/cpu/boundary.rb +0 -54
- data/lib/badline/cpu/core.rb +0 -165
- data/lib/badline/cpu/microcode.rb +0 -177
- data/lib/badline/cpu/operations.rb +0 -88
- data/lib/badline/cpu/saved_state.rb +0 -115
- data/lib/badline/cpu/stack_operations.rb +0 -82
- data/lib/badline/cpu.rb +0 -10
- data/lib/badline/cpu_port.rb +0 -112
- data/lib/badline/datasette.rb +0 -161
- data/lib/badline/drive/core.rb +0 -147
- data/lib/badline/drive/fast_serial.rb +0 -73
- data/lib/badline/drive/idle.rb +0 -125
- data/lib/badline/drive/idle_cpu.rb +0 -28
- data/lib/badline/drive/orbit.rb +0 -79
- data/lib/badline/drive/serial_lines.rb +0 -73
- data/lib/badline/drive/sleep.rb +0 -112
- data/lib/badline/drive/vias.rb +0 -84
- data/lib/badline/drive/watch.rb +0 -150
- data/lib/badline/drive.rb +0 -11
- data/lib/badline/drive1541/bus.rb +0 -86
- data/lib/badline/drive1541/byte_ready.rb +0 -48
- data/lib/badline/drive1541/cpu.rb +0 -11
- data/lib/badline/drive1541/disk.rb +0 -315
- data/lib/badline/drive1541/disk_state.rb +0 -86
- data/lib/badline/drive1541/disk_via.rb +0 -36
- data/lib/badline/drive1541/gcr.rb +0 -57
- data/lib/badline/drive1541/mechanism.rb +0 -313
- data/lib/badline/drive1541/mechanism_state.rb +0 -68
- data/lib/badline/drive1541/rotation.rb +0 -121
- data/lib/badline/drive1541/sector_reader.rb +0 -76
- data/lib/badline/drive1541/serial_port.rb +0 -18
- data/lib/badline/drive1541/track.rb +0 -98
- data/lib/badline/drive1541.rb +0 -111
- data/lib/badline/drive1571/bus.rb +0 -111
- data/lib/badline/drive1571/cpu.rb +0 -11
- data/lib/badline/drive1571/serial_port.rb +0 -37
- data/lib/badline/drive1571/serial_via.rb +0 -25
- data/lib/badline/drive1571/wd1770.rb +0 -120
- data/lib/badline/drive1571.rb +0 -175
- data/lib/badline/drive1581/bus.rb +0 -137
- data/lib/badline/drive1581/cpu.rb +0 -11
- data/lib/badline/drive1581/disk.rb +0 -135
- data/lib/badline/drive1581/disk_state.rb +0 -87
- data/lib/badline/drive1581/mechanism.rb +0 -117
- data/lib/badline/drive1581/serial_port.rb +0 -52
- data/lib/badline/drive1581/slot.rb +0 -78
- data/lib/badline/drive1581/track.rb +0 -100
- data/lib/badline/drive1581/track_bytes.rb +0 -75
- data/lib/badline/drive1581/wd1772/registers.rb +0 -89
- data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
- data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
- data/lib/badline/drive1581/wd1772/state.rb +0 -66
- data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
- data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
- data/lib/badline/drive1581/wd1772/turn.rb +0 -73
- data/lib/badline/drive1581/wd1772.rb +0 -216
- data/lib/badline/drive1581.rb +0 -233
- data/lib/badline/iec_bus.rb +0 -159
- data/lib/badline/instruction.rb +0 -334
- data/lib/badline/instruction_set/arithmetic.rb +0 -114
- data/lib/badline/instruction_set/bitwise.rb +0 -126
- data/lib/badline/instruction_set/branch.rb +0 -79
- data/lib/badline/instruction_set/flag.rb +0 -63
- data/lib/badline/instruction_set/illegal.rb +0 -270
- data/lib/badline/instruction_set/inc_dec.rb +0 -69
- data/lib/badline/instruction_set/stack.rb +0 -52
- data/lib/badline/instruction_set/transfer.rb +0 -137
- data/lib/badline/instruction_set.rb +0 -55
- data/lib/badline/interrupts.rb +0 -104
- data/lib/badline/joystick.rb +0 -25
- data/lib/badline/kernal_trap/channel.rb +0 -181
- data/lib/badline/keyboard.rb +0 -112
- data/lib/badline/ram_expansion/banking.rb +0 -30
- data/lib/badline/ram_expansion/plus256k.rb +0 -54
- data/lib/badline/ram_expansion/plus60k.rb +0 -43
- data/lib/badline/ram_expansion/unexpanded.rb +0 -28
- data/lib/badline/ram_expansion.rb +0 -21
- data/lib/badline/reu/dma/saved_state.rb +0 -50
- data/lib/badline/reu/dma.rb +0 -273
- data/lib/badline/reu/ram.rb +0 -107
- data/lib/badline/reu/saved_state.rb +0 -80
- data/lib/badline/reu/trigger.rb +0 -32
- data/lib/badline/reu.rb +0 -289
- data/lib/badline/sid/catch_up.rb +0 -120
- data/lib/badline/sid/decimator.rb +0 -64
- data/lib/badline/sid/envelope/state.rb +0 -68
- data/lib/badline/sid/envelope.rb +0 -239
- data/lib/badline/sid/filter.rb +0 -263
- data/lib/badline/sid/voice.rb +0 -77
- data/lib/badline/sid/waveform/combined.rb +0 -126
- data/lib/badline/sid/waveform/fast_forward.rb +0 -105
- data/lib/badline/sid/waveform/noise_writeback.rb +0 -122
- data/lib/badline/sid/waveform/state.rb +0 -66
- data/lib/badline/sid/waveform.rb +0 -305
- data/lib/badline/sid.rb +0 -303
- data/lib/badline/time_of_day.rb +0 -228
- data/lib/badline/traps.rb +0 -19
- data/lib/badline/via/control_lines.rb +0 -122
- data/lib/badline/via/fast_forward.rb +0 -53
- data/lib/badline/via/interrupt_register.rb +0 -67
- data/lib/badline/via/shift_register.rb +0 -180
- data/lib/badline/via/state.rb +0 -42
- data/lib/badline/via/timer1.rb +0 -131
- data/lib/badline/via/timer2.rb +0 -133
- data/lib/badline/via.rb +0 -266
- data/lib/badline/vic/bank.rb +0 -133
- data/lib/badline/vic/border_mask.rb +0 -86
- data/lib/badline/vic/collisions.rb +0 -115
- data/lib/badline/vic/color_patches.rb +0 -47
- data/lib/badline/vic/display_state.rb +0 -185
- data/lib/badline/vic/graphics_mode.rb +0 -164
- data/lib/badline/vic/graphics_shifter.rb +0 -207
- data/lib/badline/vic/register_log.rb +0 -81
- data/lib/badline/vic/registers.rb +0 -195
- data/lib/badline/vic/sequencer.rb +0 -275
- data/lib/badline/vic/sequencer_output.rb +0 -116
- data/lib/badline/vic/sequencer_state.rb +0 -89
- data/lib/badline/vic/sprite/internal_bus.rb +0 -68
- data/lib/badline/vic/sprite/saved_state.rb +0 -64
- data/lib/badline/vic/sprite/shifter.rb +0 -146
- data/lib/badline/vic/sprite/timing.rb +0 -56
- data/lib/badline/vic/sprite.rb +0 -337
- data/lib/badline/vic/sprites.rb +0 -282
- data/lib/badline/vic/sprites_state.rb +0 -57
- data/lib/badline/vic.rb +0 -853
- data/lib/badline/vic20/sound/output.rb +0 -83
- data/lib/badline/vic20/sound.rb +0 -233
- data/lib/badline/z80/arithmetic.rb +0 -117
- data/lib/badline/z80/bit_page.rb +0 -55
- data/lib/badline/z80/block_io.rb +0 -58
- data/lib/badline/z80/block_transfers.rb +0 -59
- data/lib/badline/z80/bus_cycles.rb +0 -111
- data/lib/badline/z80/core.rb +0 -113
- data/lib/badline/z80/exchanges.rb +0 -50
- data/lib/badline/z80/extended_page.rb +0 -89
- data/lib/badline/z80/flags.rb +0 -37
- data/lib/badline/z80/interrupt_acceptance.rb +0 -46
- data/lib/badline/z80/jumps.rb +0 -82
- data/lib/badline/z80/loads.rb +0 -98
- data/lib/badline/z80/main_page.rb +0 -134
- data/lib/badline/z80/registers.rb +0 -120
- data/lib/badline/z80/saved_state.rb +0 -69
- data/lib/badline/z80/shifts.rb +0 -64
- data/lib/badline/z80.rb +0 -11
- /data/lib/badline/snapshot/{fields.rb → vice/fields.rb} +0 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class VIC
|
|
6
|
+
# = VIC-II display state
|
|
7
|
+
#
|
|
8
|
+
# The bad line condition, the video counters it drives, and the DMA it
|
|
9
|
+
# starts. A condition that arrives mid-line opens the row late, which is
|
|
10
|
+
# what makes the screen scroll sideways or lose a column of cells.
|
|
11
|
+
class DisplayState
|
|
12
|
+
FIRST_LINE = 0x30 # 48: bad lines and the DEN-at-$30 latch begin here
|
|
13
|
+
LAST_LINE = 0xf7 # 247
|
|
14
|
+
COLUMNS_PER_ROW = 40
|
|
15
|
+
|
|
16
|
+
# AEC follows BA three cycles later; the c-accesses before it read
|
|
17
|
+
# the bus the CPU still drives.
|
|
18
|
+
BA_DELAY = 3
|
|
19
|
+
|
|
20
|
+
# Columns run two ahead of Bauer's cycle numbers: column 10 is his
|
|
21
|
+
# cycle 12. BA falls on a match in columns 10-52, the c-accesses run
|
|
22
|
+
# in 13-52 and the g-accesses in 14-53. VC and VMLI reload in column
|
|
23
|
+
# 12 and the row counter steps in column 56.
|
|
24
|
+
DMA_FIRST = 10
|
|
25
|
+
DMA_LAST = 52
|
|
26
|
+
FETCH_FIRST = 13
|
|
27
|
+
GRAPHICS_FIRST = 14
|
|
28
|
+
GRAPHICS_LAST = 53
|
|
29
|
+
LOAD_COLUMN = 12
|
|
30
|
+
RC_COLUMN = 56
|
|
31
|
+
|
|
32
|
+
GRAPHICS_COLUMNS = Array.new(65) { |column| column.between?(GRAPHICS_FIRST, GRAPHICS_LAST) }.freeze
|
|
33
|
+
|
|
34
|
+
attr_reader :vc_base, :vc, :vmli, :rc, :bad_lines_enabled
|
|
35
|
+
|
|
36
|
+
# The wrap column is the last column of a rasterline, 62 on the 6569,
|
|
37
|
+
# which already compares against the line about to start, the same
|
|
38
|
+
# wrap the raster IRQ latch uses.
|
|
39
|
+
def initialize(registers, wrap_column = 62)
|
|
40
|
+
@registers = registers
|
|
41
|
+
@wrap_column = wrap_column
|
|
42
|
+
@vc_base = 0
|
|
43
|
+
@vc = 0
|
|
44
|
+
@vmli = 0
|
|
45
|
+
@rc = 0
|
|
46
|
+
@display = false
|
|
47
|
+
@bad_lines_enabled = false
|
|
48
|
+
@matched = false
|
|
49
|
+
@ba = nil
|
|
50
|
+
new_line(0)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def display? = @display
|
|
54
|
+
|
|
55
|
+
# Sets VCBASE, VC, RC and VMLI, in that order, and the display and
|
|
56
|
+
# bad-line flags, as a VICE snapshot gives them.
|
|
57
|
+
def restore_counters(counters, display, bad_lines_enabled)
|
|
58
|
+
@vc_base, @vc, @rc, @vmli = counters
|
|
59
|
+
@display = display
|
|
60
|
+
@bad_lines_enabled = bad_lines_enabled
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def idle? = !@display
|
|
64
|
+
def bad_line? = !@ba.nil?
|
|
65
|
+
|
|
66
|
+
# The bad line condition as the last column compared it.
|
|
67
|
+
def bad_line_condition? = @matched
|
|
68
|
+
|
|
69
|
+
# True once AEC has followed BA down and the VIC owns the bus.
|
|
70
|
+
def bus_taken?(column) = @ba ? column >= @ba + BA_DELAY : false
|
|
71
|
+
|
|
72
|
+
# The CPU kept the bus through the cycle before +column+, so on a bad
|
|
73
|
+
# line AEC falls BA_DELAY cycles after it at the earliest.
|
|
74
|
+
def keep_bus(column)
|
|
75
|
+
@ba &&= column
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def fetching?(column)
|
|
79
|
+
@matched && column >= FETCH_FIRST && column <= DMA_LAST
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def save_state(out)
|
|
83
|
+
out.int(@vc_base).int(@vc).int(@vmli).int(@rc).boolean(@display).boolean(@bad_lines_enabled)
|
|
84
|
+
out.boolean(@matched).optional_int(@ba).int(@line_bits).boolean(@den_line).boolean(@in_window)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def load_state(input)
|
|
88
|
+
@vc_base = input.int
|
|
89
|
+
@vc = input.int
|
|
90
|
+
@vmli = input.int
|
|
91
|
+
@rc = input.int
|
|
92
|
+
@display = input.boolean?
|
|
93
|
+
@bad_lines_enabled = input.boolean?
|
|
94
|
+
@matched = input.boolean?
|
|
95
|
+
@ba = input.optional_int
|
|
96
|
+
@line_bits = input.int
|
|
97
|
+
@den_line = input.boolean?
|
|
98
|
+
@in_window = input.boolean?
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def new_frame
|
|
102
|
+
@vc_base = 0
|
|
103
|
+
@bad_lines_enabled = false
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def new_line(line)
|
|
107
|
+
@ba = nil
|
|
108
|
+
raster_step(line)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# The raster counter moved on to +line+, at the line's start or, under
|
|
112
|
+
# the VIC-IIe's TEST bit, within it.
|
|
113
|
+
def raster_step(line)
|
|
114
|
+
@line_bits = line & 0b111
|
|
115
|
+
@den_line = line == FIRST_LINE
|
|
116
|
+
@in_window = line.between?(FIRST_LINE, LAST_LINE)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Returns true when this compare opened display state.
|
|
120
|
+
def cycle(rasterline, column)
|
|
121
|
+
match = column == @wrap_column ? wrap_match(rasterline + 1) : line_match
|
|
122
|
+
@matched = match
|
|
123
|
+
opened = false
|
|
124
|
+
if match
|
|
125
|
+
opened = !@display
|
|
126
|
+
@display = true
|
|
127
|
+
@ba = column if @ba.nil? && column >= DMA_FIRST && column <= DMA_LAST
|
|
128
|
+
end
|
|
129
|
+
load_counters(match) if column == LOAD_COLUMN
|
|
130
|
+
check_row_counter(match) if column == RC_COLUMN
|
|
131
|
+
opened
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# A g-access in display state consumes one buffer cell and one video
|
|
135
|
+
# matrix address. A row that opens mid-line makes fewer of them, and
|
|
136
|
+
# the shortfall carries into VCBASE.
|
|
137
|
+
def graphics_column?(column) = GRAPHICS_COLUMNS[column]
|
|
138
|
+
|
|
139
|
+
def graphics_access(column)
|
|
140
|
+
return unless graphics_column?(column)
|
|
141
|
+
|
|
142
|
+
@vc = (@vc + 1) & 0x3ff
|
|
143
|
+
@vmli += 1
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
private
|
|
147
|
+
|
|
148
|
+
def line_match
|
|
149
|
+
latch_den if @den_line
|
|
150
|
+
@bad_lines_enabled && @in_window && @line_bits == @registers.yscroll
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# The wrap column compares against the line about to start. The DEN
|
|
154
|
+
# latch is level-sensitive across the counter's increment, so this one
|
|
155
|
+
# column sees both the line ending and the line starting.
|
|
156
|
+
def wrap_match(line)
|
|
157
|
+
latch_den if @den_line || line == FIRST_LINE
|
|
158
|
+
return false unless line.between?(FIRST_LINE, LAST_LINE)
|
|
159
|
+
|
|
160
|
+
@bad_lines_enabled && (line & 0b111) == @registers.yscroll
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def latch_den
|
|
164
|
+
@bad_lines_enabled = true if @registers.display_enabled?
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def load_counters(match)
|
|
168
|
+
@vc = @vc_base
|
|
169
|
+
@vmli = 0
|
|
170
|
+
@rc = 0 if match
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# A condition still standing when the row counter wraps puts the logic
|
|
174
|
+
# straight back into display state, so a forced row rolls into the
|
|
175
|
+
# next one instead of leaving the line idle (Bauer 3.7.2 step 5).
|
|
176
|
+
def check_row_counter(match)
|
|
177
|
+
if @rc == 7
|
|
178
|
+
@display = false
|
|
179
|
+
@vc_base = @vc
|
|
180
|
+
end
|
|
181
|
+
@display ||= match
|
|
182
|
+
@rc = (@rc + 1) & 0b111 if @display
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class VIC
|
|
6
|
+
module GraphicsMode
|
|
7
|
+
# Foreground masks depend only on the data byte, so each byte maps to a
|
|
8
|
+
# precomputed frozen pattern shared by reference instead of being
|
|
9
|
+
# written out pixel by pixel.
|
|
10
|
+
HIRES_FG = Array.new(256) do |data|
|
|
11
|
+
Array.new(8) { |i| data.anybits?(1 << (7 - i)) }.freeze
|
|
12
|
+
end.freeze
|
|
13
|
+
|
|
14
|
+
# The high bit of each 2-bit pair (10/11) is foreground.
|
|
15
|
+
PAIR_FG = Array.new(256) do |data|
|
|
16
|
+
Array.new(8) { |i| (data >> (6 - (i & ~1))).allbits?(0b10) }.freeze
|
|
17
|
+
end.freeze
|
|
18
|
+
|
|
19
|
+
# The same patterns as masks, all bits set for a foreground pixel.
|
|
20
|
+
HIRES_MASK = Array.new(256) do |data|
|
|
21
|
+
Array.new(8) { |i| data.anybits?(1 << (7 - i)) ? -1 : 0 }.freeze
|
|
22
|
+
end.freeze
|
|
23
|
+
|
|
24
|
+
NO_FG = HIRES_FG[0]
|
|
25
|
+
|
|
26
|
+
module Hires
|
|
27
|
+
def paint_hires(data, color, background, seq)
|
|
28
|
+
seq.cur_fg = HIRES_FG[data]
|
|
29
|
+
colors = seq.cur_colors
|
|
30
|
+
return colors.fill(background) if data.zero?
|
|
31
|
+
|
|
32
|
+
mask = HIRES_MASK[data]
|
|
33
|
+
flip = color ^ background
|
|
34
|
+
colors[0] = background ^ (flip & mask[0])
|
|
35
|
+
colors[1] = background ^ (flip & mask[1])
|
|
36
|
+
colors[2] = background ^ (flip & mask[2])
|
|
37
|
+
colors[3] = background ^ (flip & mask[3])
|
|
38
|
+
colors[4] = background ^ (flip & mask[4])
|
|
39
|
+
colors[5] = background ^ (flip & mask[5])
|
|
40
|
+
colors[6] = background ^ (flip & mask[6])
|
|
41
|
+
colors[7] = background ^ (flip & mask[7])
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Decodes 2-bit pixel pairs into double-wide pixels, each pair indexing
|
|
46
|
+
# the four colours in the mode's palette.
|
|
47
|
+
module Multicolor
|
|
48
|
+
def paint_pairs(data, seq)
|
|
49
|
+
seq.cur_fg = PAIR_FG[data]
|
|
50
|
+
colors = seq.cur_colors
|
|
51
|
+
palette = @palette
|
|
52
|
+
colors[0] = colors[1] = palette[data >> 6]
|
|
53
|
+
colors[2] = colors[3] = palette[(data >> 4) & 0b11]
|
|
54
|
+
colors[4] = colors[5] = palette[(data >> 2) & 0b11]
|
|
55
|
+
colors[6] = colors[7] = palette[data & 0b11]
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Each mode paints the byte a g-access read with the screen byte and
|
|
60
|
+
# colour nibble it latched. The VIC reads the byte itself, in the
|
|
61
|
+
# g-access column. #fg gives the foreground mask #paint would leave,
|
|
62
|
+
# without the colours.
|
|
63
|
+
class Text
|
|
64
|
+
include Hires
|
|
65
|
+
|
|
66
|
+
def paint(data, _screencode, color, seq)
|
|
67
|
+
paint_hires(data, color, seq.registers.background, seq)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def fg(data, _screencode, _color) = HIRES_FG[data]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
class MulticolorText
|
|
74
|
+
include Hires
|
|
75
|
+
include Multicolor
|
|
76
|
+
|
|
77
|
+
def initialize
|
|
78
|
+
@palette = Array.new(4, 0)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def paint(data, _screencode, color, seq)
|
|
82
|
+
registers = seq.registers
|
|
83
|
+
if color.anybits?(0x08)
|
|
84
|
+
palette = @palette
|
|
85
|
+
palette[0] = registers.background(0)
|
|
86
|
+
palette[1] = registers.background(1)
|
|
87
|
+
palette[2] = registers.background(2)
|
|
88
|
+
palette[3] = color & 0x07
|
|
89
|
+
paint_pairs(data, seq)
|
|
90
|
+
else
|
|
91
|
+
paint_hires(data, color & 0x07, registers.background, seq)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def fg(data, _screencode, color) = color.anybits?(0x08) ? PAIR_FG[data] : HIRES_FG[data]
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
class ExtendedBackgroundText
|
|
99
|
+
include Hires
|
|
100
|
+
|
|
101
|
+
def paint(data, screencode, color, seq)
|
|
102
|
+
background = seq.registers.background((screencode >> 6) & 0b11)
|
|
103
|
+
paint_hires(data, color, background, seq)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def fg(data, _screencode, _color) = HIRES_FG[data]
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
class Bitmap
|
|
110
|
+
include Hires
|
|
111
|
+
|
|
112
|
+
def paint(data, screencode, _color, seq)
|
|
113
|
+
foreground = (screencode >> 4) & 0x0f
|
|
114
|
+
background = screencode & 0x0f
|
|
115
|
+
paint_hires(data, foreground, background, seq)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def fg(data, _screencode, _color) = HIRES_FG[data]
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
class MulticolorBitmap
|
|
122
|
+
include Multicolor
|
|
123
|
+
|
|
124
|
+
def initialize
|
|
125
|
+
@palette = Array.new(4, 0)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def paint(data, screencode, color, seq)
|
|
129
|
+
palette = @palette
|
|
130
|
+
palette[0] = seq.registers.background(0)
|
|
131
|
+
palette[1] = (screencode >> 4) & 0x0f
|
|
132
|
+
palette[2] = screencode & 0x0f
|
|
133
|
+
palette[3] = color & 0x0f
|
|
134
|
+
paint_pairs(data, seq)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def fg(data, _screencode, _color) = PAIR_FG[data]
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
class Null
|
|
141
|
+
def paint(_data, _screencode, _color, seq)
|
|
142
|
+
seq.cur_fg = NO_FG
|
|
143
|
+
seq.cur_colors.fill(0)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def fg(_data, _screencode, _color) = NO_FG
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
NULL_MODE = Null.new
|
|
150
|
+
|
|
151
|
+
# Indexed by ECM/BMM/MCM; the three invalid combinations decode to
|
|
152
|
+
# black.
|
|
153
|
+
MODES = [
|
|
154
|
+
Text.new, # 000 standard text
|
|
155
|
+
MulticolorText.new, # 001 multicolour text
|
|
156
|
+
Bitmap.new, # 010 standard bitmap
|
|
157
|
+
MulticolorBitmap.new, # 011 multicolour bitmap
|
|
158
|
+
ExtendedBackgroundText.new, # 100 ECM text
|
|
159
|
+
NULL_MODE, # 101 invalid
|
|
160
|
+
NULL_MODE, # 110 invalid
|
|
161
|
+
NULL_MODE # 111 invalid
|
|
162
|
+
].freeze
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class VIC
|
|
6
|
+
class GraphicsShifter
|
|
7
|
+
# The shifter's state for a snapshot.
|
|
8
|
+
module SavedState
|
|
9
|
+
def save_state(out)
|
|
10
|
+
out.int(@next_ecm_bmm).int(@black_below).ints(@colors).booleans(@fg)
|
|
11
|
+
out.int(@gbuf).int(@vbuf).int(@cbuf).int(@flop).int(@pixel)
|
|
12
|
+
out.int(@mode_lookup).int(@mode_read).boolean(@late_mcm).boolean(@late_read)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def load_state(input)
|
|
16
|
+
@next_ecm_bmm = input.int
|
|
17
|
+
@black_below = input.int
|
|
18
|
+
input.ints_into(@colors)
|
|
19
|
+
input.booleans_into(@fg)
|
|
20
|
+
load_buffers(input)
|
|
21
|
+
@mode_lookup = input.int
|
|
22
|
+
@mode_read = input.int
|
|
23
|
+
@late_mcm = input.boolean?
|
|
24
|
+
@late_read = input.boolean?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def load_buffers(input)
|
|
30
|
+
@gbuf = input.int
|
|
31
|
+
@vbuf = input.int
|
|
32
|
+
@cbuf = input.int
|
|
33
|
+
@flop = input.int
|
|
34
|
+
@pixel = input.int
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "badline/chips/vic/graphics_shifter/saved_state"
|
|
4
|
+
|
|
5
|
+
module Badline
|
|
6
|
+
module Chips
|
|
7
|
+
class VIC
|
|
8
|
+
# The graphics shift register, pixel by pixel, for the groups where a
|
|
9
|
+
# mode or XSCROLL change lands (VICE x64sc `draw_graphics`). The
|
|
10
|
+
# sequencer paints whole bytes everywhere else, which comes to the same
|
|
11
|
+
# thing while nothing changes.
|
|
12
|
+
#
|
|
13
|
+
# The byte a group draws loads at pixel XSCROLL. ECM and BMM take hold at
|
|
14
|
+
# pixel 4 as they rise and at pixel 6 as they fall (the 6569's colour
|
|
15
|
+
# latency), except that BMM falls at pixel 5 out of any mode but hi-res
|
|
16
|
+
# bitmap. MCM takes hold at pixel 4 for the colour lookup but only at
|
|
17
|
+
# pixel 7 for how the register is read, where a rising MCM also resets
|
|
18
|
+
# the multicolour flip-flop. An MCM that falls out of the invalid
|
|
19
|
+
# ECM+MCM mode is a pixel later on both counts: the lookup changes at
|
|
20
|
+
# pixel 5 and the read at the next group's pixel 0. The mode bits are
|
|
21
|
+
# the sequencer's: ECM 4, BMM 2, MCM 1.
|
|
22
|
+
#
|
|
23
|
+
# The 8565 has no colour latency: ECM and BMM take hold, rising or
|
|
24
|
+
# falling, at the next group's pixel 0, and an MCM that falls out of
|
|
25
|
+
# ECM+MCM does so on time. Where that pixel 0 takes the group out of an
|
|
26
|
+
# invalid mode, it is still black into hi-res text, and so is a
|
|
27
|
+
# background pixel into multicolour bitmap.
|
|
28
|
+
class GraphicsShifter
|
|
29
|
+
include SavedState
|
|
30
|
+
|
|
31
|
+
ECM = 0b100
|
|
32
|
+
ECM_BMM = 0b110
|
|
33
|
+
MULTICOLOR_BITMAP = 0b011
|
|
34
|
+
ECM_MCM = 0b101
|
|
35
|
+
BMM = 0b010
|
|
36
|
+
|
|
37
|
+
# The group #draw painted, and which of its pixels are foreground.
|
|
38
|
+
attr_reader :colors, :fg
|
|
39
|
+
|
|
40
|
+
def initialize(registers, model: :mos6569)
|
|
41
|
+
@registers = registers
|
|
42
|
+
@latency = model != :mos8565
|
|
43
|
+
@next_ecm_bmm = 0
|
|
44
|
+
@black_below = 0
|
|
45
|
+
@colors = Array.new(8, 0)
|
|
46
|
+
@fg = Array.new(8, false)
|
|
47
|
+
@gbuf = 0
|
|
48
|
+
@vbuf = 0
|
|
49
|
+
@cbuf = 0
|
|
50
|
+
@flop = 0
|
|
51
|
+
@pixel = 0
|
|
52
|
+
@mode_lookup = 0
|
|
53
|
+
@mode_read = 0
|
|
54
|
+
@late_mcm = false
|
|
55
|
+
@late_read = false
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Rebuilds the state at the end of a group that painted whole bytes:
|
|
59
|
+
# the byte loaded at pixel shift under an unchanging mode.
|
|
60
|
+
def prime(data, screencode, color, shift, mode)
|
|
61
|
+
@mode_lookup = mode
|
|
62
|
+
@next_ecm_bmm = mode & ECM_BMM
|
|
63
|
+
@mode_read = mode & 1
|
|
64
|
+
@late_read = false
|
|
65
|
+
load(data, screencode, color)
|
|
66
|
+
(8 - shift).times { read_pixel }
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Draws one group, loading the byte at pixel shift.
|
|
70
|
+
def draw(data, screencode, color, shift, mode)
|
|
71
|
+
i = 0
|
|
72
|
+
while i < 8
|
|
73
|
+
step_mode(i, mode)
|
|
74
|
+
load(data, screencode, color) if i == shift
|
|
75
|
+
pixel = read_pixel
|
|
76
|
+
@colors[i] = pixel < @black_below ? 0 : lookup(pixel)
|
|
77
|
+
@black_below = 0
|
|
78
|
+
@fg[i] = pixel >= 2
|
|
79
|
+
i += 1
|
|
80
|
+
end
|
|
81
|
+
@next_ecm_bmm = mode & ECM_BMM
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
def step_mode(pixel, mode)
|
|
87
|
+
case pixel
|
|
88
|
+
when 0 then start_group
|
|
89
|
+
when 4 then step_lookup(mode)
|
|
90
|
+
when 5 then step_early_fall(mode)
|
|
91
|
+
when 6 then @mode_lookup &= mode | 1 if @latency
|
|
92
|
+
when 7 then step_read
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def start_group
|
|
97
|
+
end_late_read
|
|
98
|
+
return if @latency
|
|
99
|
+
|
|
100
|
+
invalid = @mode_lookup > ECM
|
|
101
|
+
@mode_lookup = (@mode_lookup & ~ECM_BMM) | @next_ecm_bmm
|
|
102
|
+
@black_below = black_pixels_out_of_invalid if invalid
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# The pixel values below which pixel 0 stays black as the group leaves
|
|
106
|
+
# an invalid mode: all four into hi-res text, the background ones into
|
|
107
|
+
# multicolour bitmap.
|
|
108
|
+
def black_pixels_out_of_invalid
|
|
109
|
+
case @mode_lookup
|
|
110
|
+
when 0 then 4
|
|
111
|
+
when MULTICOLOR_BITMAP then 2
|
|
112
|
+
else 0
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def step_lookup(mode)
|
|
117
|
+
@late_mcm = @latency && @mode_lookup.allbits?(ECM_MCM) && mode.nobits?(1)
|
|
118
|
+
rising = @latency ? mode & ECM_BMM : 0
|
|
119
|
+
@mode_lookup = (@mode_lookup & ~1) | (mode & 1) | (@late_mcm ? 1 : 0) | rising
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def step_early_fall(mode)
|
|
123
|
+
@mode_lookup &= ~1 if @late_mcm
|
|
124
|
+
@mode_lookup &= mode | ~BMM if @latency && @mode_lookup != BMM
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def step_read
|
|
128
|
+
return @late_read = true if @late_mcm
|
|
129
|
+
|
|
130
|
+
mcm = @mode_lookup & 1
|
|
131
|
+
@flop = 0 if mcm == 1 && @mode_read.zero?
|
|
132
|
+
@mode_read = mcm
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def end_late_read
|
|
136
|
+
return unless @late_read
|
|
137
|
+
|
|
138
|
+
@mode_read = 0
|
|
139
|
+
@late_read = false
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def load(data, screencode, color)
|
|
143
|
+
@gbuf = data
|
|
144
|
+
@vbuf = screencode
|
|
145
|
+
@cbuf = color & 0x0f
|
|
146
|
+
@flop = 1
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def read_pixel
|
|
150
|
+
multicolor = multicolor?
|
|
151
|
+
if @mode_read == 1 && multicolor
|
|
152
|
+
@pixel = @gbuf >> 6 if @flop == 1
|
|
153
|
+
elsif @gbuf.anybits?(0x80)
|
|
154
|
+
@pixel = multicolor && @mode_read.zero? ? 2 : 3
|
|
155
|
+
else
|
|
156
|
+
@pixel = 0
|
|
157
|
+
end
|
|
158
|
+
@gbuf = (@gbuf << 1) & 0xff
|
|
159
|
+
@flop ^= 1
|
|
160
|
+
@pixel
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def multicolor? = @mode_lookup.anybits?(BMM) || @cbuf.anybits?(0x08)
|
|
164
|
+
|
|
165
|
+
def lookup(pixel)
|
|
166
|
+
case @mode_lookup
|
|
167
|
+
when 0 then pixel < 2 ? @registers.background : @cbuf
|
|
168
|
+
when 1 then pixel == 3 ? @cbuf & 0x07 : @registers.background(pixel)
|
|
169
|
+
when 2 then pixel < 2 ? @vbuf & 0x0f : @vbuf >> 4
|
|
170
|
+
when 3 then multicolor_bitmap(pixel)
|
|
171
|
+
when 4 then pixel < 2 ? @registers.background(@vbuf >> 6) : @cbuf
|
|
172
|
+
else 0
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def multicolor_bitmap(pixel)
|
|
177
|
+
case pixel
|
|
178
|
+
when 0 then @registers.background
|
|
179
|
+
when 1 then @vbuf >> 4
|
|
180
|
+
when 2 then @vbuf & 0x0f
|
|
181
|
+
else @cbuf
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class VIC
|
|
6
|
+
# Mid-line writes to the sprite registers, keyed by the pixel at which
|
|
7
|
+
# they become visible. Compositing replays the line through the log, so
|
|
8
|
+
# each pixel is drawn with the register values that were in effect when
|
|
9
|
+
# the VIC reached it.
|
|
10
|
+
class RegisterLog
|
|
11
|
+
def initialize(registers)
|
|
12
|
+
@registers = registers
|
|
13
|
+
@entries = []
|
|
14
|
+
@seed = []
|
|
15
|
+
@values = Array.new(2**6, 0)
|
|
16
|
+
@cursor = 0
|
|
17
|
+
@next_x = 0
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# The pixel at which the next logged write takes effect.
|
|
21
|
+
attr_reader :next_x
|
|
22
|
+
|
|
23
|
+
# The entries as pixel, register and value in turn, the seed with -1
|
|
24
|
+
# for a register the line hasn't logged, and a next pixel past the
|
|
25
|
+
# last entry as -1.
|
|
26
|
+
def save_state(out)
|
|
27
|
+
out.ints(@entries.flatten)
|
|
28
|
+
out.ints(@seed.map { |value| value.nil? ? -1 : value })
|
|
29
|
+
out.ints(@values).int(@cursor).int(@next_x.infinite? ? -1 : @next_x)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def load_state(input)
|
|
33
|
+
@entries.replace(input.ints.each_slice(3).to_a)
|
|
34
|
+
@seed.replace(input.ints.map { |value| value.negative? ? nil : value })
|
|
35
|
+
input.ints_into(@values)
|
|
36
|
+
@cursor = input.int
|
|
37
|
+
next_x = input.int
|
|
38
|
+
@next_x = next_x.negative? ? Float::INFINITY : next_x
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def empty? = @entries.empty?
|
|
42
|
+
def length = @entries.length
|
|
43
|
+
|
|
44
|
+
def clear
|
|
45
|
+
return if @entries.empty?
|
|
46
|
+
|
|
47
|
+
@entries.clear
|
|
48
|
+
@seed.clear
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def log(pixel_x, reg, old, value)
|
|
52
|
+
@seed[reg] = old if @seed[reg].nil?
|
|
53
|
+
@entries << [pixel_x, reg, value]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def prepare
|
|
57
|
+
@entries.sort_by! { |entry| entry[0] }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Restart the cursor before the line's first pixel, with every logged
|
|
61
|
+
# register back at the value it held when the line started.
|
|
62
|
+
def rewind
|
|
63
|
+
@values.length.times { |reg| @values[reg] = @registers[reg] }
|
|
64
|
+
@seed.each_with_index { |value, reg| @values[reg] = value unless value.nil? }
|
|
65
|
+
@cursor = 0
|
|
66
|
+
@next_x = @entries.empty? ? Float::INFINITY : @entries[0][0]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def [](reg) = @values[reg]
|
|
70
|
+
|
|
71
|
+
# Apply every write visible at or before pixel_x.
|
|
72
|
+
def advance(pixel_x)
|
|
73
|
+
while @cursor < @entries.length && @entries[@cursor][0] <= pixel_x
|
|
74
|
+
entry = @entries[@cursor]
|
|
75
|
+
@values[entry[1]] = entry[2]
|
|
76
|
+
@cursor += 1
|
|
77
|
+
end
|
|
78
|
+
@next_x = @cursor < @entries.length ? @entries[@cursor][0] : Float::INFINITY
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|