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
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class VIC < Cycleable
|
|
5
|
-
class Sprite
|
|
6
|
-
# = InternalBus
|
|
7
|
-
#
|
|
8
|
-
# What a sprite's s-accesses read while its DMA is off. The first and
|
|
9
|
-
# third fall in phi2, where the VIC's internal bus floats to $ff unless
|
|
10
|
-
# the CPU reads or writes a VIC register in that cycle, and the middle
|
|
11
|
-
# one is the idle fetch at $3fff (sbsprf24's readme).
|
|
12
|
-
class InternalBus
|
|
13
|
-
# The columns of a raster line, and where the region puts the
|
|
14
|
-
# sprites in it.
|
|
15
|
-
attr_reader :columns, :timing
|
|
16
|
-
|
|
17
|
-
def initialize(bank, timing)
|
|
18
|
-
@bank = bank
|
|
19
|
-
@timing = timing
|
|
20
|
-
@columns = timing.columns
|
|
21
|
-
@sprite_cycle = timing.sprite_cycle
|
|
22
|
-
@lines = 0
|
|
23
|
-
@ghost = 0xff
|
|
24
|
-
@value = Array.new(columns, 0xff)
|
|
25
|
-
@line = Array.new(columns, -1)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def save_state(out)
|
|
29
|
-
out.int(@lines).int(@ghost).ints(@value).ints(@line)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def load_state(input)
|
|
33
|
-
@lines = input.int
|
|
34
|
-
@ghost = input.int
|
|
35
|
-
input.ints_into(@value)
|
|
36
|
-
input.ints_into(@line)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
# Sprites 3-7 fetch in Bauer cycles 1-10, so the idle byte is taken
|
|
40
|
-
# as the line starts.
|
|
41
|
-
def start_line(sprites_enabled)
|
|
42
|
-
@lines += 1
|
|
43
|
-
@ghost = @bank.peek(0x3fff) if sprites_enabled
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
# The VIC has advanced to `column`, so the access runs in Bauer cycle
|
|
47
|
-
# `column + 1`, and column 0 is the first cycle of the line about to
|
|
48
|
-
# start.
|
|
49
|
-
def access(column, value)
|
|
50
|
-
@value[column] = value
|
|
51
|
-
@line[column] = column.zero? ? @lines + 1 : @lines
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# The row sprite `index` (3-7) fetched this line, in the phi2 halves
|
|
55
|
-
# of the two cycles from its p-access: Bauer cycles 2n-5 and 2n-4 on
|
|
56
|
-
# the 6569.
|
|
57
|
-
def row(index)
|
|
58
|
-
column = (@sprite_cycle + (2 * index) - 1) % @columns
|
|
59
|
-
(phi2(column) << 16) | (@ghost << 8) | phi2(column + 1)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
private
|
|
63
|
-
|
|
64
|
-
def phi2(column) = @line[column] == @lines ? @value[column] : 0xff
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
end
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class VIC < Cycleable
|
|
5
|
-
class Sprite
|
|
6
|
-
# The sprite's save_state and load_state.
|
|
7
|
-
module SavedState
|
|
8
|
-
# The shift register, MC, MCBASE, the expansion flip-flop and whether
|
|
9
|
-
# the sprite shows, for a VICE snapshot.
|
|
10
|
-
attr_reader :sr, :mc, :mcbase, :exp_ff, :display_on
|
|
11
|
-
|
|
12
|
-
# Sets MC, MCBASE, the expansion flip-flop, whether the sprite's DMA
|
|
13
|
-
# runs and whether it shows, as a VICE snapshot gives them.
|
|
14
|
-
def restore_counters(counter, base, expanded, dma, shows)
|
|
15
|
-
@mc = counter
|
|
16
|
-
@mcbase = base
|
|
17
|
-
@exp_ff = expanded
|
|
18
|
-
@dma = dma
|
|
19
|
-
@display_on = shows
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def save_state(out)
|
|
23
|
-
out.boolean(@dma).boolean(@display_on).int(@mcbase).int(@mc).boolean(@exp_ff).optional_int(@crunched_mc)
|
|
24
|
-
out.int(@bits).boolean(@row_ready).optional_int(@prev_bits).boolean(@first_byte_lost).boolean(@blind)
|
|
25
|
-
out.int(@show_from).optional_int(@stop_x)
|
|
26
|
-
out.ints(@codes).int(@leftmost).int(@span).ints(@reload_codes).int(@reload_leftmost).int(@reload_span)
|
|
27
|
-
out.int(@sr).int(@latch).boolean(@mc_flop).boolean(@xe_flop)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def load_state(input)
|
|
31
|
-
load_counters(input)
|
|
32
|
-
@show_from = input.int
|
|
33
|
-
@stop_x = input.optional_int
|
|
34
|
-
input.ints_into(@codes)
|
|
35
|
-
@leftmost = input.int
|
|
36
|
-
@span = input.int
|
|
37
|
-
input.ints_into(@reload_codes)
|
|
38
|
-
@reload_leftmost = input.int
|
|
39
|
-
@reload_span = input.int
|
|
40
|
-
@sr = input.int
|
|
41
|
-
@latch = input.int
|
|
42
|
-
@mc_flop = input.boolean?
|
|
43
|
-
@xe_flop = input.boolean?
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
private
|
|
47
|
-
|
|
48
|
-
def load_counters(input)
|
|
49
|
-
@dma = input.boolean?
|
|
50
|
-
@display_on = input.boolean?
|
|
51
|
-
@mcbase = input.int
|
|
52
|
-
@mc = input.int
|
|
53
|
-
@exp_ff = input.boolean?
|
|
54
|
-
@crunched_mc = input.optional_int
|
|
55
|
-
@bits = input.int
|
|
56
|
-
@row_ready = input.boolean?
|
|
57
|
-
@prev_bits = input.optional_int
|
|
58
|
-
@first_byte_lost = input.boolean?
|
|
59
|
-
@blind = input.boolean?
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
end
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class VIC < Cycleable
|
|
5
|
-
class Sprite
|
|
6
|
-
# The X comparator and the 24-bit shift register behind it: where a
|
|
7
|
-
# line fires the sprite, and the pixels each firing shifts out.
|
|
8
|
-
module Shifter
|
|
9
|
-
private
|
|
10
|
-
|
|
11
|
-
# The first pixel of every comparator match along the line. Writes to
|
|
12
|
-
# $d000/$d010 move the compare value mid-line, so a sprite can miss
|
|
13
|
-
# its match entirely and pick up a later one, a second one, or none.
|
|
14
|
-
def comparator_hits(log)
|
|
15
|
-
return compare_x(@registers) unless log
|
|
16
|
-
|
|
17
|
-
hits = []
|
|
18
|
-
log.rewind
|
|
19
|
-
log.advance(0)
|
|
20
|
-
from = 0
|
|
21
|
-
while from < @width
|
|
22
|
-
upto = [log.next_x, @width].min
|
|
23
|
-
compare_x(log).each do |start|
|
|
24
|
-
match = (start - 1) % @width
|
|
25
|
-
hits << start if match >= from && match < upto
|
|
26
|
-
end
|
|
27
|
-
break if upto >= @width
|
|
28
|
-
|
|
29
|
-
from = upto
|
|
30
|
-
log.advance(from)
|
|
31
|
-
end
|
|
32
|
-
hits
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
# The pixels the sprite starts at, one past each comparator match.
|
|
36
|
-
# The 6569's X counter only runs to 503, so the eight coordinates
|
|
37
|
-
# above it never match and the sprite stays dark — the gap the
|
|
38
|
-
# spritegap tests find at $1f8.
|
|
39
|
-
def compare_x(view)
|
|
40
|
-
msb = view[0x10].anybits?(@bit) ? 0x100 : 0
|
|
41
|
-
@timing.x_pixels[msb | view[index * 2]]
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# Pixels from the X match to the next reload.
|
|
45
|
-
def reload_cut(start) = (start < @reload_x ? @reload_x : @reload_x + @width) - start
|
|
46
|
-
|
|
47
|
-
# A run that reaches the next reload is cut there, holding its last
|
|
48
|
-
# pixel through K+6. Returns the span that is left.
|
|
49
|
-
def cut_at_reload(cut, span, codes)
|
|
50
|
-
return span if cut > span || cut >= MAX_SPAN
|
|
51
|
-
|
|
52
|
-
RELOAD_HOLD.times { |i| codes[cut + i] = codes[cut - 1] }
|
|
53
|
-
cut + RELOAD_HOLD
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
# Shift one firing out into `codes`, up to the sprite's end, `cut`
|
|
57
|
-
# pixels from the reload.
|
|
58
|
-
def run(log, start, codes, bits, cut)
|
|
59
|
-
@sr = bits
|
|
60
|
-
log&.rewind
|
|
61
|
-
pos = start
|
|
62
|
-
count = 0
|
|
63
|
-
boundary = log ? 0 : Float::INFINITY
|
|
64
|
-
mc = multicolor?
|
|
65
|
-
expanded = x_expanded?
|
|
66
|
-
while count < MAX_SPAN
|
|
67
|
-
if pos >= boundary
|
|
68
|
-
log.advance(pos)
|
|
69
|
-
expanded = log[0x1d].anybits?(@bit)
|
|
70
|
-
mc = logged_multicolor(log, mc, expanded, count)
|
|
71
|
-
boundary = log.next_x
|
|
72
|
-
end
|
|
73
|
-
count.zero? ? prime(mc) : step(mc, expanded, count == cut - 1)
|
|
74
|
-
break if @latch.zero? && @sr.zero?
|
|
75
|
-
|
|
76
|
-
codes[count] = @latch
|
|
77
|
-
count += 1
|
|
78
|
-
pos += 1
|
|
79
|
-
end
|
|
80
|
-
count
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
# The X match loads the shift register and arms both flip-flops, so
|
|
84
|
-
# the sprite's first pixel comes straight off the fetched row.
|
|
85
|
-
def prime(multicolor)
|
|
86
|
-
@mc_flop = @new_chip && !multicolor
|
|
87
|
-
@xe_flop = false
|
|
88
|
-
@latch = (@sr >> 22) & (multicolor ? 3 : 2)
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
# The multicolor bit as the log has it at the pixel. A change after
|
|
92
|
-
# the first pixel reaches the 8565's flip-flop.
|
|
93
|
-
def logged_multicolor(log, was, expanded, count)
|
|
94
|
-
multicolor = log[0x1c].anybits?(@bit)
|
|
95
|
-
switch_multicolor(multicolor, expanded) if @new_chip && multicolor != was && count.positive?
|
|
96
|
-
multicolor
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
# On the 8565 a multicolor change works on the flip-flop instead of
|
|
100
|
-
# the next pixels. It stays as it is unless the change lands between
|
|
101
|
-
# the two halves of an expanded pixel, where it flips, or is set by a
|
|
102
|
-
# switch to hi-res.
|
|
103
|
-
def switch_multicolor(multicolor, expanded)
|
|
104
|
-
return unless expanded && !@xe_flop
|
|
105
|
-
|
|
106
|
-
@mc_flop = multicolor ? !@mc_flop : true
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
# One pixel of the sequencer. An unexpanded sprite shifts every pixel;
|
|
110
|
-
# an expanded one shifts every other, and the multicolor latch reloads
|
|
111
|
-
# every other shift, so its pairs stretch with the expansion. Both
|
|
112
|
-
# flip-flops sit idle while their register bit is clear, which is why
|
|
113
|
-
# the first pixel after a mid-sprite change repeats the last one.
|
|
114
|
-
def step(multicolor, expanded, last)
|
|
115
|
-
shift = true
|
|
116
|
-
if expanded
|
|
117
|
-
shift = @xe_flop
|
|
118
|
-
@xe_flop = !@xe_flop
|
|
119
|
-
else
|
|
120
|
-
@xe_flop = false
|
|
121
|
-
end
|
|
122
|
-
@mc_flop = false unless multicolor || @new_chip
|
|
123
|
-
return unless shift
|
|
124
|
-
|
|
125
|
-
@sr = (@sr << 1) & 0xffffff
|
|
126
|
-
load_latch(multicolor, last)
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
# A multicolor pair loaded on the last pixel before the reload keeps
|
|
130
|
-
# only its high bit, as a hi-res pixel does (spritefetchbug).
|
|
131
|
-
# On the 8565 a hi-res pixel with the multicolor flip-flop clear
|
|
132
|
-
# sets it and loads nothing, so the latch repeats its last pixel.
|
|
133
|
-
def load_latch(multicolor, last)
|
|
134
|
-
if multicolor
|
|
135
|
-
@latch = (@sr >> 22) & (last ? 2 : 3) if @mc_flop
|
|
136
|
-
@mc_flop = !@mc_flop
|
|
137
|
-
elsif @new_chip && !@mc_flop
|
|
138
|
-
@mc_flop = true
|
|
139
|
-
else
|
|
140
|
-
@latch = (@sr >> 22) & 2
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
end
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class VIC < Cycleable
|
|
5
|
-
class Sprite
|
|
6
|
-
# = Timing
|
|
7
|
-
#
|
|
8
|
-
# Where a region puts the sprites in the line: the cycles of their
|
|
9
|
-
# fetches and of the display compare, the pixels those land on, and
|
|
10
|
-
# the raster pixels the X counter reads each coordinate at. Where the
|
|
11
|
-
# fetches or the compare run a cycle later than on the 6569, what
|
|
12
|
-
# hangs off them moves 8 pixels with them.
|
|
13
|
-
class Timing
|
|
14
|
-
# The X counter's value where it steps back on a raster of more than
|
|
15
|
-
# 512 pixels, to run over the eight values below it again.
|
|
16
|
-
HOLD_AT = 0x188
|
|
17
|
-
|
|
18
|
-
attr_reader :columns, :sprite_cycle, :display_off_x, :x_pixels
|
|
19
|
-
|
|
20
|
-
def initialize(region)
|
|
21
|
-
@columns = region.cycles_per_line
|
|
22
|
-
@sprite_cycle = region.sprite_cycle
|
|
23
|
-
@shift = region.sprite_cycle - Region::PAL.sprite_cycle
|
|
24
|
-
@display_off_x = DISPLAY_OFF_X + (8 * (region.sprite_display_cycle - Region::PAL.sprite_display_cycle))
|
|
25
|
-
@x_pixels = Timing.x_pixels(@columns * 8, region.x_hold)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
# The column BA falls in for a sprite's own fetch: 55 for sprite 0 on
|
|
29
|
-
# the 6569, and two later for each sprite after it.
|
|
30
|
-
def ba_column(index) = 55 + @shift + (2 * index)
|
|
31
|
-
|
|
32
|
-
# The raster pixel of a sprite's reload, counted from the start of
|
|
33
|
-
# the line it is fetched on, so past the end of it for sprites 3-7
|
|
34
|
-
# on the 6569.
|
|
35
|
-
def reload_x(index) = RELOAD_X + (8 * @shift) + (RELOAD_STEP * index)
|
|
36
|
-
|
|
37
|
-
# The X counter at a raster pixel: X_OFFSET behind it, wrapping at
|
|
38
|
-
# the end of the line, less the pixels it held for from HOLD_AT on,
|
|
39
|
-
# where it ran over $180-$187 a second time.
|
|
40
|
-
def self.xpos(pixel, width, hold)
|
|
41
|
-
count = (pixel - X_OFFSET) % width
|
|
42
|
-
count < HOLD_AT ? count : count - hold
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# The raster pixels at which the X counter reads each coordinate, 512
|
|
46
|
-
# lists. A sprite starts at one where its X matches. On the 6569 the
|
|
47
|
-
# coordinates past 503 have none.
|
|
48
|
-
def self.x_pixels(width, hold)
|
|
49
|
-
pixels = Array.new(512) { [] }
|
|
50
|
-
width.times { |pixel| pixels[xpos(pixel, width, hold)] << pixel }
|
|
51
|
-
pixels.each(&:freeze).freeze
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
data/lib/badline/vic/sprite.rb
DELETED
|
@@ -1,337 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "badline/vic/sprite/internal_bus"
|
|
4
|
-
require "badline/vic/sprite/shifter"
|
|
5
|
-
require "badline/vic/sprite/saved_state"
|
|
6
|
-
require "badline/vic/sprite/timing"
|
|
7
|
-
|
|
8
|
-
module Badline
|
|
9
|
-
class VIC < Cycleable
|
|
10
|
-
# = Sprite
|
|
11
|
-
#
|
|
12
|
-
# The DMA/display state machine and the pixel sequencer for one sprite.
|
|
13
|
-
# The sequencer is a 24-bit shift register clocked once per pixel: the X
|
|
14
|
-
# comparator starts it, the expansion flip-flop gates the shift, and the
|
|
15
|
-
# multicolor flip-flop gates a two-bit output latch that feeds the color
|
|
16
|
-
# mux. Registers written mid-sprite therefore take hold from the pixel
|
|
17
|
-
# they reach, rather than re-decoding the row.
|
|
18
|
-
class Sprite
|
|
19
|
-
X_OFFSET = 104
|
|
20
|
-
|
|
21
|
-
# MCBASE and MC are six-bit byte counters into the sprite's 64-byte
|
|
22
|
-
# block. A sprite ends when MCBASE reaches exactly 63, which is why a
|
|
23
|
-
# mid-line $d017 write that steps it past 63 keeps it running.
|
|
24
|
-
LAST_MCBASE = 63
|
|
25
|
-
MC_MASK = 0x3f
|
|
26
|
-
|
|
27
|
-
# 24 bits at two pixels each, plus slack for a mid-sprite expansion
|
|
28
|
-
# change stretching the tail.
|
|
29
|
-
MAX_SPAN = 64
|
|
30
|
-
|
|
31
|
-
# Latch codes are the multicolor bit pairs: 0 is transparent, 1 and 3
|
|
32
|
-
# are the shared colors, 2 the sprite's own.
|
|
33
|
-
SHARED0 = 1
|
|
34
|
-
OWN_COLOR = 2
|
|
35
|
-
SHARED1 = 3
|
|
36
|
-
|
|
37
|
-
# The s-accesses reload the shift register partway through the line,
|
|
38
|
-
# at raster pixel 459 for sprite 0 and 16 later for each sprite after
|
|
39
|
-
# it. A sprite still shifting there loses the rest of its row, and the
|
|
40
|
-
# comparator is ignored for the twelve pixels from it, running on into
|
|
41
|
-
# the next line from a reload near the end of this one (the spritescan
|
|
42
|
-
# dumps). Its output holds the last pixel for seven, through K+6
|
|
43
|
-
# (spritefetchbug).
|
|
44
|
-
RELOAD_X = 459
|
|
45
|
-
RELOAD_STEP = 16
|
|
46
|
-
RELOAD_DEAD = 12
|
|
47
|
-
RELOAD_HOLD = 7
|
|
48
|
-
|
|
49
|
-
# On the line of its last row, a sprite whose DMA ended at cycle 16
|
|
50
|
-
# loses its display at cycle 58, so no hit from this pixel on starts
|
|
51
|
-
# it (spritegap3). One already shifting runs on. A region whose
|
|
52
|
-
# display compare falls later moves it with the compare.
|
|
53
|
-
DISPLAY_OFF_X = 460
|
|
54
|
-
|
|
55
|
-
include Shifter
|
|
56
|
-
include SavedState
|
|
57
|
-
|
|
58
|
-
attr_reader :index, :leftmost, :span, :codes,
|
|
59
|
-
:reload_leftmost, :reload_span, :reload_codes
|
|
60
|
-
|
|
61
|
-
def initialize(index, registers, bank, bus, model: :mos6569)
|
|
62
|
-
@index = index
|
|
63
|
-
@new_chip = model == :mos8565
|
|
64
|
-
@registers = registers
|
|
65
|
-
@bank = bank
|
|
66
|
-
@bus = bus
|
|
67
|
-
@width = bus.columns * 8
|
|
68
|
-
@timing = bus.timing
|
|
69
|
-
@bit = 1 << index
|
|
70
|
-
@dma = false
|
|
71
|
-
@display_on = false
|
|
72
|
-
@mcbase = 0
|
|
73
|
-
@mc = 0
|
|
74
|
-
@exp_ff = true
|
|
75
|
-
@crunched_mc = nil
|
|
76
|
-
@bits = 0
|
|
77
|
-
@row_ready = false
|
|
78
|
-
@codes = Array.new(MAX_SPAN + RELOAD_HOLD, 0)
|
|
79
|
-
@leftmost = 0
|
|
80
|
-
@span = 0
|
|
81
|
-
@reload_codes = Array.new(MAX_SPAN + RELOAD_HOLD, 0)
|
|
82
|
-
@reload_leftmost = 0
|
|
83
|
-
@reload_span = 0
|
|
84
|
-
reload = @timing.reload_x(index)
|
|
85
|
-
@reload_x = reload % @width
|
|
86
|
-
@reload_next_line = reload < @width
|
|
87
|
-
@sr = 0
|
|
88
|
-
@latch = 0
|
|
89
|
-
@mc_flop = false
|
|
90
|
-
@xe_flop = false
|
|
91
|
-
@first_byte_lost = false
|
|
92
|
-
@blind = false
|
|
93
|
-
@show_from = 0
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def displaying? = @dma
|
|
97
|
-
|
|
98
|
-
# True when this line has a row for the sequencer: its own, the next
|
|
99
|
-
# one for a sprite that reloads late in the line, or the last one for
|
|
100
|
-
# a sprite that reloads at its start.
|
|
101
|
-
def rendering?
|
|
102
|
-
return true if @row_ready
|
|
103
|
-
|
|
104
|
-
@reload_next_line ? @dma && @display_on : !@prev_bits.nil?
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def enabled? = @registers[0x15].anybits?(@bit)
|
|
108
|
-
def multicolor? = @registers[0x1c].anybits?(@bit)
|
|
109
|
-
def x_expanded? = @registers[0x1d].anybits?(@bit)
|
|
110
|
-
def y_expanded? = @registers[0x17].anybits?(@bit)
|
|
111
|
-
def priority? = @registers[0x1b].anybits?(@bit)
|
|
112
|
-
|
|
113
|
-
def x
|
|
114
|
-
msb = @registers[0x10].anybits?(@bit) ? 0x100 : 0
|
|
115
|
-
msb | @registers[index * 2]
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
# The Y comparator is eight bits wide, so the PAL lines above 255
|
|
119
|
-
# match the coordinates 0-55 a second time (spritey).
|
|
120
|
-
def y_match?(line) = (line & 0xff) == @registers[(index * 2) + 1]
|
|
121
|
-
|
|
122
|
-
def color = @registers[0x27 + index] & 0x0f
|
|
123
|
-
|
|
124
|
-
# Cycle 16: MCBASE takes MC, which the three s-accesses stepped past
|
|
125
|
-
# the row, but only while the expansion flip-flop is set.
|
|
126
|
-
def advance_mcbase
|
|
127
|
-
mc = @crunched_mc || ((@mc + 3) & MC_MASK)
|
|
128
|
-
@crunched_mc = nil
|
|
129
|
-
@mcbase = mc if @exp_ff && @dma
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
# The end-of-sprite compare, a column after MCBASE moves. MCBASE has
|
|
133
|
-
# to land on 63 exactly, so a crunched sprite steps over it and runs
|
|
134
|
-
# on through the rest of its block. Only the DMA stops here; the
|
|
135
|
-
# display waits for cycle 58.
|
|
136
|
-
def finish_mcbase
|
|
137
|
-
@dma = false if @mcbase == LAST_MCBASE
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
# Clearing MxYE sets the expansion flip-flop at once. Cleared in
|
|
141
|
-
# cycle 15, while the flip-flop is still reset, it also crunches MC:
|
|
142
|
-
# the bits step to a mix of MC and MCBASE (Bauer §3.8, VICE
|
|
143
|
-
# `d017_store`) that cycle 16 then hands to MCBASE.
|
|
144
|
-
def clear_y_expansion(crunch)
|
|
145
|
-
return if @exp_ff
|
|
146
|
-
|
|
147
|
-
@exp_ff = true
|
|
148
|
-
return unless crunch && @dma
|
|
149
|
-
|
|
150
|
-
mc = (@mc + 3) & MC_MASK
|
|
151
|
-
@crunched_mc = (0x2a & @mcbase & mc) | (0x15 & (@mcbase | mc))
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
# Cycle 56, after the second Y compare: MxYE inverts the expansion
|
|
155
|
-
# flip-flop of a sprite with DMA running.
|
|
156
|
-
def toggle_expansion
|
|
157
|
-
@exp_ff = !@exp_ff if @dma && y_expanded?
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
# Cycles 55 and 56: a Y/enable match starts the DMA and rewinds
|
|
161
|
-
# MCBASE, and returns true. Display is enabled separately in cycle 58,
|
|
162
|
-
# so the rows render from the following line on.
|
|
163
|
-
#
|
|
164
|
-
# On the VIC's side, BA falls at the sprite's own column
|
|
165
|
-
# (Timing#ba_column) — 55 for sprite 0 on the 6569, two later for each
|
|
166
|
-
# sprite after it, a column behind the window the CPU sees
|
|
167
|
-
# (VIC#layout_columns) — or two columns after
|
|
168
|
-
# this compare, whichever is later. AEC follows three columns on, and
|
|
169
|
-
# the first of the three s-accesses runs in the column it arrives in:
|
|
170
|
-
# a DMA starting on the second compare therefore loses that access for
|
|
171
|
-
# sprite 0, alone among the eight in following the compares
|
|
172
|
-
# immediately (spriteenable2).
|
|
173
|
-
def check_dma(line, column)
|
|
174
|
-
return false if @dma || !enabled? || !y_match?(line)
|
|
175
|
-
|
|
176
|
-
@first_byte_lost = column + 2 > @timing.ba_column(index)
|
|
177
|
-
@dma = true
|
|
178
|
-
@mcbase = 0
|
|
179
|
-
@exp_ff = true
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
# Cycle 58: MC is reloaded from MCBASE for the coming row, and a
|
|
183
|
-
# sprite with DMA running starts displaying only while MxE and Y still
|
|
184
|
-
# match — a write to either between the compares and here keeps the
|
|
185
|
-
# data fetch running invisibly. The display goes off only here, and
|
|
186
|
-
# only once the DMA has, so a DMA restarted on the line of its last
|
|
187
|
-
# row keeps a display that was already on (spriterestart).
|
|
188
|
-
def check_display(line)
|
|
189
|
-
@mc = @mcbase
|
|
190
|
-
if @dma
|
|
191
|
-
@display_on = true if enabled? && y_match?(line)
|
|
192
|
-
else
|
|
193
|
-
@display_on = false
|
|
194
|
-
end
|
|
195
|
-
blind_fetch if @blind && @display_on
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
# The address of the s-access that falls in phi1, the middle of the
|
|
199
|
-
# three, or nil when the sprite's DMA is off and the VIC idles there.
|
|
200
|
-
def phi1_address
|
|
201
|
-
(pointer * 64) + ((@mc + 1) & MC_MASK) if @dma
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
# The row fetched at the end of the previous line renders on this one.
|
|
205
|
-
# A lost first s-access reads back the $ff the CPU is still driving.
|
|
206
|
-
def start_line
|
|
207
|
-
@span = 0
|
|
208
|
-
@reload_span = 0
|
|
209
|
-
@prev_bits = (@bits if @row_ready && @dma)
|
|
210
|
-
@row_ready = false
|
|
211
|
-
@blind = !@dma && !@reload_next_line
|
|
212
|
-
@show_from = 0
|
|
213
|
-
lost = @first_byte_lost
|
|
214
|
-
@first_byte_lost = false
|
|
215
|
-
return unless @dma && @display_on
|
|
216
|
-
|
|
217
|
-
@bits = row_bits(@mc)
|
|
218
|
-
@bits |= 0xff << 16 if lost
|
|
219
|
-
@row_ready = true
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
# Replay the line through the pixel sequencer, filling the code buffer
|
|
223
|
-
# from the X match on. A log of mid-line register writes makes the
|
|
224
|
-
# comparator and the shift register see the values each pixel was
|
|
225
|
-
# drawn with.
|
|
226
|
-
#
|
|
227
|
-
# The row can be shown once before the reload and once after it, so a
|
|
228
|
-
# sprite moved past the beam can fire a second time on the same line
|
|
229
|
-
# (spritex). A match inside the dead pixels shows nothing.
|
|
230
|
-
def sequence(log = nil)
|
|
231
|
-
@span = 0
|
|
232
|
-
@reload_span = 0
|
|
233
|
-
reload_bits = reload_row
|
|
234
|
-
return unless @row_ready || @prev_bits || reload_bits
|
|
235
|
-
|
|
236
|
-
log = nil if log.nil? || log.empty?
|
|
237
|
-
@stop_x = @dma ? nil : @timing.display_off_x
|
|
238
|
-
comparator_hits(log).each { |start| sequence_hit(log, start, reload_bits) }
|
|
239
|
-
end
|
|
240
|
-
|
|
241
|
-
# The color at a raster position, for a sprite sequenced with the
|
|
242
|
-
# registers as they stand.
|
|
243
|
-
def pixel(raster_x)
|
|
244
|
-
code = code_at(raster_x, @leftmost, @span, @codes) ||
|
|
245
|
-
code_at(raster_x, @reload_leftmost, @reload_span, @reload_codes)
|
|
246
|
-
return nil if code.nil? || code.zero?
|
|
247
|
-
|
|
248
|
-
palette(@registers, Array.new(4, 0))[code]
|
|
249
|
-
end
|
|
250
|
-
|
|
251
|
-
# Fill a four-entry lookup from latch code to color, against a view of
|
|
252
|
-
# the color registers.
|
|
253
|
-
def palette(view, into)
|
|
254
|
-
into[SHARED0] = view[0x25] & 0x0f
|
|
255
|
-
into[OWN_COLOR] = view[0x27 + index] & 0x0f
|
|
256
|
-
into[SHARED1] = view[0x26] & 0x0f
|
|
257
|
-
into
|
|
258
|
-
end
|
|
259
|
-
|
|
260
|
-
private
|
|
261
|
-
|
|
262
|
-
# On the line whose compare started the DMA, sprites 3-7 ran their
|
|
263
|
-
# s-accesses before it was on, so the shift register holds what the
|
|
264
|
-
# VIC saw on its bus instead of a row, and a hit from the display
|
|
265
|
-
# turning on shows it (sbsprf24).
|
|
266
|
-
def blind_fetch
|
|
267
|
-
@bits = @bus.row(index)
|
|
268
|
-
@row_ready = true
|
|
269
|
-
@show_from = @timing.display_off_x
|
|
270
|
-
end
|
|
271
|
-
|
|
272
|
-
def code_at(raster_x, leftmost, span, codes)
|
|
273
|
-
dist = raster_x - leftmost
|
|
274
|
-
dist += @width if dist.negative?
|
|
275
|
-
codes[dist] if dist < span
|
|
276
|
-
end
|
|
277
|
-
|
|
278
|
-
def sequence_hit(log, start, reload_bits)
|
|
279
|
-
return if (@stop_x && start >= @stop_x) || start < @show_from || start < @reload_x + RELOAD_DEAD - @width
|
|
280
|
-
|
|
281
|
-
if start < @reload_x
|
|
282
|
-
sequence_early(log, start)
|
|
283
|
-
elsif start >= @reload_x + RELOAD_DEAD
|
|
284
|
-
sequence_reloaded(log, start, reload_bits)
|
|
285
|
-
end
|
|
286
|
-
end
|
|
287
|
-
|
|
288
|
-
def sequence_early(log, start)
|
|
289
|
-
bits = early_row
|
|
290
|
-
return unless bits && @span.zero?
|
|
291
|
-
|
|
292
|
-
@leftmost = start
|
|
293
|
-
cut = reload_cut(start)
|
|
294
|
-
@span = cut_at_reload(cut, run(log, start, @codes, bits, cut), @codes)
|
|
295
|
-
end
|
|
296
|
-
|
|
297
|
-
def sequence_reloaded(log, start, bits)
|
|
298
|
-
return unless bits && @reload_span.zero?
|
|
299
|
-
|
|
300
|
-
@reload_leftmost = start
|
|
301
|
-
cut = reload_cut(start)
|
|
302
|
-
@reload_span = cut_at_reload(cut, run(log, start, @reload_codes, bits, cut), @reload_codes)
|
|
303
|
-
end
|
|
304
|
-
|
|
305
|
-
# The row in the shift register ahead of the reload: this line's for
|
|
306
|
-
# sprites 0-2, and for the others the one their reload at the start of
|
|
307
|
-
# the last line brought in.
|
|
308
|
-
def early_row = @reload_next_line ? current_row : @prev_bits
|
|
309
|
-
|
|
310
|
-
def current_row = (@bits if @row_ready)
|
|
311
|
-
|
|
312
|
-
# The row the reload brings in. Sprites 0-2 reload late in the line
|
|
313
|
-
# with the next line's row, so one that fires after it shows that row
|
|
314
|
-
# a line early (spritegap); the others reload at the start of the line
|
|
315
|
-
# with the row it already has.
|
|
316
|
-
def reload_row
|
|
317
|
-
return current_row unless @reload_next_line
|
|
318
|
-
return unless @dma && @display_on
|
|
319
|
-
|
|
320
|
-
bits = row_bits(@mc)
|
|
321
|
-
bits |= 0xff << 16 if @first_byte_lost
|
|
322
|
-
bits
|
|
323
|
-
end
|
|
324
|
-
|
|
325
|
-
# The three s-accesses step MC through the sprite's block, wrapping
|
|
326
|
-
# within it.
|
|
327
|
-
def row_bits(counter)
|
|
328
|
-
base = pointer * 64
|
|
329
|
-
(@bank.peek(base + counter) << 16) |
|
|
330
|
-
(@bank.peek(base + ((counter + 1) & MC_MASK)) << 8) |
|
|
331
|
-
@bank.peek(base + ((counter + 2) & MC_MASK))
|
|
332
|
-
end
|
|
333
|
-
|
|
334
|
-
def pointer = @bank.peek(@registers.screen_base + 0x3f8 + index)
|
|
335
|
-
end
|
|
336
|
-
end
|
|
337
|
-
end
|