badline 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -0
- data/CLAUDE.md +59 -31
- data/README.md +1 -1
- data/doc/library.md +9 -9
- data/doc/pinned-behaviour.md +105 -105
- data/doc/snapshots.md +1 -4
- data/lib/badline/audio/bare_player.rb +4 -4
- data/lib/badline/audio/cli.rb +6 -6
- data/lib/badline/audio/jukebox.rb +2 -2
- data/lib/badline/audio/machine_player.rb +2 -2
- data/lib/badline/{media → audio}/queue.rb +1 -1
- data/lib/badline/audio/queued_tune.rb +6 -6
- data/lib/badline/audio/renderer.rb +5 -5
- data/lib/badline/audio/stereo.rb +1 -1
- data/lib/badline/c128/{bus_state.rb → bus/saved_state.rb} +6 -6
- data/lib/badline/c128/bus.rb +30 -51
- data/lib/badline/c128/color_lines.rb +2 -2
- data/lib/badline/c128/cpu.rb +1 -1
- data/lib/badline/c128/drives.rb +10 -11
- data/lib/badline/c128/fast_serial.rb +5 -5
- data/lib/badline/c128/mmu_pages.rb +1 -1
- data/lib/badline/c128/modes.rb +2 -2
- data/lib/badline/c128/saved_state.rb +21 -47
- data/lib/badline/c128/z80.rb +2 -2
- data/lib/badline/c128.rb +18 -72
- data/lib/badline/{computer → c64}/attachments.rb +16 -47
- data/lib/badline/c64/banked_ram/banking.rb +32 -0
- data/lib/badline/c64/banked_ram/plus256k.rb +56 -0
- data/lib/badline/c64/banked_ram/plus60k.rb +45 -0
- data/lib/badline/c64/banked_ram/unexpanded.rb +30 -0
- data/lib/badline/c64/banked_ram.rb +23 -0
- data/lib/badline/c64/bus/extra_sids.rb +32 -0
- data/lib/badline/c64/bus/fittings.rb +40 -0
- data/lib/badline/c64/bus/pla.rb +149 -0
- data/lib/badline/c64/bus/roms.rb +41 -0
- data/lib/badline/c64/bus/saved_state.rb +68 -0
- data/lib/badline/c64/bus/sid_slots.rb +44 -0
- data/lib/badline/c64/bus.rb +218 -0
- data/lib/badline/c64/cartridge/action_replay.rb +128 -0
- data/lib/badline/c64/cartridge/atomic_power.rb +26 -0
- data/lib/badline/c64/cartridge/bank.rb +83 -0
- data/lib/badline/c64/cartridge/comal80.rb +52 -0
- data/lib/badline/c64/cartridge/dinamic.rb +36 -0
- data/lib/badline/c64/cartridge/easy_flash.rb +147 -0
- data/lib/badline/c64/cartridge/epyx_fastload.rb +81 -0
- data/lib/badline/c64/cartridge/final_cartridge3.rb +91 -0
- data/lib/badline/c64/cartridge/flash/saved_state.rb +40 -0
- data/lib/badline/c64/cartridge/flash.rb +279 -0
- data/lib/badline/c64/cartridge/freezer.rb +35 -0
- data/lib/badline/c64/cartridge/fun_play.rb +40 -0
- data/lib/badline/c64/cartridge/g_mod2.rb +76 -0
- data/lib/badline/c64/cartridge/game_system.rb +42 -0
- data/lib/badline/c64/cartridge/geo_ram.rb +81 -0
- data/lib/badline/c64/cartridge/kcs_power.rb +77 -0
- data/lib/badline/c64/cartridge/mach5.rb +34 -0
- data/lib/badline/c64/cartridge/magic_desk.rb +32 -0
- data/lib/badline/c64/cartridge/ocean.rb +37 -0
- data/lib/badline/c64/cartridge/pagefox.rb +70 -0
- data/lib/badline/c64/cartridge/retro_replay/saved_state.rb +47 -0
- data/lib/badline/c64/cartridge/retro_replay.rb +286 -0
- data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
- data/lib/badline/c64/cartridge/rgcd.rb +60 -0
- data/lib/badline/c64/cartridge/saved_state.rb +63 -0
- data/lib/badline/c64/cartridge/simons_basic.rb +37 -0
- data/lib/badline/c64/cartridge/standard.rb +17 -0
- data/lib/badline/c64/cartridge/super_games.rb +50 -0
- data/lib/badline/c64/cartridge/westermann.rb +32 -0
- data/lib/badline/c64/cartridge/zaxxon.rb +68 -0
- data/lib/badline/c64/cartridge.rb +258 -0
- data/lib/badline/c64/color_memory.rb +27 -0
- data/lib/badline/c64/common.rb +34 -0
- data/lib/badline/c64/kernal_traps.rb +89 -0
- data/lib/badline/c64/reu/dma/saved_state.rb +52 -0
- data/lib/badline/c64/reu/dma.rb +275 -0
- data/lib/badline/c64/reu/ram.rb +109 -0
- data/lib/badline/c64/reu/saved_state.rb +55 -0
- data/lib/badline/c64/reu/trigger.rb +34 -0
- data/lib/badline/c64/reu.rb +291 -0
- data/lib/badline/{computer → c64}/saved_state.rb +13 -18
- data/lib/badline/{computer → c64}/true_drives.rb +20 -31
- data/lib/badline/{computer.rb → c64.rb} +22 -80
- data/lib/badline/chips/cia/fast_forward.rb +62 -0
- data/lib/badline/chips/cia/interrupt_register.rb +145 -0
- data/lib/badline/chips/cia/saved_state.rb +49 -0
- data/lib/badline/chips/cia/serial/saved_state.rb +45 -0
- data/lib/badline/chips/cia/serial.rb +250 -0
- data/lib/badline/chips/cia/time_of_day.rb +232 -0
- data/lib/badline/chips/cia/timer.rb +208 -0
- data/lib/badline/chips/cia.rb +281 -0
- data/lib/badline/chips/cpu/addressing.rb +133 -0
- data/lib/badline/chips/cpu/boundary.rb +56 -0
- data/lib/badline/chips/cpu/core.rb +167 -0
- data/lib/badline/chips/cpu/instruction.rb +338 -0
- data/lib/badline/chips/cpu/instruction_set/arithmetic.rb +118 -0
- data/lib/badline/chips/cpu/instruction_set/bitwise.rb +130 -0
- data/lib/badline/chips/cpu/instruction_set/branch.rb +83 -0
- data/lib/badline/chips/cpu/instruction_set/flag.rb +67 -0
- data/lib/badline/chips/cpu/instruction_set/illegal.rb +274 -0
- data/lib/badline/chips/cpu/instruction_set/inc_dec.rb +73 -0
- data/lib/badline/chips/cpu/instruction_set/stack.rb +56 -0
- data/lib/badline/chips/cpu/instruction_set/transfer.rb +141 -0
- data/lib/badline/chips/cpu/instruction_set.rb +59 -0
- data/lib/badline/chips/cpu/interrupts.rb +108 -0
- data/lib/badline/chips/cpu/microcode.rb +179 -0
- data/lib/badline/chips/cpu/operations.rb +90 -0
- data/lib/badline/chips/cpu/port.rb +116 -0
- data/lib/badline/chips/cpu/saved_state.rb +117 -0
- data/lib/badline/chips/cpu/stack_operations.rb +84 -0
- data/lib/badline/chips/cpu/traps.rb +23 -0
- data/lib/badline/chips/cpu.rb +12 -0
- data/lib/badline/chips/sid/catch_up.rb +122 -0
- data/lib/badline/chips/sid/decimator.rb +66 -0
- data/lib/badline/chips/sid/envelope/saved_state.rb +70 -0
- data/lib/badline/chips/sid/envelope.rb +241 -0
- data/lib/badline/chips/sid/filter/saved_state.rb +42 -0
- data/lib/badline/chips/sid/filter.rb +241 -0
- data/lib/badline/chips/sid/saved_state.rb +52 -0
- data/lib/badline/chips/sid/voice.rb +79 -0
- data/lib/badline/chips/sid/waveform/combined.rb +128 -0
- data/lib/badline/chips/sid/waveform/fast_forward.rb +107 -0
- data/lib/badline/chips/sid/waveform/noise_writeback.rb +124 -0
- data/lib/badline/chips/sid/waveform/saved_state.rb +68 -0
- data/lib/badline/chips/sid/waveform.rb +307 -0
- data/lib/badline/chips/sid.rb +265 -0
- data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
- data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -1
- data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -1
- data/lib/badline/chips/vdc/saved_state.rb +36 -0
- data/lib/badline/{c128 → chips}/vdc/window.rb +1 -1
- data/lib/badline/{c128 → chips}/vdc.rb +7 -31
- data/lib/badline/chips/via/control_lines.rb +124 -0
- data/lib/badline/chips/via/fast_forward.rb +55 -0
- data/lib/badline/chips/via/interrupt_register.rb +69 -0
- data/lib/badline/chips/via/saved_state.rb +44 -0
- data/lib/badline/chips/via/shift_register.rb +182 -0
- data/lib/badline/chips/via/timer1.rb +133 -0
- data/lib/badline/chips/via/timer2.rb +135 -0
- data/lib/badline/chips/via.rb +268 -0
- data/lib/badline/chips/vic/bank.rb +135 -0
- data/lib/badline/chips/vic/border_mask.rb +88 -0
- data/lib/badline/chips/vic/collisions.rb +117 -0
- data/lib/badline/chips/vic/color_patches.rb +49 -0
- data/lib/badline/chips/vic/display_state.rb +187 -0
- data/lib/badline/chips/vic/graphics_mode.rb +166 -0
- data/lib/badline/chips/vic/graphics_shifter/saved_state.rb +40 -0
- data/lib/badline/chips/vic/graphics_shifter.rb +187 -0
- data/lib/badline/chips/vic/register_log.rb +83 -0
- data/lib/badline/chips/vic/registers.rb +197 -0
- data/lib/badline/chips/vic/saved_state.rb +82 -0
- data/lib/badline/chips/vic/sequencer/saved_state.rb +91 -0
- data/lib/badline/chips/vic/sequencer.rb +277 -0
- data/lib/badline/chips/vic/sequencer_output.rb +118 -0
- data/lib/badline/chips/vic/sprite/internal_bus.rb +70 -0
- data/lib/badline/chips/vic/sprite/saved_state.rb +66 -0
- data/lib/badline/chips/vic/sprite/shifter.rb +148 -0
- data/lib/badline/chips/vic/sprite/timing.rb +58 -0
- data/lib/badline/chips/vic/sprite.rb +339 -0
- data/lib/badline/chips/vic/sprites/saved_state.rb +59 -0
- data/lib/badline/chips/vic/sprites.rb +284 -0
- data/lib/badline/chips/vic.rb +783 -0
- data/lib/badline/chips/vic_i/painter/saved_state.rb +40 -0
- data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +6 -30
- data/lib/badline/{vic20/vic → chips/vic_i}/saved_state.rb +2 -2
- data/lib/badline/chips/vic_i/sound/output.rb +85 -0
- data/lib/badline/chips/vic_i/sound.rb +235 -0
- data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
- data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +5 -5
- data/lib/badline/chips/z80/arithmetic.rb +119 -0
- data/lib/badline/chips/z80/bit_page.rb +57 -0
- data/lib/badline/chips/z80/block_io.rb +60 -0
- data/lib/badline/chips/z80/block_transfers.rb +61 -0
- data/lib/badline/chips/z80/bus_cycles.rb +113 -0
- data/lib/badline/chips/z80/core.rb +115 -0
- data/lib/badline/chips/z80/exchanges.rb +52 -0
- data/lib/badline/chips/z80/extended_page.rb +91 -0
- data/lib/badline/chips/z80/flags.rb +39 -0
- data/lib/badline/chips/z80/interrupt_acceptance.rb +48 -0
- data/lib/badline/chips/z80/jumps.rb +84 -0
- data/lib/badline/chips/z80/loads.rb +100 -0
- data/lib/badline/chips/z80/main_page.rb +136 -0
- data/lib/badline/chips/z80/registers.rb +122 -0
- data/lib/badline/chips/z80/saved_state.rb +71 -0
- data/lib/badline/chips/z80/shifts.rb +66 -0
- data/lib/badline/chips/z80.rb +13 -0
- data/lib/badline/core.rb +27 -29
- data/lib/badline/drives/datasette/saved_state.rb +37 -0
- data/lib/badline/drives/datasette.rb +140 -0
- data/lib/badline/drives/engine/core.rb +149 -0
- data/lib/badline/drives/engine/fast_serial.rb +75 -0
- data/lib/badline/drives/engine/idle.rb +127 -0
- data/lib/badline/drives/engine/idle_cpu.rb +30 -0
- data/lib/badline/drives/engine/orbit.rb +81 -0
- data/lib/badline/drives/engine/serial_lines.rb +75 -0
- data/lib/badline/drives/engine/sleep.rb +114 -0
- data/lib/badline/drives/engine/vias.rb +86 -0
- data/lib/badline/drives/engine/watch.rb +152 -0
- data/lib/badline/drives/engine.rb +11 -0
- data/lib/badline/drives/model1541/bus.rb +88 -0
- data/lib/badline/drives/model1541/byte_ready.rb +50 -0
- data/lib/badline/drives/model1541/cpu.rb +13 -0
- data/lib/badline/drives/model1541/disk/saved_state.rb +88 -0
- data/lib/badline/drives/model1541/disk.rb +317 -0
- data/lib/badline/drives/model1541/disk_via.rb +38 -0
- data/lib/badline/drives/model1541/gcr.rb +59 -0
- data/lib/badline/drives/model1541/mechanism/saved_state.rb +72 -0
- data/lib/badline/drives/model1541/mechanism.rb +315 -0
- data/lib/badline/drives/model1541/rotation.rb +123 -0
- data/lib/badline/drives/model1541/saved_state.rb +44 -0
- data/lib/badline/drives/model1541/sector_reader.rb +78 -0
- data/lib/badline/drives/model1541/serial_port.rb +20 -0
- data/lib/badline/drives/model1541/track.rb +100 -0
- data/lib/badline/drives/model1541.rb +81 -0
- data/lib/badline/drives/model1571/bus.rb +113 -0
- data/lib/badline/drives/model1571/cpu.rb +13 -0
- data/lib/badline/drives/model1571/saved_state.rb +47 -0
- data/lib/badline/drives/model1571/serial_port.rb +39 -0
- data/lib/badline/drives/model1571/serial_via.rb +27 -0
- data/lib/badline/drives/model1571/wd1770.rb +122 -0
- data/lib/badline/drives/model1571.rb +142 -0
- data/lib/badline/drives/model1581/bus.rb +139 -0
- data/lib/badline/drives/model1581/cpu.rb +13 -0
- data/lib/badline/drives/model1581/disk/saved_state.rb +89 -0
- data/lib/badline/drives/model1581/disk.rb +137 -0
- data/lib/badline/drives/model1581/mechanism.rb +119 -0
- data/lib/badline/drives/model1581/saved_state.rb +42 -0
- data/lib/badline/drives/model1581/serial_port.rb +54 -0
- data/lib/badline/drives/model1581/slot.rb +79 -0
- data/lib/badline/drives/model1581/track.rb +102 -0
- data/lib/badline/drives/model1581/track_bytes.rb +77 -0
- data/lib/badline/drives/model1581/wd1772/registers.rb +91 -0
- data/lib/badline/drives/model1581/wd1772/saved_state.rb +68 -0
- data/lib/badline/drives/model1581/wd1772/sector_writes.rb +75 -0
- data/lib/badline/drives/model1581/wd1772/sectors.rb +152 -0
- data/lib/badline/drives/model1581/wd1772/stepping.rb +111 -0
- data/lib/badline/drives/model1581/wd1772/tracks.rb +127 -0
- data/lib/badline/drives/model1581/wd1772/turn.rb +75 -0
- data/lib/badline/drives/model1581/wd1772.rb +218 -0
- data/lib/badline/drives/model1581.rb +206 -0
- data/lib/badline/drives/serial_bus.rb +161 -0
- data/lib/badline/frontend/boot.rb +10 -61
- data/lib/badline/frontend/machine_window.rb +3 -1
- data/lib/badline/frontend/player/filter_view.rb +1 -1
- data/lib/badline/frontend/player/player_controller.rb +2 -2
- data/lib/badline/frontend/player/player_screen.rb +1 -0
- data/lib/badline/frontend/player/theme.rb +7 -7
- data/lib/badline/frontend/timeline.rb +3 -3
- data/lib/badline/input/control_ports.rb +78 -0
- data/lib/badline/input/joystick.rb +27 -0
- data/lib/badline/input/keyboard.rb +114 -0
- data/lib/badline/input.rb +3 -0
- data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
- data/lib/badline/kernal_trap/dos/channel.rb +183 -0
- data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
- data/lib/badline/kernal_trap/{drive.rb → dos.rb} +11 -10
- data/lib/badline/kernal_trap/{file.rb → file_routine.rb} +1 -1
- data/lib/badline/kernal_trap/load.rb +6 -6
- data/lib/badline/kernal_trap/save.rb +5 -5
- data/lib/badline/kernal_trap/serial.rb +7 -7
- data/lib/badline/kernal_trap.rb +2 -3
- data/lib/badline/machine/clocking.rb +50 -0
- data/lib/badline/machine.rb +63 -7
- data/lib/badline/media/boot_disk.rb +2 -2
- data/lib/badline/media/disk_list.rb +3 -3
- data/lib/badline/media/disk_set.rb +1 -1
- data/lib/badline/media/extensions.rb +33 -0
- data/lib/badline/media/program.rb +28 -0
- data/lib/badline/media/true_drive.rb +4 -3
- data/lib/badline/media/tune.rb +35 -0
- data/lib/badline/media/vic20_cartridge.rb +1 -7
- data/lib/badline/media/vic20_media.rb +38 -80
- data/lib/badline/media.rb +84 -81
- data/lib/badline/model.rb +1 -1
- data/lib/badline/options/event.rb +3 -1
- data/lib/badline/roms/README +6 -6
- data/lib/badline/sdl.rb +1 -0
- data/lib/badline/{storage/sid_file.rb → sid_tune/file.rb} +3 -3
- data/lib/badline/{storage → sid_tune}/hvsc.rb +7 -7
- data/lib/badline/{storage → sid_tune}/song_lengths.rb +2 -2
- data/lib/badline/{storage → sid_tune}/stil/credit.rb +1 -1
- data/lib/badline/{storage → sid_tune}/stil.rb +3 -3
- data/lib/badline/sid_tune.rb +6 -0
- data/lib/badline/snapshot/c128_setup.rb +43 -0
- data/lib/badline/snapshot/c64_setup.rb +79 -0
- data/lib/badline/snapshot/image.rb +5 -25
- data/lib/badline/snapshot/machine_state.rb +10 -2
- data/lib/badline/snapshot/setup.rb +22 -66
- data/lib/badline/snapshot/state.rb +8 -17
- data/lib/badline/snapshot/storage_setup.rb +68 -0
- data/lib/badline/snapshot/vic20_setup.rb +37 -0
- data/lib/badline/snapshot/vice/c64_mem.rb +1 -1
- data/lib/badline/snapshot/vice/restore.rb +1 -1
- data/lib/badline/snapshot/vice/reu1764.rb +1 -1
- data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
- data/lib/badline/snapshot/vice.rb +7 -5
- data/lib/badline/snapshot.rb +13 -12
- data/lib/badline/storage/d64_image.rb +15 -9
- data/lib/badline/storage/d71_image.rb +0 -2
- data/lib/badline/storage/d81_image.rb +0 -2
- data/lib/badline/storage/disk_image/writing.rb +2 -2
- data/lib/badline/storage/disk_image.rb +3 -6
- data/lib/badline/storage/g64_image.rb +2 -2
- data/lib/badline/storage/host_directory.rb +0 -5
- data/lib/badline/storage/t64.rb +2 -8
- data/lib/badline/storage/unavailable.rb +1 -1
- data/lib/badline/storage.rb +0 -37
- data/lib/badline/support/c128_checkpoint.rb +39 -0
- data/lib/badline/support/checkpoint.rb +108 -0
- data/lib/badline/support/vic20_checkpoint.rb +38 -0
- data/lib/badline/support.rb +5 -0
- data/lib/badline/version.rb +1 -1
- data/lib/badline/vic20/attachments.rb +11 -81
- data/lib/badline/vic20/bus/saved_state.rb +35 -0
- data/lib/badline/vic20/bus.rb +3 -25
- data/lib/badline/vic20/cpu.rb +1 -1
- data/lib/badline/vic20/port_wiring.rb +4 -4
- data/lib/badline/vic20/saved_state.rb +16 -60
- data/lib/badline/vic20/user_via_ports.rb +2 -2
- data/lib/badline/vic20.rb +20 -51
- metadata +250 -221
- data/lib/badline/address_bus/extra_sids.rb +0 -30
- data/lib/badline/address_bus/fittings.rb +0 -38
- data/lib/badline/address_bus/pla.rb +0 -147
- data/lib/badline/address_bus/roms.rb +0 -39
- data/lib/badline/address_bus/saved_state.rb +0 -72
- data/lib/badline/address_bus/sid_slots.rb +0 -42
- data/lib/badline/address_bus.rb +0 -235
- data/lib/badline/cartridge/action_replay.rb +0 -126
- data/lib/badline/cartridge/atomic_power.rb +0 -24
- data/lib/badline/cartridge/bank.rb +0 -81
- data/lib/badline/cartridge/comal80.rb +0 -50
- data/lib/badline/cartridge/dinamic.rb +0 -34
- data/lib/badline/cartridge/easy_flash.rb +0 -145
- data/lib/badline/cartridge/epyx_fastload.rb +0 -79
- data/lib/badline/cartridge/final_cartridge3.rb +0 -89
- data/lib/badline/cartridge/flash.rb +0 -306
- data/lib/badline/cartridge/freezer.rb +0 -33
- data/lib/badline/cartridge/fun_play.rb +0 -38
- data/lib/badline/cartridge/g_mod2.rb +0 -74
- data/lib/badline/cartridge/game_system.rb +0 -40
- data/lib/badline/cartridge/geo_ram.rb +0 -79
- data/lib/badline/cartridge/kcs_power.rb +0 -75
- data/lib/badline/cartridge/mach5.rb +0 -32
- data/lib/badline/cartridge/magic_desk.rb +0 -30
- data/lib/badline/cartridge/ocean.rb +0 -35
- data/lib/badline/cartridge/pagefox.rb +0 -68
- data/lib/badline/cartridge/retro_replay.rb +0 -320
- data/lib/badline/cartridge/rex_utility.rb +0 -29
- data/lib/badline/cartridge/rgcd.rb +0 -58
- data/lib/badline/cartridge/simons_basic.rb +0 -35
- data/lib/badline/cartridge/standard.rb +0 -15
- data/lib/badline/cartridge/super_games.rb +0 -48
- data/lib/badline/cartridge/westermann.rb +0 -30
- data/lib/badline/cartridge/zaxxon.rb +0 -66
- data/lib/badline/cartridge.rb +0 -303
- data/lib/badline/checkpoint.rb +0 -98
- data/lib/badline/cia/fast_forward.rb +0 -60
- data/lib/badline/cia/interrupt_register.rb +0 -143
- data/lib/badline/cia/serial.rb +0 -275
- data/lib/badline/cia/state.rb +0 -47
- data/lib/badline/cia/timer.rb +0 -206
- data/lib/badline/cia.rb +0 -279
- data/lib/badline/color_memory.rb +0 -25
- data/lib/badline/computer/kernal_traps.rb +0 -29
- data/lib/badline/control_ports.rb +0 -76
- data/lib/badline/cpu/addressing.rb +0 -131
- data/lib/badline/cpu/boundary.rb +0 -54
- data/lib/badline/cpu/core.rb +0 -165
- data/lib/badline/cpu/microcode.rb +0 -177
- data/lib/badline/cpu/operations.rb +0 -88
- data/lib/badline/cpu/saved_state.rb +0 -115
- data/lib/badline/cpu/stack_operations.rb +0 -82
- data/lib/badline/cpu.rb +0 -10
- data/lib/badline/cycleable.rb +0 -38
- data/lib/badline/datasette.rb +0 -161
- data/lib/badline/drive/core.rb +0 -147
- data/lib/badline/drive/fast_serial.rb +0 -73
- data/lib/badline/drive/idle.rb +0 -125
- data/lib/badline/drive/idle_cpu.rb +0 -28
- data/lib/badline/drive/orbit.rb +0 -79
- data/lib/badline/drive/serial_lines.rb +0 -73
- data/lib/badline/drive/sleep.rb +0 -112
- data/lib/badline/drive/vias.rb +0 -84
- data/lib/badline/drive/watch.rb +0 -150
- data/lib/badline/drive.rb +0 -11
- data/lib/badline/drive1541/bus.rb +0 -86
- data/lib/badline/drive1541/byte_ready.rb +0 -48
- data/lib/badline/drive1541/cpu.rb +0 -11
- data/lib/badline/drive1541/disk.rb +0 -318
- data/lib/badline/drive1541/disk_state.rb +0 -94
- data/lib/badline/drive1541/disk_via.rb +0 -36
- data/lib/badline/drive1541/gcr.rb +0 -57
- data/lib/badline/drive1541/mechanism.rb +0 -313
- data/lib/badline/drive1541/mechanism_state.rb +0 -68
- data/lib/badline/drive1541/rotation.rb +0 -121
- data/lib/badline/drive1541/sector_reader.rb +0 -76
- data/lib/badline/drive1541/serial_port.rb +0 -18
- data/lib/badline/drive1541/track.rb +0 -98
- data/lib/badline/drive1541.rb +0 -111
- data/lib/badline/drive1571/bus.rb +0 -111
- data/lib/badline/drive1571/cpu.rb +0 -11
- data/lib/badline/drive1571/serial_port.rb +0 -37
- data/lib/badline/drive1571/serial_via.rb +0 -25
- data/lib/badline/drive1571/wd1770.rb +0 -120
- data/lib/badline/drive1571.rb +0 -175
- data/lib/badline/drive1581/bus.rb +0 -137
- data/lib/badline/drive1581/cpu.rb +0 -11
- data/lib/badline/drive1581/disk.rb +0 -135
- data/lib/badline/drive1581/disk_state.rb +0 -87
- data/lib/badline/drive1581/mechanism.rb +0 -117
- data/lib/badline/drive1581/serial_port.rb +0 -52
- data/lib/badline/drive1581/slot.rb +0 -78
- data/lib/badline/drive1581/track.rb +0 -100
- data/lib/badline/drive1581/track_bytes.rb +0 -75
- data/lib/badline/drive1581/wd1772/registers.rb +0 -89
- data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
- data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
- data/lib/badline/drive1581/wd1772/state.rb +0 -66
- data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
- data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
- data/lib/badline/drive1581/wd1772/turn.rb +0 -73
- data/lib/badline/drive1581/wd1772.rb +0 -216
- data/lib/badline/drive1581.rb +0 -233
- data/lib/badline/iec_bus.rb +0 -159
- data/lib/badline/instruction.rb +0 -334
- data/lib/badline/instruction_set/arithmetic.rb +0 -114
- data/lib/badline/instruction_set/bitwise.rb +0 -126
- data/lib/badline/instruction_set/branch.rb +0 -79
- data/lib/badline/instruction_set/flag.rb +0 -63
- data/lib/badline/instruction_set/illegal.rb +0 -270
- data/lib/badline/instruction_set/inc_dec.rb +0 -69
- data/lib/badline/instruction_set/stack.rb +0 -52
- data/lib/badline/instruction_set/transfer.rb +0 -137
- data/lib/badline/instruction_set.rb +0 -55
- data/lib/badline/interrupts.rb +0 -104
- data/lib/badline/joystick.rb +0 -25
- data/lib/badline/kernal_trap/channel.rb +0 -181
- data/lib/badline/keyboard.rb +0 -112
- data/lib/badline/ram_expansion/banking.rb +0 -30
- data/lib/badline/ram_expansion/plus256k.rb +0 -54
- data/lib/badline/ram_expansion/plus60k.rb +0 -43
- data/lib/badline/ram_expansion/unexpanded.rb +0 -28
- data/lib/badline/ram_expansion.rb +0 -21
- data/lib/badline/reu/dma/saved_state.rb +0 -50
- data/lib/badline/reu/dma.rb +0 -273
- data/lib/badline/reu/ram.rb +0 -107
- data/lib/badline/reu/saved_state.rb +0 -80
- data/lib/badline/reu/trigger.rb +0 -32
- data/lib/badline/reu.rb +0 -289
- data/lib/badline/sid/catch_up.rb +0 -120
- data/lib/badline/sid/decimator.rb +0 -64
- data/lib/badline/sid/envelope/state.rb +0 -68
- data/lib/badline/sid/envelope.rb +0 -239
- data/lib/badline/sid/filter.rb +0 -263
- data/lib/badline/sid/voice.rb +0 -77
- data/lib/badline/sid/waveform/combined.rb +0 -126
- data/lib/badline/sid/waveform/fast_forward.rb +0 -105
- data/lib/badline/sid/waveform/noise_writeback.rb +0 -122
- data/lib/badline/sid/waveform/state.rb +0 -66
- data/lib/badline/sid/waveform.rb +0 -305
- data/lib/badline/sid.rb +0 -303
- data/lib/badline/time_of_day.rb +0 -228
- data/lib/badline/traps.rb +0 -19
- data/lib/badline/via/control_lines.rb +0 -122
- data/lib/badline/via/fast_forward.rb +0 -53
- data/lib/badline/via/interrupt_register.rb +0 -67
- data/lib/badline/via/shift_register.rb +0 -180
- data/lib/badline/via/state.rb +0 -42
- data/lib/badline/via/timer1.rb +0 -131
- data/lib/badline/via/timer2.rb +0 -133
- data/lib/badline/via.rb +0 -266
- data/lib/badline/vic/bank.rb +0 -133
- data/lib/badline/vic/border_mask.rb +0 -86
- data/lib/badline/vic/collisions.rb +0 -115
- data/lib/badline/vic/color_patches.rb +0 -47
- data/lib/badline/vic/display_state.rb +0 -185
- data/lib/badline/vic/graphics_mode.rb +0 -164
- data/lib/badline/vic/graphics_shifter.rb +0 -207
- data/lib/badline/vic/register_log.rb +0 -81
- data/lib/badline/vic/registers.rb +0 -195
- data/lib/badline/vic/sequencer.rb +0 -275
- data/lib/badline/vic/sequencer_output.rb +0 -116
- data/lib/badline/vic/sequencer_state.rb +0 -89
- data/lib/badline/vic/sprite/internal_bus.rb +0 -68
- data/lib/badline/vic/sprite/saved_state.rb +0 -64
- data/lib/badline/vic/sprite/shifter.rb +0 -146
- data/lib/badline/vic/sprite/timing.rb +0 -56
- data/lib/badline/vic/sprite.rb +0 -337
- data/lib/badline/vic/sprites.rb +0 -282
- data/lib/badline/vic/sprites_state.rb +0 -57
- data/lib/badline/vic.rb +0 -852
- data/lib/badline/vic20/sound/output.rb +0 -83
- data/lib/badline/vic20/sound.rb +0 -233
- data/lib/badline/z80/arithmetic.rb +0 -117
- data/lib/badline/z80/bit_page.rb +0 -55
- data/lib/badline/z80/block_io.rb +0 -58
- data/lib/badline/z80/block_transfers.rb +0 -59
- data/lib/badline/z80/bus_cycles.rb +0 -111
- data/lib/badline/z80/core.rb +0 -113
- data/lib/badline/z80/exchanges.rb +0 -50
- data/lib/badline/z80/extended_page.rb +0 -89
- data/lib/badline/z80/flags.rb +0 -37
- data/lib/badline/z80/interrupt_acceptance.rb +0 -46
- data/lib/badline/z80/jumps.rb +0 -82
- data/lib/badline/z80/loads.rb +0 -98
- data/lib/badline/z80/main_page.rb +0 -134
- data/lib/badline/z80/registers.rb +0 -120
- data/lib/badline/z80/saved_state.rb +0 -69
- data/lib/badline/z80/shifts.rb +0 -64
- data/lib/badline/z80.rb +0 -11
- /data/lib/badline/snapshot/{fields.rb → vice/fields.rb} +0 -0
data/lib/badline/cia.rb
DELETED
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "badline/cia/interrupt_register"
|
|
4
|
-
require "badline/cia/serial"
|
|
5
|
-
require "badline/cia/timer"
|
|
6
|
-
require "badline/cia/state"
|
|
7
|
-
require "badline/cia/fast_forward"
|
|
8
|
-
|
|
9
|
-
module Badline
|
|
10
|
-
# CIA (Complex Interface Adapter) chip
|
|
11
|
-
class CIA
|
|
12
|
-
include Addressable
|
|
13
|
-
include State
|
|
14
|
-
include FastForward
|
|
15
|
-
|
|
16
|
-
# The original NMOS 6526 of the breadbin C64, and the HMOS 6526A of the
|
|
17
|
-
# C64C, which differs from it only in its interrupt control register.
|
|
18
|
-
MODELS = %i[mos6526 mos6526a].freeze
|
|
19
|
-
|
|
20
|
-
attr_reader :start, :control_a, :control_b, :serial, :model
|
|
21
|
-
|
|
22
|
-
# What's on the ports outside the chip. It pulls port lines low through
|
|
23
|
-
# read_a and read_b, and on CIA 1 drives PB4 through port_b4_high?.
|
|
24
|
-
attr_accessor :peripheral
|
|
25
|
-
|
|
26
|
-
# Timer A and timer B.
|
|
27
|
-
def timers = [@ta, @tb]
|
|
28
|
-
|
|
29
|
-
# Port A and B's data and direction registers.
|
|
30
|
-
def port_registers = [@data_port_a, @data_port_b, @data_dir_a, @data_dir_b]
|
|
31
|
-
|
|
32
|
-
def interrupt_status = @icr.status
|
|
33
|
-
|
|
34
|
-
def interrupt_control = @icr.mask
|
|
35
|
-
|
|
36
|
-
def interrupt!(delay = 1) = @icr.assert!(delay)
|
|
37
|
-
|
|
38
|
-
def time_of_day = @tod
|
|
39
|
-
|
|
40
|
-
def timer_a = @ta.counter
|
|
41
|
-
|
|
42
|
-
def timer_a=(value)
|
|
43
|
-
@ta.counter = value
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def timer_a_latch = @ta.latch
|
|
47
|
-
|
|
48
|
-
def timer_a_latch=(value)
|
|
49
|
-
@ta.latch = value
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def timer_b = @tb.counter
|
|
53
|
-
|
|
54
|
-
def timer_b=(value)
|
|
55
|
-
@tb.counter = value
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def timer_b_latch = @tb.latch
|
|
59
|
-
|
|
60
|
-
def timer_b_latch=(value)
|
|
61
|
-
@tb.latch = value
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
# +tod_hz+ is the rate of the pulses on the TOD pin, the region's mains
|
|
65
|
-
# unless a machine feeds it otherwise, and 0 for a pin held still.
|
|
66
|
-
def initialize(start: 0, peripheral: nil, model: :mos6526, region: Region::PAL, tod_hz: nil)
|
|
67
|
-
raise ArgumentError, "unknown CIA model #{model}" unless MODELS.include?(model)
|
|
68
|
-
|
|
69
|
-
addressable_at(start, length: 2**8)
|
|
70
|
-
|
|
71
|
-
@model = model
|
|
72
|
-
@clock_hz = region.clock_hz
|
|
73
|
-
@mains_hz = tod_hz || region.mains_hz
|
|
74
|
-
|
|
75
|
-
@peripheral = peripheral
|
|
76
|
-
@port_b4_handler = nil
|
|
77
|
-
@port_a_handler = nil
|
|
78
|
-
@port_b4_high = true
|
|
79
|
-
reset!
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
# The RES line: ports back to inputs, timers stopped with their latches
|
|
83
|
-
# full, interrupts masked and the TOD clock stopped at 1:00:00.0. The
|
|
84
|
-
# PB4 level carries over and is resampled on the next cycle.
|
|
85
|
-
def reset!
|
|
86
|
-
@data_port_a = 0x00
|
|
87
|
-
@data_port_b = 0x00
|
|
88
|
-
@data_dir_a = 0x00
|
|
89
|
-
@data_dir_b = 0x00
|
|
90
|
-
@port_b4_driven_high = true
|
|
91
|
-
@cnt_high = true
|
|
92
|
-
@cnt_rise = false
|
|
93
|
-
@tod = TimeOfDay.new(clock_hz: @clock_hz, mains_hz: @mains_hz)
|
|
94
|
-
@icr = InterruptRegister.new(@model)
|
|
95
|
-
@icr_status = @icr.status
|
|
96
|
-
@control_a = ControlRegister.new(%i[start output out_mode run_mode load
|
|
97
|
-
in_mode serial_mode clock_frequency])
|
|
98
|
-
@control_b = ControlRegister.new(%i[start output out_mode run_mode load
|
|
99
|
-
in_cnt in_timer_a alarm])
|
|
100
|
-
@ta = Timer.new(@control_a)
|
|
101
|
-
@tb = Timer.new(@control_b)
|
|
102
|
-
@serial = Serial.new(@control_a)
|
|
103
|
-
@port_a_handler&.call
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
# Register a change handler on the PB4 line. On CIA 1, this feeds the
|
|
107
|
-
# light pen input.
|
|
108
|
-
def on_port_b4_change(&handler)
|
|
109
|
-
@port_b4_handler = handler
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
# Register a handler for writes that can move port A's lines: to the
|
|
113
|
-
# data register or DDR, and the reset. On CIA 2, this tells the drives
|
|
114
|
-
# on the serial bus that the C64 may have moved a line.
|
|
115
|
-
def on_port_a_write(&handler)
|
|
116
|
-
@port_a_handler = handler
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
# A falling edge on the FLAG pin. On CIA 1 the datasette's tape read
|
|
120
|
-
# line drives it, on CIA 2 the serial bus SRQ.
|
|
121
|
-
def flag! = raise_interrupt(:flag)
|
|
122
|
-
|
|
123
|
-
def interrupted? = @icr_status.value >= 0x80
|
|
124
|
-
|
|
125
|
-
def cycle!
|
|
126
|
-
@icr.cycle! unless @icr.quiet
|
|
127
|
-
refresh_port_b4 if @port_b4_handler
|
|
128
|
-
level = @serial.cnt
|
|
129
|
-
level == @cnt_high ? @cnt_rise = false : cnt_edge(level)
|
|
130
|
-
underflowed = update_timers
|
|
131
|
-
@serial.cycle!(underflowed) { trigger_serial } if underflowed || !@serial.idle
|
|
132
|
-
@tod.cycle! { trigger_alarm }
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
def read_port_a
|
|
136
|
-
lines = driven_lines(@data_port_a, @data_dir_a)
|
|
137
|
-
return lines unless peripheral
|
|
138
|
-
|
|
139
|
-
lines & peripheral.read_a(lines, driven_lines(@data_port_b, @data_dir_b))
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
# Port A as driven by the data/direction registers alone, without
|
|
143
|
-
# peripheral pulldown. Cheap path for the VIC bank lookup.
|
|
144
|
-
def port_a_lines = driven_lines(@data_port_a, @data_dir_a)
|
|
145
|
-
|
|
146
|
-
# Port B as driven by the data/direction registers alone.
|
|
147
|
-
def port_b_lines = driven_lines(@data_port_b, @data_dir_b)
|
|
148
|
-
|
|
149
|
-
def read_port_b
|
|
150
|
-
lines = driven_lines(@data_port_b, @data_dir_b)
|
|
151
|
-
lines &= peripheral.read_b(driven_lines(@data_port_a, @data_dir_a), lines) if peripheral
|
|
152
|
-
apply_timer_output(lines)
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
def peek(addr)
|
|
156
|
-
case offset_of(addr) & 0x0f
|
|
157
|
-
when 0x00 then read_port_a
|
|
158
|
-
when 0x01 then read_port_b
|
|
159
|
-
when 0x02 then @data_dir_a
|
|
160
|
-
when 0x03 then @data_dir_b
|
|
161
|
-
when 0x04 then low_byte(@ta.counter)
|
|
162
|
-
when 0x05 then high_byte(@ta.counter)
|
|
163
|
-
when 0x06 then low_byte(@tb.counter)
|
|
164
|
-
when 0x07 then high_byte(@tb.counter)
|
|
165
|
-
when 0x08 then @tod.tenths
|
|
166
|
-
when 0x09 then @tod.seconds
|
|
167
|
-
when 0x0a then @tod.minutes
|
|
168
|
-
when 0x0b then @tod.hours
|
|
169
|
-
when 0x0c then @serial.data
|
|
170
|
-
when 0x0d then @icr.read
|
|
171
|
-
when 0x0e then control_a.value
|
|
172
|
-
when 0x0f then control_b.value
|
|
173
|
-
end
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
def poke(addr, value)
|
|
177
|
-
case offset_of(addr) & 0x0f
|
|
178
|
-
when 0x00 then update_port_a { @data_port_a = value }
|
|
179
|
-
when 0x01 then update_port_b { @data_port_b = value }
|
|
180
|
-
when 0x02 then update_port_a { @data_dir_a = value }
|
|
181
|
-
when 0x03 then update_port_b { @data_dir_b = value }
|
|
182
|
-
when 0x04 then @ta.write_latch_low(value)
|
|
183
|
-
when 0x05 then @ta.write_latch_high(value)
|
|
184
|
-
when 0x06 then @tb.write_latch_low(value)
|
|
185
|
-
when 0x07 then @tb.write_latch_high(value)
|
|
186
|
-
when 0x08 then @tod.write(:tenths, value, alarm: control_b.alarm?)
|
|
187
|
-
when 0x09 then @tod.write(:seconds, value, alarm: control_b.alarm?)
|
|
188
|
-
when 0x0a then @tod.write(:minutes, value, alarm: control_b.alarm?)
|
|
189
|
-
when 0x0b then @tod.write_hours(value, alarm: control_b.alarm?)
|
|
190
|
-
when 0x0c then @serial.write(value)
|
|
191
|
-
when 0x0d then @icr.write(value)
|
|
192
|
-
when 0x0e then write_control_a(value)
|
|
193
|
-
when 0x0f then @tb.write_control(value)
|
|
194
|
-
end
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
private
|
|
198
|
-
|
|
199
|
-
def update_port_a
|
|
200
|
-
yield
|
|
201
|
-
@port_a_handler&.call
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
def update_port_b
|
|
205
|
-
yield
|
|
206
|
-
@port_b4_driven_high = driven_lines(@data_port_b, @data_dir_b).anybits?(0x10)
|
|
207
|
-
refresh_port_b4 if @port_b4_handler
|
|
208
|
-
end
|
|
209
|
-
|
|
210
|
-
# PB4 is also control port 1's fire line, and a peripheral pulls it low
|
|
211
|
-
# without any register write, so the level is resampled every cycle rather
|
|
212
|
-
# than only after a poke.
|
|
213
|
-
def refresh_port_b4
|
|
214
|
-
high = @port_b4_driven_high && (peripheral.nil? || peripheral.port_b4_high?)
|
|
215
|
-
return if high == @port_b4_high
|
|
216
|
-
|
|
217
|
-
@port_b4_high = high
|
|
218
|
-
@port_b4_handler.call(high)
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
def driven_lines(register, direction)
|
|
222
|
-
# Output bits are driven from the data register; input bits float high.
|
|
223
|
-
# External peripherals can still pull any line low (wired-AND).
|
|
224
|
-
(register & direction) | (~direction & 0xff)
|
|
225
|
-
end
|
|
226
|
-
|
|
227
|
-
def apply_timer_output(value)
|
|
228
|
-
value = with_bit(value, 6, @ta.output?) if control_a.output?
|
|
229
|
-
value = with_bit(value, 7, @tb.output?) if control_b.output?
|
|
230
|
-
value
|
|
231
|
-
end
|
|
232
|
-
|
|
233
|
-
def with_bit(value, bit, set)
|
|
234
|
-
set ? value | (1 << bit) : value & ~(1 << bit)
|
|
235
|
-
end
|
|
236
|
-
|
|
237
|
-
def trigger_alarm = raise_interrupt(:alarm)
|
|
238
|
-
def trigger_serial = raise_interrupt(:serial)
|
|
239
|
-
|
|
240
|
-
def raise_interrupt(source) = @icr.flag(source)
|
|
241
|
-
|
|
242
|
-
# CNT is sampled once a cycle. When the serial port drives it from this
|
|
243
|
-
# cycle's timer A underflow, the new level is picked up on the next one.
|
|
244
|
-
def cnt_edge(level)
|
|
245
|
-
@cnt_high = level
|
|
246
|
-
@cnt_rise = level
|
|
247
|
-
@serial.rising_edge! { trigger_serial } if level
|
|
248
|
-
end
|
|
249
|
-
|
|
250
|
-
# Returns whether timer A underflowed, which clocks the serial port.
|
|
251
|
-
#
|
|
252
|
-
# CRB bits 6-5 pick timer B's source: ø2, CNT edges, timer A
|
|
253
|
-
# underflows, or timer A underflows gated by the CNT level. Every source
|
|
254
|
-
# drives the same count-enable line, so a cascaded underflow goes through
|
|
255
|
-
# the input pipeline exactly as a CNT edge does.
|
|
256
|
-
def update_timers
|
|
257
|
-
@ta.cycle!(@control_a.value & 0x20 == 0x20 ? @cnt_rise : true)
|
|
258
|
-
underflowed = @ta.underflowed
|
|
259
|
-
@tb.cycle!(
|
|
260
|
-
case @control_b.value & 0x60
|
|
261
|
-
when 0x00 then true
|
|
262
|
-
when 0x20 then @cnt_rise
|
|
263
|
-
when 0x40 then underflowed
|
|
264
|
-
else underflowed && @cnt_high
|
|
265
|
-
end
|
|
266
|
-
)
|
|
267
|
-
@icr.flag(:timer_a) if underflowed
|
|
268
|
-
@icr.timer_b_underflow! if @tb.underflowed
|
|
269
|
-
underflowed
|
|
270
|
-
end
|
|
271
|
-
|
|
272
|
-
def write_control_a(value)
|
|
273
|
-
was_output = control_a.serial_mode?
|
|
274
|
-
@ta.write_control(value)
|
|
275
|
-
@serial.reset! { trigger_serial } if control_a.serial_mode? != was_output
|
|
276
|
-
@tod.fifty_hz = control_a.clock_frequency?
|
|
277
|
-
end
|
|
278
|
-
end
|
|
279
|
-
end
|
data/lib/badline/color_memory.rb
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
# Colour RAM is four bits wide. A CPU read takes the upper nibble off the
|
|
5
|
-
# open data bus, which still holds the byte the VIC fetched in phi1.
|
|
6
|
-
class ColorMemory < Memory
|
|
7
|
-
def initialize(vic, start: 0xd800, length: 2**10)
|
|
8
|
-
super(start:, length:)
|
|
9
|
-
@vic = vic
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def peek(addr)
|
|
13
|
-
(@vic.phi1_data & 0xf0) | @storage[offset_of(addr)]
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def poke(addr, value)
|
|
17
|
-
super(addr, value & 0x0f)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
# The four bits the cell stores, as the VIC's c-access sees them.
|
|
21
|
-
def nibble(addr)
|
|
22
|
-
@storage[offset_of(addr)]
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Computer
|
|
5
|
-
# The LOAD, SAVE and serial traps on the KERNAL a KernalTrap::Layout
|
|
6
|
-
# describes, which serve the disk in device 8 (Attachments#mount).
|
|
7
|
-
module KernalTraps
|
|
8
|
-
private
|
|
9
|
-
|
|
10
|
-
def install_kernal_traps(layout)
|
|
11
|
-
@trap_layout = layout
|
|
12
|
-
load_trap = KernalTrap::Load.new(cpu:, bus: address_bus, layout:, drive: @drive)
|
|
13
|
-
cpu.install_trap(layout.load) { load_trap.call }
|
|
14
|
-
@serial_trap = KernalTrap::Serial.new(cpu:, bus: address_bus, layout:, drive: @drive,
|
|
15
|
-
device: serial_trap_device).install
|
|
16
|
-
save_trap = @save_trap = KernalTrap::Save.new(cpu:, bus: address_bus, layout:, drive: @drive)
|
|
17
|
-
cpu.install_trap(layout.save) { save_trap.call }
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def remove_kernal_traps
|
|
21
|
-
cpu.remove_trap(@trap_layout.load)
|
|
22
|
-
cpu.remove_trap(@trap_layout.save)
|
|
23
|
-
@serial_trap.uninstall
|
|
24
|
-
@serial_trap = nil
|
|
25
|
-
@save_trap = nil
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
# CIA 1's control ports and the keyboard matrix that spans them.
|
|
5
|
-
#
|
|
6
|
-
# Port A carries the matrix rows together with joystick 2, port B the matrix
|
|
7
|
-
# columns together with joystick 1. Every switch is active low, so the
|
|
8
|
-
# joysticks are wired-AND onto the lines *before* the matrix settles: a stick
|
|
9
|
-
# held in a direction selects rows and columns of its own, which is where
|
|
10
|
-
# hardware's phantom keypresses come from. Paddles and a 1351 mouse have
|
|
11
|
-
# buttons on those same lines.
|
|
12
|
-
#
|
|
13
|
-
# The ports also carry SID's POTX/POTY lines, which reach them through analog
|
|
14
|
-
# switches closed by CIA 1 PA6 (port 1) and PA7 (port 2). Close both and the
|
|
15
|
-
# pots sit in parallel, so SID charges through the lower of the two
|
|
16
|
-
# resistances; close neither and the lines float high. Reading a pot asks the
|
|
17
|
-
# CIA for the current select lines, since a program sets them and then goes
|
|
18
|
-
# straight to SID without touching the ports again.
|
|
19
|
-
#
|
|
20
|
-
# A matrix may have rows beyond port A's eight. Their select lines come from
|
|
21
|
-
# outside the CIA and are pushed into +extra_rows+, bit 0 for the ninth row
|
|
22
|
-
# upwards, active low like port A; idle, every line is high and none of
|
|
23
|
-
# those rows is selected. They settle with port A's lines as rows 8 and up,
|
|
24
|
-
# so their keys reach port B, but port A reads only its own eight.
|
|
25
|
-
class ControlPorts
|
|
26
|
-
PORT1_POTS = 0x40
|
|
27
|
-
PORT2_POTS = 0x80
|
|
28
|
-
FIRE = 0x10
|
|
29
|
-
|
|
30
|
-
attr_reader :keyboard, :joystick1, :joystick2
|
|
31
|
-
attr_accessor :device1, :device2, :port_a_source, :extra_rows
|
|
32
|
-
|
|
33
|
-
def initialize(keyboard:, joystick1:, joystick2:)
|
|
34
|
-
@keyboard = keyboard
|
|
35
|
-
@joystick1 = joystick1
|
|
36
|
-
@joystick2 = joystick2
|
|
37
|
-
@device1 = nil
|
|
38
|
-
@device2 = nil
|
|
39
|
-
@port_a_source = nil
|
|
40
|
-
@extra_rows = 0xff
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def read_a(port_a, port_b) = scan(port_a, port_b).first & 0xff
|
|
44
|
-
|
|
45
|
-
def read_b(port_a, port_b) = scan(port_a, port_b).last
|
|
46
|
-
|
|
47
|
-
# Control port 1 pin 6 is both the port B fire line and the VIC's light
|
|
48
|
-
# pen input, so joystick 1's button and a 1351's left button latch
|
|
49
|
-
# $D013/$D014. The CIA samples this every cycle, so it skips the matrix and
|
|
50
|
-
# asks only what the port's own devices drive.
|
|
51
|
-
def port_b4_high? = port_bits(@joystick1, @device1).anybits?(FIRE)
|
|
52
|
-
|
|
53
|
-
def pot_x = selected_devices.map(&:pot_x).min || 0xff
|
|
54
|
-
|
|
55
|
-
def pot_y = selected_devices.map(&:pot_y).min || 0xff
|
|
56
|
-
|
|
57
|
-
private
|
|
58
|
-
|
|
59
|
-
def selected_devices
|
|
60
|
-
lines = @port_a_source&.port_a_lines || 0x00
|
|
61
|
-
devices = []
|
|
62
|
-
devices << @device1 if @device1 && lines.anybits?(PORT1_POTS)
|
|
63
|
-
devices << @device2 if @device2 && lines.anybits?(PORT2_POTS)
|
|
64
|
-
devices
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def scan(port_a, port_b)
|
|
68
|
-
keyboard.scan((port_a & port_bits(@joystick2, @device2)) | (@extra_rows << 8),
|
|
69
|
-
port_b & port_bits(@joystick1, @device1))
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def port_bits(joystick, device)
|
|
73
|
-
device ? joystick.port_bits & device.port_bits : joystick.port_bits
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
end
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class CPU
|
|
5
|
-
# Steps that read an instruction's operand bytes and work out the
|
|
6
|
-
# address it operates on, which they leave in @address. Also the
|
|
7
|
-
# single-step implied, accumulator and immediate instructions, and JMP.
|
|
8
|
-
module Addressing
|
|
9
|
-
private
|
|
10
|
-
|
|
11
|
-
def op_implied_dummy
|
|
12
|
-
@memory.peek(@program_counter)
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def op_implied_exec
|
|
16
|
-
@memory.peek(@program_counter)
|
|
17
|
-
send(@operation, nil, nil)
|
|
18
|
-
end_instruction
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def op_accumulator_exec
|
|
22
|
-
@memory.peek(@program_counter)
|
|
23
|
-
send(@operation, :accumulator, @a)
|
|
24
|
-
end_instruction
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def op_immediate_read
|
|
28
|
-
value = @memory.peek(@program_counter)
|
|
29
|
-
@program_counter = (@program_counter + 1) & 0xffff
|
|
30
|
-
send(@operation, nil, value)
|
|
31
|
-
end_instruction
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def op_zp
|
|
35
|
-
@address = @memory.peek(@program_counter)
|
|
36
|
-
@program_counter = (@program_counter + 1) & 0xffff
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def op_zp_x
|
|
40
|
-
@memory.peek(@address)
|
|
41
|
-
@address = (@address + @x) & 0xff
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def op_zp_y
|
|
45
|
-
@memory.peek(@address)
|
|
46
|
-
@address = (@address + @y) & 0xff
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def op_abs_low
|
|
50
|
-
@address = @memory.peek(@program_counter)
|
|
51
|
-
@program_counter = (@program_counter + 1) & 0xffff
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def op_abs_high
|
|
55
|
-
@address |= @memory.peek(@program_counter) << 8
|
|
56
|
-
@program_counter = (@program_counter + 1) & 0xffff
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def op_abs_high_x
|
|
60
|
-
high = @memory.peek(@program_counter)
|
|
61
|
-
@program_counter = (@program_counter + 1) & 0xffff
|
|
62
|
-
index_address(high, @x)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def op_abs_high_y
|
|
66
|
-
high = @memory.peek(@program_counter)
|
|
67
|
-
@program_counter = (@program_counter + 1) & 0xffff
|
|
68
|
-
index_address(high, @y)
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def op_idx_dummy
|
|
72
|
-
@memory.peek(@dummy_address)
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def op_zp_pointer
|
|
76
|
-
@pointer = @memory.peek(@program_counter)
|
|
77
|
-
@program_counter = (@program_counter + 1) & 0xffff
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def op_pointer_x
|
|
81
|
-
@memory.peek(@pointer)
|
|
82
|
-
@pointer = (@pointer + @x) & 0xff
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def op_pointer_low
|
|
86
|
-
@address = @memory.peek(@pointer)
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def op_pointer_high
|
|
90
|
-
@address |= @memory.peek((@pointer + 1) & 0xff) << 8
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def op_pointer_high_y
|
|
94
|
-
index_address(@memory.peek((@pointer + 1) & 0xff), @y)
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
def op_jmp_high
|
|
98
|
-
@program_counter = @address | (@memory.peek(@program_counter) << 8)
|
|
99
|
-
end_instruction
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def op_indirect_low
|
|
103
|
-
@pointer = @address
|
|
104
|
-
@address = @memory.peek(@pointer)
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
# The pointer's high byte never increments, so JMP ($30FF) reads its
|
|
108
|
-
# target's high byte from $3000, not $3100.
|
|
109
|
-
def op_indirect_high
|
|
110
|
-
high = @memory.peek((@pointer & 0xff00) | ((@pointer + 1) & 0xff))
|
|
111
|
-
@program_counter = @address | (high << 8)
|
|
112
|
-
end_instruction
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
# Adds an index register to a base address. The 6502 adds to the low
|
|
116
|
-
# byte first and spends the next cycle reading from that address,
|
|
117
|
-
# before the carry reaches the high byte. Read instructions skip that
|
|
118
|
-
# cycle when there is no carry.
|
|
119
|
-
def index_address(high, index)
|
|
120
|
-
low = @address
|
|
121
|
-
@address = (((high << 8) | low) + index) & 0xffff
|
|
122
|
-
@boundary_crossed = (low + index) > 0xff
|
|
123
|
-
if @optional_dummy && !@boundary_crossed
|
|
124
|
-
@index += 1
|
|
125
|
-
else
|
|
126
|
-
@dummy_address = (high << 8) | ((low + index) & 0xff)
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
|
-
end
|
data/lib/badline/cpu/boundary.rb
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class CPU
|
|
5
|
-
# The steps at an instruction boundary: the opcode fetch that starts
|
|
6
|
-
# an instruction, and the ends of one.
|
|
7
|
-
module Boundary
|
|
8
|
-
private
|
|
9
|
-
|
|
10
|
-
# The first cycle of every instruction. Starts an interrupt if one was
|
|
11
|
-
# pending when the previous instruction ended. Otherwise reads the
|
|
12
|
-
# opcode and switches to its plan.
|
|
13
|
-
def op_fetch
|
|
14
|
-
return start_interrupt if @boundary_nmi || @boundary_irq
|
|
15
|
-
|
|
16
|
-
run_traps
|
|
17
|
-
opcode = @memory.peek(@program_counter)
|
|
18
|
-
log(opcode) if @debug
|
|
19
|
-
micro = MICROCODE[opcode]
|
|
20
|
-
@operation = micro.operation
|
|
21
|
-
@plan = micro.plan
|
|
22
|
-
@writes = micro.writes
|
|
23
|
-
@optional_dummy = micro.optional_dummy
|
|
24
|
-
@index = 1
|
|
25
|
-
@boundary_crossed = false
|
|
26
|
-
@program_counter = (@program_counter + 1) & 0xffff
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def end_instruction
|
|
30
|
-
@instructions += 1
|
|
31
|
-
end_sequence
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# Makes the next cycle an opcode fetch, and saves the pending interrupt
|
|
35
|
-
# flags for op_fetch. The next cycle polls before op_fetch runs, which
|
|
36
|
-
# updates the live flags.
|
|
37
|
-
def end_sequence
|
|
38
|
-
@plan = FETCH_PLAN
|
|
39
|
-
@writes = FETCH_WRITES
|
|
40
|
-
@index = 0
|
|
41
|
-
@boundary_irq = @irq_pending
|
|
42
|
-
@boundary_nmi = @nmi_pending
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def log(opcode)
|
|
46
|
-
instruction = Instruction.find(opcode)
|
|
47
|
-
puts(
|
|
48
|
-
"#{@cycles}: PC: #{format16(@program_counter)} - " \
|
|
49
|
-
"#{instruction.name.upcase} #{instruction.addressing_mode}"
|
|
50
|
-
)
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|