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
data/lib/badline/vic.rb
DELETED
|
@@ -1,853 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "badline/vic/bank"
|
|
4
|
-
require "badline/vic/registers"
|
|
5
|
-
require "badline/vic/display_state"
|
|
6
|
-
require "badline/vic/sequencer"
|
|
7
|
-
require "badline/vic/sprites"
|
|
8
|
-
|
|
9
|
-
module Badline
|
|
10
|
-
class VIC
|
|
11
|
-
include Addressable
|
|
12
|
-
include IntegerHelper
|
|
13
|
-
|
|
14
|
-
# The 6569 of the breadbin C64, the HMOS 8565 of the C64C, and the
|
|
15
|
-
# C128's VIC-IIe, the 8566 (PAL) and 8564 (NTSC). The VIC-IIe draws as
|
|
16
|
-
# the 8565 and adds the $D02F and $D030 registers.
|
|
17
|
-
MODELS = %i[mos6569 mos8565 mos8566 mos8564].freeze
|
|
18
|
-
|
|
19
|
-
# The sixteen colours #display's palette indices stand for, as RGB.
|
|
20
|
-
PALETTE = [
|
|
21
|
-
0x000000, 0xffffff, 0x924a40, 0x84c5cc,
|
|
22
|
-
0x9351b6, 0x72b14b, 0x483aaa, 0xd5df7c,
|
|
23
|
-
0x675200, 0xc33d00, 0xc18178, 0x606060,
|
|
24
|
-
0x8a8a8a, 0xb3ec91, 0x867ade, 0xb3b3b3
|
|
25
|
-
].freeze
|
|
26
|
-
|
|
27
|
-
# The sixteen colours' luminances, out of 32, as Philip Timmermann
|
|
28
|
-
# (Pepto) measured them on the 6569.
|
|
29
|
-
LUMINANCES = [0, 32, 10, 20, 12, 16, 8, 24, 12, 8, 16, 10, 15, 24, 15, 20].freeze
|
|
30
|
-
|
|
31
|
-
# The sixteen colours on a green monochrome monitor, which shows only
|
|
32
|
-
# their luminance, as the PET 64's does.
|
|
33
|
-
GREEN_PALETTE = LUMINANCES.map do |luminance|
|
|
34
|
-
green = luminance * 255 / 32
|
|
35
|
-
((green / 4) << 16) | (green << 8) | (green / 4)
|
|
36
|
-
end.freeze
|
|
37
|
-
|
|
38
|
-
attr_reader :display, :width, :height, :vic_bank, :column,
|
|
39
|
-
:rasterline, :dirty_lines, :model, :region
|
|
40
|
-
|
|
41
|
-
# The RGB colours #display's palette indices stand for: PALETTE, or
|
|
42
|
-
# GREEN_PALETTE on a monochrome monitor.
|
|
43
|
-
attr_accessor :palette
|
|
44
|
-
|
|
45
|
-
# The line of #display the beam draws, which is the raster line unless
|
|
46
|
-
# the VIC-IIe's TEST bit has moved the raster counter on since the
|
|
47
|
-
# last vertical sync (#test_step!).
|
|
48
|
-
attr_reader :output_line
|
|
49
|
-
|
|
50
|
-
# The parts a VICE snapshot reads and sets.
|
|
51
|
-
attr_reader :registers, :display_state, :sequencer, :sprites, :character_buffer, :color_buffer,
|
|
52
|
-
:fetch_d011
|
|
53
|
-
|
|
54
|
-
# Returns the byte the CPU's halted read would see, for the c-accesses
|
|
55
|
-
# that run before AEC. Without it they read colour RAM.
|
|
56
|
-
attr_writer :open_bus
|
|
57
|
-
|
|
58
|
-
LIGHTPEN_IRQ = 0x08 # $D019 latch bit
|
|
59
|
-
COLOR_REGISTERS = 0x20..0x2e
|
|
60
|
-
|
|
61
|
-
# What the 8565 shows on the pixel before a color register write takes
|
|
62
|
-
# hold, where the 6569 shows the old color: the grey dot.
|
|
63
|
-
GREY_DOT = 0x0f
|
|
64
|
-
|
|
65
|
-
# A g-access reaches the pixel output this many columns after it runs.
|
|
66
|
-
GRAPHICS_DELAY = 2
|
|
67
|
-
|
|
68
|
-
# What a column's g-access passed to the sequencer.
|
|
69
|
-
G_BLANK = 0
|
|
70
|
-
G_IDLE = 1
|
|
71
|
-
G_DISPLAY = 2
|
|
72
|
-
|
|
73
|
-
# The idle g-access in the column a mid-row bad line opens display
|
|
74
|
-
# state reads here on a 6569.
|
|
75
|
-
DMA_DELAY_IDLE_ADDRESS = 0x38ff
|
|
76
|
-
|
|
77
|
-
# The $d011 mode bits a g-access still sees for a cycle after they fall:
|
|
78
|
-
# BMM always, and ECM too when the access it leaves read the character
|
|
79
|
-
# ROM.
|
|
80
|
-
FETCH_HOLD = 0x20
|
|
81
|
-
FETCH_HOLD_ROM = 0x60
|
|
82
|
-
|
|
83
|
-
# The hooks a column can carry, as bits: MCBASE, the left border
|
|
84
|
-
# compare with the end of the sprite, the sprite DMA compare, the
|
|
85
|
-
# expansion flip-flop, the sprite display compare, and the start of the
|
|
86
|
-
# vertical border for the line after the last column.
|
|
87
|
-
HOOK_MCBASE = 1
|
|
88
|
-
HOOK_LEFT = 2
|
|
89
|
-
HOOK_DMA = 4
|
|
90
|
-
HOOK_EXPANSION = 8
|
|
91
|
-
HOOK_DISPLAY = 16
|
|
92
|
-
HOOK_LAST = 32
|
|
93
|
-
|
|
94
|
-
# The vertical sync starts this many lines into the vertical blank,
|
|
95
|
-
# and lasts VSYNC_LINES.
|
|
96
|
-
VSYNC_DELAY = 3
|
|
97
|
-
VSYNC_LINES = 3
|
|
98
|
-
|
|
99
|
-
# On the 6569 the DMA compares fall in columns 53 and 54 and the
|
|
100
|
-
# display compare in column 57. A region whose sprite fetches run later
|
|
101
|
-
# moves them with the fetches (Region::Profile#sprite_cycle).
|
|
102
|
-
DMA_COLUMN = 53
|
|
103
|
-
EXPANSION_COLUMN = 54
|
|
104
|
-
|
|
105
|
-
# BA falls three columns ahead of each sprite's pair of s-accesses, and
|
|
106
|
-
# the five-column windows step two columns apart from sprite 0 at column
|
|
107
|
-
# 54 on the 6569, a column later where the fetches are. From sprite 3 on
|
|
108
|
-
# they reach past the end of the line, so each is split: the tail
|
|
109
|
-
# columns fall on the line whose DMA compare started the fetch, the head
|
|
110
|
-
# columns on the line after it.
|
|
111
|
-
SPRITE_BA_FIRST = 54
|
|
112
|
-
SPRITE_BA_LENGTH = 5
|
|
113
|
-
|
|
114
|
-
def initialize(debug: false, model: :mos6569, region: Region::PAL)
|
|
115
|
-
raise ArgumentError, "unknown VIC-II model #{model}" unless MODELS.include?(model)
|
|
116
|
-
|
|
117
|
-
addressable_at(0xd000, length: 2**10)
|
|
118
|
-
@model = model
|
|
119
|
-
@iie = %i[mos8566 mos8564].include?(model)
|
|
120
|
-
@core = model == :mos6569 ? :mos6569 : :mos8565
|
|
121
|
-
@region = region
|
|
122
|
-
@palette = PALETTE
|
|
123
|
-
@lightpen_extra = @core == :mos8565 ? 1 : 2
|
|
124
|
-
@grey_dots = @core == :mos8565
|
|
125
|
-
@delayed_fetch = @core == :mos8565
|
|
126
|
-
@dma_delay_idle = @core == :mos6569
|
|
127
|
-
@bank_swaps = @core == :mos8565
|
|
128
|
-
@vic_bank = VIC::Bank.new(self)
|
|
129
|
-
@debug = debug
|
|
130
|
-
|
|
131
|
-
@columns_per_line = region.cycles_per_line
|
|
132
|
-
@sprite_cycle = region.sprite_cycle
|
|
133
|
-
@sprite_shift = region.sprite_cycle - Region::PAL.sprite_cycle
|
|
134
|
-
@width = @columns_per_line * 8
|
|
135
|
-
@height = region.lines_per_frame
|
|
136
|
-
@last_column = @columns_per_line - 1
|
|
137
|
-
@last_line = @height - 1
|
|
138
|
-
@vsync_line = region.vblank[0] + VSYNC_DELAY
|
|
139
|
-
layout_columns
|
|
140
|
-
@blank_columns = Array.new(@columns_per_line) { |column| Region.blanked?(column, region.hblank) }.freeze
|
|
141
|
-
@blank_lines = Array.new(@height) { |line| Region.blanked?(line, region.vblank) }.freeze
|
|
142
|
-
@display = Array.new(@width * @height, 0)
|
|
143
|
-
@lines = Array.new(@height) { Array.new(@width, 0) }
|
|
144
|
-
@dirty_lines = Array.new(@height, true)
|
|
145
|
-
@render = true
|
|
146
|
-
|
|
147
|
-
power_on!
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
# The VIC has no reset pin, so only a power cycle brings back the
|
|
151
|
-
# registers, the raster position and the fetch and sprite state it
|
|
152
|
-
# starts with. The display keeps its buffers, cleared to black.
|
|
153
|
-
def power_on!
|
|
154
|
-
@registers = VIC::Registers.new(iie: @iie)
|
|
155
|
-
@register_bytes = @registers.bytes
|
|
156
|
-
@display_state = VIC::DisplayState.new(@registers, @last_column)
|
|
157
|
-
@sequencer = VIC::Sequencer.new(@width, @registers, @vic_bank, model: @core, region: @region)
|
|
158
|
-
@sequencer.render = @render
|
|
159
|
-
@sprites = VIC::Sprites.new(@registers, @vic_bank, @width, model: @core, region: @region)
|
|
160
|
-
@display.fill(0)
|
|
161
|
-
@lines.each { |line| line.fill(0) }
|
|
162
|
-
@dirty_lines.fill(true)
|
|
163
|
-
|
|
164
|
-
@column = 0
|
|
165
|
-
@rasterline = 0
|
|
166
|
-
@output_line = 0
|
|
167
|
-
|
|
168
|
-
@character_buffer = Array.new(40, 0)
|
|
169
|
-
@color_buffer = Array.new(40, 0)
|
|
170
|
-
@sprite_ba = Array.new(@width / 8, false)
|
|
171
|
-
@g_tick = 0
|
|
172
|
-
@g_kind = Array.new(4, G_BLANK)
|
|
173
|
-
@g_kept_char = 0
|
|
174
|
-
@g_kept_color = 0
|
|
175
|
-
@g_data = @sequencer.ring_data
|
|
176
|
-
@g_char = @sequencer.ring_char
|
|
177
|
-
@g_color = @sequencer.ring_color
|
|
178
|
-
@g_display = false
|
|
179
|
-
@fetch_d011 = @register_bytes[0x11]
|
|
180
|
-
@lp_triggered = false
|
|
181
|
-
@lp_low = false
|
|
182
|
-
@raster_match = false
|
|
183
|
-
@test_wrap = false
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
# Everything the VIC holds between cycles: the beam, the fetch and
|
|
187
|
-
# g-access pipeline, the light pen and raster latches, the finished
|
|
188
|
-
# lines, on the VIC-IIe the display line and the TEST bit's wrap, the
|
|
189
|
-
# registers and the display, sequencer and sprite logic.
|
|
190
|
-
# Whether it renders is the host's, and every line comes back dirty so
|
|
191
|
-
# a front end repaints.
|
|
192
|
-
def save_state(out)
|
|
193
|
-
out.marker("VIC")
|
|
194
|
-
out.int(@column).int(@rasterline)
|
|
195
|
-
out.int(@g_tick).ints(@g_kind).int(@g_kept_char).int(@g_kept_color).boolean(@g_display)
|
|
196
|
-
out.int(@fetch_d011).boolean(@lp_triggered).boolean(@lp_low).boolean(@raster_match)
|
|
197
|
-
out.int(@vic_bank.lines)
|
|
198
|
-
out.blob(@character_buffer).blob(@color_buffer).booleans(@sprite_ba)
|
|
199
|
-
@lines.each { |line| out.blob(line) }
|
|
200
|
-
out.int(@output_line).boolean(@test_wrap) if @iie
|
|
201
|
-
@registers.save_state(out)
|
|
202
|
-
@display_state.save_state(out)
|
|
203
|
-
@sequencer.save_state(out)
|
|
204
|
-
@sprites.save_state(out)
|
|
205
|
-
end
|
|
206
|
-
|
|
207
|
-
def load_state(input)
|
|
208
|
-
input.marker("VIC")
|
|
209
|
-
load_beam(input)
|
|
210
|
-
load_buffers(input)
|
|
211
|
-
load_lines(input)
|
|
212
|
-
load_test_state(input) if @iie
|
|
213
|
-
@registers.load_state(input)
|
|
214
|
-
@display_state.load_state(input)
|
|
215
|
-
@sequencer.load_state(input)
|
|
216
|
-
@sprites.load_state(input)
|
|
217
|
-
end
|
|
218
|
-
|
|
219
|
-
def cycle!
|
|
220
|
-
start_line! if @column.zero?
|
|
221
|
-
|
|
222
|
-
# The g-access runs in the first half of the cycle, ahead of the bad
|
|
223
|
-
# line compare, and the c-access in the second half, after it.
|
|
224
|
-
draw!
|
|
225
|
-
dma_delay_idle_access if @display_state.cycle(@rasterline, @column)
|
|
226
|
-
|
|
227
|
-
fetch_character_data! if dma_active?
|
|
228
|
-
|
|
229
|
-
hooks = @hook_columns[@column]
|
|
230
|
-
column_hooks(hooks) if hooks
|
|
231
|
-
|
|
232
|
-
@column += 1
|
|
233
|
-
if @column == @columns_per_line
|
|
234
|
-
finish_line!
|
|
235
|
-
@column = 0
|
|
236
|
-
step_output_line
|
|
237
|
-
@rasterline = @rasterline == @last_line ? 0 : @rasterline + 1
|
|
238
|
-
check_raster_irq!(@rasterline.zero? ? @last_line : @rasterline)
|
|
239
|
-
end
|
|
240
|
-
watch_collisions
|
|
241
|
-
nil
|
|
242
|
-
end
|
|
243
|
-
|
|
244
|
-
# The sprite and border hooks that fall on named cycles, one column
|
|
245
|
-
# ahead of Bauer's numbering — two for MCBASE, the DMA compares and the
|
|
246
|
-
# expansion flip-flop, which the `spriteenable` and `spritecrunch`
|
|
247
|
-
# references place a column earlier still. Guarded in
|
|
248
|
-
# #cycle! so an ordinary column pays an array read rather than the
|
|
249
|
-
# dispatch.
|
|
250
|
-
def column_hooks(hooks)
|
|
251
|
-
@sprites.advance_mcbase if hooks.anybits?(HOOK_MCBASE)
|
|
252
|
-
if hooks.anybits?(HOOK_LEFT)
|
|
253
|
-
@sequencer.left_compare_vertical_border
|
|
254
|
-
finish_sprite_mcbase
|
|
255
|
-
end
|
|
256
|
-
check_sprite_dma if hooks.anybits?(HOOK_DMA)
|
|
257
|
-
@sprites.toggle_expansion if hooks.anybits?(HOOK_EXPANSION)
|
|
258
|
-
@sprites.check_display(@rasterline) if hooks.anybits?(HOOK_DISPLAY)
|
|
259
|
-
@sequencer.start_vertical_border(@rasterline == @last_line ? 0 : @rasterline + 1) if hooks.anybits?(HOOK_LAST)
|
|
260
|
-
end
|
|
261
|
-
|
|
262
|
-
# The IRQ line is held asserted while any enabled latch bit is set in
|
|
263
|
-
# $D019/$D01A, until the program acknowledges it by writing to $D019.
|
|
264
|
-
def interrupted?
|
|
265
|
-
@registers.irq_line?
|
|
266
|
-
end
|
|
267
|
-
|
|
268
|
-
# The VIC-IIe's $D02F lines K0-K2 and $D030 bits, for the machine to
|
|
269
|
-
# read. The 6569 and 8565 give 7, false and false.
|
|
270
|
-
def extra_keyboard_lines = @registers.extra_keyboard_lines
|
|
271
|
-
def fast? = @registers.fast?
|
|
272
|
-
def test? = @registers.test?
|
|
273
|
-
|
|
274
|
-
# $D030's FAST and TEST bits as bits 0 and 1, which the C128 reads once
|
|
275
|
-
# a cycle.
|
|
276
|
-
def clock_bits = @registers.clock_bits
|
|
277
|
-
|
|
278
|
-
# Whether the cycle just run was one of the five refresh cycles, Bauer's
|
|
279
|
-
# 11-15, whose phi1 half the VIC keeps in the VIC-IIe's FAST mode.
|
|
280
|
-
# @column has already advanced, so it is the Bauer cycle less one.
|
|
281
|
-
def refresh_cycle? = @column.between?(10, 14)
|
|
282
|
-
|
|
283
|
-
# In the VIC-IIe's FAST mode the 8502 drives the bus in both halves of
|
|
284
|
-
# the cycle, and the VIC's accesses in the cycle just run latched what
|
|
285
|
-
# it put there. The g-access, or the idle access, took the byte of
|
|
286
|
-
# phi1. A c-access took the byte of phi2 as one made before AEC does
|
|
287
|
-
# (#fetch_character_data!): $ff for the video matrix, unless the CPU
|
|
288
|
-
# was reading or writing the VIC's own registers, and the byte's low
|
|
289
|
-
# nibble for colour. AEC can't follow BA down while the CPU runs at
|
|
290
|
-
# 2 MHz, so on a bad line it falls three cycles after FAST mode ends.
|
|
291
|
-
def take_cpu_bus(phi1, phi2, register_access)
|
|
292
|
-
slot = @g_tick
|
|
293
|
-
@g_data[slot] = phi1 unless @g_kind[slot] == G_BLANK
|
|
294
|
-
display_state = @display_state
|
|
295
|
-
display_state.keep_bus(@column)
|
|
296
|
-
return unless display_state.fetching?(@column.zero? ? @last_column : @column - 1)
|
|
297
|
-
|
|
298
|
-
vmli = display_state.vmli
|
|
299
|
-
@character_buffer[vmli] = register_access ? phi2 : 0xff
|
|
300
|
-
@color_buffer[vmli] = phi2 & 0x0f
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
# The VIC-IIe's TEST bit clocks the raster counter in every cycle, and
|
|
304
|
-
# the C128 calls this ahead of each cycle the bit is set in. The line's
|
|
305
|
-
# last cycle, whose own step it falls in with, adds nothing more. The
|
|
306
|
-
# counter takes two steps from the frame's last line to line 0, as line
|
|
307
|
-
# 0 reads the last line for its first cycle.
|
|
308
|
-
def test_step!
|
|
309
|
-
return if @column == @last_column
|
|
310
|
-
|
|
311
|
-
if @rasterline == @last_line
|
|
312
|
-
@test_wrap = !@test_wrap
|
|
313
|
-
return if @test_wrap
|
|
314
|
-
|
|
315
|
-
@rasterline = 0
|
|
316
|
-
@display_state.new_frame
|
|
317
|
-
else
|
|
318
|
-
@test_wrap = false
|
|
319
|
-
@rasterline += 1
|
|
320
|
-
end
|
|
321
|
-
@display_state.raster_step(@rasterline)
|
|
322
|
-
check_raster_irq!
|
|
323
|
-
end
|
|
324
|
-
|
|
325
|
-
def peek(addr)
|
|
326
|
-
i = offset_of(addr) % (2**6)
|
|
327
|
-
case i
|
|
328
|
-
when 0x11 then (@registers[0x11] & 0x7f) | ((raster_counter & 0x100) >> 1)
|
|
329
|
-
when 0x12 then raster_counter & 0xff
|
|
330
|
-
when 0x19 then irq_status # Latch + master IRQ bit, unused bits read 1
|
|
331
|
-
when 0x1e, 0x1f then read_collision(i)
|
|
332
|
-
else @registers.read(i)
|
|
333
|
-
end.tap { |value| @sprites.bus_data(@column, value) }
|
|
334
|
-
end
|
|
335
|
-
|
|
336
|
-
# The register file as stored, read without a bus access's side effects.
|
|
337
|
-
def register_file = Array.new(0x40) { |reg| @registers[reg] }
|
|
338
|
-
|
|
339
|
-
def poke(addr, value)
|
|
340
|
-
reg = offset_of(addr) % (2**6)
|
|
341
|
-
@sprites.bus_data(@column, value)
|
|
342
|
-
log_register_change(reg, value)
|
|
343
|
-
@registers.write(reg, value)
|
|
344
|
-
compare_raster_writes(reg)
|
|
345
|
-
end
|
|
346
|
-
|
|
347
|
-
def position
|
|
348
|
-
(@rasterline * @width) + (@column * 8)
|
|
349
|
-
end
|
|
350
|
-
|
|
351
|
-
def dma_active?
|
|
352
|
-
@display_state.fetching?(@column)
|
|
353
|
-
end
|
|
354
|
-
|
|
355
|
-
# Asked once the VIC has advanced, so @column is one ahead of the cycle
|
|
356
|
-
# the CPU is about to run. A bad line holds BA on the condition as it
|
|
357
|
-
# stands rather than the latched match.
|
|
358
|
-
def ba_low?
|
|
359
|
-
return true if @sprite_ba[@column]
|
|
360
|
-
|
|
361
|
-
@display_state.bad_line_condition? &&
|
|
362
|
-
@column > DisplayState::DMA_FIRST && @column <= DisplayState::DMA_LAST + 1
|
|
363
|
-
end
|
|
364
|
-
|
|
365
|
-
# Whether this is the first cycle of sprite 0's BA window on the line
|
|
366
|
-
# whose raster matches its Y, where the sprite's DMA starts. An REU
|
|
367
|
-
# that moved a byte on the cycle before doesn't see BA fall here. Pinned by
|
|
368
|
-
# REU/bonzai/spritetiming.
|
|
369
|
-
def reu_ba_late?
|
|
370
|
-
@column == SPRITE_BA_FIRST + @sprite_shift && sprite_zero_starting?
|
|
371
|
-
end
|
|
372
|
-
|
|
373
|
-
# Whether BA passes straight from a bad line's window to sprite 0's on
|
|
374
|
-
# this cycle, the first of sprite 0's. An REU sees the bad line's DMA
|
|
375
|
-
# end here. Pinned by REU/reutiming2/e4-m2 and e6-m2.
|
|
376
|
-
def reu_ba_handed_on?
|
|
377
|
-
@column == DisplayState::DMA_LAST + 2 && @sprite_ba[@column] && @display_state.bad_line_condition?
|
|
378
|
-
end
|
|
379
|
-
|
|
380
|
-
# Light pen input level (CIA1 PB4). A falling edge triggers the latch.
|
|
381
|
-
def lightpen_level(high)
|
|
382
|
-
@lp_low = !high
|
|
383
|
-
trigger_lightpen if @lp_low
|
|
384
|
-
end
|
|
385
|
-
|
|
386
|
-
# The first trigger per frame latches the beam position into LPX/LPY and
|
|
387
|
-
# raises the LP IRQ. The latch happens one cycle after the edge, with
|
|
388
|
-
# the model's extra half-pixels, two on the 6569 and one on the 8565; a
|
|
389
|
-
# trigger on the last line is consumed without latching unless it lands
|
|
390
|
-
# on the line's first cycle.
|
|
391
|
-
def trigger_lightpen
|
|
392
|
-
return if @lp_triggered
|
|
393
|
-
|
|
394
|
-
@lp_triggered = true
|
|
395
|
-
column = @column + 1
|
|
396
|
-
line = @rasterline
|
|
397
|
-
if column == @columns_per_line
|
|
398
|
-
column = 0
|
|
399
|
-
line = line == @last_line ? 0 : line + 1
|
|
400
|
-
end
|
|
401
|
-
return if line == @last_line && column.positive?
|
|
402
|
-
|
|
403
|
-
vic_x = Sprite::Timing.xpos(column * 8, @width, @region.x_hold)
|
|
404
|
-
latch_lightpen((vic_x >> 1) + @lightpen_extra, line)
|
|
405
|
-
end
|
|
406
|
-
|
|
407
|
-
# The byte the VIC fetched in the phi1 half of the cycle the CPU is
|
|
408
|
-
# running, worked out from the VIC's state. The CPU cycle after column
|
|
409
|
-
# c is Bauer cycle c + 2, and each Bauer cycle has a fixed access (VICE
|
|
410
|
-
# `cycle_phi1_fetch`).
|
|
411
|
-
def phi1_data
|
|
412
|
-
vic_bank.peek(phi1_address)
|
|
413
|
-
end
|
|
414
|
-
|
|
415
|
-
def hblank? = @blank_columns[@column]
|
|
416
|
-
def vblank? = @blank_lines[@rasterline]
|
|
417
|
-
def blanking? = @blank_lines[@rasterline] || @blank_columns[@column]
|
|
418
|
-
|
|
419
|
-
def render? = @render
|
|
420
|
-
|
|
421
|
-
# Whether finished lines are painted into #display. A headless run that
|
|
422
|
-
# only reads the machine's state can turn it off: the sprite
|
|
423
|
-
# collisions, lightpen and every register still behave the same, but
|
|
424
|
-
# #display keeps the last lines painted. Turned back on, it is whole
|
|
425
|
-
# again from the start of the next frame.
|
|
426
|
-
def render=(on)
|
|
427
|
-
@render = on
|
|
428
|
-
@sequencer.render = on
|
|
429
|
-
end
|
|
430
|
-
|
|
431
|
-
# Puts the beam at the start of `line`.
|
|
432
|
-
def restore_line(line)
|
|
433
|
-
@rasterline = @output_line = line
|
|
434
|
-
@column = 0
|
|
435
|
-
end
|
|
436
|
-
|
|
437
|
-
# The latches a VICE snapshot holds: the raster match, the light pen's
|
|
438
|
-
# line held low and its trigger, as bits 0, 1 and 2.
|
|
439
|
-
def latch_bits = (@raster_match ? 1 : 0) | (@lp_low ? 2 : 0) | (@lp_triggered ? 4 : 0)
|
|
440
|
-
|
|
441
|
-
# Sets the latches from latch_bits, and the $D011 the next g-access
|
|
442
|
-
# holds.
|
|
443
|
-
def restore_latches(bits, fetch_d011)
|
|
444
|
-
@raster_match = bits.anybits?(1)
|
|
445
|
-
@lp_low = bits.anybits?(2)
|
|
446
|
-
@lp_triggered = bits.anybits?(4)
|
|
447
|
-
@fetch_d011 = fetch_d011
|
|
448
|
-
end
|
|
449
|
-
|
|
450
|
-
# Marks the columns BA is low for the sprites whose DMA runs.
|
|
451
|
-
def rebuild_sprite_ba
|
|
452
|
-
@sprite_ba.fill(false)
|
|
453
|
-
8.times do |n|
|
|
454
|
-
next unless @sprites[n].displaying?
|
|
455
|
-
|
|
456
|
-
@sprite_ba_tail[n].each { |c| @sprite_ba[c] = true }
|
|
457
|
-
@sprite_ba_head[n].each { |c| @sprite_ba[c] = true }
|
|
458
|
-
end
|
|
459
|
-
end
|
|
460
|
-
|
|
461
|
-
# Reset the dirty flags once the frontend has consumed them.
|
|
462
|
-
def clear_dirty_lines!
|
|
463
|
-
@dirty_lines.fill(false)
|
|
464
|
-
end
|
|
465
|
-
|
|
466
|
-
private
|
|
467
|
-
|
|
468
|
-
def load_beam(input)
|
|
469
|
-
@column = input.int
|
|
470
|
-
@rasterline = @output_line = input.int
|
|
471
|
-
if input.schema < 9
|
|
472
|
-
input.int
|
|
473
|
-
input.boolean?
|
|
474
|
-
end
|
|
475
|
-
@g_tick = input.int
|
|
476
|
-
input.ints_into(@g_kind)
|
|
477
|
-
@g_kept_char = input.int
|
|
478
|
-
@g_kept_color = input.int
|
|
479
|
-
@g_display = input.boolean?
|
|
480
|
-
@fetch_d011 = input.int
|
|
481
|
-
@lp_triggered = input.boolean?
|
|
482
|
-
@lp_low = input.boolean?
|
|
483
|
-
@raster_match = input.boolean?
|
|
484
|
-
@vic_bank.lines = input.int
|
|
485
|
-
end
|
|
486
|
-
|
|
487
|
-
def load_buffers(input)
|
|
488
|
-
input.blob_into(@character_buffer)
|
|
489
|
-
input.blob_into(@color_buffer)
|
|
490
|
-
input.booleans_into(@sprite_ba)
|
|
491
|
-
end
|
|
492
|
-
|
|
493
|
-
# The VIC-IIe's display line and TEST wrap, which only its TEST bit
|
|
494
|
-
# moves off the raster line.
|
|
495
|
-
def load_test_state(input)
|
|
496
|
-
@output_line = input.int
|
|
497
|
-
@test_wrap = input.boolean?
|
|
498
|
-
end
|
|
499
|
-
|
|
500
|
-
# The display is the finished lines one after another.
|
|
501
|
-
def load_lines(input)
|
|
502
|
-
@lines.each_with_index do |line, number|
|
|
503
|
-
input.blob_into(line)
|
|
504
|
-
@display[number * @width, @width] = line
|
|
505
|
-
end
|
|
506
|
-
@dirty_lines.fill(true)
|
|
507
|
-
end
|
|
508
|
-
|
|
509
|
-
# The raster counter as $D011/$D012 read it. Every line advances on the
|
|
510
|
-
# CPU cycle paired with column 62 except line 0, which the counter
|
|
511
|
-
# reaches a cycle later, together with the line 0 raster compare.
|
|
512
|
-
def raster_counter
|
|
513
|
-
@column.zero? && @rasterline.zero? ? @last_line : @rasterline
|
|
514
|
-
end
|
|
515
|
-
|
|
516
|
-
# Mid-line writes to the color and sprite registers are logged against
|
|
517
|
-
# the cycle after the write (the CPU runs after the VIC within a machine
|
|
518
|
-
# cycle, so @column already points there); each register adds its own
|
|
519
|
-
# pixel delay on top. On the 8565 a color register write that leaves
|
|
520
|
-
# the value as it was still shows its grey dot.
|
|
521
|
-
def log_register_change(reg, value)
|
|
522
|
-
old = @registers[reg]
|
|
523
|
-
return if old == value && !grey_dot?(reg)
|
|
524
|
-
|
|
525
|
-
if (0x20..0x24).cover?(reg)
|
|
526
|
-
@sequencer.colors_changed! unless reg == 0x20
|
|
527
|
-
@sequencer.color_patches.log(reg, old, value, @column * 8) if @render && !blanking?
|
|
528
|
-
else
|
|
529
|
-
log_sprite_change(reg, old, value)
|
|
530
|
-
end
|
|
531
|
-
end
|
|
532
|
-
|
|
533
|
-
def grey_dot?(reg) = @grey_dots && COLOR_REGISTERS.cover?(reg)
|
|
534
|
-
|
|
535
|
-
# A sprite color shows its grey dot as a write of light grey on the
|
|
536
|
-
# pixel before the new color.
|
|
537
|
-
def log_sprite_change(reg, old, value)
|
|
538
|
-
beam_x = @column * 8
|
|
539
|
-
@sprites.log_change(reg, old, GREY_DOT, beam_x - 1) if grey_dot?(reg)
|
|
540
|
-
@sprites.log_change(reg, old, value, beam_x)
|
|
541
|
-
end
|
|
542
|
-
|
|
543
|
-
# On the 6569 Bauer cycles 1-10 and 58-63 are sprite p- and s-accesses,
|
|
544
|
-
# 11-15 refresh, 16-55 g-accesses and 56-57 idle. Where the sprite
|
|
545
|
-
# fetches start later, the idle cycles before them grow, and on the
|
|
546
|
-
# 6567R8 cycle 10 idles too. @column has already advanced, so it is the
|
|
547
|
-
# Bauer cycle less one.
|
|
548
|
-
def phi1_address
|
|
549
|
-
cycle = @column + 1
|
|
550
|
-
slot = (cycle - @sprite_cycle) % @columns_per_line
|
|
551
|
-
if slot < 16
|
|
552
|
-
sprite_phi1_address(slot)
|
|
553
|
-
elsif cycle.between?(11, 15)
|
|
554
|
-
0x3f00 | ((0xff - (5 * @rasterline) - (cycle - 11)) & 0xff)
|
|
555
|
-
elsif cycle.between?(16, 55)
|
|
556
|
-
graphics_phi1_address
|
|
557
|
-
else
|
|
558
|
-
0x3fff
|
|
559
|
-
end
|
|
560
|
-
end
|
|
561
|
-
|
|
562
|
-
# Each sprite takes two cycles from sprite 0's, the p-access and then
|
|
563
|
-
# the middle s-access.
|
|
564
|
-
def sprite_phi1_address(slot)
|
|
565
|
-
n = slot >> 1
|
|
566
|
-
return @registers.screen_base + 0x3f8 + n if slot.even?
|
|
567
|
-
|
|
568
|
-
@sprites[n].phi1_address || 0x3fff
|
|
569
|
-
end
|
|
570
|
-
|
|
571
|
-
# The g-access of the column just run. In display state it used the
|
|
572
|
-
# VC and VMLI it then stepped past.
|
|
573
|
-
def graphics_phi1_address
|
|
574
|
-
return @registers.ecm.nonzero? ? 0x39ff : 0x3fff unless @g_display
|
|
575
|
-
|
|
576
|
-
graphics_address(@registers[0x11], @display_state.vmli - 1, (@display_state.vc - 1) & 0x3ff)
|
|
577
|
-
end
|
|
578
|
-
|
|
579
|
-
# A $d011/$d012 write is compared in the next column. A write in the
|
|
580
|
-
# line's second last column is left to its last, which compares the
|
|
581
|
-
# next line.
|
|
582
|
-
def compare_raster_writes(reg)
|
|
583
|
-
return unless (0x11..0x12).cover?(reg)
|
|
584
|
-
return if @column == @last_column
|
|
585
|
-
|
|
586
|
-
check_raster_irq!
|
|
587
|
-
@sequencer.compare_vertical_border(@rasterline) if reg == 0x11
|
|
588
|
-
end
|
|
589
|
-
|
|
590
|
-
def check_sprite_dma
|
|
591
|
-
rebuild_sprite_ba if @sprites.check_dma(@rasterline, @column)
|
|
592
|
-
end
|
|
593
|
-
|
|
594
|
-
# A sprite whose DMA ends here fetches nothing at the end of this line,
|
|
595
|
-
# so its BA tail goes too.
|
|
596
|
-
def finish_sprite_mcbase
|
|
597
|
-
@sprites.finish_mcbase
|
|
598
|
-
rebuild_sprite_ba if @sprites.stopped_dma?
|
|
599
|
-
end
|
|
600
|
-
|
|
601
|
-
# The trigger re-arms at the start of each frame; if the pen line is
|
|
602
|
-
# still low, the latch retriggers immediately with a fixed LPX of $d1.
|
|
603
|
-
def start_lightpen_frame
|
|
604
|
-
@lp_triggered = false
|
|
605
|
-
return unless @lp_low
|
|
606
|
-
|
|
607
|
-
@lp_triggered = true
|
|
608
|
-
latch_lightpen(0xd1, 0)
|
|
609
|
-
end
|
|
610
|
-
|
|
611
|
-
def latch_lightpen(lpx, line)
|
|
612
|
-
@registers.write(0x13, lpx & 0xff)
|
|
613
|
-
@registers.write(0x14, line & 0xff)
|
|
614
|
-
@registers.latch_irq!(LIGHTPEN_IRQ)
|
|
615
|
-
end
|
|
616
|
-
|
|
617
|
-
def sprite_zero_starting?
|
|
618
|
-
@registers[0x15].anybits?(0x01) && @registers[0x01] == (@rasterline & 0xff)
|
|
619
|
-
end
|
|
620
|
-
|
|
621
|
-
# Splits the sprite BA windows at the end of the line and marks the hook
|
|
622
|
-
# columns, for a line of the region's length: 14, 15, 53, 54 and 57, and
|
|
623
|
-
# the line's last column, which starts the vertical border for the line
|
|
624
|
-
# after it. The marks let an ordinary column cost one array read instead
|
|
625
|
-
# of the dispatch.
|
|
626
|
-
def layout_columns
|
|
627
|
-
last = @last_column
|
|
628
|
-
windows = Array.new(8) do |n|
|
|
629
|
-
first = SPRITE_BA_FIRST + @sprite_shift + (2 * n)
|
|
630
|
-
first...(first + SPRITE_BA_LENGTH)
|
|
631
|
-
end
|
|
632
|
-
@sprite_ba_tail = windows.map { |w| w.select { |c| c <= last } }.freeze
|
|
633
|
-
@sprite_ba_head = windows.map { |w| w.filter_map { |c| c - last - 1 if c > last } }.freeze
|
|
634
|
-
@hook_columns = layout_hooks.map { |hooks| hooks unless hooks.zero? }.freeze
|
|
635
|
-
end
|
|
636
|
-
|
|
637
|
-
def layout_hooks
|
|
638
|
-
hooks = Array.new(@columns_per_line, 0)
|
|
639
|
-
hooks[14] |= HOOK_MCBASE
|
|
640
|
-
hooks[15] |= HOOK_LEFT
|
|
641
|
-
hooks[DMA_COLUMN + @sprite_shift] |= HOOK_DMA
|
|
642
|
-
hooks[DMA_COLUMN + @sprite_shift + 1] |= HOOK_DMA
|
|
643
|
-
hooks[EXPANSION_COLUMN] |= HOOK_EXPANSION
|
|
644
|
-
hooks[@region.sprite_display_cycle - 1] |= HOOK_DISPLAY
|
|
645
|
-
hooks[@last_column] |= HOOK_LAST
|
|
646
|
-
hooks
|
|
647
|
-
end
|
|
648
|
-
|
|
649
|
-
# Runs this column's g-access and draws the one from GRAPHICS_DELAY
|
|
650
|
-
# columns earlier. The access reads its byte now, through the mode,
|
|
651
|
-
# $d018 and bank of this cycle. A column with no g-access, or one made
|
|
652
|
-
# while the vertical border flip-flop is set, latches nothing: it passes
|
|
653
|
-
# on zero data with the screen byte and colour the last g-access
|
|
654
|
-
# latched, which an idle g-access clears.
|
|
655
|
-
def draw!
|
|
656
|
-
@vic_bank.sample_lines if @bank_swaps
|
|
657
|
-
slot = @g_tick = (@g_tick + 1) & 3
|
|
658
|
-
display_state = @display_state
|
|
659
|
-
access = display_state.graphics_column?(@column) && !@sequencer.vertical_closed?
|
|
660
|
-
if access
|
|
661
|
-
latch_graphics(slot, display_state)
|
|
662
|
-
else
|
|
663
|
-
@g_kind[slot] = G_BLANK
|
|
664
|
-
@g_data[slot] = 0
|
|
665
|
-
@g_char[slot] = @g_kept_char
|
|
666
|
-
@g_color[slot] = @g_kept_color
|
|
667
|
-
end
|
|
668
|
-
@g_display = display_state.display?
|
|
669
|
-
display_state.graphics_access(@column) if @g_display
|
|
670
|
-
emit_graphics((slot - GRAPHICS_DELAY) & 3, @column - 16) unless blanking?
|
|
671
|
-
@sequencer.latch_xscroll(@register_bytes[0x16] & 0b111) if access
|
|
672
|
-
@fetch_d011 = @register_bytes[0x11]
|
|
673
|
-
end
|
|
674
|
-
|
|
675
|
-
def latch_graphics(slot, display_state)
|
|
676
|
-
unless display_state.display?
|
|
677
|
-
@g_kind[slot] = G_IDLE
|
|
678
|
-
@g_data[slot] = vic_bank.peek(@registers.ecm.zero? ? 0x3fff : 0x39ff)
|
|
679
|
-
@g_char[slot] = @g_color[slot] = @g_kept_char = @g_kept_color = 0
|
|
680
|
-
return
|
|
681
|
-
end
|
|
682
|
-
|
|
683
|
-
vmli = display_state.vmli
|
|
684
|
-
@g_kind[slot] = G_DISPLAY
|
|
685
|
-
@g_data[slot] = fetch_graphics(vmli, display_state.vc)
|
|
686
|
-
@g_char[slot] = @g_kept_char = @character_buffer[vmli] || 0
|
|
687
|
-
@g_color[slot] = @g_kept_color = @color_buffer[vmli] || 1
|
|
688
|
-
end
|
|
689
|
-
|
|
690
|
-
# On the 6569 a bad line that opens display state mid-row (DMA delay)
|
|
691
|
-
# moves the idle g-access of the column that triggers it from $3fff (or
|
|
692
|
-
# $39ff) to DMA_DELAY_IDLE_ADDRESS, unless YSCROLL is 0 (vsp-tester,
|
|
693
|
-
# colorfetchbug/main).
|
|
694
|
-
def dma_delay_idle_access
|
|
695
|
-
slot = @g_tick
|
|
696
|
-
return unless @dma_delay_idle && @g_kind[slot] == G_IDLE
|
|
697
|
-
return if @registers.yscroll.zero?
|
|
698
|
-
|
|
699
|
-
@g_data[slot] = vic_bank.peek(DMA_DELAY_IDLE_ADDRESS)
|
|
700
|
-
end
|
|
701
|
-
|
|
702
|
-
# The 6569's g-access sees a mode bit that falls a cycle late: it
|
|
703
|
-
# addresses with $d011 as this column has it, OR-ed with the held bits
|
|
704
|
-
# the column before had. When BMM changes and the access moves from RAM
|
|
705
|
-
# onto the character ROM, the low address byte still comes from the old
|
|
706
|
-
# mode. The 8565's addresses with $d011 as the column before had it
|
|
707
|
-
# (VICE x64sc `vicii_fetch_graphics`).
|
|
708
|
-
def fetch_graphics(vmli, counter)
|
|
709
|
-
d011 = @register_bytes[0x11]
|
|
710
|
-
last = @fetch_d011
|
|
711
|
-
return vic_bank.peek(graphics_address(d011, vmli, counter)) if d011 == last
|
|
712
|
-
return vic_bank.peek(graphics_address(last, vmli, counter)) if @delayed_fetch
|
|
713
|
-
|
|
714
|
-
from = graphics_address(last, vmli, counter)
|
|
715
|
-
from_rom = vic_bank.character_rom?(from)
|
|
716
|
-
address = graphics_address(d011 | (last & (from_rom ? FETCH_HOLD_ROM : FETCH_HOLD)), vmli, counter)
|
|
717
|
-
if (d011 ^ last).anybits?(0x20) && !from_rom
|
|
718
|
-
to = graphics_address(d011, vmli, counter)
|
|
719
|
-
address = (from & 0xff) | (to & 0x3f00) if vic_bank.character_rom?(to)
|
|
720
|
-
end
|
|
721
|
-
vic_bank.peek(address)
|
|
722
|
-
end
|
|
723
|
-
|
|
724
|
-
def graphics_address(d011, vmli, counter)
|
|
725
|
-
rc = @display_state.rc
|
|
726
|
-
case d011 & 0x60
|
|
727
|
-
when 0x00 then @registers.char_base | ((@character_buffer[vmli] || 0) << 3) | rc
|
|
728
|
-
when 0x20 then @registers.bitmap_base | (counter << 3) | rc
|
|
729
|
-
when 0x40 then (@registers.char_base | ((@character_buffer[vmli] || 0) << 3) | rc) & 0x39ff
|
|
730
|
-
else (@registers.bitmap_base | (counter << 3) | rc) & 0x39ff
|
|
731
|
-
end
|
|
732
|
-
end
|
|
733
|
-
|
|
734
|
-
def emit_graphics(slot, col)
|
|
735
|
-
@sequencer.emit(slot, col, @g_kind[slot] == G_DISPLAY)
|
|
736
|
-
end
|
|
737
|
-
|
|
738
|
-
# Fold the rest of the line's sprite collisions in — they latch whether
|
|
739
|
-
# or not there is a line to draw — then composite the active sprites
|
|
740
|
-
# over the finished background and copy the line into the frame display.
|
|
741
|
-
def finish_line!
|
|
742
|
-
return finish_blank_line if vblank? || !@render
|
|
743
|
-
|
|
744
|
-
composite = @sprites.active?
|
|
745
|
-
@sequencer.apply_color_patches
|
|
746
|
-
@sequencer.snapshot_line if composite
|
|
747
|
-
@sprites.finish_line(composite ? @sequencer.colors : nil, @sequencer.fg)
|
|
748
|
-
@sequencer.apply_border if composite
|
|
749
|
-
|
|
750
|
-
colors = @sequencer.colors
|
|
751
|
-
output_line = @output_line
|
|
752
|
-
line = @lines[output_line]
|
|
753
|
-
return if line == colors
|
|
754
|
-
|
|
755
|
-
line[0, @width] = colors
|
|
756
|
-
@display[output_line * @width, @width] = colors
|
|
757
|
-
@dirty_lines[output_line] = true
|
|
758
|
-
end
|
|
759
|
-
|
|
760
|
-
# A blanked line paints nothing, and is never shown unless the TEST
|
|
761
|
-
# bit has moved the beam off the raster line, where it shows black.
|
|
762
|
-
def finish_blank_line
|
|
763
|
-
@sprites.finish_line(nil, @sequencer.fg)
|
|
764
|
-
return if @output_line == @rasterline || !@render
|
|
765
|
-
|
|
766
|
-
line = @output_line
|
|
767
|
-
@lines[line].fill(0)
|
|
768
|
-
@display.fill(0, line * @width, @width)
|
|
769
|
-
@dirty_lines[line] = true
|
|
770
|
-
end
|
|
771
|
-
|
|
772
|
-
# The display line the beam draws next follows the one before it, and
|
|
773
|
-
# a line that ends in the vertical sync puts it back on the raster
|
|
774
|
-
# line. Only the VIC-IIe's TEST bit moves the raster counter on between
|
|
775
|
-
# the two, so the lines it skips shift the picture up until the next
|
|
776
|
-
# sync.
|
|
777
|
-
def step_output_line
|
|
778
|
-
@output_line = if @rasterline.between?(@vsync_line, @vsync_line + VSYNC_LINES - 1)
|
|
779
|
-
@rasterline + 1
|
|
780
|
-
else
|
|
781
|
-
@output_line == @last_line ? 0 : @output_line + 1
|
|
782
|
-
end
|
|
783
|
-
end
|
|
784
|
-
|
|
785
|
-
def video_matrix(index)
|
|
786
|
-
vic_bank.peek_phi2(@registers.screen_base + index)
|
|
787
|
-
end
|
|
788
|
-
|
|
789
|
-
def start_line!
|
|
790
|
-
if @rasterline.zero?
|
|
791
|
-
@display_state.new_frame
|
|
792
|
-
start_lightpen_frame
|
|
793
|
-
# The line 0 raster compare happens one cycle later than on all
|
|
794
|
-
# other lines (Bauer 3.12).
|
|
795
|
-
check_raster_irq!
|
|
796
|
-
end
|
|
797
|
-
@sequencer.new_line(@rasterline)
|
|
798
|
-
@sprites.start_line
|
|
799
|
-
rebuild_sprite_ba
|
|
800
|
-
@display_state.new_line(@rasterline)
|
|
801
|
-
end
|
|
802
|
-
|
|
803
|
-
# The raster compare latches the flag only as the line and the target
|
|
804
|
-
# come to match, so a target moved along with the raster line holds the
|
|
805
|
-
# match without latching again (VICE x64sc). It runs at each line step
|
|
806
|
-
# and after each $d011/$d012 write. The line asserts via #interrupted?
|
|
807
|
-
# when the mask bit in $D01A is set.
|
|
808
|
-
def check_raster_irq!(line = @rasterline)
|
|
809
|
-
match = line == @registers.raster_target
|
|
810
|
-
@registers.latch_raster_irq! if match && !@raster_match
|
|
811
|
-
@raster_match = match
|
|
812
|
-
end
|
|
813
|
-
|
|
814
|
-
# A collision register carries the pixels drawn up to the cycle before
|
|
815
|
-
# the read — the VIC runs ahead of the CPU within a machine cycle, so
|
|
816
|
-
# the column the read lands on has not latched yet — and the reset the
|
|
817
|
-
# read asserts outlives it, swallowing the pixels drawn under it.
|
|
818
|
-
def read_collision(reg)
|
|
819
|
-
beam_x = @column * 8
|
|
820
|
-
@sprites.collide_upto(beam_x, @sequencer.fg)
|
|
821
|
-
@registers.read(reg).tap { @sprites.clear_collision(reg, beam_x) }
|
|
822
|
-
end
|
|
823
|
-
|
|
824
|
-
# A collision raises its $D019 bit as the beam crosses the pixel rather
|
|
825
|
-
# than when the line is folded at its end, so while an enabled
|
|
826
|
-
# collision IRQ is still unlatched the fold keeps up with the beam.
|
|
827
|
-
def watch_collisions
|
|
828
|
-
return if (@registers[0x1a] & ~@registers[0x19]).nobits?(0x06)
|
|
829
|
-
|
|
830
|
-
@sprites.collide_upto(@column * 8, @sequencer.fg)
|
|
831
|
-
end
|
|
832
|
-
|
|
833
|
-
def irq_status
|
|
834
|
-
@sprites.collide_upto(@column * 8, @sequencer.fg)
|
|
835
|
-
(@registers[0x19] & 0x0f) | 0x70 | (interrupted? ? 0x80 : 0)
|
|
836
|
-
end
|
|
837
|
-
|
|
838
|
-
# A c-access that falls between BA and AEC reads a bus the CPU still
|
|
839
|
-
# drives: the video matrix byte comes back as $ff, and the colour
|
|
840
|
-
# nibble is the low nibble of the byte at the halted CPU's PC.
|
|
841
|
-
def fetch_character_data!
|
|
842
|
-
vmli = @display_state.vmli
|
|
843
|
-
vc = @display_state.vc
|
|
844
|
-
if @display_state.bus_taken?(@column)
|
|
845
|
-
@character_buffer[vmli] = video_matrix(vc)
|
|
846
|
-
@color_buffer[vmli] = vic_bank.peek_color(vc)
|
|
847
|
-
else
|
|
848
|
-
@character_buffer[vmli] = 0xff
|
|
849
|
-
@color_buffer[vmli] = @open_bus ? @open_bus.call & 0x0f : vic_bank.peek_color(vc)
|
|
850
|
-
end
|
|
851
|
-
end
|
|
852
|
-
end
|
|
853
|
-
end
|