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,286 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class SID
|
|
6
|
+
class Waveform
|
|
7
|
+
# An oscillator's fields in a keyed snapshot module, under `prefix`:
|
|
8
|
+
# the phase, the noise register and its pipeline, the delayed
|
|
9
|
+
# shapers, the sync edge, the floating output and the pulse level.
|
|
10
|
+
# What the registers set comes from them on load.
|
|
11
|
+
module KeyedState
|
|
12
|
+
# The fields reSID keeps for an oscillator between cycles, for VICE's
|
|
13
|
+
# SIDEXTENDED module: the phase, the noise register, its shift pipeline
|
|
14
|
+
# and reset countdown, the floating output's countdown and the pulse
|
|
15
|
+
# level.
|
|
16
|
+
def resid_fields
|
|
17
|
+
[@accumulator, @shift_register, @shift_pipeline, @shift_register_reset, @floating_ttl, @pulse]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Takes the fields resid_fields gives from `fields`, from `at` on.
|
|
21
|
+
def restore_resid_fields(fields, at)
|
|
22
|
+
@accumulator = fields[at]
|
|
23
|
+
@shift_register = fields[at + 1]
|
|
24
|
+
@shift_pipeline = fields[at + 2]
|
|
25
|
+
@shift_register_reset = fields[at + 3]
|
|
26
|
+
@floating_ttl = fields[at + 4]
|
|
27
|
+
@pulse = fields[at + 5]
|
|
28
|
+
@stale = true
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def save_fields(out, prefix)
|
|
32
|
+
out.int("#{prefix}accumulator", @accumulator).int("#{prefix}shift_register", @shift_register)
|
|
33
|
+
out.int("#{prefix}shift_register_reset", @shift_register_reset)
|
|
34
|
+
out.int("#{prefix}shift_pipeline", @shift_pipeline).int("#{prefix}delayed_triangle", @delayed_triangle)
|
|
35
|
+
out.int("#{prefix}delayed_sawtooth", @delayed_sawtooth).bool("#{prefix}msb_rising", @msb_rising)
|
|
36
|
+
out.int("#{prefix}floating", @floating).int("#{prefix}floating_ttl", @floating_ttl)
|
|
37
|
+
out.int("#{prefix}pulse", @pulse)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def load_fields(input, prefix)
|
|
41
|
+
@accumulator = input.masked("#{prefix}accumulator", @accumulator, 0xffffff)
|
|
42
|
+
@shift_register = input.masked("#{prefix}shift_register", @shift_register, 0x7fffff)
|
|
43
|
+
@shift_register_reset = input.int("#{prefix}shift_register_reset", @shift_register_reset)
|
|
44
|
+
@shift_pipeline = input.int("#{prefix}shift_pipeline", @shift_pipeline)
|
|
45
|
+
@delayed_triangle = input.masked("#{prefix}delayed_triangle", @delayed_triangle, 0xfff)
|
|
46
|
+
@delayed_sawtooth = input.masked("#{prefix}delayed_sawtooth", @delayed_sawtooth, 0xfff)
|
|
47
|
+
@msb_rising = input.bool("#{prefix}msb_rising", @msb_rising)
|
|
48
|
+
@floating = input.masked("#{prefix}floating", @floating, 0xfff)
|
|
49
|
+
@floating_ttl = input.int("#{prefix}floating_ttl", @floating_ttl)
|
|
50
|
+
@pulse = input.masked("#{prefix}pulse", @pulse, 0xfff)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# The frequency, pulse width and control bits as the registers
|
|
54
|
+
# hold them, without the test bit's or the waveform change's
|
|
55
|
+
# effects on the noise register, which already happened.
|
|
56
|
+
def restore_registers(frequency, pulse_width, control)
|
|
57
|
+
@frequency = frequency
|
|
58
|
+
@pulse_width = pulse_width & 0xfff
|
|
59
|
+
@selected = (control >> 4) & 0x0f
|
|
60
|
+
@test = control.anybits?(0x08)
|
|
61
|
+
@ring = control.anybits?(0x04)
|
|
62
|
+
@sync = control.anybits?(0x02)
|
|
63
|
+
@stale = true
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
include KeyedState
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
class Envelope
|
|
71
|
+
# The envelope generator's fields in a keyed snapshot module, under
|
|
72
|
+
# `prefix`: the state, the counters and pipelines between them. The
|
|
73
|
+
# rates and the gate come from the registers on load.
|
|
74
|
+
module KeyedState
|
|
75
|
+
# The fields reSID keeps for an envelope between cycles, for VICE's
|
|
76
|
+
# SIDEXTENDED module: the rate and exponential counters, the level, the
|
|
77
|
+
# state as an index into STATES, whether it holds at zero, the two
|
|
78
|
+
# periods and the pipeline.
|
|
79
|
+
def resid_fields
|
|
80
|
+
[@rate_counter, @exponential_counter, @counter, STATES.index(@state).to_i, @hold_zero ? 1 : 0,
|
|
81
|
+
@rate_period, @exponential_period, @envelope_pipeline]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Takes the fields resid_fields gives from `fields`, from `at` on.
|
|
85
|
+
def restore_resid_fields(fields, at)
|
|
86
|
+
@rate_counter = fields[at]
|
|
87
|
+
@exponential_counter = fields[at + 1]
|
|
88
|
+
@counter = @env3 = fields[at + 2]
|
|
89
|
+
state = fields[at + 3]
|
|
90
|
+
@state = @next_state = STATES.fetch(state.clamp(0, STATES.length - 1)).to_sym
|
|
91
|
+
@hold_zero = fields[at + 4] != 0
|
|
92
|
+
@rate_period = fields[at + 5]
|
|
93
|
+
@exponential_period = fields[at + 6]
|
|
94
|
+
@envelope_pipeline = fields[at + 7]
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def save_fields(out, prefix)
|
|
98
|
+
out.text("#{prefix}state", @state.to_s).text("#{prefix}next_state", @next_state.to_s)
|
|
99
|
+
out.int("#{prefix}counter", @counter).int("#{prefix}env3", @env3)
|
|
100
|
+
out.int("#{prefix}rate_counter", @rate_counter)
|
|
101
|
+
out.int("#{prefix}rate_period", @rate_period).bool("#{prefix}reset_rate_counter", @reset_rate_counter)
|
|
102
|
+
out.int("#{prefix}exponential_counter", @exponential_counter)
|
|
103
|
+
out.int("#{prefix}exponential_period", @exponential_period)
|
|
104
|
+
out.int("#{prefix}state_pipeline", @state_pipeline).int("#{prefix}envelope_pipeline", @envelope_pipeline)
|
|
105
|
+
out.int("#{prefix}exponential_pipeline", @exponential_pipeline).bool("#{prefix}hold_zero", @hold_zero)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def load_fields(input, prefix)
|
|
109
|
+
@state = state_named(input.choice("#{prefix}state", STATE_NAMES, @state.to_s))
|
|
110
|
+
@next_state = state_named(input.choice("#{prefix}next_state", STATE_NAMES, @next_state.to_s))
|
|
111
|
+
@counter = input.byte("#{prefix}counter", @counter)
|
|
112
|
+
@env3 = input.byte("#{prefix}env3", @env3)
|
|
113
|
+
@rate_counter = input.masked("#{prefix}rate_counter", @rate_counter, 0x7fff)
|
|
114
|
+
@rate_period = input.int("#{prefix}rate_period", @rate_period)
|
|
115
|
+
@reset_rate_counter = input.bool("#{prefix}reset_rate_counter", @reset_rate_counter)
|
|
116
|
+
load_pipeline_fields(input, prefix)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# The rates and the gate as the registers hold them.
|
|
120
|
+
def restore_registers(attack_decay, sustain_release, control)
|
|
121
|
+
@attack = (attack_decay >> 4) & 0x0f
|
|
122
|
+
@decay = attack_decay & 0x0f
|
|
123
|
+
@sustain = (sustain_release >> 4) & 0x0f
|
|
124
|
+
@release = sustain_release & 0x0f
|
|
125
|
+
@gate = control.anybits?(0x01)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
private
|
|
129
|
+
|
|
130
|
+
def load_pipeline_fields(input, prefix)
|
|
131
|
+
@exponential_counter = input.int("#{prefix}exponential_counter", @exponential_counter)
|
|
132
|
+
@exponential_period = input.int("#{prefix}exponential_period", @exponential_period)
|
|
133
|
+
@state_pipeline = input.int("#{prefix}state_pipeline", @state_pipeline)
|
|
134
|
+
@envelope_pipeline = input.int("#{prefix}envelope_pipeline", @envelope_pipeline)
|
|
135
|
+
@exponential_pipeline = input.int("#{prefix}exponential_pipeline", @exponential_pipeline)
|
|
136
|
+
@hold_zero = input.bool("#{prefix}hold_zero", @hold_zero)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def state_named(name)
|
|
140
|
+
case name
|
|
141
|
+
when "attack" then :attack
|
|
142
|
+
when "decay_sustain" then :decay_sustain
|
|
143
|
+
else :release
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
STATE_NAMES = STATES.map(&:to_s).freeze
|
|
149
|
+
|
|
150
|
+
include KeyedState
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
class Voice
|
|
154
|
+
# A voice's oscillator under `prefix`wave. and its envelope under
|
|
155
|
+
# `prefix`env.
|
|
156
|
+
module KeyedState
|
|
157
|
+
def save_fields(out, prefix)
|
|
158
|
+
@waveform.save_fields(out, "#{prefix}wave.")
|
|
159
|
+
@envelope.save_fields(out, "#{prefix}env.")
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def load_fields(input, prefix)
|
|
163
|
+
@waveform.load_fields(input, "#{prefix}wave.")
|
|
164
|
+
@envelope.load_fields(input, "#{prefix}env.")
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
include KeyedState
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
class Filter
|
|
172
|
+
class External
|
|
173
|
+
# The output filter's integrators and output, under `prefix`.
|
|
174
|
+
module KeyedState
|
|
175
|
+
def save_fields(out, prefix)
|
|
176
|
+
out.int("#{prefix}lowpass", @lowpass).int("#{prefix}highpass", @highpass).int("#{prefix}output", @output)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def load_fields(input, prefix)
|
|
180
|
+
@lowpass = input.int("#{prefix}lowpass", @lowpass)
|
|
181
|
+
@highpass = input.int("#{prefix}highpass", @highpass)
|
|
182
|
+
@output = input.int("#{prefix}output", @output)
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
include KeyedState
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# The filter's integrators and its last input, under `prefix`, and
|
|
190
|
+
# the output filter's under ext. The cutoff, resonance, routing,
|
|
191
|
+
# mode and volume come from the registers on load.
|
|
192
|
+
module KeyedState
|
|
193
|
+
def save_fields(out, prefix)
|
|
194
|
+
out.int("#{prefix}highpass", @highpass).int("#{prefix}bandpass", @bandpass)
|
|
195
|
+
out.int("#{prefix}lowpass", @lowpass).int("#{prefix}unfiltered", @unfiltered).int("#{prefix}input", @input)
|
|
196
|
+
@external.save_fields(out, "ext.")
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def load_fields(input, prefix)
|
|
200
|
+
@highpass = input.int("#{prefix}highpass", @highpass)
|
|
201
|
+
@bandpass = input.int("#{prefix}bandpass", @bandpass)
|
|
202
|
+
@lowpass = input.int("#{prefix}lowpass", @lowpass)
|
|
203
|
+
@unfiltered = input.int("#{prefix}unfiltered", @unfiltered)
|
|
204
|
+
@input = input.int("#{prefix}input", @input)
|
|
205
|
+
@external.load_fields(input, "ext.")
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# $D415 to $D418 as written.
|
|
209
|
+
def restore_registers(cutoff_low, cutoff_high, resonance, mode_volume)
|
|
210
|
+
self.cutoff = (cutoff_high << 3) | (cutoff_low & 0x07)
|
|
211
|
+
write_resonance(resonance)
|
|
212
|
+
write_mode_volume(mode_volume)
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
include KeyedState
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# The SID's fields in a keyed snapshot module (Snapshot::Keyed): the
|
|
220
|
+
# registers as written, the data bus latch and its decay, each
|
|
221
|
+
# voice's under voice1. to voice3., and the filter's under filter.
|
|
222
|
+
# and ext. Saving catches the DSP up first, so no span or deferred
|
|
223
|
+
# write is left to save. What the registers decode to is worked out
|
|
224
|
+
# from them on load.
|
|
225
|
+
module KeyedState
|
|
226
|
+
def save_fields(out)
|
|
227
|
+
catch_up
|
|
228
|
+
out.bytes("registers", @registers.read(0, 0x20)).int("bus_value", @bus_value).int("bus_ttl", @bus_ttl)
|
|
229
|
+
@voice1.save_fields(out, "voice1.")
|
|
230
|
+
@voice2.save_fields(out, "voice2.")
|
|
231
|
+
@voice3.save_fields(out, "voice3.")
|
|
232
|
+
@filter.save_fields(out, "filter.")
|
|
233
|
+
out
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def load_fields(input)
|
|
237
|
+
@registers.write(0, input.bytes_into("registers", @registers.read(0, 0x20)))
|
|
238
|
+
@bus_value = input.byte("bus_value", @bus_value)
|
|
239
|
+
@bus_ttl = input.int("bus_ttl", @bus_ttl)
|
|
240
|
+
@pending_cycles = 0
|
|
241
|
+
@deferred_writes.clear
|
|
242
|
+
@voice1.load_fields(input, "voice1.")
|
|
243
|
+
@voice2.load_fields(input, "voice2.")
|
|
244
|
+
@voice3.load_fields(input, "voice3.")
|
|
245
|
+
@filter.load_fields(input, "filter.")
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# How far the recording has got into the sample it is averaging,
|
|
249
|
+
# under `prefix`, for a host that carries on recording from a
|
|
250
|
+
# snapshot: it calls #record, then #load_recording_fields.
|
|
251
|
+
def save_recording_fields(out, prefix)
|
|
252
|
+
decimator = @decimator
|
|
253
|
+
raise ArgumentError, "the SID isn't recording" if decimator.nil?
|
|
254
|
+
|
|
255
|
+
decimator.save_fields(out, prefix)
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def load_recording_fields(input, prefix)
|
|
259
|
+
decimator = @decimator
|
|
260
|
+
raise ArgumentError, "the SID isn't recording" if decimator.nil?
|
|
261
|
+
|
|
262
|
+
decimator.load_fields(input, prefix)
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def restored!
|
|
266
|
+
restore_voice(@voice1, 0x00)
|
|
267
|
+
restore_voice(@voice2, 0x07)
|
|
268
|
+
restore_voice(@voice3, 0x0e)
|
|
269
|
+
@filter.restore_registers(register(0x15), register(0x16), register(0x17), register(0x18))
|
|
270
|
+
update_span_rules
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
private
|
|
274
|
+
|
|
275
|
+
def restore_voice(voice, base)
|
|
276
|
+
control = register(base + 4)
|
|
277
|
+
voice.waveform.restore_registers(register(base) | (register(base + 1) << 8),
|
|
278
|
+
register(base + 2) | (register(base + 3) << 8), control)
|
|
279
|
+
voice.envelope.restore_registers(register(base + 5), register(base + 6), control)
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
include KeyedState
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class SID
|
|
6
|
+
# One of the three voices: a waveform generator amplitude-modulated by
|
|
7
|
+
# its envelope.
|
|
8
|
+
#
|
|
9
|
+
# The 6581 waveform DAC swings around a midpoint well above ground, so
|
|
10
|
+
# even a silent voice carries a large DC offset into the mixer. The
|
|
11
|
+
# 8580's is centred and carries none.
|
|
12
|
+
class Voice
|
|
13
|
+
WAVE_ZERO = { mos6581: 0x380, mos8580: 0x800 }.freeze
|
|
14
|
+
DC_OFFSET = { mos6581: 0x800 * 0xff, mos8580: 0 }.freeze
|
|
15
|
+
|
|
16
|
+
attr_reader :waveform, :envelope
|
|
17
|
+
|
|
18
|
+
# Each voice hard-syncs and ring-modulates against the previous one,
|
|
19
|
+
# wrapping from the first back round to the last.
|
|
20
|
+
def self.linked(count, model:)
|
|
21
|
+
voices = Array.new(count) { new(model:) }
|
|
22
|
+
waveforms = voices.map(&:waveform)
|
|
23
|
+
waveforms.each_with_index do |waveform, i|
|
|
24
|
+
waveform.sync_source = waveforms[i - 1]
|
|
25
|
+
waveform.sync_dest = waveforms[(i + 1) % count]
|
|
26
|
+
end
|
|
27
|
+
voices
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def initialize(model: :mos6581)
|
|
31
|
+
@waveform = Waveform.new(model:)
|
|
32
|
+
@envelope = Envelope.new
|
|
33
|
+
@wave_zero = WAVE_ZERO.fetch(model)
|
|
34
|
+
@dc_offset = DC_OFFSET.fetch(model)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def model=(model)
|
|
38
|
+
@waveform.model = model
|
|
39
|
+
@wave_zero = WAVE_ZERO.fetch(model)
|
|
40
|
+
@dc_offset = DC_OFFSET.fetch(model)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def reset!
|
|
44
|
+
@waveform.reset!
|
|
45
|
+
@envelope = Envelope.new
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def control=(value)
|
|
49
|
+
@waveform.control = value
|
|
50
|
+
@envelope.control = value
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def cycle!
|
|
54
|
+
@envelope.cycle!
|
|
55
|
+
@waveform.cycle!
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def fast_forward(cycles)
|
|
59
|
+
@envelope.fast_forward(cycles)
|
|
60
|
+
@waveform.fast_forward(cycles)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def output
|
|
64
|
+
((@waveform.output - @wave_zero) * @envelope.output) + @dc_offset
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class SID
|
|
6
|
+
class Waveform
|
|
7
|
+
# The shapes the chip puts out when more than one waveform is selected.
|
|
8
|
+
#
|
|
9
|
+
# Selecting several shapers connects their outputs to the same twelve
|
|
10
|
+
# DAC lines. Each line settles somewhere between the levels the
|
|
11
|
+
# shapers drive it to, and couples to the lines around it through the
|
|
12
|
+
# resistances between them, so a bit reads high only when enough of
|
|
13
|
+
# its own drive and its neighbours' is high. Modelled here as a
|
|
14
|
+
# threshold on a weighted sum: each selected shaper adds its bit times
|
|
15
|
+
# its strength, a high pulse adds its strength to every line, and the
|
|
16
|
+
# neighbours contribute with one weight per distance below and one per
|
|
17
|
+
# distance above.
|
|
18
|
+
#
|
|
19
|
+
# A low pulse grounds every line.
|
|
20
|
+
#
|
|
21
|
+
# The parameters come from bin/sidwavefit, fitted against OSC3 dumps of
|
|
22
|
+
# real chips in SID/resid-test (oscsample0/1-6581/8580wf30/50/60/70).
|
|
23
|
+
# The tables are built from them once per chip model.
|
|
24
|
+
module Combined
|
|
25
|
+
BITS = 12
|
|
26
|
+
|
|
27
|
+
# Per chip and selection (triangle $1, sawtooth $2, pulse $4): the
|
|
28
|
+
# triangle's strength next to a sawtooth (the sawtooth, or a lone
|
|
29
|
+
# triangle, has strength 1), the pulse's strength, the threshold as
|
|
30
|
+
# a fraction of the full drive, then the weights of the lines one to
|
|
31
|
+
# eleven bits below and one to eleven bits above.
|
|
32
|
+
PARAMETERS = {
|
|
33
|
+
mos6581: {
|
|
34
|
+
0x3 => [0.522, 6.4087, 0.9062,
|
|
35
|
+
0.5304, 0.278, 0.1473, 0.0773, 0.0, 0.0184, 0.0113, 0.0251, 0.0594, 0.2001, 0.2001,
|
|
36
|
+
0.4103, 0.1756, 0.0687, 0.0282, 0.0115, 0.0047, 0.0031, 0.2001, 0.2001, 0.2001, 0.2001],
|
|
37
|
+
0x5 => [5.871, 0.0, 0.7485,
|
|
38
|
+
0.6522, 0.5913, 0.5404, 0.4828, 0.428, 0.361, 0.2955, 0.2453, 0.1558, 0.0501, 0.0016,
|
|
39
|
+
0.7106, 0.6667, 0.6426, 0.6376, 0.5761, 0.6639, 0.7193, 0.4728, 0.4306, 0.392, 0.357],
|
|
40
|
+
0x6 => [3.8329, 4.7751, 0.9565,
|
|
41
|
+
0.815, 0.8302, 0.8204, 0.8107, 0.8511, 0.8416, 0.8322, 0.8728, 0.8636, 0.8545, 0.8954,
|
|
42
|
+
0.8071, 0.7979, 0.7465, 0.7771, 0.7643, 0.7572, 0.7054, 0.4585, 0.4159, 0.3773, 0.3421],
|
|
43
|
+
0x7 => [5.5703, 0.2543, 0.9575,
|
|
44
|
+
0.7177, 0.515, 0.3696, 0.2653, 0.1904, 0.1367, 0.0606, 0.0953, 0.0506, 0.0363, 0.2261,
|
|
45
|
+
0.6347, 0.286, 0.203, 0.0817, 0.0438, 0.1235, 0.2001, 0.2001, 0.2001, 0.2001, 0.2001]
|
|
46
|
+
},
|
|
47
|
+
mos8580: {
|
|
48
|
+
0x3 => [0.2223, 7.7741, 0.8869,
|
|
49
|
+
0.4626, 0.2025, 0.0911, 0.041, 0.0185, 0.0, 0.0008, 0.0, 0.0, 0.0127, 0.0063,
|
|
50
|
+
0.5633, 0.311, 0.2099, 0.0881, 0.0255, 0.0, 0.0431, 0.2002, 0.2002, 0.2002, 0.2002],
|
|
51
|
+
0x5 => [3.1022, 1.1282, 0.9157,
|
|
52
|
+
0.2731, 0.2748, 0.0031, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
|
53
|
+
0.6228, 0.7375, 0.6094, 0.6667, 0.4381, 0.4714, 0.3648, 0.2669, 0.2264, 0.2001, 0.2001],
|
|
54
|
+
0x6 => [0.9477, 0.0012, 0.7837,
|
|
55
|
+
0.2565, 0.2289, 0.1095, 0.0805, 0.0282, 0.0281, 0.0, 0.0, 0.0, 0.0, 0.0063,
|
|
56
|
+
0.3382, 0.3131, 0.3129, 0.2898, 0.233, 0.1762, 0.2135, 0.2002, 0.2002, 0.2002, 0.2002],
|
|
57
|
+
0x7 => [1.219, 1.1111, 0.9473,
|
|
58
|
+
0.3829, 0.1466, 0.0577, 0.0215, 0.0082, 0.0032, 0.0, 0.0, 0.0, 0.0, 0.0,
|
|
59
|
+
0.7273, 0.6845, 0.566, 0.4807, 0.6, 0.1954, 0.4651, 0.2194, 0.2002, 0.2002, 0.2002]
|
|
60
|
+
}
|
|
61
|
+
}.freeze
|
|
62
|
+
|
|
63
|
+
# A compiled parameter set: the weight matrix, and per line the sum
|
|
64
|
+
# of its weights and the threshold against the full drive.
|
|
65
|
+
class Network
|
|
66
|
+
attr_reader :triangle_strength, :pulse_strength
|
|
67
|
+
|
|
68
|
+
def initialize(params)
|
|
69
|
+
@triangle_strength, @pulse_strength, threshold = params[0, 3]
|
|
70
|
+
below = [1.0] + params[3, BITS - 1]
|
|
71
|
+
above = [1.0] + params[3 + BITS - 1, BITS - 1]
|
|
72
|
+
@weights = Array.new(BITS) do |i|
|
|
73
|
+
Array.new(BITS) { |j| j <= i ? below[i - j] : above[j - i] }.freeze
|
|
74
|
+
end.freeze
|
|
75
|
+
@norms = @weights.map(&:sum).freeze
|
|
76
|
+
@threshold = threshold
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# `drives` holds [bits, strength] for each selected shaper; a high
|
|
80
|
+
# pulse is passed separately, as it drives every line alike.
|
|
81
|
+
def shape(drives, pulse)
|
|
82
|
+
total = drives.sum { |_, strength| strength }
|
|
83
|
+
total += @pulse_strength if pulse
|
|
84
|
+
out = 0
|
|
85
|
+
BITS.times do |i|
|
|
86
|
+
level = pulse ? @pulse_strength * @norms[i] : 0.0
|
|
87
|
+
weights = @weights[i]
|
|
88
|
+
drives.each do |bits, strength|
|
|
89
|
+
BITS.times { |j| level += weights[j] * strength if bits[j] == 1 }
|
|
90
|
+
end
|
|
91
|
+
out |= 1 << i if level >= @threshold * @norms[i] * total
|
|
92
|
+
end
|
|
93
|
+
out
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
module_function
|
|
98
|
+
|
|
99
|
+
# The pulse-high shapes of the four combinations without noise.
|
|
100
|
+
def tables(model)
|
|
101
|
+
@tables ||= {}
|
|
102
|
+
@tables[model] ||= PARAMETERS.fetch(model).to_h do |selected, params|
|
|
103
|
+
[selected, table(selected, params)]
|
|
104
|
+
end.freeze
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# One combination's shapes, indexed by the phase (the sawtooth), or
|
|
108
|
+
# for triangle and pulse by the triangle. A triangle combined with a
|
|
109
|
+
# sawtooth is never folded, so it is the phase shifted left one bit.
|
|
110
|
+
def table(selected, params)
|
|
111
|
+
network = Network.new(params)
|
|
112
|
+
Array.new(1 << BITS) do |index|
|
|
113
|
+
triangle = selected == 0x5 ? index : (index << 1) & 0xfff
|
|
114
|
+
network.shape(drives(selected, network, index, triangle), selected.anybits?(0x4))
|
|
115
|
+
end.freeze
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def drives(selected, network, saw, triangle)
|
|
119
|
+
drives = []
|
|
120
|
+
drives << [saw, 1.0] if selected.anybits?(0x2)
|
|
121
|
+
drives << [triangle, selected.anybits?(0x2) ? network.triangle_strength : 1.0] if selected.anybits?(0x1)
|
|
122
|
+
drives
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class SID
|
|
6
|
+
class Waveform
|
|
7
|
+
# Running an oscillator many cycles in one step, for the catch-ups that
|
|
8
|
+
# fast-forward the voices between whole cycles.
|
|
9
|
+
module FastForward
|
|
10
|
+
# Runs `cycles` cycles as #cycle! would, for an oscillator that is not
|
|
11
|
+
# feeding back. What those cycles latch onto the output is left to the
|
|
12
|
+
# whole cycle that follows, which latches over it.
|
|
13
|
+
def fast_forward(cycles)
|
|
14
|
+
drain_floating(cycles) if @selected.zero?
|
|
15
|
+
if @test
|
|
16
|
+
bleed_shift_register(cycles)
|
|
17
|
+
else
|
|
18
|
+
while @shift_pipeline != 0 && cycles != 0
|
|
19
|
+
advance
|
|
20
|
+
cycles -= 1
|
|
21
|
+
end
|
|
22
|
+
skip_ahead(cycles) if cycles != 0 && @frequency != 0
|
|
23
|
+
compare_pulse(((@accumulator - @frequency) & 0xffffff) >> 12)
|
|
24
|
+
end
|
|
25
|
+
@stale = true
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# The cycle on which the accumulator MSB next rises, counting the next
|
|
29
|
+
# one as 1, or nil if it never will. The test bit leaves the last
|
|
30
|
+
# rise standing for as long as it is held.
|
|
31
|
+
def cycles_to_msb_rise
|
|
32
|
+
return (@msb_rising ? 1 : nil) if @test
|
|
33
|
+
return if @frequency.zero?
|
|
34
|
+
|
|
35
|
+
distance = (MSB - @accumulator) & 0xffffff
|
|
36
|
+
distance = 0x1000000 if distance.zero?
|
|
37
|
+
(distance + @frequency - 1) / @frequency
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# A combined waveform with sawtooth (on the 6581) or noise in the mix
|
|
41
|
+
# writes back into the oscillator every cycle, so it cannot be
|
|
42
|
+
# fast-forwarded. Triangle and pulse alone write nothing back.
|
|
43
|
+
def feedback?
|
|
44
|
+
combined_waveform? && (@selected.anybits?(0x8) || (@topbit_feedback && @selected.anybits?(0x2)))
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Whether a catch-up has to run this oscillator a cycle at a time.
|
|
48
|
+
# While synthesizing, every combined waveform does, so the filter
|
|
49
|
+
# integrates it a cycle at a time.
|
|
50
|
+
def stepped?(synthesizing) = synthesizing ? combined_waveform? : feedback?
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def combined_waveform? = !@test && combined?(@selected)
|
|
55
|
+
|
|
56
|
+
# Advances an accumulator with no shift in flight. Each rise of bit 19
|
|
57
|
+
# shifts the LFSR two cycles on, so a rise in the last two cycles
|
|
58
|
+
# leaves its shift pending for the cycles after.
|
|
59
|
+
def skip_ahead(cycles)
|
|
60
|
+
previous = @accumulator
|
|
61
|
+
@accumulator += @frequency * cycles
|
|
62
|
+
rises = bit19_rises(previous, @accumulator)
|
|
63
|
+
if rises != 0
|
|
64
|
+
@shift_pipeline = pipeline_after(cycles)
|
|
65
|
+
rises -= 1 if @shift_pipeline != 0
|
|
66
|
+
rises.times { shift_noise }
|
|
67
|
+
end
|
|
68
|
+
@accumulator &= 0xffffff
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Bit 19 rises at most once a cycle, on each odd multiple of 2^19,
|
|
72
|
+
# and at most once in any eight.
|
|
73
|
+
def bit19_rises(from, to) = ((to + 0x80000) >> 20) - ((from + 0x80000) >> 20)
|
|
74
|
+
|
|
75
|
+
# How far a rise on one of the last two cycles has come.
|
|
76
|
+
def pipeline_after(cycles)
|
|
77
|
+
last = @accumulator - @frequency
|
|
78
|
+
return 2 if bit19_rises(last, @accumulator) != 0
|
|
79
|
+
return 1 if cycles > 1 && bit19_rises(last - @frequency, last) != 0
|
|
80
|
+
|
|
81
|
+
0
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def drain_floating(cycles)
|
|
85
|
+
return if @floating_ttl.zero?
|
|
86
|
+
|
|
87
|
+
@floating_ttl -= cycles
|
|
88
|
+
return unless @floating_ttl <= 0
|
|
89
|
+
|
|
90
|
+
@floating_ttl = 0
|
|
91
|
+
@floating = 0x000
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def bleed_shift_register(cycles = 1)
|
|
95
|
+
return if @shift_register_reset.zero?
|
|
96
|
+
|
|
97
|
+
@shift_register_reset -= cycles
|
|
98
|
+
return unless @shift_register_reset <= 0
|
|
99
|
+
|
|
100
|
+
@shift_register_reset = 0
|
|
101
|
+
@shift_register = SHIFT_REGISTER_RESET
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|