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,119 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class TED
|
|
6
|
+
# The raster and the clock the TED gives the CPU, a single clock
|
|
7
|
+
# cycle at a time.
|
|
8
|
+
#
|
|
9
|
+
# A line is 456 dots, horizontal counts 0-455, and a single clock
|
|
10
|
+
# cycle 8 of them, so a line is 57 cycles; #column counts them, the
|
|
11
|
+
# cycle at count 8 * column. The line count steps at count 376, in
|
|
12
|
+
# column 47, and runs 0-311 on PAL and 0-261 with $FF07 bit 6 set
|
|
13
|
+
# (NTSC). The datasheet's horizontal and vertical decode tables give
|
|
14
|
+
# those counts.
|
|
15
|
+
#
|
|
16
|
+
# The CPU runs once in a single clock cycle and twice in a double
|
|
17
|
+
# clock one. The datasheet's "System Clock Doubling": in the display
|
|
18
|
+
# window's lines the clock is single from count 400 round to 344,
|
|
19
|
+
# columns 50-56 and 0-42, and double in columns 43-49. The window is
|
|
20
|
+
# lines 0-203: the datasheet says 0-204, but xplus4 runs line 204 at
|
|
21
|
+
# double clock, as the lines below it. In the other lines it is double
|
|
22
|
+
# but for the five refresh cycles at counts 304-344, columns 38-42,
|
|
23
|
+
# which are single everywhere. With $FF06 bit 4 clear (blank) every
|
|
24
|
+
# line is double but for refresh, and $FF13 bit 1 or $FF07 bit 5
|
|
25
|
+
# (freeze) makes every cycle single.
|
|
26
|
+
#
|
|
27
|
+
# So a display line gives the CPU 64 cycles and a border line 109,
|
|
28
|
+
# the counts measured on real machines.
|
|
29
|
+
#
|
|
30
|
+
# DMA: each character row takes the bus for 40 cycles on two lines,
|
|
31
|
+
# the line before the row for the attributes and the row's first
|
|
32
|
+
# line for the character pointers (the datasheet's register 20). A
|
|
33
|
+
# row starts on the line after one whose low three bits match $FF06
|
|
34
|
+
# bits 0-2, as the KERNAL's scroll of 3 puts the first row on line 4,
|
|
35
|
+
# where the datasheet's 25-row window starts, and a row starts only
|
|
36
|
+
# in lines 0-203. xplus4 takes the bus on the same lines. The fetches run in columns 54-56 and 0-36, and BA
|
|
37
|
+
# goes low 3 cycles before the first, in column 51, so the CPU stops
|
|
38
|
+
# at its next read. A DMA line leaves the CPU 24 cycles.
|
|
39
|
+
module Beam
|
|
40
|
+
CYCLES_PER_LINE = 57
|
|
41
|
+
LINE_STEP_COLUMN = 47
|
|
42
|
+
BA_COLUMN = 51
|
|
43
|
+
DMA_COLUMN = 54
|
|
44
|
+
DMA_END_COLUMN = 36
|
|
45
|
+
REFRESH_COLUMNS = (38..42)
|
|
46
|
+
DOUBLE_COLUMNS = (43..49)
|
|
47
|
+
LAST_DISPLAY_LINE = 203
|
|
48
|
+
|
|
49
|
+
# The single clock cycle in the line, 0-56.
|
|
50
|
+
attr_reader :column
|
|
51
|
+
|
|
52
|
+
# The raster line.
|
|
53
|
+
attr_reader :line
|
|
54
|
+
|
|
55
|
+
# How many cycles the CPU runs in this cycle: 0 while the TED holds
|
|
56
|
+
# the bus for DMA, 1 at single clock and 2 at double clock.
|
|
57
|
+
attr_reader :cpu_slots
|
|
58
|
+
|
|
59
|
+
# Whether BA is low, from 3 cycles before DMA to its end.
|
|
60
|
+
def ba_low? = @ba_low
|
|
61
|
+
|
|
62
|
+
# Lines a frame, by $FF07 bit 6.
|
|
63
|
+
def lines_per_frame = @registers[0x07].anybits?(0x40) ? 262 : 312
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
def reset_beam
|
|
68
|
+
@column = 0
|
|
69
|
+
@line = 0
|
|
70
|
+
@dma_line = false
|
|
71
|
+
@ba_low = false
|
|
72
|
+
@cpu_slots = 1
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def move_beam
|
|
76
|
+
column = @column + 1
|
|
77
|
+
column = 0 if column == CYCLES_PER_LINE
|
|
78
|
+
@column = column
|
|
79
|
+
return unless column == LINE_STEP_COLUMN
|
|
80
|
+
|
|
81
|
+
line = @line + 1
|
|
82
|
+
line = 0 if line >= lines_per_frame
|
|
83
|
+
self.line = line
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def decide_clock
|
|
87
|
+
column = @column
|
|
88
|
+
@dma_line = dma_line? if column == BA_COLUMN
|
|
89
|
+
if @dma_line && (column >= BA_COLUMN || column <= DMA_END_COLUMN)
|
|
90
|
+
@ba_low = true
|
|
91
|
+
@cpu_slots = column >= DMA_COLUMN || column <= DMA_END_COLUMN ? 0 : 1
|
|
92
|
+
return
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
@ba_low = false
|
|
96
|
+
@cpu_slots = single_clock?(column) ? 1 : 2
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def single_clock?(column)
|
|
100
|
+
return true if REFRESH_COLUMNS.include?(column) || @registers[0x13].anybits?(0x02) || frozen?
|
|
101
|
+
|
|
102
|
+
display_window? && !DOUBLE_COLUMNS.include?(column)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def display_window? = @registers[0x06].anybits?(0x10) && @line <= LAST_DISPLAY_LINE
|
|
106
|
+
|
|
107
|
+
def dma_line?
|
|
108
|
+
return false unless @registers[0x06].anybits?(0x10)
|
|
109
|
+
|
|
110
|
+
phase = (@line - (@registers[0x06] & 0x07)) & 0x07
|
|
111
|
+
return false if phase > 1
|
|
112
|
+
|
|
113
|
+
row = phase.zero? ? @line + 1 : @line
|
|
114
|
+
row <= LAST_DISPLAY_LINE
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class TED
|
|
6
|
+
# The three 16-bit timers at $FF00-$FF05, which count down once a
|
|
7
|
+
# single clock cycle whatever clock the CPU runs at. Each raises its
|
|
8
|
+
# interrupt flag as it counts down to zero. Timer 1's next count then
|
|
9
|
+
# loads the value last written to it, and timers 2 and 3 roll over to
|
|
10
|
+
# $FFFF.
|
|
11
|
+
#
|
|
12
|
+
# A write to a timer's low byte stops it until its high byte is
|
|
13
|
+
# written. Timer 1's writes set its reload value and its count
|
|
14
|
+
# together, and timers 2 and 3's set the count.
|
|
15
|
+
module Timers
|
|
16
|
+
# The interrupt flag each timer raises in $FF09.
|
|
17
|
+
TIMER_FLAGS = [0x08, 0x10, 0x40].freeze
|
|
18
|
+
|
|
19
|
+
# The counts, the reload value of timer 1, and which timers run.
|
|
20
|
+
attr_reader :timer_counts, :timer_running
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def reset_timers
|
|
25
|
+
@timer_counts = [0, 0, 0]
|
|
26
|
+
@timer_running = [false, false, false]
|
|
27
|
+
@timer1_reload = 0
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def count_timers
|
|
31
|
+
i = 0
|
|
32
|
+
while i < 3
|
|
33
|
+
count_timer(i) if @timer_running[i]
|
|
34
|
+
i += 1
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def count_timer(index)
|
|
39
|
+
count = @timer_counts[index]
|
|
40
|
+
if count.zero? && index.zero?
|
|
41
|
+
@timer_counts[0] = @timer1_reload
|
|
42
|
+
return
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
count = (count - 1) & 0xffff
|
|
46
|
+
@timer_counts[index] = count
|
|
47
|
+
@interrupt_flags |= TIMER_FLAGS[index] if count.zero?
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def read_timer(register)
|
|
51
|
+
count = @timer_counts[register >> 1]
|
|
52
|
+
register.even? ? count & 0xff : count >> 8
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def write_timer(register, value)
|
|
56
|
+
index = register >> 1
|
|
57
|
+
count = @timer_counts[index]
|
|
58
|
+
count = register.even? ? (count & 0xff00) | value : (count & 0x00ff) | (value << 8)
|
|
59
|
+
@timer_counts[index] = count
|
|
60
|
+
@timer1_reload = count if index.zero?
|
|
61
|
+
@timer_running[index] = register.odd?
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "badline/chips/ted/timers"
|
|
4
|
+
require "badline/chips/ted/beam"
|
|
5
|
+
|
|
6
|
+
module Badline
|
|
7
|
+
module Chips
|
|
8
|
+
# The TED of the Commodore 264 series, the 7360 and 8360: its registers
|
|
9
|
+
# at $FF00-$FF1F, the raster, the three timers, the interrupt, the
|
|
10
|
+
# keyboard latch and the clock it gives the CPU (Beam). It paints no
|
|
11
|
+
# picture and plays no sound yet: those registers keep what is written
|
|
12
|
+
# to them.
|
|
13
|
+
#
|
|
14
|
+
# The machine clocks it once a single clock cycle, 57 to a line, and
|
|
15
|
+
# asks it then how many cycles the CPU runs in that one (#cpu_slots)
|
|
16
|
+
# and whether BA is low (#ba_low?).
|
|
17
|
+
#
|
|
18
|
+
# $FF08 is the keyboard latch: a write latches the K0-K7 inputs, which
|
|
19
|
+
# the keyboard port answers for the byte written (KeyboardPort#latch),
|
|
20
|
+
# and a read returns them. $FF09 holds the interrupt flags, each
|
|
21
|
+
# cleared by writing a 1 to it, with bit 7 set while the interrupt
|
|
22
|
+
# line is pulled. $FF0A holds the mask and bit 8 of the raster compare,
|
|
23
|
+
# and $FF0B the compare's low byte. $FF13 bit 0 reads whether the CPU
|
|
24
|
+
# sees ROM at $8000-$FFFF (#rom_selected=). $FF1C and $FF1D read and
|
|
25
|
+
# set the raster line, and $FF1E reads the horizontal position's top 8
|
|
26
|
+
# bits.
|
|
27
|
+
class TED
|
|
28
|
+
include Timers
|
|
29
|
+
include Beam
|
|
30
|
+
|
|
31
|
+
# The clock a TED is fed, its single clock: the crystal divided by 20
|
|
32
|
+
# on PAL machines and by 16 on NTSC ones (the Plus/4 hardware manual's
|
|
33
|
+
# TED datasheet).
|
|
34
|
+
Profile = Data.define(:name, :clock_hz)
|
|
35
|
+
|
|
36
|
+
PAL = Profile.new(name: :pal, clock_hz: 886_724)
|
|
37
|
+
NTSC = Profile.new(name: :ntsc, clock_hz: 894_886)
|
|
38
|
+
|
|
39
|
+
RASTER_FLAG = 0x02
|
|
40
|
+
|
|
41
|
+
# The interrupt sources a mask bit can enable: the raster, the light
|
|
42
|
+
# pen and the three timers.
|
|
43
|
+
SOURCES = 0x5e
|
|
44
|
+
|
|
45
|
+
attr_reader :profile, :interrupt_flags, :interrupt_mask
|
|
46
|
+
|
|
47
|
+
# What answers the keyboard latch: an object with #latch(value).
|
|
48
|
+
attr_writer :keyboard_port
|
|
49
|
+
|
|
50
|
+
# Whether the CPU sees ROM at $8000-$FFFF, which $FF13 bit 0 reads.
|
|
51
|
+
attr_writer :rom_selected
|
|
52
|
+
|
|
53
|
+
def initialize(profile = PAL)
|
|
54
|
+
@profile = profile
|
|
55
|
+
@keyboard_port = nil
|
|
56
|
+
@rom_selected = true
|
|
57
|
+
power_on!
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def power_on!
|
|
61
|
+
@registers = Array.new(0x20, 0)
|
|
62
|
+
@interrupt_flags = 0
|
|
63
|
+
@interrupt_mask = 0
|
|
64
|
+
@raster_compare = 0
|
|
65
|
+
@key_latch = 0xff
|
|
66
|
+
reset_timers
|
|
67
|
+
reset_beam
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Counts the timers and moves the beam on a cycle, unless $FF07's
|
|
71
|
+
# freeze bit holds them, then decides the CPU's clock for the cycle.
|
|
72
|
+
def cycle!
|
|
73
|
+
unless frozen?
|
|
74
|
+
count_timers
|
|
75
|
+
move_beam
|
|
76
|
+
end
|
|
77
|
+
decide_clock
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Whether the interrupt line is pulled: a flag raised whose mask bit
|
|
81
|
+
# is set.
|
|
82
|
+
def irq? = @interrupt_flags.anybits?(@interrupt_mask & SOURCES)
|
|
83
|
+
|
|
84
|
+
def peek(addr)
|
|
85
|
+
register = addr & 0x3f
|
|
86
|
+
return 0xff if register >= 0x20
|
|
87
|
+
|
|
88
|
+
case register
|
|
89
|
+
when 0x00..0x05 then read_timer(register)
|
|
90
|
+
when 0x08 then @key_latch
|
|
91
|
+
when 0x09 then read_interrupt_flags
|
|
92
|
+
when 0x0a then @interrupt_mask | 0xa0
|
|
93
|
+
when 0x0b then @raster_compare & 0xff
|
|
94
|
+
when 0x13 then (@registers[0x13] & 0xfe) | (@rom_selected ? 1 : 0)
|
|
95
|
+
when 0x1c then 0xfe | (@line >> 8)
|
|
96
|
+
when 0x1d then @line & 0xff
|
|
97
|
+
when 0x1e then @column << 2
|
|
98
|
+
else @registers[register]
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def poke(addr, value)
|
|
103
|
+
register = addr & 0x3f
|
|
104
|
+
return if register >= 0x20
|
|
105
|
+
|
|
106
|
+
@registers[register] = value
|
|
107
|
+
case register
|
|
108
|
+
when 0x00..0x05 then write_timer(register, value)
|
|
109
|
+
when 0x08 then @key_latch = @keyboard_port ? @keyboard_port.latch(value) : 0xff
|
|
110
|
+
when 0x09 then @interrupt_flags &= ~value
|
|
111
|
+
when 0x0a then write_interrupt_mask(value)
|
|
112
|
+
when 0x0b then @raster_compare = (@raster_compare & 0x100) | value
|
|
113
|
+
when 0x1c then self.line = (@line & 0xff) | ((value & 0x01) << 8)
|
|
114
|
+
when 0x1d then self.line = (@line & 0x100) | value
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
private
|
|
119
|
+
|
|
120
|
+
# $FF07 bit 5 stops the beam and the timers.
|
|
121
|
+
def frozen? = @registers[0x07].anybits?(0x20)
|
|
122
|
+
|
|
123
|
+
def read_interrupt_flags
|
|
124
|
+
value = @interrupt_flags | 0x21
|
|
125
|
+
irq? ? value | 0x80 : value
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def write_interrupt_mask(value)
|
|
129
|
+
@interrupt_mask = value & 0x5f
|
|
130
|
+
@raster_compare = (@raster_compare & 0xff) | ((value & 0x01) << 8)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def line=(value)
|
|
134
|
+
@line = value
|
|
135
|
+
raster_reached
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def raster_reached
|
|
139
|
+
@interrupt_flags |= RASTER_FLAG if @line == @raster_compare
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
# The 6523 TIA, a tri-port interface adapter: three 8-bit ports, A, B
|
|
6
|
+
# and C at registers 0-2, each with its direction register at 3-5, a 1
|
|
7
|
+
# making the pin an output. Its three address lines repeat the
|
|
8
|
+
# registers every 8 bytes, and registers 6 and 7 read $FF.
|
|
9
|
+
#
|
|
10
|
+
# A pin read as an output returns what the port drives, and one read as
|
|
11
|
+
# an input returns what the other side drives, #inputs, per port.
|
|
12
|
+
class TIA
|
|
13
|
+
attr_reader :ports, :directions
|
|
14
|
+
|
|
15
|
+
# What the other side drives onto each port's pins.
|
|
16
|
+
attr_reader :inputs
|
|
17
|
+
|
|
18
|
+
def initialize
|
|
19
|
+
@inputs = [0, 0, 0]
|
|
20
|
+
reset!
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def reset!
|
|
24
|
+
@ports = [0, 0, 0]
|
|
25
|
+
@directions = [0, 0, 0]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def peek(addr)
|
|
29
|
+
register = addr & 0x07
|
|
30
|
+
return 0xff if register > 5
|
|
31
|
+
return @directions[register - 3] if register >= 3
|
|
32
|
+
|
|
33
|
+
direction = @directions[register]
|
|
34
|
+
(@ports[register] & direction) | (@inputs[register] & ~direction & 0xff)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def poke(addr, value)
|
|
38
|
+
register = addr & 0x07
|
|
39
|
+
return if register > 5
|
|
40
|
+
|
|
41
|
+
if register >= 3
|
|
42
|
+
@directions[register - 3] = value
|
|
43
|
+
else
|
|
44
|
+
@ports[register] = value
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class VDC
|
|
6
|
+
class Raster
|
|
7
|
+
# The raster's fields in a keyed snapshot module, under `prefix`:
|
|
8
|
+
# the frame count, where the beam is in the character rows and the
|
|
9
|
+
# frame, and the frame's size and sync as it latched them.
|
|
10
|
+
module KeyedState
|
|
11
|
+
def save_fields(out, prefix)
|
|
12
|
+
out.int("#{prefix}frame", @frame).int("#{prefix}row", @row).int("#{prefix}row_line", @row_line)
|
|
13
|
+
out.bool("#{prefix}adjusting", @adjusting).int("#{prefix}frame_line", @frame_line)
|
|
14
|
+
out.int("#{prefix}frame_lines", @frame_lines).int("#{prefix}sync_start", @sync_start)
|
|
15
|
+
out.int("#{prefix}sync_lines", @sync_lines)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def load_fields(input, prefix)
|
|
19
|
+
@frame = input.int("#{prefix}frame", @frame)
|
|
20
|
+
@row = input.int("#{prefix}row", @row)
|
|
21
|
+
@row_line = input.int("#{prefix}row_line", @row_line)
|
|
22
|
+
@adjusting = input.bool("#{prefix}adjusting", @adjusting)
|
|
23
|
+
@frame_line = input.int("#{prefix}frame_line", @frame_line)
|
|
24
|
+
@frame_lines = input.int("#{prefix}frame_lines", @frame_lines)
|
|
25
|
+
@sync_start = input.int("#{prefix}sync_start", @sync_start)
|
|
26
|
+
@sync_lines = input.int("#{prefix}sync_lines", @sync_lines)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
include KeyedState
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class Window
|
|
34
|
+
# The start addresses the frame latched, under `prefix`.
|
|
35
|
+
module KeyedState
|
|
36
|
+
def save_fields(out, prefix)
|
|
37
|
+
out.int("#{prefix}display_start", @display_start).int("#{prefix}attribute_start", @attribute_start)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def load_fields(input, prefix)
|
|
41
|
+
@display_start = input.word("#{prefix}display_start", @display_start)
|
|
42
|
+
@attribute_start = input.word("#{prefix}attribute_start", @attribute_start)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
include KeyedState
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
class Painter
|
|
50
|
+
# The display's size, as the frame latched it, and the window's
|
|
51
|
+
# start addresses. The picture is painted again.
|
|
52
|
+
module KeyedState
|
|
53
|
+
def save_fields(out)
|
|
54
|
+
out.int("display.width", @width).int("display.height", @height)
|
|
55
|
+
@window.save_fields(out, "window.")
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def load_fields(input)
|
|
59
|
+
resize(input.int("display.width", @width), input.int("display.height", @height))
|
|
60
|
+
@window.load_fields(input, "window.")
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
include KeyedState
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# The VDC's fields in a keyed snapshot module (Snapshot::Keyed): the
|
|
68
|
+
# registers, the RAM, the register selected, the data latches, the
|
|
69
|
+
# dot clock's phase and the line's length in the same units
|
|
70
|
+
# (dots·Hz, the line latched at its start), how long an access or
|
|
71
|
+
# block operation stays busy from now, the raster under raster.* and
|
|
72
|
+
# the display's size and window under display.* and window.*. The
|
|
73
|
+
# RAM's layout comes from R28 on load.
|
|
74
|
+
module KeyedState
|
|
75
|
+
def save_fields(out)
|
|
76
|
+
out.bytes("registers", @registers).bytes("ram", @memory.ram).int("selected", @selected)
|
|
77
|
+
out.int("read_latch", @read_latch).int("write_data", @write_data).int("phase", @phase)
|
|
78
|
+
out.int("line_units", @line_units).int("busy_for", @busy_until - @phase)
|
|
79
|
+
@raster.save_fields(out, "raster.")
|
|
80
|
+
@painter.save_fields(out)
|
|
81
|
+
out
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def load_fields(input)
|
|
85
|
+
input.bytes_into("registers", @registers)
|
|
86
|
+
input.bytes_into("ram", @memory.ram)
|
|
87
|
+
@selected = input.masked("selected", @selected, 0x3f)
|
|
88
|
+
@read_latch = input.byte("read_latch", @read_latch)
|
|
89
|
+
@write_data = input.byte("write_data", @write_data)
|
|
90
|
+
@phase = input.int("phase", @phase)
|
|
91
|
+
@line_units = input.int("line_units", @line_units)
|
|
92
|
+
@busy_until = @phase + input.int("busy_for", @busy_until - @phase)
|
|
93
|
+
@raster.load_fields(input, "raster.")
|
|
94
|
+
@painter.load_fields(input)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def restored!
|
|
98
|
+
@memory.mode64 = @registers[28].anybits?(0x10)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
include KeyedState
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Badline
|
|
4
|
-
|
|
4
|
+
module Chips
|
|
5
5
|
class VDC
|
|
6
6
|
# Paints the VDC's scan lines into its display, one line at a time,
|
|
7
7
|
# from the registers as they stand when the line ends. Each pixel of
|
|
@@ -56,18 +56,6 @@ module Badline
|
|
|
56
56
|
[0, 0, shown.clamp(1, @width), (frame_lines - sync_lines).clamp(1, @height)]
|
|
57
57
|
end
|
|
58
58
|
|
|
59
|
-
# The display's size and the window's start addresses. The display
|
|
60
|
-
# starts again cleared, to be painted while the VDC renders.
|
|
61
|
-
def save_state(out)
|
|
62
|
-
out.int(@width).int(@height)
|
|
63
|
-
@window.save_state(out)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def load_state(input)
|
|
67
|
-
resize(input.int, input.int)
|
|
68
|
-
@window.load_state(input)
|
|
69
|
-
end
|
|
70
|
-
|
|
71
59
|
def clear_dirty_lines!
|
|
72
60
|
@dirty_lines.fill(false)
|
|
73
61
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Badline
|
|
4
|
-
|
|
4
|
+
module Chips
|
|
5
5
|
class VDC
|
|
6
6
|
# The VDC's raster: R0 + 1 characters a line, R9 + 1 lines a row,
|
|
7
7
|
# R4 + 1 rows a frame and then R5 more lines, with the frame's size
|
|
@@ -30,22 +30,6 @@ module Badline
|
|
|
30
30
|
# Outside the displayed rows, as status bit 5 reads.
|
|
31
31
|
def vertical_blank? = @adjusting || @row >= @registers[6]
|
|
32
32
|
|
|
33
|
-
def save_state(out)
|
|
34
|
-
out.int(@frame).int(@row).int(@row_line).boolean(@adjusting).int(@frame_line).int(@frame_lines)
|
|
35
|
-
out.int(@sync_start).int(@sync_lines)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def load_state(input)
|
|
39
|
-
@frame = input.int
|
|
40
|
-
@row = input.int
|
|
41
|
-
@row_line = input.int
|
|
42
|
-
@adjusting = input.boolean?
|
|
43
|
-
@frame_line = input.int
|
|
44
|
-
@frame_lines = input.int
|
|
45
|
-
@sync_start = input.int
|
|
46
|
-
@sync_lines = input.int
|
|
47
|
-
end
|
|
48
|
-
|
|
49
33
|
def end_line(render)
|
|
50
34
|
paint_line if render
|
|
51
35
|
@frame_line += 1
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Badline
|
|
4
|
-
|
|
4
|
+
module Chips
|
|
5
5
|
class VDC
|
|
6
6
|
# Paints the characters of a displayed line, R1 of them from the
|
|
7
7
|
# line's first dot, in text mode or, with R25 bit 7, bitmap mode.
|
|
@@ -57,15 +57,6 @@ module Badline
|
|
|
57
57
|
@attribute_start = (regs[20] << 8) | regs[21]
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
-
def save_state(out)
|
|
61
|
-
out.int(@display_start).int(@attribute_start)
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def load_state(input)
|
|
65
|
-
@display_start = input.int
|
|
66
|
-
@attribute_start = input.int
|
|
67
|
-
end
|
|
68
|
-
|
|
69
60
|
def paint(line, row, row_line, frame)
|
|
70
61
|
regs = @registers
|
|
71
62
|
lay_out_cell
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "badline/
|
|
4
|
-
require "badline/
|
|
5
|
-
require "badline/
|
|
6
|
-
require "badline/
|
|
3
|
+
require "badline/chips/vdc/memory"
|
|
4
|
+
require "badline/chips/vdc/window"
|
|
5
|
+
require "badline/chips/vdc/painter"
|
|
6
|
+
require "badline/chips/vdc/raster"
|
|
7
|
+
require "badline/chips/vdc/keyed_parts"
|
|
7
8
|
|
|
8
9
|
module Badline
|
|
9
|
-
|
|
10
|
+
module Chips
|
|
10
11
|
# The 8563 or 8568 VDC: the address register at $D600 and the data
|
|
11
12
|
# register at $D601, mirrored through $D6FF, in front of 37 internal
|
|
12
13
|
# registers (38 on the 8568), the VDC's own RAM (Memory) and its 80
|
|
@@ -112,32 +113,6 @@ module Badline
|
|
|
112
113
|
@painter.clear!
|
|
113
114
|
end
|
|
114
115
|
|
|
115
|
-
# Everything the VDC holds but its display, which it paints again
|
|
116
|
-
# while it renders: the registers, the RAM, the data port and the
|
|
117
|
-
# raster. Whether it renders is the host's.
|
|
118
|
-
def save_state(out)
|
|
119
|
-
out.marker("VDC")
|
|
120
|
-
out.ints(@registers).blob(@memory.ram)
|
|
121
|
-
out.int(@selected).int(@read_latch).int(@write_data).int(@busy_until).int(@phase).int(@line_units)
|
|
122
|
-
@raster.save_state(out)
|
|
123
|
-
@painter.save_state(out)
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def load_state(input)
|
|
127
|
-
input.marker("VDC")
|
|
128
|
-
input.ints_into(@registers)
|
|
129
|
-
input.blob_into(@memory.ram)
|
|
130
|
-
@memory.mode64 = @registers[28].anybits?(0x10)
|
|
131
|
-
@selected = input.int
|
|
132
|
-
@read_latch = input.int
|
|
133
|
-
@write_data = input.int
|
|
134
|
-
@busy_until = input.int
|
|
135
|
-
@phase = input.int
|
|
136
|
-
@line_units = input.int
|
|
137
|
-
@raster.load_state(input)
|
|
138
|
-
@painter.load_state(input)
|
|
139
|
-
end
|
|
140
|
-
|
|
141
116
|
# The frames the raster has finished, which the blinking counts.
|
|
142
117
|
def frame = @raster.frame
|
|
143
118
|
|