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
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class CPU
|
|
5
|
-
# The CPU's state for a snapshot: the registers, the interrupt lines and
|
|
6
|
-
# their pipeline, and the step of the instruction in flight, named by
|
|
7
|
-
# where its plan comes from.
|
|
8
|
-
module SavedState
|
|
9
|
-
# Writes everything the CPU holds, down to the step of the instruction
|
|
10
|
-
# it is in, for load_state to put back. The interrupt lines, BA stalls
|
|
11
|
-
# and SO are state too; the traps and the debug flag belong to the host.
|
|
12
|
-
def save_state(out)
|
|
13
|
-
out.marker("CPU")
|
|
14
|
-
out.int(@program_counter).int(@stack_pointer).int(@a).int(@x).int(@y).int(@status.value)
|
|
15
|
-
[@irq, @nmi, @irq_sample, @irq_pending, @nmi_sample, @nmi_pending, @skip_poll, @boundary_irq,
|
|
16
|
-
@boundary_nmi, @boundary_crossed, @brk, @pending_write, @so_high, @optional_dummy,
|
|
17
|
-
@branch_taken].each { |flag| out.boolean(flag) }
|
|
18
|
-
out.optional_int(@interrupt).optional_int(@stalled_at).int(@cycles).int(@instructions)
|
|
19
|
-
out.int(plan_source).int(@index).int(OPERATIONS.index(@operation) || -1)
|
|
20
|
-
[@address, @dummy_address, @value, @rmw_result, @pointer].each { |register| out.optional_int(register) }
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def load_state(input)
|
|
24
|
-
input.marker("CPU")
|
|
25
|
-
@program_counter = input.int
|
|
26
|
-
@stack_pointer = input.int
|
|
27
|
-
@a = input.int
|
|
28
|
-
@x = input.int
|
|
29
|
-
@y = input.int
|
|
30
|
-
@status.value = input.int
|
|
31
|
-
load_flags(input)
|
|
32
|
-
@interrupt = input.optional_int
|
|
33
|
-
@stalled_at = input.optional_int
|
|
34
|
-
@cycles = input.int
|
|
35
|
-
@instructions = input.int
|
|
36
|
-
load_plan(input.int)
|
|
37
|
-
@index = input.int
|
|
38
|
-
operation = input.int
|
|
39
|
-
@operation = operation.negative? ? nil : OPERATIONS.fetch(operation)
|
|
40
|
-
load_working_registers(input)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# Drops the instruction or interrupt sequence in flight and the
|
|
44
|
-
# interrupt lines' pipeline, so the next cycle fetches an opcode at the
|
|
45
|
-
# program counter, and sets the cycle count. A snapshot taken between
|
|
46
|
-
# instructions, as VICE's are, restores through here.
|
|
47
|
-
def resume(cycles)
|
|
48
|
-
@irq_sample = @irq_pending = false
|
|
49
|
-
@nmi_sample = @nmi_pending = false
|
|
50
|
-
@skip_poll = false
|
|
51
|
-
@interrupt = nil
|
|
52
|
-
@brk = false
|
|
53
|
-
@stalled_at = nil
|
|
54
|
-
@cycles = cycles
|
|
55
|
-
end_sequence
|
|
56
|
-
@pending_write = false
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
private
|
|
60
|
-
|
|
61
|
-
# Where the plan running comes from: an opcode's microcode, or FETCH,
|
|
62
|
-
# INTERRUPT or JAMMED below it.
|
|
63
|
-
def plan_source
|
|
64
|
-
return FETCH if @plan.equal?(FETCH_PLAN)
|
|
65
|
-
return INTERRUPT if @plan.equal?(INTERRUPT_PLAN)
|
|
66
|
-
return JAMMED if @plan.equal?(JAMMED_PLAN)
|
|
67
|
-
|
|
68
|
-
MICROCODE.index { |micro| micro.plan.equal?(@plan) && micro.operation == @operation } ||
|
|
69
|
-
MICROCODE.index { |micro| micro.plan.equal?(@plan) }
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def load_plan(source)
|
|
73
|
-
case source
|
|
74
|
-
when FETCH then use_plan(FETCH_PLAN, FETCH_WRITES)
|
|
75
|
-
when INTERRUPT then use_plan(INTERRUPT_PLAN, INTERRUPT_WRITES)
|
|
76
|
-
when JAMMED then use_plan(JAMMED_PLAN, JAMMED_WRITES)
|
|
77
|
-
else
|
|
78
|
-
micro = MICROCODE.fetch(source)
|
|
79
|
-
use_plan(micro.plan, micro.writes)
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def use_plan(plan, writes)
|
|
84
|
-
@plan = plan
|
|
85
|
-
@writes = writes
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def load_flags(input)
|
|
89
|
-
@irq = input.boolean?
|
|
90
|
-
@nmi = input.boolean?
|
|
91
|
-
@irq_sample = input.boolean?
|
|
92
|
-
@irq_pending = input.boolean?
|
|
93
|
-
@nmi_sample = input.boolean?
|
|
94
|
-
@nmi_pending = input.boolean?
|
|
95
|
-
@skip_poll = input.boolean?
|
|
96
|
-
@boundary_irq = input.boolean?
|
|
97
|
-
@boundary_nmi = input.boolean?
|
|
98
|
-
@boundary_crossed = input.boolean?
|
|
99
|
-
@brk = input.boolean?
|
|
100
|
-
@pending_write = input.boolean?
|
|
101
|
-
@so_high = input.boolean?
|
|
102
|
-
@optional_dummy = input.boolean?
|
|
103
|
-
@branch_taken = input.boolean?
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def load_working_registers(input)
|
|
107
|
-
@address = input.optional_int
|
|
108
|
-
@dummy_address = input.optional_int
|
|
109
|
-
@value = input.optional_int
|
|
110
|
-
@rmw_result = input.optional_int
|
|
111
|
-
@pointer = input.optional_int
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
end
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class CPU
|
|
5
|
-
# Steps that use the stack: PHA, PHP, PLA, PLP, JSR, RTS and RTI.
|
|
6
|
-
module StackOperations
|
|
7
|
-
private
|
|
8
|
-
|
|
9
|
-
def op_push_exec
|
|
10
|
-
send(@operation, nil, nil)
|
|
11
|
-
end_instruction
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def op_pull_dummy
|
|
15
|
-
@memory.peek(stack_address)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def op_pull_exec
|
|
19
|
-
send(@operation, nil, nil)
|
|
20
|
-
end_instruction
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def op_pull_low
|
|
24
|
-
@stack_pointer = (@stack_pointer + 1) & 0xff
|
|
25
|
-
@address = @memory.peek(stack_address)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def op_pull_high
|
|
29
|
-
@stack_pointer = (@stack_pointer + 1) & 0xff
|
|
30
|
-
@address |= @memory.peek(stack_address) << 8
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def op_rts_fixup
|
|
34
|
-
@memory.peek(@address)
|
|
35
|
-
@program_counter = (@address + 1) & 0xffff
|
|
36
|
-
end_instruction
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def op_rti_pull_status
|
|
40
|
-
@stack_pointer = (@stack_pointer + 1) & 0xff
|
|
41
|
-
@status.value = @memory.peek(stack_address)
|
|
42
|
-
@status.break = false
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def op_rti_pull_high
|
|
46
|
-
@stack_pointer = (@stack_pointer + 1) & 0xff
|
|
47
|
-
@program_counter = @address | (@memory.peek(stack_address) << 8)
|
|
48
|
-
end_instruction
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def op_jsr_low
|
|
52
|
-
@address = @memory.peek(@program_counter)
|
|
53
|
-
@program_counter = (@program_counter + 2) & 0xffff
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def op_jsr_dummy
|
|
57
|
-
@memory.peek(stack_address)
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def op_jsr_push_high
|
|
61
|
-
@memory.poke(stack_address, high_byte(return_address))
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def op_jsr_push_low
|
|
65
|
-
@memory.poke(stack_address(-1), low_byte(return_address))
|
|
66
|
-
@stack_pointer = (@stack_pointer - 2) & 0xff
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
# JSR reads its target's high byte after pushing the return address.
|
|
70
|
-
# A JSR running from the stack page can overwrite its own operand
|
|
71
|
-
# with that push, and then jumps to the overwritten address.
|
|
72
|
-
def op_jsr_high
|
|
73
|
-
@program_counter = @address | (@memory.peek(return_address) << 8)
|
|
74
|
-
end_instruction
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def return_address
|
|
78
|
-
(@program_counter - 1) & 0xffff
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|
data/lib/badline/cpu.rb
DELETED
data/lib/badline/cpu_port.rb
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
# The I/O port of the 6510 and the 8502 at $00 (direction) and $01
|
|
5
|
-
# (data). An input pin reads its pull-up, P4 reads the datasette's sense
|
|
6
|
-
# line, and a pin without a pull-up holds the charge last driven onto
|
|
7
|
-
# it. P5 drives the datasette motor through an inverter: low runs it.
|
|
8
|
-
#
|
|
9
|
-
# The 6510 has pull-ups on P0-P2 and P4 and leaves P3, P6 and P7
|
|
10
|
-
# floating. The 8502 adds a CAPS LOCK pin on P6, high while the key is
|
|
11
|
-
# up.
|
|
12
|
-
class CPUPort
|
|
13
|
-
TAPE_SENSE = 0b0001_0000
|
|
14
|
-
|
|
15
|
-
# The direction and output registers, and the charge on the floating
|
|
16
|
-
# pins.
|
|
17
|
-
attr_reader :ddr, :data, :floating
|
|
18
|
-
|
|
19
|
-
# The port as the banking logic reads it (PortStatus).
|
|
20
|
-
attr_reader :status
|
|
21
|
-
|
|
22
|
-
# Whether CAPS LOCK is down, holding its pin low.
|
|
23
|
-
attr_reader :caps_lock
|
|
24
|
-
|
|
25
|
-
# +pullups+ and +floating+ are the masks of the pins with a pull-up and
|
|
26
|
-
# of the floating ones, and +caps_lock+ the CAPS LOCK pin's, 0 where
|
|
27
|
-
# there is none.
|
|
28
|
-
def initialize(datasette, pullups:, floating:, caps_lock: 0)
|
|
29
|
-
@datasette = datasette
|
|
30
|
-
@pullups = pullups
|
|
31
|
-
@floating_mask = floating
|
|
32
|
-
@caps_lock_pin = caps_lock
|
|
33
|
-
@caps_lock = false
|
|
34
|
-
@ddr = 0x00
|
|
35
|
-
@data = 0x00
|
|
36
|
-
@floating = 0x00
|
|
37
|
-
@change_handler = nil
|
|
38
|
-
@status = PortStatus.new(%i[basic kernal io tape_out tape_switch tape_motor], value: input_value)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
# Calls the block after every write to the port, for the bus to remap
|
|
42
|
-
# its banks.
|
|
43
|
-
def on_change(&handler)
|
|
44
|
-
@change_handler = handler
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
# What a read of $01 sees.
|
|
48
|
-
def value = @status.value
|
|
49
|
-
|
|
50
|
-
def write_ddr(value)
|
|
51
|
-
@ddr = value
|
|
52
|
-
update
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def write_data(value)
|
|
56
|
-
@data = value
|
|
57
|
-
update
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
# The RES line clears the direction and output registers. The floating
|
|
61
|
-
# pins keep their charge.
|
|
62
|
-
def reset!
|
|
63
|
-
@ddr = 0x00
|
|
64
|
-
@data = 0x00
|
|
65
|
-
update
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
# Sets the registers and the charge, as a snapshot restores them, and
|
|
69
|
-
# drives the motor and calls the change handler as a write does.
|
|
70
|
-
def restore(ddr, data, floating)
|
|
71
|
-
load(ddr, data, floating)
|
|
72
|
-
update
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
# Sets the registers and the charge, as a snapshot loads them, without
|
|
76
|
-
# driving the motor or calling the change handler.
|
|
77
|
-
def load(ddr, data, floating)
|
|
78
|
-
@ddr = ddr
|
|
79
|
-
@data = data
|
|
80
|
-
@floating = floating
|
|
81
|
-
refresh
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# Holds CAPS LOCK down, or lets it up.
|
|
85
|
-
def caps_lock=(down)
|
|
86
|
-
@caps_lock = down
|
|
87
|
-
refresh
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
# Reads the inputs again, after the datasette's sense line changes.
|
|
91
|
-
def refresh
|
|
92
|
-
@status.value = input_value
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
private
|
|
96
|
-
|
|
97
|
-
def update
|
|
98
|
-
driven = @ddr & @floating_mask
|
|
99
|
-
@floating = (@floating & ~driven) | (@data & driven)
|
|
100
|
-
refresh
|
|
101
|
-
@datasette.motor = !@status.tape_motor?
|
|
102
|
-
@change_handler&.call
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def input_value
|
|
106
|
-
input = @pullups | (@floating & @floating_mask)
|
|
107
|
-
input |= @caps_lock_pin unless @caps_lock
|
|
108
|
-
input &= ~TAPE_SENSE if @datasette.sense_low?
|
|
109
|
-
(@data & @ddr) | (input & ~@ddr & 0xff)
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
|
-
end
|
data/lib/badline/datasette.rb
DELETED
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
# The 1530 datasette. Plays a pulse stream into CIA 1's FLAG pin while the
|
|
5
|
-
# motor runs with a key pressed, and reports the keys through the cassette
|
|
6
|
-
# sense line on the $01 port. With RECORD down too, it records the
|
|
7
|
-
# machine's write line onto the tape instead.
|
|
8
|
-
class Datasette
|
|
9
|
-
# What inserting a tape raises on a machine without a cassette port.
|
|
10
|
-
class Missing < ArgumentError; end
|
|
11
|
-
|
|
12
|
-
attr_reader :tape
|
|
13
|
-
attr_writer :motor
|
|
14
|
-
|
|
15
|
-
def initialize(tape = nil)
|
|
16
|
-
@tape = tape
|
|
17
|
-
@connected = true
|
|
18
|
-
@playing = false
|
|
19
|
-
@recording = false
|
|
20
|
-
@write_high = true
|
|
21
|
-
@since = 0
|
|
22
|
-
@motor = false
|
|
23
|
-
@countdown = 0
|
|
24
|
-
@flag_handler = nil
|
|
25
|
-
@sense_handler = nil
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
# Falling edges on the tape read line.
|
|
29
|
-
def on_flag(&handler)
|
|
30
|
-
@flag_handler = handler
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# The cassette sense line, which the $01 port reads back.
|
|
34
|
-
def on_sense_change(&handler)
|
|
35
|
-
@sense_handler = handler
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
# Whether the machine has a datasette at its cassette port. The SX-64
|
|
39
|
-
# has none: its keys stay up and it takes no tape.
|
|
40
|
-
def connected? = @connected
|
|
41
|
-
|
|
42
|
-
def disconnect!
|
|
43
|
-
eject
|
|
44
|
-
@connected = false
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def insert(tape)
|
|
48
|
-
raise Missing, "this machine has no datasette" unless @connected
|
|
49
|
-
|
|
50
|
-
@tape = tape
|
|
51
|
-
rewind
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def eject
|
|
55
|
-
stop!
|
|
56
|
-
@tape = nil
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def rewind
|
|
60
|
-
@tape&.rewind
|
|
61
|
-
@countdown = 0
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def play! = press(true)
|
|
65
|
-
def stop! = press(false)
|
|
66
|
-
|
|
67
|
-
# Presses RECORD and PLAY together.
|
|
68
|
-
def record!
|
|
69
|
-
return if !@connected || @tape.nil?
|
|
70
|
-
|
|
71
|
-
press(true)
|
|
72
|
-
@recording = true
|
|
73
|
-
@since = 0
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def recording? = @recording
|
|
77
|
-
|
|
78
|
-
# The machine's tape write line. While the deck records with its motor
|
|
79
|
-
# running, each rising edge ends a pulse on the tape, as long as the
|
|
80
|
-
# time since the edge before, and plays back as a falling edge on the
|
|
81
|
-
# read line.
|
|
82
|
-
def write_line=(high)
|
|
83
|
-
rose = high && !@write_high
|
|
84
|
-
@write_high = high
|
|
85
|
-
return unless rose && @recording && running?
|
|
86
|
-
|
|
87
|
-
@tape.record_pulse(@since)
|
|
88
|
-
@since = 0
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def playing? = @playing
|
|
92
|
-
|
|
93
|
-
# Sense reads low while a key is down on the deck.
|
|
94
|
-
def sense_low? = @playing
|
|
95
|
-
|
|
96
|
-
def motor? = @motor
|
|
97
|
-
|
|
98
|
-
def running? = @playing && @motor && !@tape.nil?
|
|
99
|
-
|
|
100
|
-
# The keys, the motor, the countdown to the next pulse and the tape:
|
|
101
|
-
# its path, its bytes and how far it has played.
|
|
102
|
-
def save_state(out)
|
|
103
|
-
out.marker("DATASETTE")
|
|
104
|
-
out.boolean(@playing).boolean(@motor).int(@countdown).boolean(!@tape.nil?)
|
|
105
|
-
return unless @tape
|
|
106
|
-
|
|
107
|
-
out.string(@tape.path).blob(@tape.bytes).int(@tape.position)
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
# The tape goes back in from the bytes the state holds, without its
|
|
111
|
-
# host file, unless the tape in is the same one. The sense and flag
|
|
112
|
-
# handlers don't fire.
|
|
113
|
-
def load_state(input)
|
|
114
|
-
input.marker("DATASETTE")
|
|
115
|
-
@playing = input.boolean?
|
|
116
|
-
@motor = input.boolean?
|
|
117
|
-
@countdown = input.int
|
|
118
|
-
return @tape = nil unless input.boolean?
|
|
119
|
-
|
|
120
|
-
path = input.string
|
|
121
|
-
bytes = input.blob
|
|
122
|
-
position = input.int
|
|
123
|
-
@tape = Storage::TAP.new(path, bytes:) unless @tape&.path&.b == path && @tape.bytes == bytes
|
|
124
|
-
@tape.position = position
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
def cycle!
|
|
128
|
-
return unless running?
|
|
129
|
-
return @since += 1 if @recording
|
|
130
|
-
|
|
131
|
-
@countdown = @tape.next_pulse.to_i if @countdown.zero?
|
|
132
|
-
return if @countdown.zero?
|
|
133
|
-
|
|
134
|
-
@countdown -= 1
|
|
135
|
-
@flag_handler&.call if @countdown.zero?
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
def inspect
|
|
139
|
-
"#<#{self.class.name} tape=#{@tape ? @tape.class.name : 'none'} " \
|
|
140
|
-
"playing=#{@playing} motor=#{@motor}>"
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
private
|
|
144
|
-
|
|
145
|
-
def press(down)
|
|
146
|
-
return if down == @playing || !@connected
|
|
147
|
-
|
|
148
|
-
finish_recording unless down
|
|
149
|
-
@playing = down
|
|
150
|
-
@sense_handler&.call
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
# Releasing the keys ends a recording, and writes the tape out.
|
|
154
|
-
def finish_recording
|
|
155
|
-
return unless @recording
|
|
156
|
-
|
|
157
|
-
@recording = false
|
|
158
|
-
@tape.save
|
|
159
|
-
end
|
|
160
|
-
end
|
|
161
|
-
end
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
# The VICE debug cartridge register, mapped at $D7FF on the C64. It is a
|
|
5
|
-
# VICE facility rather than real hardware, enabled there with -debugcart:
|
|
6
|
-
# writing a byte ends the run with that value as the exit code. The VICE
|
|
7
|
-
# test suites write $00 for success and $ff for failure.
|
|
8
|
-
#
|
|
9
|
-
# Wraps the SID's top mirror page, so every other access falls through.
|
|
10
|
-
class DebugRegister
|
|
11
|
-
ADDRESS = 0xd7ff
|
|
12
|
-
|
|
13
|
-
def initialize(sid, &handler)
|
|
14
|
-
@sid = sid
|
|
15
|
-
@handler = handler
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def peek(addr)
|
|
19
|
-
@sid.peek(addr)
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def poke(addr, value)
|
|
23
|
-
return @handler.call(value) if addr == ADDRESS
|
|
24
|
-
|
|
25
|
-
@sid.poke(addr, value)
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
data/lib/badline/drive/core.rb
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
module Drive
|
|
5
|
-
# What every Commodore disk drive here shares: a 6502 running the DOS
|
|
6
|
-
# ROM, with chips on its bus facing the serial bus and the disk
|
|
7
|
-
# mechanism, on a clock of its own.
|
|
8
|
-
#
|
|
9
|
-
# The drive runs on its own crystal, so it clocks against the host's
|
|
10
|
-
# clock through a fractional accumulator: each host cycle adds the
|
|
11
|
-
# drive's clock rate worth of phase, and every whole host period in it
|
|
12
|
-
# runs a drive cycle. Against the PAL C64's 985,248 Hz a drive at
|
|
13
|
-
# 1 MHz runs one drive cycle per host cycle and a second one about
|
|
14
|
-
# every 67. The host sets its clock on attaching the drive, and until
|
|
15
|
-
# then a 1 MHz drive runs one cycle per host cycle.
|
|
16
|
-
#
|
|
17
|
-
# The Mechanism reads a Disk put in with insert.
|
|
18
|
-
#
|
|
19
|
-
# While the DOS idles, host_cycle! skips the drive's cycles and catches
|
|
20
|
-
# up on them later, exactly (see Idle). The readers of the drive's parts
|
|
21
|
-
# catch up first, so they find the drive as running every cycle would
|
|
22
|
-
# have left it. Once the DOS's timer interrupts come round, the drive
|
|
23
|
-
# sleeps through them too (see Orbit).
|
|
24
|
-
#
|
|
25
|
-
# A model includes Core and builds its parts, sets @clock_hz and
|
|
26
|
-
# @idle_loop, and runs one drive cycle in step. It hears ATN on
|
|
27
|
-
# connecting (hear_atn), drives the serial bus (serial_output), and
|
|
28
|
-
# answers Idle's and Orbit's questions about its chips, as VIAs does
|
|
29
|
-
# for the 1541 and the 1571.
|
|
30
|
-
module Core
|
|
31
|
-
include Sleep
|
|
32
|
-
include Idle
|
|
33
|
-
include Orbit
|
|
34
|
-
|
|
35
|
-
attr_reader :device, :serial_bus
|
|
36
|
-
|
|
37
|
-
def cpu
|
|
38
|
-
settle!
|
|
39
|
-
@cpu
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def bus
|
|
43
|
-
settle!
|
|
44
|
-
@bus
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def mechanism
|
|
48
|
-
settle!
|
|
49
|
-
@mechanism
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def cycles
|
|
53
|
-
settle!
|
|
54
|
-
@cycles
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def ram = bus.ram
|
|
58
|
-
|
|
59
|
-
def host_clock_hz=(clock_hz)
|
|
60
|
-
settle!
|
|
61
|
-
@host_clock_hz = clock_hz
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
# Plugs the drive into a serial bus, leaving the one it was on. A drive
|
|
65
|
-
# starts out on a bus of its own, with nothing else on it.
|
|
66
|
-
def connect(serial_bus)
|
|
67
|
-
settle!
|
|
68
|
-
@serial_bus&.detach(self)
|
|
69
|
-
@serial_bus = serial_bus
|
|
70
|
-
@serial_port.bus = serial_bus
|
|
71
|
-
serial_bus.attach(self)
|
|
72
|
-
hear_atn
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
# Puts a Disk in the drive (Disk.from_d64 makes one from an image).
|
|
76
|
-
# Nil takes the disk out.
|
|
77
|
-
def insert(disk)
|
|
78
|
-
settle!
|
|
79
|
-
@mechanism.insert(disk)
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def disk = mechanism.disk
|
|
83
|
-
|
|
84
|
-
# Whether the LED is lit. Reading it leaves the drive asleep: the LED
|
|
85
|
-
# is the same at the end of every pass the drive sleeps through.
|
|
86
|
-
def led_on? = @mechanism.led_on?
|
|
87
|
-
|
|
88
|
-
# Stores what the head wrote since the motor last stopped in the
|
|
89
|
-
# disk's image, as the motor stopping does.
|
|
90
|
-
def flush
|
|
91
|
-
settle!
|
|
92
|
-
@mechanism.flush
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
# Runs the drive cycles that fall in one host cycle: none, one or two.
|
|
96
|
-
# The host has run this cycle already, and the drive sees what it did
|
|
97
|
-
# from the next one on (see SerialPort). Asleep, the drive owes the
|
|
98
|
-
# cycles instead, until ATN moves or its counters are due (see Idle).
|
|
99
|
-
# It looks at ATN only after the machine pushed its lines into the bus
|
|
100
|
-
# (see host_written!).
|
|
101
|
-
def host_cycle!
|
|
102
|
-
if @asleep
|
|
103
|
-
return if (@slept += 1) != @wake_at && @host_still
|
|
104
|
-
|
|
105
|
-
return doze
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
phase = @phase + @clock_hz
|
|
109
|
-
while phase >= @host_clock_hz
|
|
110
|
-
@asleep ? @owed += 1 : run_cycle
|
|
111
|
-
phase -= @host_clock_hz
|
|
112
|
-
end
|
|
113
|
-
@phase = phase
|
|
114
|
-
settle! if @serial_port.atn_moved?
|
|
115
|
-
@serial_port.latch_host
|
|
116
|
-
plan_wake if @asleep
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
# The machine pushed its lines into the bus, so ATN may have moved.
|
|
120
|
-
def host_written!
|
|
121
|
-
@host_still = false
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
# The host moved its fast serial pins, which a 1541 has none to hear.
|
|
125
|
-
def fast_lines_moved = nil
|
|
126
|
-
|
|
127
|
-
# Runs one drive cycle, catching up first on any the drive owes (see
|
|
128
|
-
# step).
|
|
129
|
-
def cycle!
|
|
130
|
-
settle!
|
|
131
|
-
step
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
def inspect
|
|
135
|
-
"#<#{self.class.name} cycles=#{cycles} cpu=(#{cpu.inspect})>"
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
private
|
|
139
|
-
|
|
140
|
-
# A drive cycle from host_cycle!, which may find the idle loop.
|
|
141
|
-
def run_cycle
|
|
142
|
-
step
|
|
143
|
-
idle_loop_reached if @cpu.program_counter == @idle_loop && @idle_skip
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
end
|
|
147
|
-
end
|