badline 0.12.1 → 0.14.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 +66 -1
- data/CLAUDE.md +86 -38
- data/CONTRIBUTING.md +4 -3
- data/README.md +9 -6
- data/doc/library.md +9 -9
- data/doc/media.md +2 -1
- data/doc/pinned-behaviour.md +134 -105
- data/doc/snapshot-format.md +1047 -0
- data/doc/snapshots.md +73 -43
- data/lib/badline/audio/bare_player.rb +53 -20
- data/lib/badline/audio/cli.rb +6 -6
- data/lib/badline/audio/jukebox.rb +2 -2
- data/lib/badline/audio/machine_player.rb +16 -10
- data/lib/badline/{media → audio}/queue.rb +1 -1
- data/lib/badline/audio/queued_tune.rb +6 -6
- data/lib/badline/audio/renderer.rb +33 -22
- data/lib/badline/audio/stereo.rb +1 -1
- data/lib/badline/c128/banks.rb +6 -3
- data/lib/badline/c128/bus/keyed_state.rb +45 -0
- data/lib/badline/c128/bus.rb +35 -20
- data/lib/badline/c128/color_lines.rb +2 -2
- data/lib/badline/c128/cpu.rb +1 -1
- data/lib/badline/c128/drives.rb +14 -34
- data/lib/badline/c128/fast_serial.rb +5 -5
- data/lib/badline/c128/keyed_modules.rb +117 -0
- data/lib/badline/c128/keyed_state.rb +91 -0
- data/lib/badline/c128/keys.rb +9 -0
- data/lib/badline/c128/mmu.rb +9 -8
- data/lib/badline/c128/mmu_pages.rb +21 -1
- data/lib/badline/c128/modes.rb +21 -11
- data/lib/badline/c128/z80.rb +2 -2
- data/lib/badline/c128/z80_turns.rb +1 -1
- data/lib/badline/c128.rb +21 -16
- data/lib/badline/c64/attachments.rb +42 -0
- data/lib/badline/c64/banked_ram/banking.rb +32 -0
- data/lib/badline/c64/banked_ram/plus256k.rb +64 -0
- data/lib/badline/c64/banked_ram/plus60k.rb +47 -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/debug_register.rb +32 -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/keyed_state.rb +41 -0
- data/lib/badline/c64/bus/pla.rb +149 -0
- data/lib/badline/c64/bus/roms.rb +41 -0
- data/lib/badline/c64/bus/sid_slots.rb +44 -0
- data/lib/badline/c64/bus.rb +219 -0
- data/lib/badline/c64/cartridge/action_replay.rb +115 -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 +132 -0
- data/lib/badline/c64/cartridge/epyx_fastload.rb +73 -0
- data/lib/badline/c64/cartridge/final_cartridge3.rb +79 -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 +64 -0
- data/lib/badline/c64/cartridge/game_system.rb +42 -0
- data/lib/badline/c64/cartridge/geo_ram.rb +65 -0
- data/lib/badline/c64/cartridge/kcs_power.rb +69 -0
- data/lib/badline/c64/cartridge/keyed_state.rb +393 -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 +60 -0
- data/lib/badline/c64/cartridge/retro_replay.rb +278 -0
- data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
- data/lib/badline/c64/cartridge/rgcd.rb +50 -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 +40 -0
- data/lib/badline/c64/cartridge/westermann.rb +32 -0
- data/lib/badline/c64/cartridge/zaxxon.rb +52 -0
- data/lib/badline/c64/cartridge.rb +232 -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 +39 -36
- data/lib/badline/c64/keyed_modules.rb +111 -0
- data/lib/badline/c64/keyed_state.rb +68 -0
- data/lib/badline/c64/reu/dma.rb +271 -0
- data/lib/badline/c64/reu/keyed_state.rb +140 -0
- data/lib/badline/c64/reu/ram.rb +94 -0
- data/lib/badline/c64/reu/trigger.rb +34 -0
- data/lib/badline/c64/reu.rb +289 -0
- data/lib/badline/c64/true_drives.rb +120 -0
- data/lib/badline/{computer.rb → c64.rb} +24 -15
- data/lib/badline/chips/cia/fast_forward.rb +62 -0
- data/lib/badline/chips/cia/interrupt_register.rb +128 -0
- data/lib/badline/chips/cia/keyed_parts.rb +213 -0
- data/lib/badline/chips/cia/serial.rb +246 -0
- data/lib/badline/chips/cia/time_of_day.rb +210 -0
- data/lib/badline/chips/cia/timer.rb +188 -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 +183 -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/keyed_state.rb +177 -0
- data/lib/badline/chips/cpu/microcode.rb +195 -0
- data/lib/badline/chips/cpu/operations.rb +90 -0
- data/lib/badline/chips/cpu/port.rb +133 -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 +17 -0
- data/lib/badline/chips/sid/catch_up.rb +122 -0
- data/lib/badline/chips/sid/decimator.rb +68 -0
- data/lib/badline/chips/sid/envelope.rb +236 -0
- data/lib/badline/chips/sid/filter.rb +227 -0
- data/lib/badline/chips/sid/keyed_parts.rb +286 -0
- data/lib/badline/chips/sid/voice.rb +69 -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.rb +305 -0
- data/lib/badline/chips/sid.rb +264 -0
- data/lib/badline/chips/ted/beam.rb +119 -0
- data/lib/badline/chips/ted/timers.rb +66 -0
- data/lib/badline/chips/ted.rb +143 -0
- data/lib/badline/chips/tia.rb +49 -0
- data/lib/badline/chips/vdc/keyed_parts.rb +105 -0
- data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
- data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -13
- data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -17
- data/lib/badline/{c128 → chips}/vdc/window.rb +1 -10
- data/lib/badline/{c128 → chips}/vdc.rb +6 -31
- data/lib/badline/chips/via/control_lines.rb +109 -0
- data/lib/badline/chips/via/fast_forward.rb +55 -0
- data/lib/badline/chips/via/interrupt_register.rb +60 -0
- data/lib/badline/chips/via/keyed_parts.rb +163 -0
- data/lib/badline/chips/via/shift_register.rb +168 -0
- data/lib/badline/chips/via/timer1.rb +120 -0
- data/lib/badline/chips/via/timer2.rb +117 -0
- data/lib/badline/chips/via.rb +267 -0
- data/lib/badline/chips/vic/bank.rb +135 -0
- data/lib/badline/chips/vic/border_mask.rb +78 -0
- data/lib/badline/chips/vic/collisions.rb +106 -0
- data/lib/badline/chips/vic/color_patches.rb +38 -0
- data/lib/badline/chips/vic/display_state.rb +168 -0
- data/lib/badline/chips/vic/graphics_mode.rb +166 -0
- data/lib/badline/chips/vic/graphics_shifter.rb +183 -0
- data/lib/badline/chips/vic/keyed_parts.rb +228 -0
- data/lib/badline/chips/vic/keyed_sprites.rb +225 -0
- data/lib/badline/chips/vic/keyed_state.rb +102 -0
- data/lib/badline/chips/vic/register_log.rb +65 -0
- data/lib/badline/chips/vic/registers.rb +188 -0
- data/lib/badline/chips/vic/sequencer.rb +275 -0
- data/lib/badline/chips/vic/sequencer_output.rb +118 -0
- data/lib/badline/chips/vic/sprite/internal_bus.rb +59 -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 +337 -0
- data/lib/badline/chips/vic/sprites.rb +281 -0
- data/lib/badline/chips/vic.rb +787 -0
- data/lib/badline/chips/vic_i/keyed_parts.rb +142 -0
- data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +2 -30
- data/lib/badline/chips/vic_i/sound/output.rb +85 -0
- data/lib/badline/chips/vic_i/sound.rb +227 -0
- data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
- data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +6 -6
- 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/keyed_state.rb +73 -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/shifts.rb +66 -0
- data/lib/badline/chips/z80.rb +13 -0
- data/lib/badline/chips.rb +10 -0
- data/lib/badline/core.rb +13 -32
- data/lib/badline/drives/datasette/keyed_state.rb +38 -0
- data/lib/badline/drives/datasette.rb +173 -0
- data/lib/badline/drives/engine/core.rb +152 -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 +72 -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 +75 -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.rb +318 -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/keyed_state.rb +251 -0
- data/lib/badline/drives/model1541/mechanism.rb +313 -0
- data/lib/badline/drives/model1541/rotation.rb +123 -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 +80 -0
- data/lib/badline/drives/model1571/bus.rb +100 -0
- data/lib/badline/drives/model1571/cpu.rb +13 -0
- data/lib/badline/drives/model1571/keyed_state.rb +108 -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 +108 -0
- data/lib/badline/drives/model1571.rb +141 -0
- data/lib/badline/drives/model1581/bus.rb +126 -0
- data/lib/badline/drives/model1581/cpu.rb +13 -0
- data/lib/badline/drives/model1581/disk.rb +133 -0
- data/lib/badline/drives/model1581/keyed_state.rb +280 -0
- data/lib/badline/drives/model1581/mechanism.rb +98 -0
- data/lib/badline/drives/model1581/serial_port.rb +54 -0
- data/lib/badline/drives/model1581/slot.rb +61 -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/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 +216 -0
- data/lib/badline/drives/model1581.rb +206 -0
- data/lib/badline/drives/serial_bus.rb +161 -0
- data/lib/badline/drives.rb +8 -0
- data/lib/badline/frontend/app.rb +3 -3
- data/lib/badline/frontend/boot.rb +4 -4
- data/lib/badline/frontend/controls.rb +19 -3
- data/lib/badline/frontend/drive_led.rb +44 -21
- data/lib/badline/frontend/machine_window.rb +3 -1
- data/lib/badline/frontend/menu/menu_dialogs.rb +2 -2
- 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/snapshots.rb +12 -1
- data/lib/badline/frontend/timeline.rb +30 -12
- 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/matrix_typist.rb +98 -0
- data/lib/badline/input.rb +4 -0
- data/lib/badline/kernal_trap/chrout.rb +45 -0
- data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
- data/lib/badline/kernal_trap/dos/channel.rb +156 -0
- data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -26
- data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -10
- data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -9
- data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -19
- data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
- data/lib/badline/kernal_trap/{drive.rb → dos.rb} +9 -27
- data/lib/badline/kernal_trap/file_routine.rb +4 -4
- data/lib/badline/kernal_trap/keyed_state.rb +150 -0
- data/lib/badline/kernal_trap/layout.rb +75 -11
- data/lib/badline/kernal_trap/load.rb +19 -21
- data/lib/badline/kernal_trap/routine.rb +12 -0
- data/lib/badline/kernal_trap/save.rb +12 -22
- data/lib/badline/kernal_trap/serial.rb +8 -24
- data/lib/badline/kernal_trap.rb +3 -2
- data/lib/badline/machine/clocking.rb +1 -1
- data/lib/badline/machine/keyboard_buffer.rb +49 -0
- data/lib/badline/machine/settling.rb +29 -0
- data/lib/badline/machine.rb +10 -7
- data/lib/badline/media/boot_disk.rb +14 -2
- data/lib/badline/media/extensions.rb +10 -0
- 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/memory.rb +3 -6
- data/lib/badline/model.rb +1 -1
- data/lib/badline/options/family.rb +5 -2
- data/lib/badline/options/help.rb +42 -16
- data/lib/badline/options/table.rb +2 -0
- data/lib/badline/options/validation.rb +2 -0
- data/lib/badline/options.rb +6 -1
- data/lib/badline/plus4/acia.rb +45 -0
- data/lib/badline/plus4/bus.rb +312 -0
- data/lib/badline/plus4/cpu.rb +10 -0
- data/lib/badline/plus4/cpu_port.rb +93 -0
- data/lib/badline/plus4/keyboard_port.rb +51 -0
- data/lib/badline/plus4/model.rb +38 -0
- data/lib/badline/plus4/user_port.rb +31 -0
- data/lib/badline/plus4.rb +164 -0
- data/lib/badline/roms/README +44 -6
- data/lib/badline/roms/plus4/basic.rom +0 -0
- data/lib/badline/roms/plus4/function-high.rom +0 -0
- data/lib/badline/roms/plus4/function-low.rom +0 -0
- data/lib/badline/roms/plus4/kernal-ntsc.rom +0 -0
- data/lib/badline/roms/plus4/kernal-pal.rom +0 -0
- 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 +32 -0
- data/lib/badline/snapshot/c64_setup.rb +83 -0
- data/lib/badline/snapshot/container.rb +4 -0
- data/lib/badline/snapshot/field_doc/markdown.rb +112 -0
- data/lib/badline/snapshot/field_doc.rb +109 -0
- data/lib/badline/snapshot/image.rb +132 -46
- data/lib/badline/snapshot/keyed/cursor.rb +40 -0
- data/lib/badline/snapshot/keyed/modules.rb +66 -0
- data/lib/badline/snapshot/keyed/reader.rb +188 -0
- data/lib/badline/snapshot/keyed/recorder.rb +88 -0
- data/lib/badline/snapshot/keyed/report.rb +26 -0
- data/lib/badline/snapshot/keyed/writer.rb +55 -0
- data/lib/badline/snapshot/keyed.rb +64 -0
- data/lib/badline/snapshot/machine_state.rb +17 -64
- data/lib/badline/snapshot/storage_setup.rb +63 -0
- data/lib/badline/snapshot/vic20_setup.rb +28 -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 +3 -3
- data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
- data/lib/badline/snapshot/vice.rb +13 -35
- data/lib/badline/snapshot.rb +44 -22
- data/lib/badline/storage/crt_file.rb +3 -1
- 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 +10 -5
- data/lib/badline/storage/host_directory.rb +0 -5
- data/lib/badline/storage/t64.rb +2 -8
- data/lib/badline/storage/tap.rb +43 -15
- 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 +8 -5
- data/lib/badline/vic20/bus/keyed_state.rb +52 -0
- data/lib/badline/vic20/bus.rb +2 -25
- data/lib/badline/vic20/cpu.rb +1 -1
- data/lib/badline/vic20/keyed_modules.rb +73 -0
- data/lib/badline/vic20/keyed_state.rb +45 -0
- data/lib/badline/vic20/port_wiring.rb +4 -4
- data/lib/badline/vic20/user_via_ports.rb +2 -2
- data/lib/badline/vic20.rb +22 -17
- data/lib/badline.rb +1 -0
- metadata +271 -228
- 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/c128/bus_state.rb +0 -53
- data/lib/badline/c128/saved_state.rb +0 -143
- 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/chrout_trap.rb +0 -43
- 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/attachments.rb +0 -88
- data/lib/badline/computer/saved_state.rb +0 -117
- data/lib/badline/computer/true_drives.rb +0 -69
- 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/debug_register.rb +0 -28
- 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/keyboard_buffer.rb +0 -33
- 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/snapshot/setup.rb +0 -75
- data/lib/badline/snapshot/state.rb +0 -189
- 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/saved_state.rb +0 -124
- data/lib/badline/vic20/sound/output.rb +0 -83
- data/lib/badline/vic20/sound.rb +0 -233
- data/lib/badline/vic20/vic/saved_state.rb +0 -55
- 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,188 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class VIC
|
|
6
|
+
# = VIC-II Registers
|
|
7
|
+
#
|
|
8
|
+
# == Sprite positions
|
|
9
|
+
#
|
|
10
|
+
# $D000: Sprite 0 X
|
|
11
|
+
# $D001: Sprite 0 Y
|
|
12
|
+
# $D002: Sprite 1 X
|
|
13
|
+
# $D003: Sprite 1 Y
|
|
14
|
+
# $D004: Sprite 2 X
|
|
15
|
+
# $D005: Sprite 2 Y
|
|
16
|
+
# $D006: Sprite 3 X
|
|
17
|
+
# $D007: Sprite 3 Y
|
|
18
|
+
# $D008: Sprite 4 X
|
|
19
|
+
# $D009: Sprite 4 Y
|
|
20
|
+
# $D00A: Sprite 5 X
|
|
21
|
+
# $D00B: Sprite 5 Y
|
|
22
|
+
# $D00C: Sprite 6 X
|
|
23
|
+
# $D00D: Sprite 6 Y
|
|
24
|
+
# $D00E: Sprite 7 X
|
|
25
|
+
# $D00F: Sprite 7 Y
|
|
26
|
+
#
|
|
27
|
+
# $D010: Most Significant Bits of Sprites 0-7 Horizontal Position
|
|
28
|
+
# $D011: Vertical Fine Scrolling and Control Register
|
|
29
|
+
# $D012: Rasterline
|
|
30
|
+
# - Read: Current rasterline
|
|
31
|
+
# - Write: Set rasterline interrupt
|
|
32
|
+
#
|
|
33
|
+
# == Light pen
|
|
34
|
+
#
|
|
35
|
+
# $D013: Light Pen Horizontal Position
|
|
36
|
+
# $D014: Light Pen Vertical Position
|
|
37
|
+
#
|
|
38
|
+
# $D015: Sprite Enable Register
|
|
39
|
+
# $D016: Horizontal Fine Scrolling and Control Register
|
|
40
|
+
# $D017: Sprite Vertical Expansion Register
|
|
41
|
+
# $D018: VIC-II Chip Memory Control Register
|
|
42
|
+
# $D019: VIC Interrupt Flag Register
|
|
43
|
+
# $D01A: IRQ Mask Register
|
|
44
|
+
# $D01B: Sprite to Foreground Display Priority Register
|
|
45
|
+
# $D01C: Sprite Multicolor Registers
|
|
46
|
+
# $D01D: Sprite Horizontal Expansion Register
|
|
47
|
+
#
|
|
48
|
+
# == Sprite collision detection
|
|
49
|
+
#
|
|
50
|
+
# $D01E: Sprite to Sprite Collision Register
|
|
51
|
+
# $D01F: Sprite to Foreground Collision Register
|
|
52
|
+
#
|
|
53
|
+
# == Color registers
|
|
54
|
+
#
|
|
55
|
+
# All color registers are 4bit, bits 4-7 always read 1.
|
|
56
|
+
#
|
|
57
|
+
# $D020: Border color
|
|
58
|
+
# $D021: Background color 0
|
|
59
|
+
# $D022: Background color 1
|
|
60
|
+
# $D023: Background color 2
|
|
61
|
+
# $D024: Background color 3
|
|
62
|
+
# $D025: Sprite multicolor 0
|
|
63
|
+
# $D026: Sprite multicolor 1
|
|
64
|
+
# $D027: Sprite 0 color
|
|
65
|
+
# $D028: Sprite 1 color
|
|
66
|
+
# $D029: Sprite 2 color
|
|
67
|
+
# $D02A: Sprite 3 color
|
|
68
|
+
# $D02B: Sprite 4 color
|
|
69
|
+
# $D02C: Sprite 5 color
|
|
70
|
+
# $D02D: Sprite 6 color
|
|
71
|
+
# $D02E: Sprite 7 color
|
|
72
|
+
#
|
|
73
|
+
# == VIC-IIe (8566 and 8564)
|
|
74
|
+
#
|
|
75
|
+
# $D02F: Extra keyboard lines K0-K2 in bits 0-2, bits 3-7 read 1
|
|
76
|
+
# $D030: FAST (2 MHz) in bit 0 and TEST in bit 1, bits 2-7 read 1
|
|
77
|
+
#
|
|
78
|
+
# $D02F-$D03F: Not in use on the 6569 and 8565, always reads 0xff,
|
|
79
|
+
# and $D031-$D03F on the VIC-IIe
|
|
80
|
+
# $D040-$D3FF: Repeat $D0000 to $D03F every 64 bytes
|
|
81
|
+
class Registers
|
|
82
|
+
include IntegerHelper
|
|
83
|
+
|
|
84
|
+
# The raw register bytes, for the per-column reads on the hot path.
|
|
85
|
+
attr_reader :bytes
|
|
86
|
+
|
|
87
|
+
# Every register powers on as zero, as in VICE. A VIC-IIe reads
|
|
88
|
+
# $D02F and $D030 back as registers.
|
|
89
|
+
def initialize(iie: false)
|
|
90
|
+
@bytes = Array.new(2**6, 0)
|
|
91
|
+
@irq_line = false
|
|
92
|
+
@iie = iie
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# True while any enabled latch bit is set in $D019/$D01A. Cached and
|
|
96
|
+
# re-evaluated on writes, since it's checked every cycle.
|
|
97
|
+
def irq_line? = @irq_line
|
|
98
|
+
|
|
99
|
+
def [](reg) = @bytes[reg]
|
|
100
|
+
|
|
101
|
+
def read(reg)
|
|
102
|
+
case reg
|
|
103
|
+
when 0x16 then @bytes[reg] | 0xc0 # bits 7-6 unused, read 1
|
|
104
|
+
when 0x18 then @bytes[reg] | 0x01 # bit 0 unused, reads 1
|
|
105
|
+
when 0x1a, 0x20..0x2e then @bytes[reg] | 0xf0
|
|
106
|
+
when 0x1e, 0x1f then read_clear(reg) # collision registers clear on read
|
|
107
|
+
when 0x2f then @iie ? @bytes[reg] | 0xf8 : 0xff
|
|
108
|
+
when 0x30 then @iie ? @bytes[reg] | 0xfc : 0xff
|
|
109
|
+
when 0x31..0x3f then 0xff
|
|
110
|
+
else @bytes[reg]
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def write(reg, value)
|
|
115
|
+
case reg
|
|
116
|
+
when 0x19 # write 1 to clear
|
|
117
|
+
@bytes[reg] &= ~value
|
|
118
|
+
update_irq_line
|
|
119
|
+
when 0x1a # only the four latch bits
|
|
120
|
+
@bytes[reg] = value & 0x0f
|
|
121
|
+
update_irq_line
|
|
122
|
+
when 0x1e, 0x1f then nil # the collision registers are read-only
|
|
123
|
+
else @bytes[reg] = value
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Graphics modes
|
|
128
|
+
def ecm = @bytes[0x11][6]
|
|
129
|
+
def bmm = @bytes[0x11][5]
|
|
130
|
+
def mcm = @bytes[0x16][4]
|
|
131
|
+
# ECM/BMM from $D011 bits 6-5, MCM from $D016 bit 4.
|
|
132
|
+
def mode = ((@bytes[0x11] >> 4) & 0b110) | ((@bytes[0x16] >> 4) & 0b001)
|
|
133
|
+
|
|
134
|
+
def xscroll = @bytes[0x16] & 0b0111
|
|
135
|
+
def yscroll = @bytes[0x11] & 0b0111
|
|
136
|
+
|
|
137
|
+
def rsel? = @bytes[0x11].anybits?(0x08)
|
|
138
|
+
def csel? = @bytes[0x16].anybits?(0x08)
|
|
139
|
+
def display_enabled? = @bytes[0x11].anybits?(0x10)
|
|
140
|
+
|
|
141
|
+
def char_base = (@bytes[0x18] & 0b1110) * 0x400
|
|
142
|
+
def bitmap_base = (@bytes[0x18] & 0b1000) * 0x400
|
|
143
|
+
def screen_base = (@bytes[0x18] >> 4) * 0x400
|
|
144
|
+
|
|
145
|
+
def border = @bytes[0x20] & 0x0f
|
|
146
|
+
def background(index = 0) = @bytes[0x21 + index] & 0x0f
|
|
147
|
+
|
|
148
|
+
# The VIC-IIe's $D02F and $D030 bits. The 6569 and 8565 drive no
|
|
149
|
+
# extra keyboard lines and run at 1 MHz.
|
|
150
|
+
def extra_keyboard_lines = @iie ? @bytes[0x2f] & 0x07 : 0x07
|
|
151
|
+
def fast? = @iie && @bytes[0x30].anybits?(0x01)
|
|
152
|
+
def test? = @iie && @bytes[0x30].anybits?(0x02)
|
|
153
|
+
|
|
154
|
+
# FAST and TEST as bits 0 and 1.
|
|
155
|
+
def clock_bits = @iie ? @bytes[0x30] & 0x03 : 0
|
|
156
|
+
|
|
157
|
+
def raster_target = uint16(@bytes[0x12], (@bytes[0x11] & 0x80) >> 7)
|
|
158
|
+
|
|
159
|
+
def latch_irq!(bit)
|
|
160
|
+
@bytes[0x19] |= bit
|
|
161
|
+
update_irq_line
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def latch_raster_irq! = latch_irq!(0x01)
|
|
165
|
+
|
|
166
|
+
def collide!(reg, bits)
|
|
167
|
+
return false if bits.zero?
|
|
168
|
+
|
|
169
|
+
was_zero = @bytes[reg].zero?
|
|
170
|
+
@bytes[reg] |= bits
|
|
171
|
+
was_zero
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Works the IRQ line out from $D019 and $D01A again, after the bytes
|
|
175
|
+
# were set directly.
|
|
176
|
+
def update_irq_line
|
|
177
|
+
@irq_line = (@bytes[0x19] & @bytes[0x1a]).anybits?(0x0f)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
private
|
|
181
|
+
|
|
182
|
+
def read_clear(reg)
|
|
183
|
+
@bytes[reg].tap { @bytes[reg] = 0 }
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "badline/chips/vic/border_mask"
|
|
4
|
+
require "badline/chips/vic/color_patches"
|
|
5
|
+
require "badline/chips/vic/graphics_mode"
|
|
6
|
+
require "badline/chips/vic/graphics_shifter"
|
|
7
|
+
require "badline/chips/vic/sequencer_output"
|
|
8
|
+
|
|
9
|
+
module Badline
|
|
10
|
+
module Chips
|
|
11
|
+
class VIC
|
|
12
|
+
# = VIC-II Sequencer
|
|
13
|
+
#
|
|
14
|
+
# Turns fetched graphics data into output pixels.
|
|
15
|
+
class Sequencer
|
|
16
|
+
include Output
|
|
17
|
+
|
|
18
|
+
BORDER_Y_BOUNDS = [
|
|
19
|
+
[55, 247].freeze,
|
|
20
|
+
[51, 251].freeze
|
|
21
|
+
].freeze
|
|
22
|
+
|
|
23
|
+
MODES = GraphicsMode::MODES
|
|
24
|
+
|
|
25
|
+
attr_reader :colors, :fg, :registers, :bank, :cur_colors,
|
|
26
|
+
:color_patches
|
|
27
|
+
# The fg masks are shared frozen patterns assigned by reference, never
|
|
28
|
+
# mutated in place.
|
|
29
|
+
attr_accessor :cur_fg
|
|
30
|
+
# False leaves the line's colours unpainted and keeps only the
|
|
31
|
+
# foreground mask the sprite collisions read.
|
|
32
|
+
attr_writer :render
|
|
33
|
+
|
|
34
|
+
def initialize(width, registers, bank, model: :mos6569, region: Region::PAL)
|
|
35
|
+
@width = width
|
|
36
|
+
window_bounds(region.display_x_bounds)
|
|
37
|
+
@registers = registers
|
|
38
|
+
@bank = bank
|
|
39
|
+
@colors = Array.new(width, 0)
|
|
40
|
+
@fg = Array.new(width, false)
|
|
41
|
+
@border_mask = BorderMask.new(width)
|
|
42
|
+
# Hot-path aliases: the pixel loops write coverage straight into the
|
|
43
|
+
# mask's arrays.
|
|
44
|
+
@border = @border_mask.mask
|
|
45
|
+
@border_groups = @border_mask.groups
|
|
46
|
+
@cur_colors = Array.new(8, 0)
|
|
47
|
+
@cur_fg = GraphicsMode::NO_FG
|
|
48
|
+
@prev_colors = Array.new(8, 0)
|
|
49
|
+
@prev_fg = GraphicsMode::NO_FG
|
|
50
|
+
@vertical_border = true
|
|
51
|
+
@vertical_armed = true
|
|
52
|
+
@main_border = true
|
|
53
|
+
@color_patches = ColorPatches.new(self, grey_dots: model == :mos8565)
|
|
54
|
+
@shifter = GraphicsShifter.new(registers, model:)
|
|
55
|
+
@xscroll = 0
|
|
56
|
+
@last_shift = 0
|
|
57
|
+
@last_mode = 0
|
|
58
|
+
@settling = false
|
|
59
|
+
@ring_data = Array.new(4, 0)
|
|
60
|
+
@ring_char = Array.new(4, 0)
|
|
61
|
+
@ring_color = Array.new(4, 1)
|
|
62
|
+
@prev_fresh = false
|
|
63
|
+
@check = true
|
|
64
|
+
@render = true
|
|
65
|
+
new_line(0)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Reset the line buffers at the start of a rasterline.
|
|
69
|
+
def new_line(line)
|
|
70
|
+
@line = line
|
|
71
|
+
@left_vertical_border = nil
|
|
72
|
+
@first_csel = @registers.csel?
|
|
73
|
+
@colors.fill(@registers.border)
|
|
74
|
+
@fg.fill(false)
|
|
75
|
+
@border_mask.reset
|
|
76
|
+
@prev_colors.fill(@registers.background)
|
|
77
|
+
@prev_fg = GraphicsMode::NO_FG
|
|
78
|
+
@prev_fresh = false
|
|
79
|
+
@check = true
|
|
80
|
+
@color_patches.clear
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# The load point for the next group's byte: XSCROLL as a g-access
|
|
84
|
+
# column with the border open sees it, a column before the group that
|
|
85
|
+
# uses it (VICE x64sc `xscroll_pipe`).
|
|
86
|
+
def latch_xscroll(xscroll = @registers.xscroll)
|
|
87
|
+
return if xscroll == @xscroll
|
|
88
|
+
|
|
89
|
+
@xscroll = xscroll
|
|
90
|
+
@check = true
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# A write to a register the painted colours depend on: the byte kept
|
|
94
|
+
# from the previous group is painted again before its pixels are shown.
|
|
95
|
+
def colors_changed!
|
|
96
|
+
@prev_fresh = false
|
|
97
|
+
@check = true
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def apply_color_patches
|
|
101
|
+
@color_patches.apply(@colors, @fg)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# The vertical border compares run in every cycle of their line (VICE
|
|
105
|
+
# x64sc). The top one resets the flip-flop at once when DEN is set. The
|
|
106
|
+
# bottom one only arms it, and the armed state takes hold at the line's
|
|
107
|
+
# first cycle and at the left window edge (Bauer §3.9 rules 2-5). The
|
|
108
|
+
# VIC calls this after each $d011 write.
|
|
109
|
+
def compare_vertical_border(line)
|
|
110
|
+
top, bottom = BORDER_Y_BOUNDS[@registers.rsel? ? 1 : 0]
|
|
111
|
+
@vertical_armed = true if line == bottom
|
|
112
|
+
@vertical_armed = @vertical_border = false if line == top && @registers.display_enabled?
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# The line's first cycle, Bauer's cycle 1, which is the last column of
|
|
116
|
+
# the line before it.
|
|
117
|
+
def start_vertical_border(line)
|
|
118
|
+
compare_vertical_border(line)
|
|
119
|
+
@vertical_border = @vertical_armed
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# The 40-column left compare, a column before the column that draws its
|
|
123
|
+
# pixel. The 38-column one runs in the drawing column.
|
|
124
|
+
def left_compare_vertical_border
|
|
125
|
+
@left_vertical_border = start_vertical_border(@line) if @registers.csel?
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def border_at?(pixel_x) = @border_mask.at?(pixel_x)
|
|
129
|
+
|
|
130
|
+
# True while the vertical border flip-flop is set and stays set for the
|
|
131
|
+
# rest of the line: it can only clear mid-line on a top compare line
|
|
132
|
+
# with DEN set.
|
|
133
|
+
def vertical_closed?
|
|
134
|
+
return false unless @vertical_border
|
|
135
|
+
return true unless @line == 51 || @line == 55
|
|
136
|
+
|
|
137
|
+
top, = BORDER_Y_BOUNDS[@registers.rsel? ? 1 : 0]
|
|
138
|
+
!(@line == top && @registers.display_enabled?)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Snapshot the finished line so apply_border can restore the border
|
|
142
|
+
# pixels sprites were composited over, keeping mid-line border splits.
|
|
143
|
+
def snapshot_line = @border_mask.snapshot(@colors)
|
|
144
|
+
|
|
145
|
+
# Repaint the border over the composited line, hiding the sprites.
|
|
146
|
+
def apply_border = @border_mask.restore(@colors)
|
|
147
|
+
|
|
148
|
+
# The g-accesses the VIC hands over, as a ring the column's slot
|
|
149
|
+
# indexes: the byte read, the screen byte and the colour nibble. The
|
|
150
|
+
# slot before is the byte the previous group loaded.
|
|
151
|
+
attr_reader :ring_data, :ring_char, :ring_color
|
|
152
|
+
|
|
153
|
+
# The border flip-flops: vertical, the vertical one armed to set, and
|
|
154
|
+
# the main one.
|
|
155
|
+
def borders = [@vertical_border, @vertical_armed, @main_border]
|
|
156
|
+
|
|
157
|
+
def restore_borders(vertical, armed, main)
|
|
158
|
+
@vertical_border = vertical
|
|
159
|
+
@vertical_armed = armed
|
|
160
|
+
@main_border = main
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Paints the byte in the slot through the current mode. An idle access
|
|
164
|
+
# latches 0/0 and one that made no access passes on zero data with the
|
|
165
|
+
# kept values; under a closed border neither has foreground. A group
|
|
166
|
+
# where the mode or the load point changes, and the one after it, run
|
|
167
|
+
# the shift register pixel by pixel.
|
|
168
|
+
def emit(slot, col, display)
|
|
169
|
+
mode = @registers.mode
|
|
170
|
+
return emit_checked(slot, col, display, mode) if @check || mode != @last_mode
|
|
171
|
+
|
|
172
|
+
paint_slot(slot, mode, display)
|
|
173
|
+
output(col, @last_shift)
|
|
174
|
+
roll
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
private
|
|
178
|
+
|
|
179
|
+
# The display window's edges per CSEL state, as the region gives them.
|
|
180
|
+
# The graphics window always spans the full 40 columns, ignoring CSEL,
|
|
181
|
+
# and the border flip-flop takes [left compare, right compare] per
|
|
182
|
+
# CSEL state.
|
|
183
|
+
def window_bounds(bounds)
|
|
184
|
+
narrow, wide = bounds
|
|
185
|
+
@gfx_x_start = wide[0]
|
|
186
|
+
@gfx_x_end = wide[1] + 1
|
|
187
|
+
@window_compares = [
|
|
188
|
+
[narrow[0], narrow[1] + 1].freeze,
|
|
189
|
+
[@gfx_x_start, @gfx_x_end].freeze
|
|
190
|
+
].freeze
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# After a mode, XSCROLL or colour change: groups paint whole bytes
|
|
194
|
+
# again once the change has settled, and run pixel by pixel until then.
|
|
195
|
+
def emit_checked(slot, col, display, mode)
|
|
196
|
+
shift = @xscroll
|
|
197
|
+
if mode == @last_mode && shift == @last_shift && !@settling
|
|
198
|
+
emit_settled(slot, col, display, mode, shift)
|
|
199
|
+
else
|
|
200
|
+
emit_pixels(slot, col, mode, shift, !display && border_hidden?)
|
|
201
|
+
@settling = mode != @last_mode || shift != @last_shift
|
|
202
|
+
@last_mode = mode
|
|
203
|
+
@last_shift = shift
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def emit_settled(slot, col, display, mode, shift)
|
|
208
|
+
repaint_previous(mode, (slot - 1) & 3) unless @prev_fresh || shift.zero?
|
|
209
|
+
paint_slot(slot, mode, display)
|
|
210
|
+
output(col, shift)
|
|
211
|
+
roll
|
|
212
|
+
@prev_fresh = true
|
|
213
|
+
@check = false
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def paint_slot(slot, mode, display)
|
|
217
|
+
if !display && border_hidden?
|
|
218
|
+
@cur_fg = GraphicsMode::NO_FG
|
|
219
|
+
else
|
|
220
|
+
paint(slot, mode)
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def repaint_previous(mode, slot)
|
|
225
|
+
roll
|
|
226
|
+
paint(slot, mode)
|
|
227
|
+
roll
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def paint(slot, mode)
|
|
231
|
+
if @render
|
|
232
|
+
MODES[mode].paint(@ring_data[slot], @ring_char[slot], @ring_color[slot], self)
|
|
233
|
+
else
|
|
234
|
+
@cur_fg = MODES[mode].fg(@ring_data[slot], @ring_char[slot], @ring_color[slot])
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def emit_pixels(slot, col, mode, shift, hidden)
|
|
239
|
+
prime_shifter((slot - 1) & 3) unless @settling
|
|
240
|
+
@shifter.draw(hidden ? 0 : @ring_data[slot], @ring_char[slot], @ring_color[slot], shift, mode)
|
|
241
|
+
@cur_colors[0, 8] = @shifter.colors
|
|
242
|
+
@cur_fg = @shifter.fg
|
|
243
|
+
output(col, 0)
|
|
244
|
+
@prev_fresh = false
|
|
245
|
+
@check = true
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# Picks up from a group that painted whole bytes.
|
|
249
|
+
def prime_shifter(slot)
|
|
250
|
+
@shifter.prime(@ring_data[slot], @ring_char[slot], @ring_color[slot], @last_shift, @last_mode)
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# The group is border throughout when the main flip-flop is set and the
|
|
254
|
+
# vertical one keeps it from clearing.
|
|
255
|
+
def border_hidden? = @main_border && vertical_closed?
|
|
256
|
+
|
|
257
|
+
def pixel_shown?(pixel_x, left_compare, right_compare)
|
|
258
|
+
@main_border = true if pixel_x == right_compare
|
|
259
|
+
@main_border = false if pixel_x == left_compare && !left_vertical_border
|
|
260
|
+
!@main_border
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def left_vertical_border
|
|
264
|
+
@left_vertical_border.nil? ? start_vertical_border(@line) : @left_vertical_border
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def roll
|
|
268
|
+
@prev_colors, @cur_colors = @cur_colors, @prev_colors
|
|
269
|
+
@prev_fg, @cur_fg = @cur_fg, @prev_fg
|
|
270
|
+
nil
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class VIC
|
|
6
|
+
class Sequencer
|
|
7
|
+
# Writes a column's 8-pixel group into the line buffers, through the
|
|
8
|
+
# main border flip-flop and XSCROLL.
|
|
9
|
+
module Output
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
# Write the 8-pixel group for a column into the line buffers. The main
|
|
13
|
+
# border flip-flop only changes state in the groups containing the
|
|
14
|
+
# window edge compares, so all other groups take a branch-free bulk
|
|
15
|
+
# path: fully border or fully window. A group's first pixel, where the
|
|
16
|
+
# 40-column compares fall, still sees CSEL as the column before had it.
|
|
17
|
+
def output(col, shift)
|
|
18
|
+
x_pos = (col + 16) * 8
|
|
19
|
+
csel = @registers.csel?
|
|
20
|
+
first = @window_compares[@first_csel ? 1 : 0]
|
|
21
|
+
@first_csel = csel
|
|
22
|
+
compares = @window_compares[csel ? 1 : 0]
|
|
23
|
+
win_lo, right_compare = compares
|
|
24
|
+
|
|
25
|
+
if !first.equal?(compares) || boundary_group?(x_pos, win_lo, right_compare)
|
|
26
|
+
output_boundary(x_pos, first, compares, shift)
|
|
27
|
+
elsif @main_border
|
|
28
|
+
output_border(x_pos)
|
|
29
|
+
else
|
|
30
|
+
output_window(x_pos, shift)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# True if the group contains a window edge, where the main border
|
|
35
|
+
# flip-flop can change state.
|
|
36
|
+
def boundary_group?(x_pos, win_lo, right_compare)
|
|
37
|
+
lo_delta = win_lo - x_pos
|
|
38
|
+
hi_delta = right_compare - x_pos
|
|
39
|
+
(lo_delta >= 0 && lo_delta < 8) || (hi_delta >= 0 && hi_delta < 8)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def output_border(x_pos)
|
|
43
|
+
@colors.fill(@registers.border, x_pos, 8) if @render
|
|
44
|
+
@border_groups[x_pos >> 3] = BorderMask::FULL
|
|
45
|
+
@fg.fill(false, x_pos, 8)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def output_window(x_pos, shift)
|
|
49
|
+
in_gfx = x_pos >= @gfx_x_start && x_pos < @gfx_x_end
|
|
50
|
+
@border_groups[x_pos >> 3] = BorderMask::NONE
|
|
51
|
+
|
|
52
|
+
if shift.zero?
|
|
53
|
+
@colors[x_pos, 8] = @cur_colors if @render
|
|
54
|
+
if in_gfx
|
|
55
|
+
@fg[x_pos, 8] = @cur_fg
|
|
56
|
+
else
|
|
57
|
+
@fg.fill(false, x_pos, 8)
|
|
58
|
+
end
|
|
59
|
+
else
|
|
60
|
+
output_window_shifted(x_pos, in_gfx, shift)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def output_window_shifted(x_pos, in_gfx, shift)
|
|
65
|
+
keep = 8 - shift
|
|
66
|
+
|
|
67
|
+
if @render
|
|
68
|
+
copy(@cur_colors, 0, @colors, x_pos + shift, keep)
|
|
69
|
+
copy(@prev_colors, keep, @colors, x_pos, shift)
|
|
70
|
+
end
|
|
71
|
+
output_shifted_fg(x_pos, in_gfx, shift, keep)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def output_shifted_fg(x_pos, in_gfx, shift, keep)
|
|
75
|
+
return @fg.fill(false, x_pos, 8) unless in_gfx
|
|
76
|
+
|
|
77
|
+
copy(@cur_fg, 0, @fg, x_pos + shift, keep)
|
|
78
|
+
copy(@prev_fg, keep, @fg, x_pos, shift)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def copy(src, from, dest, to, count)
|
|
82
|
+
i = 0
|
|
83
|
+
while i < count
|
|
84
|
+
dest[to + i] = src[from + i]
|
|
85
|
+
i += 1
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Slow path for the groups where the border flip-flop can change state.
|
|
90
|
+
def output_boundary(x_pos, first, compares, shift)
|
|
91
|
+
border = @registers.border
|
|
92
|
+
win_lo, right_compare = first
|
|
93
|
+
@border_groups[x_pos >> 3] = BorderMask::MIXED
|
|
94
|
+
|
|
95
|
+
i = 0
|
|
96
|
+
while i < 8
|
|
97
|
+
src = i - shift
|
|
98
|
+
if src >= 0
|
|
99
|
+
pixel = @cur_colors[src]
|
|
100
|
+
mask = @cur_fg[src]
|
|
101
|
+
else
|
|
102
|
+
pixel = @prev_colors[8 + src]
|
|
103
|
+
mask = @prev_fg[8 + src]
|
|
104
|
+
end
|
|
105
|
+
x = x_pos + i
|
|
106
|
+
shown = pixel_shown?(x, win_lo, right_compare)
|
|
107
|
+
@colors[x] = shown ? pixel : border
|
|
108
|
+
@border[x] = !shown
|
|
109
|
+
@fg[x] = x >= @gfx_x_start && x < @gfx_x_end ? mask : false
|
|
110
|
+
win_lo, right_compare = compares if i.zero?
|
|
111
|
+
i += 1
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class VIC
|
|
6
|
+
class Sprite
|
|
7
|
+
# = InternalBus
|
|
8
|
+
#
|
|
9
|
+
# What a sprite's s-accesses read while its DMA is off. The first and
|
|
10
|
+
# third fall in phi2, where the VIC's internal bus floats to $ff unless
|
|
11
|
+
# the CPU reads or writes a VIC register in that cycle, and the middle
|
|
12
|
+
# one is the idle fetch at $3fff (sbsprf24's readme).
|
|
13
|
+
class InternalBus
|
|
14
|
+
# The columns of a raster line, and where the region puts the
|
|
15
|
+
# sprites in it.
|
|
16
|
+
attr_reader :columns, :timing
|
|
17
|
+
|
|
18
|
+
def initialize(bank, timing)
|
|
19
|
+
@bank = bank
|
|
20
|
+
@timing = timing
|
|
21
|
+
@columns = timing.columns
|
|
22
|
+
@sprite_cycle = timing.sprite_cycle
|
|
23
|
+
@lines = 0
|
|
24
|
+
@ghost = 0xff
|
|
25
|
+
@value = Array.new(columns, 0xff)
|
|
26
|
+
@line = Array.new(columns, -1)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Sprites 3-7 fetch in Bauer cycles 1-10, so the idle byte is taken
|
|
30
|
+
# as the line starts.
|
|
31
|
+
def start_line(sprites_enabled)
|
|
32
|
+
@lines += 1
|
|
33
|
+
@ghost = @bank.peek(0x3fff) if sprites_enabled
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# The VIC has advanced to `column`, so the access runs in Bauer cycle
|
|
37
|
+
# `column + 1`, and column 0 is the first cycle of the line about to
|
|
38
|
+
# start.
|
|
39
|
+
def access(column, value)
|
|
40
|
+
@value[column] = value
|
|
41
|
+
@line[column] = column.zero? ? @lines + 1 : @lines
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# The row sprite `index` (3-7) fetched this line, in the phi2 halves
|
|
45
|
+
# of the two cycles from its p-access: Bauer cycles 2n-5 and 2n-4 on
|
|
46
|
+
# the 6569.
|
|
47
|
+
def row(index)
|
|
48
|
+
column = (@sprite_cycle + (2 * index) - 1) % @columns
|
|
49
|
+
(phi2(column) << 16) | (@ghost << 8) | phi2(column + 1)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def phi2(column) = @line[column] == @lines ? @value[column] : 0xff
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|