badline 0.12.1 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +66 -1
- data/CLAUDE.md +86 -38
- data/CONTRIBUTING.md +4 -3
- data/README.md +9 -6
- data/doc/library.md +9 -9
- data/doc/media.md +2 -1
- data/doc/pinned-behaviour.md +134 -105
- data/doc/snapshot-format.md +1047 -0
- data/doc/snapshots.md +73 -43
- data/lib/badline/audio/bare_player.rb +53 -20
- data/lib/badline/audio/cli.rb +6 -6
- data/lib/badline/audio/jukebox.rb +2 -2
- data/lib/badline/audio/machine_player.rb +16 -10
- data/lib/badline/{media → audio}/queue.rb +1 -1
- data/lib/badline/audio/queued_tune.rb +6 -6
- data/lib/badline/audio/renderer.rb +33 -22
- data/lib/badline/audio/stereo.rb +1 -1
- data/lib/badline/c128/banks.rb +6 -3
- data/lib/badline/c128/bus/keyed_state.rb +45 -0
- data/lib/badline/c128/bus.rb +35 -20
- data/lib/badline/c128/color_lines.rb +2 -2
- data/lib/badline/c128/cpu.rb +1 -1
- data/lib/badline/c128/drives.rb +14 -34
- data/lib/badline/c128/fast_serial.rb +5 -5
- data/lib/badline/c128/keyed_modules.rb +117 -0
- data/lib/badline/c128/keyed_state.rb +91 -0
- data/lib/badline/c128/keys.rb +9 -0
- data/lib/badline/c128/mmu.rb +9 -8
- data/lib/badline/c128/mmu_pages.rb +21 -1
- data/lib/badline/c128/modes.rb +21 -11
- data/lib/badline/c128/z80.rb +2 -2
- data/lib/badline/c128/z80_turns.rb +1 -1
- data/lib/badline/c128.rb +21 -16
- data/lib/badline/c64/attachments.rb +42 -0
- data/lib/badline/c64/banked_ram/banking.rb +32 -0
- data/lib/badline/c64/banked_ram/plus256k.rb +64 -0
- data/lib/badline/c64/banked_ram/plus60k.rb +47 -0
- data/lib/badline/c64/banked_ram/unexpanded.rb +30 -0
- data/lib/badline/c64/banked_ram.rb +23 -0
- data/lib/badline/c64/bus/debug_register.rb +32 -0
- data/lib/badline/c64/bus/extra_sids.rb +32 -0
- data/lib/badline/c64/bus/fittings.rb +40 -0
- data/lib/badline/c64/bus/keyed_state.rb +41 -0
- data/lib/badline/c64/bus/pla.rb +149 -0
- data/lib/badline/c64/bus/roms.rb +41 -0
- data/lib/badline/c64/bus/sid_slots.rb +44 -0
- data/lib/badline/c64/bus.rb +219 -0
- data/lib/badline/c64/cartridge/action_replay.rb +115 -0
- data/lib/badline/c64/cartridge/atomic_power.rb +26 -0
- data/lib/badline/c64/cartridge/bank.rb +83 -0
- data/lib/badline/c64/cartridge/comal80.rb +52 -0
- data/lib/badline/c64/cartridge/dinamic.rb +36 -0
- data/lib/badline/c64/cartridge/easy_flash.rb +132 -0
- data/lib/badline/c64/cartridge/epyx_fastload.rb +73 -0
- data/lib/badline/c64/cartridge/final_cartridge3.rb +79 -0
- data/lib/badline/c64/cartridge/flash.rb +279 -0
- data/lib/badline/c64/cartridge/freezer.rb +35 -0
- data/lib/badline/c64/cartridge/fun_play.rb +40 -0
- data/lib/badline/c64/cartridge/g_mod2.rb +64 -0
- data/lib/badline/c64/cartridge/game_system.rb +42 -0
- data/lib/badline/c64/cartridge/geo_ram.rb +65 -0
- data/lib/badline/c64/cartridge/kcs_power.rb +69 -0
- data/lib/badline/c64/cartridge/keyed_state.rb +393 -0
- data/lib/badline/c64/cartridge/mach5.rb +34 -0
- data/lib/badline/c64/cartridge/magic_desk.rb +32 -0
- data/lib/badline/c64/cartridge/ocean.rb +37 -0
- data/lib/badline/c64/cartridge/pagefox.rb +60 -0
- data/lib/badline/c64/cartridge/retro_replay.rb +278 -0
- data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
- data/lib/badline/c64/cartridge/rgcd.rb +50 -0
- data/lib/badline/c64/cartridge/simons_basic.rb +37 -0
- data/lib/badline/c64/cartridge/standard.rb +17 -0
- data/lib/badline/c64/cartridge/super_games.rb +40 -0
- data/lib/badline/c64/cartridge/westermann.rb +32 -0
- data/lib/badline/c64/cartridge/zaxxon.rb +52 -0
- data/lib/badline/c64/cartridge.rb +232 -0
- data/lib/badline/c64/color_memory.rb +27 -0
- data/lib/badline/{computer → c64}/common.rb +2 -2
- data/lib/badline/{computer → c64}/kernal_traps.rb +39 -36
- data/lib/badline/c64/keyed_modules.rb +111 -0
- data/lib/badline/c64/keyed_state.rb +68 -0
- data/lib/badline/c64/reu/dma.rb +271 -0
- data/lib/badline/c64/reu/keyed_state.rb +140 -0
- data/lib/badline/c64/reu/ram.rb +94 -0
- data/lib/badline/c64/reu/trigger.rb +34 -0
- data/lib/badline/c64/reu.rb +289 -0
- data/lib/badline/c64/true_drives.rb +120 -0
- data/lib/badline/{computer.rb → c64.rb} +24 -15
- data/lib/badline/chips/cia/fast_forward.rb +62 -0
- data/lib/badline/chips/cia/interrupt_register.rb +128 -0
- data/lib/badline/chips/cia/keyed_parts.rb +213 -0
- data/lib/badline/chips/cia/serial.rb +246 -0
- data/lib/badline/chips/cia/time_of_day.rb +210 -0
- data/lib/badline/chips/cia/timer.rb +188 -0
- data/lib/badline/chips/cia.rb +281 -0
- data/lib/badline/chips/cpu/addressing.rb +133 -0
- data/lib/badline/chips/cpu/boundary.rb +56 -0
- data/lib/badline/chips/cpu/core.rb +183 -0
- data/lib/badline/chips/cpu/instruction.rb +338 -0
- data/lib/badline/chips/cpu/instruction_set/arithmetic.rb +118 -0
- data/lib/badline/chips/cpu/instruction_set/bitwise.rb +130 -0
- data/lib/badline/chips/cpu/instruction_set/branch.rb +83 -0
- data/lib/badline/chips/cpu/instruction_set/flag.rb +67 -0
- data/lib/badline/chips/cpu/instruction_set/illegal.rb +274 -0
- data/lib/badline/chips/cpu/instruction_set/inc_dec.rb +73 -0
- data/lib/badline/chips/cpu/instruction_set/stack.rb +56 -0
- data/lib/badline/chips/cpu/instruction_set/transfer.rb +141 -0
- data/lib/badline/chips/cpu/instruction_set.rb +59 -0
- data/lib/badline/chips/cpu/interrupts.rb +108 -0
- data/lib/badline/chips/cpu/keyed_state.rb +177 -0
- data/lib/badline/chips/cpu/microcode.rb +195 -0
- data/lib/badline/chips/cpu/operations.rb +90 -0
- data/lib/badline/chips/cpu/port.rb +133 -0
- data/lib/badline/chips/cpu/stack_operations.rb +84 -0
- data/lib/badline/chips/cpu/traps.rb +23 -0
- data/lib/badline/chips/cpu.rb +17 -0
- data/lib/badline/chips/sid/catch_up.rb +122 -0
- data/lib/badline/chips/sid/decimator.rb +68 -0
- data/lib/badline/chips/sid/envelope.rb +236 -0
- data/lib/badline/chips/sid/filter.rb +227 -0
- data/lib/badline/chips/sid/keyed_parts.rb +286 -0
- data/lib/badline/chips/sid/voice.rb +69 -0
- data/lib/badline/chips/sid/waveform/combined.rb +128 -0
- data/lib/badline/chips/sid/waveform/fast_forward.rb +107 -0
- data/lib/badline/chips/sid/waveform/noise_writeback.rb +124 -0
- data/lib/badline/chips/sid/waveform.rb +305 -0
- data/lib/badline/chips/sid.rb +264 -0
- data/lib/badline/chips/ted/beam.rb +119 -0
- data/lib/badline/chips/ted/timers.rb +66 -0
- data/lib/badline/chips/ted.rb +143 -0
- data/lib/badline/chips/tia.rb +49 -0
- data/lib/badline/chips/vdc/keyed_parts.rb +105 -0
- data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
- data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -13
- data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -17
- data/lib/badline/{c128 → chips}/vdc/window.rb +1 -10
- data/lib/badline/{c128 → chips}/vdc.rb +6 -31
- data/lib/badline/chips/via/control_lines.rb +109 -0
- data/lib/badline/chips/via/fast_forward.rb +55 -0
- data/lib/badline/chips/via/interrupt_register.rb +60 -0
- data/lib/badline/chips/via/keyed_parts.rb +163 -0
- data/lib/badline/chips/via/shift_register.rb +168 -0
- data/lib/badline/chips/via/timer1.rb +120 -0
- data/lib/badline/chips/via/timer2.rb +117 -0
- data/lib/badline/chips/via.rb +267 -0
- data/lib/badline/chips/vic/bank.rb +135 -0
- data/lib/badline/chips/vic/border_mask.rb +78 -0
- data/lib/badline/chips/vic/collisions.rb +106 -0
- data/lib/badline/chips/vic/color_patches.rb +38 -0
- data/lib/badline/chips/vic/display_state.rb +168 -0
- data/lib/badline/chips/vic/graphics_mode.rb +166 -0
- data/lib/badline/chips/vic/graphics_shifter.rb +183 -0
- data/lib/badline/chips/vic/keyed_parts.rb +228 -0
- data/lib/badline/chips/vic/keyed_sprites.rb +225 -0
- data/lib/badline/chips/vic/keyed_state.rb +102 -0
- data/lib/badline/chips/vic/register_log.rb +65 -0
- data/lib/badline/chips/vic/registers.rb +188 -0
- data/lib/badline/chips/vic/sequencer.rb +275 -0
- data/lib/badline/chips/vic/sequencer_output.rb +118 -0
- data/lib/badline/chips/vic/sprite/internal_bus.rb +59 -0
- data/lib/badline/chips/vic/sprite/shifter.rb +148 -0
- data/lib/badline/chips/vic/sprite/timing.rb +58 -0
- data/lib/badline/chips/vic/sprite.rb +337 -0
- data/lib/badline/chips/vic/sprites.rb +281 -0
- data/lib/badline/chips/vic.rb +787 -0
- data/lib/badline/chips/vic_i/keyed_parts.rb +142 -0
- data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +2 -30
- data/lib/badline/chips/vic_i/sound/output.rb +85 -0
- data/lib/badline/chips/vic_i/sound.rb +227 -0
- data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
- data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +6 -6
- data/lib/badline/chips/z80/arithmetic.rb +119 -0
- data/lib/badline/chips/z80/bit_page.rb +57 -0
- data/lib/badline/chips/z80/block_io.rb +60 -0
- data/lib/badline/chips/z80/block_transfers.rb +61 -0
- data/lib/badline/chips/z80/bus_cycles.rb +113 -0
- data/lib/badline/chips/z80/core.rb +115 -0
- data/lib/badline/chips/z80/exchanges.rb +52 -0
- data/lib/badline/chips/z80/extended_page.rb +91 -0
- data/lib/badline/chips/z80/flags.rb +39 -0
- data/lib/badline/chips/z80/interrupt_acceptance.rb +48 -0
- data/lib/badline/chips/z80/jumps.rb +84 -0
- data/lib/badline/chips/z80/keyed_state.rb +73 -0
- data/lib/badline/chips/z80/loads.rb +100 -0
- data/lib/badline/chips/z80/main_page.rb +136 -0
- data/lib/badline/chips/z80/registers.rb +122 -0
- data/lib/badline/chips/z80/shifts.rb +66 -0
- data/lib/badline/chips/z80.rb +13 -0
- data/lib/badline/chips.rb +10 -0
- data/lib/badline/core.rb +13 -32
- data/lib/badline/drives/datasette/keyed_state.rb +38 -0
- data/lib/badline/drives/datasette.rb +173 -0
- data/lib/badline/drives/engine/core.rb +152 -0
- data/lib/badline/drives/engine/fast_serial.rb +75 -0
- data/lib/badline/drives/engine/idle.rb +127 -0
- data/lib/badline/drives/engine/idle_cpu.rb +30 -0
- data/lib/badline/drives/engine/orbit.rb +81 -0
- data/lib/badline/drives/engine/serial_lines.rb +72 -0
- data/lib/badline/drives/engine/sleep.rb +114 -0
- data/lib/badline/drives/engine/vias.rb +86 -0
- data/lib/badline/drives/engine/watch.rb +152 -0
- data/lib/badline/drives/engine.rb +11 -0
- data/lib/badline/drives/model1541/bus.rb +75 -0
- data/lib/badline/drives/model1541/byte_ready.rb +50 -0
- data/lib/badline/drives/model1541/cpu.rb +13 -0
- data/lib/badline/drives/model1541/disk.rb +318 -0
- data/lib/badline/drives/model1541/disk_via.rb +38 -0
- data/lib/badline/drives/model1541/gcr.rb +59 -0
- data/lib/badline/drives/model1541/keyed_state.rb +251 -0
- data/lib/badline/drives/model1541/mechanism.rb +313 -0
- data/lib/badline/drives/model1541/rotation.rb +123 -0
- data/lib/badline/drives/model1541/sector_reader.rb +78 -0
- data/lib/badline/drives/model1541/serial_port.rb +20 -0
- data/lib/badline/drives/model1541/track.rb +100 -0
- data/lib/badline/drives/model1541.rb +80 -0
- data/lib/badline/drives/model1571/bus.rb +100 -0
- data/lib/badline/drives/model1571/cpu.rb +13 -0
- data/lib/badline/drives/model1571/keyed_state.rb +108 -0
- data/lib/badline/drives/model1571/serial_port.rb +39 -0
- data/lib/badline/drives/model1571/serial_via.rb +27 -0
- data/lib/badline/drives/model1571/wd1770.rb +108 -0
- data/lib/badline/drives/model1571.rb +141 -0
- data/lib/badline/drives/model1581/bus.rb +126 -0
- data/lib/badline/drives/model1581/cpu.rb +13 -0
- data/lib/badline/drives/model1581/disk.rb +133 -0
- data/lib/badline/drives/model1581/keyed_state.rb +280 -0
- data/lib/badline/drives/model1581/mechanism.rb +98 -0
- data/lib/badline/drives/model1581/serial_port.rb +54 -0
- data/lib/badline/drives/model1581/slot.rb +61 -0
- data/lib/badline/drives/model1581/track.rb +102 -0
- data/lib/badline/drives/model1581/track_bytes.rb +77 -0
- data/lib/badline/drives/model1581/wd1772/registers.rb +91 -0
- data/lib/badline/drives/model1581/wd1772/sector_writes.rb +75 -0
- data/lib/badline/drives/model1581/wd1772/sectors.rb +152 -0
- data/lib/badline/drives/model1581/wd1772/stepping.rb +111 -0
- data/lib/badline/drives/model1581/wd1772/tracks.rb +127 -0
- data/lib/badline/drives/model1581/wd1772/turn.rb +75 -0
- data/lib/badline/drives/model1581/wd1772.rb +216 -0
- data/lib/badline/drives/model1581.rb +206 -0
- data/lib/badline/drives/serial_bus.rb +161 -0
- data/lib/badline/drives.rb +8 -0
- data/lib/badline/frontend/app.rb +3 -3
- data/lib/badline/frontend/boot.rb +4 -4
- data/lib/badline/frontend/controls.rb +19 -3
- data/lib/badline/frontend/drive_led.rb +44 -21
- data/lib/badline/frontend/machine_window.rb +3 -1
- data/lib/badline/frontend/menu/menu_dialogs.rb +2 -2
- data/lib/badline/frontend/player/filter_view.rb +1 -1
- data/lib/badline/frontend/player/player_controller.rb +2 -2
- data/lib/badline/frontend/player/player_screen.rb +1 -0
- data/lib/badline/frontend/player/theme.rb +7 -7
- data/lib/badline/frontend/snapshots.rb +12 -1
- data/lib/badline/frontend/timeline.rb +30 -12
- data/lib/badline/input/control_ports.rb +78 -0
- data/lib/badline/input/joystick.rb +27 -0
- data/lib/badline/input/keyboard.rb +114 -0
- data/lib/badline/input/matrix_typist.rb +98 -0
- data/lib/badline/input.rb +4 -0
- data/lib/badline/kernal_trap/chrout.rb +45 -0
- data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
- data/lib/badline/kernal_trap/dos/channel.rb +156 -0
- data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -26
- data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -10
- data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -9
- data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -19
- data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
- data/lib/badline/kernal_trap/{drive.rb → dos.rb} +9 -27
- data/lib/badline/kernal_trap/file_routine.rb +4 -4
- data/lib/badline/kernal_trap/keyed_state.rb +150 -0
- data/lib/badline/kernal_trap/layout.rb +75 -11
- data/lib/badline/kernal_trap/load.rb +19 -21
- data/lib/badline/kernal_trap/routine.rb +12 -0
- data/lib/badline/kernal_trap/save.rb +12 -22
- data/lib/badline/kernal_trap/serial.rb +8 -24
- data/lib/badline/kernal_trap.rb +3 -2
- data/lib/badline/machine/clocking.rb +1 -1
- data/lib/badline/machine/keyboard_buffer.rb +49 -0
- data/lib/badline/machine/settling.rb +29 -0
- data/lib/badline/machine.rb +10 -7
- data/lib/badline/media/boot_disk.rb +14 -2
- data/lib/badline/media/extensions.rb +10 -0
- data/lib/badline/media/true_drive.rb +1 -1
- data/lib/badline/media/tune.rb +2 -2
- data/lib/badline/media.rb +3 -3
- data/lib/badline/memory.rb +3 -6
- data/lib/badline/model.rb +1 -1
- data/lib/badline/options/family.rb +5 -2
- data/lib/badline/options/help.rb +42 -16
- data/lib/badline/options/table.rb +2 -0
- data/lib/badline/options/validation.rb +2 -0
- data/lib/badline/options.rb +6 -1
- data/lib/badline/plus4/acia.rb +45 -0
- data/lib/badline/plus4/bus.rb +312 -0
- data/lib/badline/plus4/cpu.rb +10 -0
- data/lib/badline/plus4/cpu_port.rb +93 -0
- data/lib/badline/plus4/keyboard_port.rb +51 -0
- data/lib/badline/plus4/model.rb +38 -0
- data/lib/badline/plus4/user_port.rb +31 -0
- data/lib/badline/plus4.rb +164 -0
- data/lib/badline/roms/README +44 -6
- data/lib/badline/roms/plus4/basic.rom +0 -0
- data/lib/badline/roms/plus4/function-high.rom +0 -0
- data/lib/badline/roms/plus4/function-low.rom +0 -0
- data/lib/badline/roms/plus4/kernal-ntsc.rom +0 -0
- data/lib/badline/roms/plus4/kernal-pal.rom +0 -0
- data/lib/badline/sdl.rb +1 -0
- data/lib/badline/{storage/sid_file.rb → sid_tune/file.rb} +3 -3
- data/lib/badline/{storage → sid_tune}/hvsc.rb +7 -7
- data/lib/badline/{storage → sid_tune}/song_lengths.rb +2 -2
- data/lib/badline/{storage → sid_tune}/stil/credit.rb +1 -1
- data/lib/badline/{storage → sid_tune}/stil.rb +3 -3
- data/lib/badline/sid_tune.rb +6 -0
- data/lib/badline/snapshot/c128_setup.rb +32 -0
- data/lib/badline/snapshot/c64_setup.rb +83 -0
- data/lib/badline/snapshot/container.rb +4 -0
- data/lib/badline/snapshot/field_doc/markdown.rb +112 -0
- data/lib/badline/snapshot/field_doc.rb +109 -0
- data/lib/badline/snapshot/image.rb +132 -46
- data/lib/badline/snapshot/keyed/cursor.rb +40 -0
- data/lib/badline/snapshot/keyed/modules.rb +66 -0
- data/lib/badline/snapshot/keyed/reader.rb +188 -0
- data/lib/badline/snapshot/keyed/recorder.rb +88 -0
- data/lib/badline/snapshot/keyed/report.rb +26 -0
- data/lib/badline/snapshot/keyed/writer.rb +55 -0
- data/lib/badline/snapshot/keyed.rb +64 -0
- data/lib/badline/snapshot/machine_state.rb +17 -64
- data/lib/badline/snapshot/storage_setup.rb +63 -0
- data/lib/badline/snapshot/vic20_setup.rb +28 -0
- data/lib/badline/snapshot/vice/c64_mem.rb +1 -1
- data/lib/badline/snapshot/vice/restore.rb +1 -1
- data/lib/badline/snapshot/vice/reu1764.rb +3 -3
- data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
- data/lib/badline/snapshot/vice.rb +13 -35
- data/lib/badline/snapshot.rb +44 -22
- data/lib/badline/storage/crt_file.rb +3 -1
- data/lib/badline/storage/d64_image.rb +0 -2
- data/lib/badline/storage/d71_image.rb +0 -2
- data/lib/badline/storage/d81_image.rb +0 -2
- data/lib/badline/storage/disk_image.rb +3 -6
- data/lib/badline/storage/g64_image.rb +10 -5
- data/lib/badline/storage/host_directory.rb +0 -5
- data/lib/badline/storage/t64.rb +2 -8
- data/lib/badline/storage/tap.rb +43 -15
- data/lib/badline/storage/unavailable.rb +1 -1
- data/lib/badline/storage.rb +0 -37
- data/lib/badline/support/c128_checkpoint.rb +39 -0
- data/lib/badline/support/checkpoint.rb +108 -0
- data/lib/badline/support/vic20_checkpoint.rb +38 -0
- data/lib/badline/support.rb +5 -0
- data/lib/badline/version.rb +1 -1
- data/lib/badline/vic20/attachments.rb +8 -5
- data/lib/badline/vic20/bus/keyed_state.rb +52 -0
- data/lib/badline/vic20/bus.rb +2 -25
- data/lib/badline/vic20/cpu.rb +1 -1
- data/lib/badline/vic20/keyed_modules.rb +73 -0
- data/lib/badline/vic20/keyed_state.rb +45 -0
- data/lib/badline/vic20/port_wiring.rb +4 -4
- data/lib/badline/vic20/user_via_ports.rb +2 -2
- data/lib/badline/vic20.rb +22 -17
- data/lib/badline.rb +1 -0
- metadata +271 -228
- data/lib/badline/address_bus/extra_sids.rb +0 -30
- data/lib/badline/address_bus/fittings.rb +0 -38
- data/lib/badline/address_bus/pla.rb +0 -147
- data/lib/badline/address_bus/roms.rb +0 -39
- data/lib/badline/address_bus/saved_state.rb +0 -66
- data/lib/badline/address_bus/sid_slots.rb +0 -42
- data/lib/badline/address_bus.rb +0 -216
- data/lib/badline/c128/bus_state.rb +0 -53
- data/lib/badline/c128/saved_state.rb +0 -143
- data/lib/badline/cartridge/action_replay.rb +0 -126
- data/lib/badline/cartridge/atomic_power.rb +0 -24
- data/lib/badline/cartridge/bank.rb +0 -81
- data/lib/badline/cartridge/comal80.rb +0 -50
- data/lib/badline/cartridge/dinamic.rb +0 -34
- data/lib/badline/cartridge/easy_flash.rb +0 -145
- data/lib/badline/cartridge/epyx_fastload.rb +0 -79
- data/lib/badline/cartridge/final_cartridge3.rb +0 -89
- data/lib/badline/cartridge/flash.rb +0 -306
- data/lib/badline/cartridge/freezer.rb +0 -33
- data/lib/badline/cartridge/fun_play.rb +0 -38
- data/lib/badline/cartridge/g_mod2.rb +0 -74
- data/lib/badline/cartridge/game_system.rb +0 -40
- data/lib/badline/cartridge/geo_ram.rb +0 -79
- data/lib/badline/cartridge/kcs_power.rb +0 -75
- data/lib/badline/cartridge/mach5.rb +0 -32
- data/lib/badline/cartridge/magic_desk.rb +0 -30
- data/lib/badline/cartridge/ocean.rb +0 -35
- data/lib/badline/cartridge/pagefox.rb +0 -68
- data/lib/badline/cartridge/retro_replay.rb +0 -320
- data/lib/badline/cartridge/rex_utility.rb +0 -29
- data/lib/badline/cartridge/rgcd.rb +0 -58
- data/lib/badline/cartridge/simons_basic.rb +0 -35
- data/lib/badline/cartridge/standard.rb +0 -15
- data/lib/badline/cartridge/super_games.rb +0 -48
- data/lib/badline/cartridge/westermann.rb +0 -30
- data/lib/badline/cartridge/zaxxon.rb +0 -66
- data/lib/badline/cartridge.rb +0 -303
- data/lib/badline/checkpoint.rb +0 -98
- data/lib/badline/chrout_trap.rb +0 -43
- data/lib/badline/cia/fast_forward.rb +0 -60
- data/lib/badline/cia/interrupt_register.rb +0 -143
- data/lib/badline/cia/serial.rb +0 -275
- data/lib/badline/cia/state.rb +0 -47
- data/lib/badline/cia/timer.rb +0 -206
- data/lib/badline/cia.rb +0 -279
- data/lib/badline/color_memory.rb +0 -25
- data/lib/badline/computer/attachments.rb +0 -88
- data/lib/badline/computer/saved_state.rb +0 -117
- data/lib/badline/computer/true_drives.rb +0 -69
- data/lib/badline/control_ports.rb +0 -76
- data/lib/badline/cpu/addressing.rb +0 -131
- data/lib/badline/cpu/boundary.rb +0 -54
- data/lib/badline/cpu/core.rb +0 -165
- data/lib/badline/cpu/microcode.rb +0 -177
- data/lib/badline/cpu/operations.rb +0 -88
- data/lib/badline/cpu/saved_state.rb +0 -115
- data/lib/badline/cpu/stack_operations.rb +0 -82
- data/lib/badline/cpu.rb +0 -10
- data/lib/badline/cpu_port.rb +0 -112
- data/lib/badline/datasette.rb +0 -161
- data/lib/badline/debug_register.rb +0 -28
- data/lib/badline/drive/core.rb +0 -147
- data/lib/badline/drive/fast_serial.rb +0 -73
- data/lib/badline/drive/idle.rb +0 -125
- data/lib/badline/drive/idle_cpu.rb +0 -28
- data/lib/badline/drive/orbit.rb +0 -79
- data/lib/badline/drive/serial_lines.rb +0 -73
- data/lib/badline/drive/sleep.rb +0 -112
- data/lib/badline/drive/vias.rb +0 -84
- data/lib/badline/drive/watch.rb +0 -150
- data/lib/badline/drive.rb +0 -11
- data/lib/badline/drive1541/bus.rb +0 -86
- data/lib/badline/drive1541/byte_ready.rb +0 -48
- data/lib/badline/drive1541/cpu.rb +0 -11
- data/lib/badline/drive1541/disk.rb +0 -315
- data/lib/badline/drive1541/disk_state.rb +0 -86
- data/lib/badline/drive1541/disk_via.rb +0 -36
- data/lib/badline/drive1541/gcr.rb +0 -57
- data/lib/badline/drive1541/mechanism.rb +0 -313
- data/lib/badline/drive1541/mechanism_state.rb +0 -68
- data/lib/badline/drive1541/rotation.rb +0 -121
- data/lib/badline/drive1541/sector_reader.rb +0 -76
- data/lib/badline/drive1541/serial_port.rb +0 -18
- data/lib/badline/drive1541/track.rb +0 -98
- data/lib/badline/drive1541.rb +0 -111
- data/lib/badline/drive1571/bus.rb +0 -111
- data/lib/badline/drive1571/cpu.rb +0 -11
- data/lib/badline/drive1571/serial_port.rb +0 -37
- data/lib/badline/drive1571/serial_via.rb +0 -25
- data/lib/badline/drive1571/wd1770.rb +0 -120
- data/lib/badline/drive1571.rb +0 -175
- data/lib/badline/drive1581/bus.rb +0 -137
- data/lib/badline/drive1581/cpu.rb +0 -11
- data/lib/badline/drive1581/disk.rb +0 -135
- data/lib/badline/drive1581/disk_state.rb +0 -87
- data/lib/badline/drive1581/mechanism.rb +0 -117
- data/lib/badline/drive1581/serial_port.rb +0 -52
- data/lib/badline/drive1581/slot.rb +0 -78
- data/lib/badline/drive1581/track.rb +0 -100
- data/lib/badline/drive1581/track_bytes.rb +0 -75
- data/lib/badline/drive1581/wd1772/registers.rb +0 -89
- data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
- data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
- data/lib/badline/drive1581/wd1772/state.rb +0 -66
- data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
- data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
- data/lib/badline/drive1581/wd1772/turn.rb +0 -73
- data/lib/badline/drive1581/wd1772.rb +0 -216
- data/lib/badline/drive1581.rb +0 -233
- data/lib/badline/iec_bus.rb +0 -159
- data/lib/badline/instruction.rb +0 -334
- data/lib/badline/instruction_set/arithmetic.rb +0 -114
- data/lib/badline/instruction_set/bitwise.rb +0 -126
- data/lib/badline/instruction_set/branch.rb +0 -79
- data/lib/badline/instruction_set/flag.rb +0 -63
- data/lib/badline/instruction_set/illegal.rb +0 -270
- data/lib/badline/instruction_set/inc_dec.rb +0 -69
- data/lib/badline/instruction_set/stack.rb +0 -52
- data/lib/badline/instruction_set/transfer.rb +0 -137
- data/lib/badline/instruction_set.rb +0 -55
- data/lib/badline/interrupts.rb +0 -104
- data/lib/badline/joystick.rb +0 -25
- data/lib/badline/kernal_trap/channel.rb +0 -181
- data/lib/badline/keyboard.rb +0 -112
- data/lib/badline/keyboard_buffer.rb +0 -33
- data/lib/badline/ram_expansion/banking.rb +0 -30
- data/lib/badline/ram_expansion/plus256k.rb +0 -54
- data/lib/badline/ram_expansion/plus60k.rb +0 -43
- data/lib/badline/ram_expansion/unexpanded.rb +0 -28
- data/lib/badline/ram_expansion.rb +0 -21
- data/lib/badline/reu/dma/saved_state.rb +0 -50
- data/lib/badline/reu/dma.rb +0 -273
- data/lib/badline/reu/ram.rb +0 -107
- data/lib/badline/reu/saved_state.rb +0 -80
- data/lib/badline/reu/trigger.rb +0 -32
- data/lib/badline/reu.rb +0 -289
- data/lib/badline/sid/catch_up.rb +0 -120
- data/lib/badline/sid/decimator.rb +0 -64
- data/lib/badline/sid/envelope/state.rb +0 -68
- data/lib/badline/sid/envelope.rb +0 -239
- data/lib/badline/sid/filter.rb +0 -263
- data/lib/badline/sid/voice.rb +0 -77
- data/lib/badline/sid/waveform/combined.rb +0 -126
- data/lib/badline/sid/waveform/fast_forward.rb +0 -105
- data/lib/badline/sid/waveform/noise_writeback.rb +0 -122
- data/lib/badline/sid/waveform/state.rb +0 -66
- data/lib/badline/sid/waveform.rb +0 -305
- data/lib/badline/sid.rb +0 -303
- data/lib/badline/snapshot/setup.rb +0 -75
- data/lib/badline/snapshot/state.rb +0 -189
- data/lib/badline/time_of_day.rb +0 -228
- data/lib/badline/traps.rb +0 -19
- data/lib/badline/via/control_lines.rb +0 -122
- data/lib/badline/via/fast_forward.rb +0 -53
- data/lib/badline/via/interrupt_register.rb +0 -67
- data/lib/badline/via/shift_register.rb +0 -180
- data/lib/badline/via/state.rb +0 -42
- data/lib/badline/via/timer1.rb +0 -131
- data/lib/badline/via/timer2.rb +0 -133
- data/lib/badline/via.rb +0 -266
- data/lib/badline/vic/bank.rb +0 -133
- data/lib/badline/vic/border_mask.rb +0 -86
- data/lib/badline/vic/collisions.rb +0 -115
- data/lib/badline/vic/color_patches.rb +0 -47
- data/lib/badline/vic/display_state.rb +0 -185
- data/lib/badline/vic/graphics_mode.rb +0 -164
- data/lib/badline/vic/graphics_shifter.rb +0 -207
- data/lib/badline/vic/register_log.rb +0 -81
- data/lib/badline/vic/registers.rb +0 -195
- data/lib/badline/vic/sequencer.rb +0 -275
- data/lib/badline/vic/sequencer_output.rb +0 -116
- data/lib/badline/vic/sequencer_state.rb +0 -89
- data/lib/badline/vic/sprite/internal_bus.rb +0 -68
- data/lib/badline/vic/sprite/saved_state.rb +0 -64
- data/lib/badline/vic/sprite/shifter.rb +0 -146
- data/lib/badline/vic/sprite/timing.rb +0 -56
- data/lib/badline/vic/sprite.rb +0 -337
- data/lib/badline/vic/sprites.rb +0 -282
- data/lib/badline/vic/sprites_state.rb +0 -57
- data/lib/badline/vic.rb +0 -853
- data/lib/badline/vic20/saved_state.rb +0 -124
- data/lib/badline/vic20/sound/output.rb +0 -83
- data/lib/badline/vic20/sound.rb +0 -233
- data/lib/badline/vic20/vic/saved_state.rb +0 -55
- data/lib/badline/z80/arithmetic.rb +0 -117
- data/lib/badline/z80/bit_page.rb +0 -55
- data/lib/badline/z80/block_io.rb +0 -58
- data/lib/badline/z80/block_transfers.rb +0 -59
- data/lib/badline/z80/bus_cycles.rb +0 -111
- data/lib/badline/z80/core.rb +0 -113
- data/lib/badline/z80/exchanges.rb +0 -50
- data/lib/badline/z80/extended_page.rb +0 -89
- data/lib/badline/z80/flags.rb +0 -37
- data/lib/badline/z80/interrupt_acceptance.rb +0 -46
- data/lib/badline/z80/jumps.rb +0 -82
- data/lib/badline/z80/loads.rb +0 -98
- data/lib/badline/z80/main_page.rb +0 -134
- data/lib/badline/z80/registers.rb +0 -120
- data/lib/badline/z80/saved_state.rb +0 -69
- data/lib/badline/z80/shifts.rb +0 -64
- data/lib/badline/z80.rb +0 -11
- /data/lib/badline/snapshot/{fields.rb → vice/fields.rb} +0 -0
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "badline/c64/reu/ram"
|
|
4
|
+
require "badline/c64/reu/dma"
|
|
5
|
+
require "badline/c64/reu/trigger"
|
|
6
|
+
require "badline/c64/reu/keyed_state"
|
|
7
|
+
|
|
8
|
+
module Badline
|
|
9
|
+
class C64
|
|
10
|
+
# A RAM Expansion Unit: the Commodore 1700 (128K), 1764 (256K) and 1750
|
|
11
|
+
# (512K), and the bigger units built around the same 8726 RAM Expansion
|
|
12
|
+
# Controller (REC), such as the CMD 1750XL, up to 16M.
|
|
13
|
+
#
|
|
14
|
+
# The REC's eleven registers sit in I/O 2 from $DF00, repeated every 32
|
|
15
|
+
# bytes up to $DFFF, as the 1764 and 1750 manuals map them. It moves
|
|
16
|
+
# bytes between the C64 and its RAM by DMA, one bus cycle each, with the
|
|
17
|
+
# CPU held off the bus. A command with the execute bit set starts a
|
|
18
|
+
# transfer, or with bit 4 clear arms the REC to start one on the next
|
|
19
|
+
# write to $FF00, so a program can bank the ROMs out first. A transfer
|
|
20
|
+
# waits for the CPU's next read cycle with BA high, and C64 then
|
|
21
|
+
# clocks it through #dma_cycle! until it hands the bus back.
|
|
22
|
+
class REU
|
|
23
|
+
SIZES_KB = [128, 256, 512, 1024, 2048, 4096, 8192, 16_384].freeze
|
|
24
|
+
|
|
25
|
+
# The registers, by offset.
|
|
26
|
+
STATUS = 0x00
|
|
27
|
+
COMMAND = 0x01
|
|
28
|
+
C64_LOW = 0x02
|
|
29
|
+
C64_HIGH = 0x03
|
|
30
|
+
EXPANSION_LOW = 0x04
|
|
31
|
+
EXPANSION_HIGH = 0x05
|
|
32
|
+
EXPANSION_BANK = 0x06
|
|
33
|
+
LENGTH_LOW = 0x07
|
|
34
|
+
LENGTH_HIGH = 0x08
|
|
35
|
+
INTERRUPT_MASK = 0x09
|
|
36
|
+
ADDRESS_CONTROL = 0x0a
|
|
37
|
+
|
|
38
|
+
# Status: an interrupt is pending, the block ended, a verify found a
|
|
39
|
+
# difference (the manual's fault bit), and the unit is built from 256K
|
|
40
|
+
# chips, which only the 1700 isn't. Reading the status clears the top
|
|
41
|
+
# three.
|
|
42
|
+
INTERRUPT_PENDING = 0x80
|
|
43
|
+
END_OF_BLOCK = 0x40
|
|
44
|
+
FAULT = 0x20
|
|
45
|
+
CHIPS_256K = 0x10
|
|
46
|
+
|
|
47
|
+
# Command: execute, reload the registers after the transfer, don't wait
|
|
48
|
+
# for $FF00, and the transfer type in the bottom two bits.
|
|
49
|
+
EXECUTE = 0x80
|
|
50
|
+
AUTOLOAD = 0x20
|
|
51
|
+
NO_FF00_TRIGGER = 0x10
|
|
52
|
+
TRANSFER_TYPE = 0x03
|
|
53
|
+
|
|
54
|
+
# Interrupt mask: interrupts on at all, then on the end of a block and
|
|
55
|
+
# on a fault. The low five bits aren't there and read as 1.
|
|
56
|
+
INTERRUPTS_ON = 0x80
|
|
57
|
+
INTERRUPT_ON_END = 0x40
|
|
58
|
+
INTERRUPT_ON_FAULT = 0x20
|
|
59
|
+
|
|
60
|
+
# Address control: hold the C64 address or the expansion address where
|
|
61
|
+
# it is. The low six bits aren't there and read as 1.
|
|
62
|
+
FIX_C64 = 0x80
|
|
63
|
+
FIX_EXPANSION = 0x40
|
|
64
|
+
|
|
65
|
+
# The REC's bank register has three bits, and the other five read as
|
|
66
|
+
# 1. A unit past 512K latches all eight onto its own address lines.
|
|
67
|
+
BANK_STUCK = 0xf8
|
|
68
|
+
|
|
69
|
+
attr_reader :trigger
|
|
70
|
+
|
|
71
|
+
# bus is the bus the REC reaches C64 memory through, and vic the VIC,
|
|
72
|
+
# whose phi1 fetch is what a register read finds on the bus during a
|
|
73
|
+
# transfer.
|
|
74
|
+
def initialize(size_kb, bus:, vic:)
|
|
75
|
+
raise ArgumentError, "No #{size_kb}K REU. Pick one of #{SIZES_KB.join(', ')}." unless SIZES_KB.include?(size_kb)
|
|
76
|
+
|
|
77
|
+
# The 1700's REC counts 17 address bits, the others' 19.
|
|
78
|
+
span = size_kb == 128 ? 0x20000 : 0x80000
|
|
79
|
+
@size_kb = size_kb
|
|
80
|
+
size = size_kb * 1024
|
|
81
|
+
@address_mask = [size, span].max - 1
|
|
82
|
+
@bank_bits = size > span ? 0xff : 0x07
|
|
83
|
+
@chips = size_kb == 128 ? 0 : CHIPS_256K
|
|
84
|
+
@ram = RAM.new(size, span)
|
|
85
|
+
@dma = DMA.new(@ram, span, bus)
|
|
86
|
+
@trigger = Trigger.new(self)
|
|
87
|
+
@vic = vic
|
|
88
|
+
@on_irq_change = nil
|
|
89
|
+
@on_dma = nil
|
|
90
|
+
@irq = false
|
|
91
|
+
reset!
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def on_irq_change(&block)
|
|
95
|
+
@on_irq_change = block
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Called when the REC asks for the bus.
|
|
99
|
+
def on_dma(&block)
|
|
100
|
+
@on_dma = block
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def irq? = @irq
|
|
104
|
+
|
|
105
|
+
# From the moment the REC asks for the bus until it hands it back.
|
|
106
|
+
def dma? = @requested || @running
|
|
107
|
+
|
|
108
|
+
# Whether the REC ran a transfer on the last cycle clocked, which it
|
|
109
|
+
# goes on doing until the cycle it lets go of the bus.
|
|
110
|
+
def holds_bus? = @running
|
|
111
|
+
|
|
112
|
+
def reset!
|
|
113
|
+
@status = @chips
|
|
114
|
+
@command = NO_FF00_TRIGGER
|
|
115
|
+
@c64 = @c64_start = 0
|
|
116
|
+
@expansion = @expansion_start = 0
|
|
117
|
+
@bank = @bank_start = 0
|
|
118
|
+
@length = @length_start = 0xffff
|
|
119
|
+
@interrupt_mask = 0x1f
|
|
120
|
+
@address_control = 0x3f
|
|
121
|
+
@armed = @requested = @running = @ba_was_low = false
|
|
122
|
+
interrupt(false)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def peek(addr)
|
|
126
|
+
return @vic.phi1_data if @running
|
|
127
|
+
|
|
128
|
+
register = addr & 0x1f
|
|
129
|
+
value = register_value(register)
|
|
130
|
+
read_status if register == STATUS
|
|
131
|
+
value
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def poke(addr, value)
|
|
135
|
+
return if @running
|
|
136
|
+
|
|
137
|
+
register = addr & 0x1f
|
|
138
|
+
case register
|
|
139
|
+
when COMMAND then write_command(value)
|
|
140
|
+
when C64_LOW, C64_HIGH then @c64 = @c64_start = with_byte(@c64_start, value, register == C64_HIGH)
|
|
141
|
+
when EXPANSION_LOW, EXPANSION_HIGH
|
|
142
|
+
@expansion = @expansion_start = with_byte(@expansion_start, value, register == EXPANSION_HIGH)
|
|
143
|
+
when EXPANSION_BANK then @bank = @bank_start = value & @bank_bits
|
|
144
|
+
when LENGTH_LOW, LENGTH_HIGH
|
|
145
|
+
@length = @length_start = with_byte(@length_start, value, register == LENGTH_HIGH)
|
|
146
|
+
when INTERRUPT_MASK then write_interrupt_mask(value)
|
|
147
|
+
when ADDRESS_CONTROL then @address_control = value | 0x3f
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# A write to $FF00 starts the transfer the command register armed.
|
|
152
|
+
def ff00_written
|
|
153
|
+
return unless @armed
|
|
154
|
+
|
|
155
|
+
@armed = false
|
|
156
|
+
request_bus
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Clocks the REC for a cycle, given the VIC's BA line. A requested
|
|
160
|
+
# transfer starts on the first cycle with BA high as the REC sees it,
|
|
161
|
+
# even one the CPU writes on. Pinned by REU/rmw-trigger. A fetch
|
|
162
|
+
# requested on the cycle before BA falls writes its first byte on the
|
|
163
|
+
# first BA-low cycle as well, and again when it starts. Pinned by
|
|
164
|
+
# REU/badoublewrite.
|
|
165
|
+
def dma_cycle!(ba_low)
|
|
166
|
+
late = ba_low && @vic.reu_ba_late?
|
|
167
|
+
if @requested
|
|
168
|
+
return hold_off if ba_low && !late
|
|
169
|
+
|
|
170
|
+
start_transfer
|
|
171
|
+
end
|
|
172
|
+
@dma.cycle!(ba_low, late, ba_low && @vic.reu_ba_handed_on?)
|
|
173
|
+
end_transfer unless @dma.holds_bus?
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# The REU's RAM, at an address as the REC's registers give it.
|
|
177
|
+
def ram_peek(addr) = @ram.peek(addr)
|
|
178
|
+
|
|
179
|
+
def ram_poke(addr, value) = @ram.poke(addr, value)
|
|
180
|
+
|
|
181
|
+
private
|
|
182
|
+
|
|
183
|
+
def register_value(register)
|
|
184
|
+
case register
|
|
185
|
+
when STATUS then @status
|
|
186
|
+
when COMMAND then @command
|
|
187
|
+
when C64_LOW then @c64 & 0xff
|
|
188
|
+
when C64_HIGH then @c64 >> 8
|
|
189
|
+
when EXPANSION_LOW then @expansion & 0xff
|
|
190
|
+
when EXPANSION_HIGH then @expansion >> 8
|
|
191
|
+
when EXPANSION_BANK then @bank | BANK_STUCK
|
|
192
|
+
when LENGTH_LOW then @length & 0xff
|
|
193
|
+
when LENGTH_HIGH then @length >> 8
|
|
194
|
+
when INTERRUPT_MASK then @interrupt_mask
|
|
195
|
+
when ADDRESS_CONTROL then @address_control
|
|
196
|
+
else 0xff
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def read_status
|
|
201
|
+
@status &= CHIPS_256K
|
|
202
|
+
interrupt(false)
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# Writing either byte of an address or the length sets the value the
|
|
206
|
+
# transfer starts from, and puts the counter back to it.
|
|
207
|
+
def with_byte(word, value, high)
|
|
208
|
+
high ? (word & 0x00ff) | (value << 8) : (word & 0xff00) | value
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def write_command(value)
|
|
212
|
+
@command = value
|
|
213
|
+
return if value.nobits?(EXECUTE)
|
|
214
|
+
|
|
215
|
+
@armed = value.nobits?(NO_FF00_TRIGGER)
|
|
216
|
+
request_bus unless @armed
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# An interrupt enabled over a block that already ended, or a fault
|
|
220
|
+
# already found, fires at once.
|
|
221
|
+
def write_interrupt_mask(value)
|
|
222
|
+
@interrupt_mask = value | 0x1f
|
|
223
|
+
interrupt_on(@status)
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def interrupt_on(events)
|
|
227
|
+
return unless @interrupt_mask.anybits?(INTERRUPTS_ON)
|
|
228
|
+
return unless (events.anybits?(END_OF_BLOCK) && @interrupt_mask.anybits?(INTERRUPT_ON_END)) ||
|
|
229
|
+
(events.anybits?(FAULT) && @interrupt_mask.anybits?(INTERRUPT_ON_FAULT))
|
|
230
|
+
|
|
231
|
+
@status |= INTERRUPT_PENDING
|
|
232
|
+
interrupt(true)
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def interrupt(level)
|
|
236
|
+
return if @irq == level
|
|
237
|
+
|
|
238
|
+
@irq = level
|
|
239
|
+
@on_irq_change&.call(level)
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def request_bus
|
|
243
|
+
@requested = true
|
|
244
|
+
@ba_was_low = @vic.ba_low?
|
|
245
|
+
@on_dma&.call
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def hold_off
|
|
249
|
+
@dma.write_ahead(@command & TRANSFER_TYPE, @c64, @expansion | (@bank << 16)) unless @ba_was_low
|
|
250
|
+
@ba_was_low = true
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def start_transfer
|
|
254
|
+
@requested = false
|
|
255
|
+
@running = true
|
|
256
|
+
@dma.start(@command & TRANSFER_TYPE, @c64, @expansion | (@bank << 16), @length, @address_control)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
# The execute bit drops and the $FF00 trigger turns off. With autoload
|
|
260
|
+
# the addresses and the length go back to where the transfer started,
|
|
261
|
+
# and otherwise they stay where it stopped.
|
|
262
|
+
def end_transfer
|
|
263
|
+
@running = false
|
|
264
|
+
@command = (@command & ~EXECUTE & 0xff) | NO_FF00_TRIGGER
|
|
265
|
+
events = @dma.events
|
|
266
|
+
@status |= events
|
|
267
|
+
@command.anybits?(AUTOLOAD) ? reload : keep_counters
|
|
268
|
+
interrupt_on(events)
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def reload
|
|
272
|
+
@c64 = @c64_start
|
|
273
|
+
@expansion = @expansion_start
|
|
274
|
+
@bank = @bank_start
|
|
275
|
+
@length = @length_start
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def keep_counters
|
|
279
|
+
@c64 = @dma.c64 if @address_control.nobits?(FIX_C64)
|
|
280
|
+
@length = @dma.length & 0xffff
|
|
281
|
+
return if @address_control.anybits?(FIX_EXPANSION)
|
|
282
|
+
|
|
283
|
+
address = @dma.expansion & @address_mask
|
|
284
|
+
@expansion = address & 0xffff
|
|
285
|
+
@bank = (address >> 16) & 0xff
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
class C64
|
|
5
|
+
# The true drives on the machine's serial bus: a Drives::Model1541, and a
|
|
6
|
+
# Drives::Model1581 (Drives::Model1581::Slot), each in a field of its own. C64,
|
|
7
|
+
# Vic20 and C128 each include it.
|
|
8
|
+
module TrueDrives
|
|
9
|
+
include Drives::Model1581::Slot
|
|
10
|
+
|
|
11
|
+
# The true drive models a snapshot names.
|
|
12
|
+
DRIVE_MODELS = %w[1541 1571 1581].freeze
|
|
13
|
+
|
|
14
|
+
# Plugs in a Drives::Model1541, which then runs alongside the machine on its
|
|
15
|
+
# own clock and talks to it over the serial bus. The serial traps stop
|
|
16
|
+
# answering the drive's device number, so the KERNAL's TALK, LISTEN and
|
|
17
|
+
# byte transfers reach the drive. The LOAD and SAVE traps stay, and
|
|
18
|
+
# still serve a mounted image.
|
|
19
|
+
def attach_drive1541(drive)
|
|
20
|
+
@iec_bus.detach(@drive1541) if @drive1541
|
|
21
|
+
drive.host_clock_hz = timing.clock_hz
|
|
22
|
+
@drive1541 = drive
|
|
23
|
+
drive.connect(@iec_bus)
|
|
24
|
+
@serial_trap&.device = serial_trap_device
|
|
25
|
+
drive1541_attached
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# The true drive on the serial bus: the Drives::Model1581 ahead of the
|
|
29
|
+
# Drives::Model1541, or nil.
|
|
30
|
+
def true_drive = @drive1581 || @drive1541
|
|
31
|
+
|
|
32
|
+
# Plugs a Drives::Model1541 in as device 8, in place of a 1581 there, and
|
|
33
|
+
# returns it.
|
|
34
|
+
def plug_true_drive
|
|
35
|
+
detach_drive1581 if drive1581_on_device8?
|
|
36
|
+
Drives::Model1541.new.tap { |drive| attach_drive1541(drive) }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# The true drives as keyed snapshot modules, each named from its device
|
|
40
|
+
# number: BL-D8, BL-D8-CPU and so on for device 8.
|
|
41
|
+
def save_drive_modules(sections)
|
|
42
|
+
drive1541 = @drive1541
|
|
43
|
+
drive1541&.save_modules(sections, "BL-D#{drive1541.device}")
|
|
44
|
+
drive1581 = @drive1581
|
|
45
|
+
drive1581&.save_modules(sections, "BL-D#{drive1581.device}")
|
|
46
|
+
save_drive1571_modules(sections)
|
|
47
|
+
sections
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# The true drives a snapshot's modules hold, built afresh unless the
|
|
51
|
+
# same model is on the bus as the same device. A drive the snapshot
|
|
52
|
+
# doesn't have comes off the bus.
|
|
53
|
+
def load_drive_modules(modules)
|
|
54
|
+
models = []
|
|
55
|
+
8.upto(11) do |device|
|
|
56
|
+
input = modules.optional("BL-D#{device}")
|
|
57
|
+
next unless input
|
|
58
|
+
|
|
59
|
+
model = input.choice("model", DRIVE_MODELS, "1541")
|
|
60
|
+
load_drive_model(modules, input, device, model)
|
|
61
|
+
models << model
|
|
62
|
+
end
|
|
63
|
+
detach_drive1541 unless models.include?("1541")
|
|
64
|
+
detach_drive1581 unless models.include?("1581")
|
|
65
|
+
detach_drive1571 unless models.include?("1571")
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Unplugs the Drives::Model1541, leaving the serial bus with nothing on it.
|
|
69
|
+
def detach_drive1541
|
|
70
|
+
return unless @drive1541
|
|
71
|
+
|
|
72
|
+
@iec_bus.detach(@drive1541)
|
|
73
|
+
@drive1541 = nil
|
|
74
|
+
@serial_trap&.device = serial_trap_device
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
# The device number the serial traps answer: device 8, unless a true
|
|
80
|
+
# drive is on the bus as device 8.
|
|
81
|
+
def serial_trap_device
|
|
82
|
+
device = KernalTrap::Routine::DEVICE
|
|
83
|
+
@drive1541&.device == device || drive1581_on_device8? ? nil : device
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# What the machine does as a 1541 goes on its bus. The VIC-20 waits
|
|
87
|
+
# for its DOS to boot before typing.
|
|
88
|
+
def drive1541_attached = nil
|
|
89
|
+
|
|
90
|
+
def load_drive_model(modules, input, device, model)
|
|
91
|
+
case model
|
|
92
|
+
when "1581" then load_drive1581_modules(modules, input, device)
|
|
93
|
+
when "1571" then load_drive1571_modules(modules, input, device)
|
|
94
|
+
else load_drive1541_modules(modules, input, device)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def load_drive1541_modules(modules, input, device)
|
|
99
|
+
detach_drive1541 if @drive1541 && @drive1541.device != device
|
|
100
|
+
attach_drive1541(Drives::Model1541.new(device:)) unless @drive1541
|
|
101
|
+
@drive1541.load_modules(modules, input, "BL-D#{device}")
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def load_drive1581_modules(modules, input, device)
|
|
105
|
+
detach_drive1581 if @drive1581 && @drive1581.device != device
|
|
106
|
+
attach_drive1581(Drives::Model1581.new(device:)) unless @drive1581
|
|
107
|
+
@drive1581.load_modules(modules, input, "BL-D#{device}")
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# The C128D's 1571, which only the C128 has (C128::Drives).
|
|
111
|
+
def save_drive1571_modules(sections) = sections
|
|
112
|
+
|
|
113
|
+
def load_drive1571_modules(_modules, input, _device)
|
|
114
|
+
input.adjust("a 1571 doesn't plug into this machine, left out")
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def detach_drive1571 = nil
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "badline/
|
|
4
|
-
require "badline/
|
|
5
|
-
require "badline/
|
|
6
|
-
require "badline/
|
|
7
|
-
require "badline/
|
|
3
|
+
require "badline/c64/common"
|
|
4
|
+
require "badline/c64/true_drives"
|
|
5
|
+
require "badline/c64/attachments"
|
|
6
|
+
require "badline/c64/kernal_traps"
|
|
7
|
+
require "badline/c64/keyed_state"
|
|
8
|
+
require "badline/c64/keyed_modules"
|
|
8
9
|
|
|
9
10
|
module Badline
|
|
10
|
-
class
|
|
11
|
+
class C64
|
|
11
12
|
include IntegerHelper
|
|
12
|
-
include KeyboardBuffer
|
|
13
|
+
include Machine::KeyboardBuffer
|
|
13
14
|
include Machine::Clocking
|
|
15
|
+
include Machine::Settling
|
|
14
16
|
include Common
|
|
15
17
|
include Attachments
|
|
16
18
|
include KernalTraps
|
|
17
|
-
include SavedState
|
|
18
19
|
|
|
19
20
|
attr_reader :address_bus, :cpu, :cycles, :drive1541
|
|
20
21
|
|
|
@@ -32,6 +33,11 @@ module Badline
|
|
|
32
33
|
|
|
33
34
|
def ram = address_bus.ram
|
|
34
35
|
|
|
36
|
+
# Reads and writes memory as the CPU sees it, through the bus.
|
|
37
|
+
def peek(addr) = address_bus.peek(addr)
|
|
38
|
+
|
|
39
|
+
def poke(addr, value) = address_bus.poke(addr, value)
|
|
40
|
+
|
|
35
41
|
def keyboard = address_bus.keyboard
|
|
36
42
|
|
|
37
43
|
def joystick1 = address_bus.joystick1
|
|
@@ -45,18 +51,18 @@ module Badline
|
|
|
45
51
|
def install_debug_register(&) = address_bus.install_debug_register(&)
|
|
46
52
|
|
|
47
53
|
# The machine options (sid_model:, cia_model:, vic_model:, region: and
|
|
48
|
-
# ram_expansion:) configure the
|
|
54
|
+
# ram_expansion:) configure the C64::Bus. The region sets the clock,
|
|
49
55
|
# the VIC's raster and sprite timing, and the mains frequency the CIAs'
|
|
50
56
|
# TOD clocks count. The KERNAL tells PAL from NTSC by the raster, so
|
|
51
57
|
# every region boots the same ROMs. reu plugs an REU of that many K
|
|
52
58
|
# into the expansion port, where it drives the IRQ line and takes the
|
|
53
59
|
# bus for its transfers. kernal:, datasette: and board: fit the bus
|
|
54
|
-
# afterwards (
|
|
60
|
+
# afterwards (C64::Bus::Fittings): the KERNAL ROM, the cassette port,
|
|
55
61
|
# which is empty on the SX-64, and the board and case.
|
|
56
62
|
def initialize(debug: false, reu: nil, **machine)
|
|
57
|
-
@address_bus =
|
|
58
|
-
@address_bus.fit(**machine.slice(*
|
|
59
|
-
@cpu = CPU.new(@address_bus, debug:)
|
|
63
|
+
@address_bus = Bus.new(**machine.except(*Bus::Fittings::NAMES))
|
|
64
|
+
@address_bus.fit(**machine.slice(*Bus::Fittings::NAMES))
|
|
65
|
+
@cpu = Chips::CPU.new(@address_bus, debug:)
|
|
60
66
|
@vic = @address_bus.vic
|
|
61
67
|
@vic.open_bus = -> { @address_bus.ram.peek(@cpu.program_counter) }
|
|
62
68
|
@cia1 = @address_bus.cia1
|
|
@@ -73,7 +79,7 @@ module Badline
|
|
|
73
79
|
@freeze_writes = 0
|
|
74
80
|
@init_handlers = []
|
|
75
81
|
@pending_keys = nil
|
|
76
|
-
@
|
|
82
|
+
@dos = nil
|
|
77
83
|
@serial_trap = nil
|
|
78
84
|
@save_trap = nil
|
|
79
85
|
@drive1541 = nil
|
|
@@ -145,7 +151,7 @@ module Badline
|
|
|
145
151
|
address_bus.cartridge&.reset
|
|
146
152
|
@reu&.reset!
|
|
147
153
|
@dma = false
|
|
148
|
-
@
|
|
154
|
+
@dos&.reset!
|
|
149
155
|
@drive1541&.reset!
|
|
150
156
|
@drive1581&.reset!
|
|
151
157
|
@freezing = false
|
|
@@ -183,6 +189,9 @@ module Badline
|
|
|
183
189
|
# The KERNAL the traps stand in for (KernalTraps#mount).
|
|
184
190
|
def trap_layout = KernalTrap::C64_LAYOUT
|
|
185
191
|
|
|
192
|
+
# The KERNAL's keyboard buffer, which #type_text feeds.
|
|
193
|
+
def keyboard_buffer = Machine::KeyboardBuffer::C64_LAYOUT
|
|
194
|
+
|
|
186
195
|
def trap_bus = address_bus
|
|
187
196
|
|
|
188
197
|
def plug_reu(size_kb)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class CIA
|
|
6
|
+
# Running a CIA a stretch of cycles at once, for Drives::Engine::Idle.
|
|
7
|
+
module FastForward
|
|
8
|
+
# quiet_cycles for a CIA whose counters will never set a flag.
|
|
9
|
+
QUIET = 1 << 40
|
|
10
|
+
|
|
11
|
+
# Whether fast_forward can run the CIA: timer B stopped with nothing
|
|
12
|
+
# in its pipeline, no interrupt or acknowledge on its way, CNT where it
|
|
13
|
+
# was, the TOD clock stopped, and timer A either stopped, or free
|
|
14
|
+
# running (Timer#free_running?) with its interrupt masked and the
|
|
15
|
+
# serial port an idle input. Drives::Engine::Idle sleeps the 1571's CIA through
|
|
16
|
+
# such cycles, which its DOS leaves timer A running in.
|
|
17
|
+
def quiet?
|
|
18
|
+
return false unless @tb.idle? && @icr.quiet && @tod.quiet? && cnt_steady?
|
|
19
|
+
|
|
20
|
+
@ta.idle? ? @serial.idle : timer_a_free_running?
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# How many cycles the CIA can run with nothing but its counters
|
|
24
|
+
# moving: as quiet? allows, but with timer B free running too, up to
|
|
25
|
+
# the cycle before it underflows. The 1581's DOS leaves timer B
|
|
26
|
+
# interrupting every 10 ms.
|
|
27
|
+
def quiet_cycles
|
|
28
|
+
return 0 unless @icr.quiet && @tod.quiet? && cnt_steady? && timer_a_quiet?
|
|
29
|
+
return QUIET if @tb.idle?
|
|
30
|
+
return 0 unless @tb.free_running? && @control_b.value.nobits?(0x60)
|
|
31
|
+
|
|
32
|
+
@tb.counter - 1
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Runs +cycles+ cycles at once while quiet? or for quiet_cycles, as
|
|
36
|
+
# cycle! would: timer A's underflows flag in the ICR, and reach the
|
|
37
|
+
# serial port's underflow line.
|
|
38
|
+
def fast_forward(cycles)
|
|
39
|
+
@tod.fast_forward(cycles)
|
|
40
|
+
@tb.fast_forward(cycles) unless @tb.idle?
|
|
41
|
+
return if @ta.idle?
|
|
42
|
+
|
|
43
|
+
@icr.flag(:timer_a) if @ta.fast_forward(cycles).positive?
|
|
44
|
+
@serial.follow_underflow(@ta.underflowed)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def timer_a_quiet? = @ta.idle? ? @serial.idle : timer_a_free_running?
|
|
50
|
+
|
|
51
|
+
# Timer A free running with its interrupt masked, and the serial port
|
|
52
|
+
# an idle input it only clocks.
|
|
53
|
+
def timer_a_free_running?
|
|
54
|
+
@ta.free_running? && !@control_a.serial_mode? && @icr.mask.value.nobits?(0x01) && @serial.drained?
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Whether CNT holds the level the last cycle sampled.
|
|
58
|
+
def cnt_steady? = @serial.cnt == @cnt_high && !@cnt_rise
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class CIA
|
|
6
|
+
# The interrupt control register: the source flags, their mask and the
|
|
7
|
+
# IR bit that drives the interrupt line, with the 6526's acknowledge
|
|
8
|
+
# timing.
|
|
9
|
+
class InterruptRegister
|
|
10
|
+
attr_reader :status, :mask, :quiet
|
|
11
|
+
|
|
12
|
+
# The 6526A is the faster of the two: see the rules below.
|
|
13
|
+
def initialize(model = :mos6526)
|
|
14
|
+
@fast = model == :mos6526a
|
|
15
|
+
@mask = InterruptFlags.new([:timer_a, :timer_b, :alarm, :serial, :flag, 0, 0, 0])
|
|
16
|
+
@status = InterruptFlags.new([:timer_a, :timer_b, :alarm, :serial, :flag, 0, 0, :interrupt])
|
|
17
|
+
@pending = 0
|
|
18
|
+
@read = @read_last_cycle = @read_two_cycles_ago = nil
|
|
19
|
+
@timer_b_bug = false
|
|
20
|
+
@quiet = true
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# The CIA skips this while quiet: no read is recent enough to matter
|
|
24
|
+
# and no assert is due.
|
|
25
|
+
def cycle!
|
|
26
|
+
@read_two_cycles_ago = @read_last_cycle
|
|
27
|
+
@read_last_cycle = @read
|
|
28
|
+
@read = nil
|
|
29
|
+
if @pending.positive?
|
|
30
|
+
@pending -= 1
|
|
31
|
+
status.interrupt = true if @pending.zero?
|
|
32
|
+
end
|
|
33
|
+
@quiet = @pending.zero? && @read_last_cycle.nil? && @read_two_cycles_ago.nil?
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def interrupted? = status.value >= 0x80
|
|
37
|
+
|
|
38
|
+
# Raises IR on this cycle.
|
|
39
|
+
def assert_now
|
|
40
|
+
status.interrupt = true
|
|
41
|
+
@pending = 0
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Schedules IR to rise after delay cycles, keeping an earlier one.
|
|
45
|
+
def assert!(delay = 1)
|
|
46
|
+
@pending = @pending.positive? ? [@pending, delay].min : delay
|
|
47
|
+
@quiet = false
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Latch a source, pulling the interrupt line if it is armed. The 6526
|
|
51
|
+
# raises IR a cycle after the flag. The 6526A raises it on the flag's
|
|
52
|
+
# own cycle, unless the ICR was read on the cycle before.
|
|
53
|
+
def flag(source)
|
|
54
|
+
bit = source_bit(source)
|
|
55
|
+
@status.value |= bit
|
|
56
|
+
return unless mask.value.anybits?(bit)
|
|
57
|
+
|
|
58
|
+
@fast && @read_last_cycle.nil? ? assert_now : assert!
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# The 6526 timer B bug: an underflow on the cycle after a read still
|
|
62
|
+
# raises the flag, but the next read drops it unseen. The 6526A has
|
|
63
|
+
# no such bug.
|
|
64
|
+
def timer_b_underflow!
|
|
65
|
+
@timer_b_bug = !@fast && !@read_last_cycle.nil?
|
|
66
|
+
flag(:timer_b)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# A read releases the interrupt line at once, and cancels an assert
|
|
70
|
+
# due on the next cycle, but its acknowledge lands a cycle late. On
|
|
71
|
+
# the 6526 that holds only IR: the next cycle still reads IR set if it
|
|
72
|
+
# was set, or about to be. The 6526A reads an IR about to rise as set
|
|
73
|
+
# at once, and holds every bit it read: the next cycle reads them all
|
|
74
|
+
# again, along with anything flagged since.
|
|
75
|
+
def read
|
|
76
|
+
status.timer_b = false if @timer_b_bug
|
|
77
|
+
@timer_b_bug = false
|
|
78
|
+
value = status.value
|
|
79
|
+
value |= 0x80 if @fast && @pending == 1
|
|
80
|
+
@read = @pending == 1 ? value | 0x80 : value
|
|
81
|
+
@quiet = false
|
|
82
|
+
value |= held(@read_last_cycle) if @read_last_cycle
|
|
83
|
+
status.value = 0x0
|
|
84
|
+
@pending = 0
|
|
85
|
+
value
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Bit 7 picks between setting and clearing the mask bits given.
|
|
89
|
+
def write(value)
|
|
90
|
+
if value.nobits?(0x80)
|
|
91
|
+
@mask.value &= ~(value & 0x1f)
|
|
92
|
+
else
|
|
93
|
+
@mask.value |= (value & 0x1f)
|
|
94
|
+
end
|
|
95
|
+
if mask.value.anybits?(status.value & 0x1f)
|
|
96
|
+
assert!(arm_delay) unless interrupted?
|
|
97
|
+
elsif @pending == 1 && @read_two_cycles_ago
|
|
98
|
+
# On the 6526, masking the pending source cancels the assert due
|
|
99
|
+
# on the next cycle only while a read two cycles back is
|
|
100
|
+
# acknowledging.
|
|
101
|
+
@pending = 0
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
private
|
|
106
|
+
|
|
107
|
+
# Arming a pending source raises IR two cycles later on the 6526,
|
|
108
|
+
# and one cycle later on the 6526A.
|
|
109
|
+
def arm_delay = @fast ? 1 : 2
|
|
110
|
+
|
|
111
|
+
# What a read on the cycle before still holds: IR on the 6526, and
|
|
112
|
+
# every bit it read on the 6526A.
|
|
113
|
+
def held(last) = @fast ? last : last & 0x80
|
|
114
|
+
|
|
115
|
+
def source_bit(source)
|
|
116
|
+
case source
|
|
117
|
+
when :timer_a then 0x01
|
|
118
|
+
when :timer_b then 0x02
|
|
119
|
+
when :alarm then 0x04
|
|
120
|
+
when :serial then 0x08
|
|
121
|
+
when :flag then 0x10
|
|
122
|
+
else raise ArgumentError, "unknown interrupt source #{source}"
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|