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,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class CPU
|
|
6
|
+
# Steps that read or write an instruction's operand once its address is
|
|
7
|
+
# known, plus the branch and JAM steps.
|
|
8
|
+
module Operations
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def op_mem_read
|
|
12
|
+
send(@operation, @address, @memory.peek(@address))
|
|
13
|
+
end_instruction
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def op_mem_write
|
|
17
|
+
send(@operation, @address, nil)
|
|
18
|
+
end_instruction
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Read-modify-write instructions (ASL, INC and the like) take three
|
|
22
|
+
# cycles here: read the value and compute the result, write the
|
|
23
|
+
# original value back, then write the result. The instruction method
|
|
24
|
+
# hands the result over through #write_modified.
|
|
25
|
+
def op_rmw_read
|
|
26
|
+
@value = @memory.peek(@address)
|
|
27
|
+
send(@operation, @address, @value)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def op_rmw_write_original
|
|
31
|
+
@memory.poke(@address, @value)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def op_rmw_write_result
|
|
35
|
+
@memory.poke(@address, @rmw_result)
|
|
36
|
+
end_instruction
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def op_relative
|
|
40
|
+
offset = @memory.peek(@program_counter)
|
|
41
|
+
@program_counter = (@program_counter + 1) & 0xffff
|
|
42
|
+
@address = (@program_counter + signed_int8(offset)) & 0xffff
|
|
43
|
+
@branch_taken = false
|
|
44
|
+
send(@operation, @address, nil)
|
|
45
|
+
if @branch_taken
|
|
46
|
+
# A taken branch within the same page doesn't poll on its last cycle.
|
|
47
|
+
@skip_poll = true if same_page?
|
|
48
|
+
else
|
|
49
|
+
end_instruction
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def op_branch
|
|
54
|
+
@memory.peek(@program_counter)
|
|
55
|
+
return unless same_page?
|
|
56
|
+
|
|
57
|
+
@program_counter = @address
|
|
58
|
+
end_instruction
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# A branch to another page spends an extra cycle reading from the target's low byte on the old page.
|
|
62
|
+
def op_branch_fixup
|
|
63
|
+
@memory.peek((@program_counter & 0xff00) | (@address & 0xff))
|
|
64
|
+
@program_counter = @address
|
|
65
|
+
end_instruction
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def same_page?
|
|
69
|
+
@address >> 8 == @program_counter >> 8
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Runs once for each address in JAM_ADDRESSES. By the time a step runs, @index already points at the next one.
|
|
73
|
+
def op_jam
|
|
74
|
+
position = @index - 2
|
|
75
|
+
@memory.peek(JAM_ADDRESSES[position - 1])
|
|
76
|
+
return unless position == JAM_ADDRESSES.length
|
|
77
|
+
|
|
78
|
+
@plan = JAMMED_PLAN
|
|
79
|
+
@writes = JAMMED_WRITES
|
|
80
|
+
@index = 0
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def op_jammed
|
|
84
|
+
@index = 0
|
|
85
|
+
@memory.peek(0xffff)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class CPU
|
|
6
|
+
# The I/O port of the 6510 and the 8502 at $00 (direction) and $01
|
|
7
|
+
# (data). An input pin reads its pull-up, P4 reads the datasette's sense
|
|
8
|
+
# line, and a pin without a pull-up holds the charge last driven onto
|
|
9
|
+
# it. P5 drives the datasette motor through an inverter: low runs it,
|
|
10
|
+
# and P3 drives its write line.
|
|
11
|
+
#
|
|
12
|
+
# The 6510 has pull-ups on P0-P2 and P4 and leaves P3, P6 and P7
|
|
13
|
+
# floating. The 8502 adds a CAPS LOCK pin on P6, high while the key is
|
|
14
|
+
# up.
|
|
15
|
+
class Port
|
|
16
|
+
TAPE_SENSE = 0b0001_0000
|
|
17
|
+
|
|
18
|
+
# The direction and output registers, and the charge on the floating
|
|
19
|
+
# pins.
|
|
20
|
+
attr_reader :ddr, :data, :floating
|
|
21
|
+
|
|
22
|
+
# The port as the banking logic reads it (PortStatus).
|
|
23
|
+
attr_reader :status
|
|
24
|
+
|
|
25
|
+
# Whether CAPS LOCK is down, holding its pin low.
|
|
26
|
+
attr_reader :caps_lock
|
|
27
|
+
|
|
28
|
+
# +pullups+ and +floating+ are the masks of the pins with a pull-up and
|
|
29
|
+
# of the floating ones, and +caps_lock+ the CAPS LOCK pin's, 0 where
|
|
30
|
+
# there is none.
|
|
31
|
+
def initialize(datasette, pullups:, floating:, caps_lock: 0)
|
|
32
|
+
@datasette = datasette
|
|
33
|
+
@pullups = pullups
|
|
34
|
+
@floating_mask = floating
|
|
35
|
+
@caps_lock_pin = caps_lock
|
|
36
|
+
@caps_lock = false
|
|
37
|
+
@ddr = 0x00
|
|
38
|
+
@data = 0x00
|
|
39
|
+
@floating = 0x00
|
|
40
|
+
@change_handler = nil
|
|
41
|
+
@status = PortStatus.new(%i[basic kernal io tape_out tape_switch tape_motor], value: input_value)
|
|
42
|
+
@datasette.write_level = @status.tape_out?
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Calls the block after every write to the port, for the bus to remap
|
|
46
|
+
# its banks.
|
|
47
|
+
def on_change(&handler)
|
|
48
|
+
@change_handler = handler
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# What a read of $01 sees.
|
|
52
|
+
def value = @status.value
|
|
53
|
+
|
|
54
|
+
def write_ddr(value)
|
|
55
|
+
@ddr = value
|
|
56
|
+
update
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def write_data(value)
|
|
60
|
+
@data = value
|
|
61
|
+
update
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# The RES line clears the direction and output registers. The floating
|
|
65
|
+
# pins keep their charge.
|
|
66
|
+
def reset!
|
|
67
|
+
@ddr = 0x00
|
|
68
|
+
@data = 0x00
|
|
69
|
+
update
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Sets the registers and the charge, as a snapshot restores them, and
|
|
73
|
+
# drives the datasette and calls the change handler as a write does.
|
|
74
|
+
def restore(ddr, data, floating)
|
|
75
|
+
load(ddr, data, floating)
|
|
76
|
+
update
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Sets the registers and the charge, as a snapshot loads them, without
|
|
80
|
+
# driving the datasette or calling the change handler. The write
|
|
81
|
+
# line takes P3's level without recording an edge.
|
|
82
|
+
def load(ddr, data, floating)
|
|
83
|
+
@ddr = ddr
|
|
84
|
+
@data = data
|
|
85
|
+
@floating = floating
|
|
86
|
+
refresh
|
|
87
|
+
@datasette.write_level = @status.tape_out?
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# The registers and the charge in a keyed snapshot module
|
|
91
|
+
# (Snapshot::Keyed), under `prefix`. What a read sees is worked out
|
|
92
|
+
# again on load, and the bus maps its banks afterwards.
|
|
93
|
+
def save_fields(out, prefix)
|
|
94
|
+
out.int("#{prefix}ddr", @ddr).int("#{prefix}data", @data).int("#{prefix}floating", @floating)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def load_fields(input, prefix)
|
|
98
|
+
load(input.byte("#{prefix}ddr", @ddr), input.byte("#{prefix}data", @data),
|
|
99
|
+
input.byte("#{prefix}floating", @floating))
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Holds CAPS LOCK down, or lets it up.
|
|
103
|
+
def caps_lock=(down)
|
|
104
|
+
@caps_lock = down
|
|
105
|
+
refresh
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Reads the inputs again, after the datasette's sense line changes.
|
|
109
|
+
def refresh
|
|
110
|
+
@status.value = input_value
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
private
|
|
114
|
+
|
|
115
|
+
def update
|
|
116
|
+
driven = @ddr & @floating_mask
|
|
117
|
+
@floating = (@floating & ~driven) | (@data & driven)
|
|
118
|
+
refresh
|
|
119
|
+
@datasette.motor = !@status.tape_motor?
|
|
120
|
+
@datasette.write_line = @status.tape_out?
|
|
121
|
+
@change_handler&.call
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def input_value
|
|
125
|
+
input = @pullups | (@floating & @floating_mask)
|
|
126
|
+
input |= @caps_lock_pin unless @caps_lock
|
|
127
|
+
input &= ~TAPE_SENSE if @datasette.sense_low?
|
|
128
|
+
(@data & @ddr) | (input & ~@ddr & 0xff)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class CPU
|
|
6
|
+
# Steps that use the stack: PHA, PHP, PLA, PLP, JSR, RTS and RTI.
|
|
7
|
+
module StackOperations
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def op_push_exec
|
|
11
|
+
send(@operation, nil, nil)
|
|
12
|
+
end_instruction
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def op_pull_dummy
|
|
16
|
+
@memory.peek(stack_address)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def op_pull_exec
|
|
20
|
+
send(@operation, nil, nil)
|
|
21
|
+
end_instruction
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def op_pull_low
|
|
25
|
+
@stack_pointer = (@stack_pointer + 1) & 0xff
|
|
26
|
+
@address = @memory.peek(stack_address)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def op_pull_high
|
|
30
|
+
@stack_pointer = (@stack_pointer + 1) & 0xff
|
|
31
|
+
@address |= @memory.peek(stack_address) << 8
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def op_rts_fixup
|
|
35
|
+
@memory.peek(@address)
|
|
36
|
+
@program_counter = (@address + 1) & 0xffff
|
|
37
|
+
end_instruction
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def op_rti_pull_status
|
|
41
|
+
@stack_pointer = (@stack_pointer + 1) & 0xff
|
|
42
|
+
@status.value = @memory.peek(stack_address)
|
|
43
|
+
@status.break = false
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def op_rti_pull_high
|
|
47
|
+
@stack_pointer = (@stack_pointer + 1) & 0xff
|
|
48
|
+
@program_counter = @address | (@memory.peek(stack_address) << 8)
|
|
49
|
+
end_instruction
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def op_jsr_low
|
|
53
|
+
@address = @memory.peek(@program_counter)
|
|
54
|
+
@program_counter = (@program_counter + 2) & 0xffff
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def op_jsr_dummy
|
|
58
|
+
@memory.peek(stack_address)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def op_jsr_push_high
|
|
62
|
+
@memory.poke(stack_address, high_byte(return_address))
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def op_jsr_push_low
|
|
66
|
+
@memory.poke(stack_address(-1), low_byte(return_address))
|
|
67
|
+
@stack_pointer = (@stack_pointer - 2) & 0xff
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# JSR reads its target's high byte after pushing the return address.
|
|
71
|
+
# A JSR running from the stack page can overwrite its own operand
|
|
72
|
+
# with that push, and then jumps to the overwritten address.
|
|
73
|
+
def op_jsr_high
|
|
74
|
+
@program_counter = @address | (@memory.peek(return_address) << 8)
|
|
75
|
+
end_instruction
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def return_address
|
|
79
|
+
(@program_counter - 1) & 0xffff
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class CPU
|
|
6
|
+
module Traps
|
|
7
|
+
def install_trap(addr, &handler)
|
|
8
|
+
(@traps ||= {})[addr] = handler
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def remove_trap(addr)
|
|
12
|
+
@traps&.delete(addr)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def run_traps
|
|
18
|
+
@traps[@program_counter]&.call if @traps
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "badline/chips/cpu/port"
|
|
4
|
+
require "badline/chips/cpu/instruction"
|
|
5
|
+
require "badline/chips/cpu/instruction_set"
|
|
6
|
+
require "badline/chips/cpu/interrupts"
|
|
7
|
+
require "badline/chips/cpu/traps"
|
|
8
|
+
require "badline/chips/cpu/core"
|
|
9
|
+
|
|
10
|
+
module Badline
|
|
11
|
+
module Chips
|
|
12
|
+
# The C64's 6510, on the C64::Bus.
|
|
13
|
+
class CPU
|
|
14
|
+
include Core
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class SID
|
|
6
|
+
# Running the DSP over the cycles that have passed since it last caught
|
|
7
|
+
# up, in spans that fast-forward the voices and end on a whole cycle.
|
|
8
|
+
module CatchUp
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
# Runs the cycles that have passed, landing each queued write on the
|
|
12
|
+
# cycle the CPU wrote it on.
|
|
13
|
+
def catch_up
|
|
14
|
+
replayed = 0
|
|
15
|
+
i = 0
|
|
16
|
+
while i < @deferred_writes.length
|
|
17
|
+
cycle = @deferred_writes[i]
|
|
18
|
+
run(cycle - replayed)
|
|
19
|
+
replayed = cycle
|
|
20
|
+
apply_write(@deferred_writes[i + 1], @deferred_writes[i + 2])
|
|
21
|
+
i += 3
|
|
22
|
+
end
|
|
23
|
+
run(@pending_cycles - replayed)
|
|
24
|
+
@deferred_writes.clear
|
|
25
|
+
@pending_cycles = 0
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def run(cycles)
|
|
29
|
+
while cycles != 0
|
|
30
|
+
span = span(cycles)
|
|
31
|
+
fast_forward(span - 1) if span > 1
|
|
32
|
+
clock!(span)
|
|
33
|
+
cycles -= span
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# The longest stretch that can be fast-forwarded. A combined waveform
|
|
38
|
+
# feeding back into its own oscillator steps cycle by cycle, and a span
|
|
39
|
+
# never runs past an MSB rise that hard-syncs the next voice, so both
|
|
40
|
+
# land on a whole cycle.
|
|
41
|
+
def span(cycles)
|
|
42
|
+
return 1 if @stepped
|
|
43
|
+
|
|
44
|
+
span = @synthesizing ? synthesis_span(cycles) : cycles
|
|
45
|
+
return span unless @synced
|
|
46
|
+
|
|
47
|
+
span = sync_span(@waveform1, span)
|
|
48
|
+
span = sync_span(@waveform2, span)
|
|
49
|
+
sync_span(@waveform3, span)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# The filter steps at most @filter_chunk cycles at a time, and never
|
|
53
|
+
# across the end of a recorded sample.
|
|
54
|
+
def synthesis_span(cycles)
|
|
55
|
+
span = [cycles, @filter_chunk].min
|
|
56
|
+
return span unless @decimator
|
|
57
|
+
|
|
58
|
+
[@decimator.cycles_to_close, span].min
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Whether a span has to step, or watch for hard sync, only changes with
|
|
62
|
+
# a voice's control register.
|
|
63
|
+
def update_span_rules
|
|
64
|
+
@stepped = @voices.any? { |voice| voice.waveform.stepped?(@synthesizing) }
|
|
65
|
+
@synced = @voices.any? { |voice| voice.waveform.sync? }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def sync_span(waveform, span)
|
|
69
|
+
return span unless waveform.sync_dest.sync?
|
|
70
|
+
|
|
71
|
+
rise = waveform.cycles_to_msb_rise
|
|
72
|
+
rise && rise < span ? rise : span
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Unrolled over the three voices: the per-cycle block calls cost
|
|
76
|
+
# measurably on the synthesis path.
|
|
77
|
+
def fast_forward(cycles)
|
|
78
|
+
@voice1.fast_forward(cycles)
|
|
79
|
+
@voice2.fast_forward(cycles)
|
|
80
|
+
@voice3.fast_forward(cycles)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# The last cycle of a span, run whole. The filter integrates the span
|
|
84
|
+
# from the voices' output at its end.
|
|
85
|
+
def clock!(span)
|
|
86
|
+
@voice1.cycle!
|
|
87
|
+
@voice2.cycle!
|
|
88
|
+
@voice3.cycle!
|
|
89
|
+
@waveform1.synchronize!
|
|
90
|
+
@waveform2.synchronize!
|
|
91
|
+
@waveform3.synchronize!
|
|
92
|
+
return unless @synthesizing
|
|
93
|
+
|
|
94
|
+
@filter.cycle!(@voices, span)
|
|
95
|
+
record_sample(span) if @decimator
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def record_sample(span)
|
|
99
|
+
sample = @decimator.push(current_sample, span)
|
|
100
|
+
return unless sample
|
|
101
|
+
|
|
102
|
+
@samples << sample
|
|
103
|
+
record_voices if @voice_samples
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def record_voices
|
|
107
|
+
voice_samples = @voice_samples
|
|
108
|
+
voice_samples << (@voice1.output >> 7)
|
|
109
|
+
voice_samples << (@voice2.output >> 7)
|
|
110
|
+
voice_samples << (@voice3.output >> 7)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def current_sample
|
|
114
|
+
sample = @filter.output / SAMPLE_DIVISOR
|
|
115
|
+
return sample unless sample < -0x8000 || sample > 0x7fff
|
|
116
|
+
|
|
117
|
+
sample.clamp(-0x8000, 0x7fff)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class SID
|
|
6
|
+
# Reduces the SID's one-sample-per-cycle stream to an audio rate by
|
|
7
|
+
# averaging each window. Point sampling would be cheaper, but the pulse
|
|
8
|
+
# and noise waveforms carry enough energy above the output Nyquist to
|
|
9
|
+
# alias audibly.
|
|
10
|
+
#
|
|
11
|
+
# A sample can stand for several cycles at once, when the DSP has run
|
|
12
|
+
# them as one step.
|
|
13
|
+
class Decimator
|
|
14
|
+
def initialize(clock_hz:, rate:)
|
|
15
|
+
@clock_hz = clock_hz
|
|
16
|
+
@rate = rate
|
|
17
|
+
@phase = 0
|
|
18
|
+
@sum = 0
|
|
19
|
+
@count = 0
|
|
20
|
+
@cycles_to_close = window_cycles
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Cycles until the current window closes, counting the next one as 1.
|
|
24
|
+
attr_reader :cycles_to_close
|
|
25
|
+
|
|
26
|
+
# How far the current window has got, in a keyed snapshot module
|
|
27
|
+
# (Snapshot::Keyed) under `prefix`. The clock and the rate are the
|
|
28
|
+
# host's.
|
|
29
|
+
def save_fields(out, prefix)
|
|
30
|
+
out.int("#{prefix}phase", @phase).int("#{prefix}sum", @sum).int("#{prefix}count", @count)
|
|
31
|
+
out.int("#{prefix}cycles_to_close", @cycles_to_close)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def load_fields(input, prefix)
|
|
35
|
+
@phase = input.int("#{prefix}phase", @phase)
|
|
36
|
+
@sum = input.int("#{prefix}sum", @sum)
|
|
37
|
+
@count = input.int("#{prefix}count", @count)
|
|
38
|
+
@cycles_to_close = input.int("#{prefix}cycles_to_close", @cycles_to_close)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Returns the averaged sample when these cycles close a window, and
|
|
42
|
+
# nil otherwise. They must not run past the window's end.
|
|
43
|
+
def push(sample, cycles = 1)
|
|
44
|
+
@sum += sample * cycles
|
|
45
|
+
@count += cycles
|
|
46
|
+
@phase += @rate * cycles
|
|
47
|
+
@cycles_to_close -= cycles
|
|
48
|
+
return unless @phase >= @clock_hz
|
|
49
|
+
|
|
50
|
+
@phase -= @clock_hz
|
|
51
|
+
@cycles_to_close = window_cycles
|
|
52
|
+
average
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def window_cycles = (@clock_hz - @phase + @rate - 1) / @rate
|
|
58
|
+
|
|
59
|
+
def average
|
|
60
|
+
value = @sum.fdiv(@count).round
|
|
61
|
+
@sum = 0
|
|
62
|
+
@count = 0
|
|
63
|
+
value
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|