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,124 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class SID
|
|
6
|
+
class Waveform
|
|
7
|
+
# Noise combined with other waveforms: the output lines write back into
|
|
8
|
+
# the LFSR, and what they write is not always what OSC3 reads.
|
|
9
|
+
module NoiseWriteback
|
|
10
|
+
# The LFSR bits the noise shaper reads, paired with the output bit each
|
|
11
|
+
# one drives (Dag Lem's diagram in SID/noise-reset_new). A combined
|
|
12
|
+
# waveform drives the same lines, so a bit held low there is written
|
|
13
|
+
# back into the register.
|
|
14
|
+
NOISE_TAPS = [[0x100000, 0x800], [0x040000, 0x400], [0x004000, 0x200],
|
|
15
|
+
[0x000800, 0x100], [0x000200, 0x080], [0x000020, 0x040],
|
|
16
|
+
[0x000004, 0x020], [0x000001, 0x010]].freeze
|
|
17
|
+
|
|
18
|
+
# Pulse+noise with the pulse high: the noise lines next to the four
|
|
19
|
+
# below them, which nothing drives, are pulled low. The OSC3 read and
|
|
20
|
+
# the LFSR writeback see the same lines against different thresholds,
|
|
21
|
+
# so they lose a different number of bits. The 8580's pair is the one
|
|
22
|
+
# that reproduces SID/wf12nsr's pulse+noise row (it reads $f8, and the
|
|
23
|
+
# writeback leaves $fc behind), and SID/wb_testsuite's C->9 and C->E
|
|
24
|
+
# rows need that same $fc written at release. The 6581 reads $00 of a
|
|
25
|
+
# full register (SID/wf12nsr's pulse+noise row) and pulls nothing
|
|
26
|
+
# while the register holds: wb_testsuite's 8->C and C->C rows run
|
|
27
|
+
# pulse+noise and leave the register alone. Its lines only land
|
|
28
|
+
# part way through a shift (#write_back_shift).
|
|
29
|
+
PULSE_NOISE_READ = { mos6581: 0x000, mos8580: 0xf80 }.freeze
|
|
30
|
+
PULSE_NOISE_WRITE = { mos6581: 0xff0, mos8580: 0xfc0 }.freeze
|
|
31
|
+
|
|
32
|
+
# What a 6581 writes back when the test bit falls with only pulse+noise
|
|
33
|
+
# common to the old waveform and the new one (SID/wb_testsuite's D->C,
|
|
34
|
+
# E->C, F->C and D->E rows).
|
|
35
|
+
PULSE_NOISE_RELEASE = 0xf80
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
# What the lines write into the LFSR, against a lower threshold than
|
|
40
|
+
# OSC3 reads them by: a line left high between two low ones reads high
|
|
41
|
+
# (SID/noisewriteback's noise_writeback_test2) but is written low
|
|
42
|
+
# (SID/wf12nsr's noise+triangle and noise+sawtooth rows).
|
|
43
|
+
def write_back(selected, value)
|
|
44
|
+
return value & ((value << 1) | (value >> 1)) unless selected == 0xc
|
|
45
|
+
return 0x000 if @pulse.zero?
|
|
46
|
+
|
|
47
|
+
noise & @pulse_noise_write
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# What the lines write while the register is part way through a
|
|
51
|
+
# shift, where the 6581's pulse+noise writes its output as read.
|
|
52
|
+
def write_back_mid_shift(selected, value)
|
|
53
|
+
return value if pulse_noise_mid_shift?(selected)
|
|
54
|
+
|
|
55
|
+
write_back(selected, value)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def pulse_noise_mid_shift?(selected) = @topbit_feedback && selected == 0xc
|
|
59
|
+
|
|
60
|
+
def write_shift_register(value)
|
|
61
|
+
NOISE_TAPS.each { |bit, line| @shift_register &= ~bit if value.nobits?(line) }
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# The second phase of a shift writes back by the test bit release
|
|
65
|
+
# rule with the waveform left alone. The 6581's pulse+noise, which
|
|
66
|
+
# that rule leaves out, writes its lines too (SID/wf12nsr's
|
|
67
|
+
# pulse+noise row).
|
|
68
|
+
def write_back_shift
|
|
69
|
+
return unless pulse_noise_mid_shift?(@selected) || release_writes_back?(@selected, @selected)
|
|
70
|
+
|
|
71
|
+
write_shift_register(write_back_mid_shift(@selected, @output))
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Setting the test bit starts the bleed, and stalls the register part
|
|
75
|
+
# way through a shift, where a noise combination writes its output
|
|
76
|
+
# back first, from the accumulator it had. SID/noiselfsrinit's
|
|
77
|
+
# $f8/$80 pairs set the bit onto all four from noise alone, and
|
|
78
|
+
# SID/wf12nsr's pulse+noise row sets it onto pulse+noise.
|
|
79
|
+
def raise_test
|
|
80
|
+
@shift_register_reset = @shift_register_reset_delay
|
|
81
|
+
return unless @selected.anybits?(0x8) && combined?(@selected) && @shift_pipeline != 1
|
|
82
|
+
|
|
83
|
+
write_shift_register(write_back_mid_shift(@selected, shape(@selected)))
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Releasing the test bit finishes the shift it interrupted: the old
|
|
87
|
+
# waveform's output may be written back first, then a bit clocks in
|
|
88
|
+
# over the forced-high bit 22.
|
|
89
|
+
def release_test(previous)
|
|
90
|
+
value = release_write(previous)
|
|
91
|
+
write_shift_register(value) if value
|
|
92
|
+
shift_noise(1)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# What the release writes over the taps, or nil. On the 6581, a change
|
|
96
|
+
# that keeps only pulse+noise of the old waveform writes the lowest
|
|
97
|
+
# noise lines low. On the 8580, a change from pulse+noise to all four
|
|
98
|
+
# writes every line low.
|
|
99
|
+
def release_write(previous)
|
|
100
|
+
if @topbit_feedback
|
|
101
|
+
return noise & PULSE_NOISE_RELEASE if previous != 0xc && (previous & @selected) == 0xc
|
|
102
|
+
elsif previous == 0xc && @selected == 0xf
|
|
103
|
+
return 0x000
|
|
104
|
+
end
|
|
105
|
+
write_back(previous, shape(previous)) if release_writes_back?(previous, @selected)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Which waveform changes write the old output back as the test bit
|
|
109
|
+
# falls (SID/wb_testsuite, after libresidfp's do_writeback). Noise has
|
|
110
|
+
# to have been combined before and still be combined after. Nothing
|
|
111
|
+
# is written back on changing to pulse+noise or from pulse+noise to
|
|
112
|
+
# sawtooth+noise, nor, on the 6581, on trading triangle for sawtooth
|
|
113
|
+
# or back.
|
|
114
|
+
def release_writes_back?(previous, selected)
|
|
115
|
+
return false if previous <= 0x8 || selected <= 0x8
|
|
116
|
+
return false if selected == 0xc || (previous == 0xc && selected == 0xa)
|
|
117
|
+
|
|
118
|
+
!(@topbit_feedback && [previous & 0x3, selected & 0x3].sort == [0x1, 0x2])
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "badline/chips/sid/waveform/combined"
|
|
4
|
+
require "badline/chips/sid/waveform/fast_forward"
|
|
5
|
+
require "badline/chips/sid/waveform/noise_writeback"
|
|
6
|
+
|
|
7
|
+
module Badline
|
|
8
|
+
module Chips
|
|
9
|
+
class SID
|
|
10
|
+
# Waveform generator: a 24-bit phase accumulator and the shapers that
|
|
11
|
+
# read it.
|
|
12
|
+
#
|
|
13
|
+
# The accumulator advances by the 16-bit frequency every cycle, so every
|
|
14
|
+
# waveform is a pure function of the phase. Bit 23 drives hard sync and
|
|
15
|
+
# the triangle fold, bit 19 clocks the noise LFSR.
|
|
16
|
+
#
|
|
17
|
+
# Selecting more than one waveform shorts the shapers onto the lines the
|
|
18
|
+
# oscillator itself reads back, so a combined waveform is not only a
|
|
19
|
+
# shape: a low top bit reaches the accumulator MSB through the sawtooth
|
|
20
|
+
# switch, and noise in the mix is written back into the LFSR. The shape
|
|
21
|
+
# itself comes from Combined's model of the lines pulling on each other.
|
|
22
|
+
#
|
|
23
|
+
# The pulse comparator's output reaches the lines a cycle after the
|
|
24
|
+
# accumulator it compared.
|
|
25
|
+
#
|
|
26
|
+
# With nothing selected the DAC input floats, holding the last value
|
|
27
|
+
# driven onto it until the charge drains away.
|
|
28
|
+
class Waveform
|
|
29
|
+
include FastForward
|
|
30
|
+
include NoiseWriteback
|
|
31
|
+
|
|
32
|
+
# All bits high at power up, odd ones stored inverted (SID/oscinit).
|
|
33
|
+
POWER_ON_ACCUMULATOR = 0x555555
|
|
34
|
+
|
|
35
|
+
# Holding the test bit bleeds every LFSR bit high; the power-on state is
|
|
36
|
+
# one shift further on, which is what releasing the bit leaves behind.
|
|
37
|
+
SHIFT_REGISTER_RESET = 0x7fffff
|
|
38
|
+
NOISE_SEED = 0x7ffffe
|
|
39
|
+
|
|
40
|
+
# Cycles the test bit needs to bleed the LFSR high. SID/bitfade's
|
|
41
|
+
# delaynoise measures ~$950000 on a real 8580. Nothing measures the
|
|
42
|
+
# 6581: SID/resid-test's oscsample dumps show it holding its bits
|
|
43
|
+
# through the ~$8800 cycles between runs, and the slow reset
|
|
44
|
+
# (SID/noise-reset_old) allows it a second.
|
|
45
|
+
SHIFT_REGISTER_RESET_DELAY = { mos6581: 0x80000, mos8580: 0x950000 }.freeze
|
|
46
|
+
|
|
47
|
+
# Cycles the floating DAC input holds its charge (SID/osc3-wave0).
|
|
48
|
+
FLOATING_OUTPUT_TTL = 0x4000
|
|
49
|
+
|
|
50
|
+
MSB = 0x800000
|
|
51
|
+
|
|
52
|
+
attr_accessor :sync_source, :sync_dest
|
|
53
|
+
attr_reader :accumulator, :shift_register, :frequency, :pulse_width, :pulse
|
|
54
|
+
|
|
55
|
+
def initialize(model: :mos6581)
|
|
56
|
+
use_model(model)
|
|
57
|
+
@tri_saw_delay = model == :mos8580
|
|
58
|
+
@accumulator = POWER_ON_ACCUMULATOR
|
|
59
|
+
@sync_source = @sync_dest = self
|
|
60
|
+
reset!
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# The running state carries over. A 6581 never delays its shapers, so
|
|
64
|
+
# the 8580's delayed triangle and sawtooth start from the current phase.
|
|
65
|
+
def model=(model)
|
|
66
|
+
use_model(model)
|
|
67
|
+
if model == :mos8580 && !@tri_saw_delay
|
|
68
|
+
@delayed_sawtooth = sawtooth
|
|
69
|
+
@delayed_triangle = triangle
|
|
70
|
+
end
|
|
71
|
+
@tri_saw_delay = model == :mos8580
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# The RES line clears the registers and reseeds the LFSR, but leaves
|
|
75
|
+
# the accumulator alone (SID/oscinit).
|
|
76
|
+
def reset!
|
|
77
|
+
@delayed_sawtooth = @delayed_triangle = 0x000
|
|
78
|
+
@shift_register = NOISE_SEED
|
|
79
|
+
@shift_register_reset = 0
|
|
80
|
+
@shift_pipeline = 0
|
|
81
|
+
@frequency = 0x0000
|
|
82
|
+
@pulse_width = 0x000
|
|
83
|
+
@selected = 0x0
|
|
84
|
+
@test = false
|
|
85
|
+
@ring = false
|
|
86
|
+
@sync = false
|
|
87
|
+
@msb_rising = false
|
|
88
|
+
@floating = 0x000
|
|
89
|
+
@floating_ttl = 0
|
|
90
|
+
@pulse = 0xfff
|
|
91
|
+
@output = 0x000
|
|
92
|
+
@stale = true
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def sync? = @sync
|
|
96
|
+
def msb_rising? = @msb_rising
|
|
97
|
+
|
|
98
|
+
def frequency_low=(value)
|
|
99
|
+
@frequency = (@frequency & 0xff00) | value
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def frequency_high=(value)
|
|
103
|
+
@frequency = (value << 8) | (@frequency & 0x00ff)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def pulse_width_low=(value)
|
|
107
|
+
@pulse_width = (@pulse_width & 0xf00) | value
|
|
108
|
+
@stale = true
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def pulse_width_high=(value)
|
|
112
|
+
@pulse_width = ((value & 0x0f) << 8) | (@pulse_width & 0x0ff)
|
|
113
|
+
@stale = true
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# The test bit clears the accumulator and stalls the LFSR half way
|
|
117
|
+
# through a shift, holding bit 22 high while its bits bleed up.
|
|
118
|
+
def control=(value)
|
|
119
|
+
previous = @selected
|
|
120
|
+
@selected = (value >> 4) & 0x0f
|
|
121
|
+
@ring = value.anybits?(0x04)
|
|
122
|
+
@sync = value.anybits?(0x02)
|
|
123
|
+
test = value.anybits?(0x08)
|
|
124
|
+
if test
|
|
125
|
+
raise_test unless @test
|
|
126
|
+
@accumulator = 0x000000
|
|
127
|
+
@pulse = 0xfff
|
|
128
|
+
@shift_pipeline = 0
|
|
129
|
+
elsif @test
|
|
130
|
+
release_test(previous)
|
|
131
|
+
end
|
|
132
|
+
@test = test
|
|
133
|
+
@stale = true
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def cycle!
|
|
137
|
+
latch_output
|
|
138
|
+
compare_pulse
|
|
139
|
+
@test ? bleed_shift_register : advance
|
|
140
|
+
@stale = true
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Hard sync resets the next voice's accumulator when ours wraps. A
|
|
144
|
+
# source that is itself synced on the cycle its own MSB rises does not
|
|
145
|
+
# pass the sync on.
|
|
146
|
+
def synchronize!
|
|
147
|
+
return unless @msb_rising && @sync_dest.sync? &&
|
|
148
|
+
!(@sync && @sync_source.msb_rising?)
|
|
149
|
+
|
|
150
|
+
@sync_dest.reset_accumulator
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def reset_accumulator
|
|
154
|
+
@accumulator = 0x000000
|
|
155
|
+
@stale = true
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Held for the rest of the cycle once computed, so the filter, OSC3 and
|
|
159
|
+
# the oscillator's own feedback all see one value per cycle.
|
|
160
|
+
def output
|
|
161
|
+
return @output unless @stale
|
|
162
|
+
|
|
163
|
+
@stale = false
|
|
164
|
+
@output = @selected.zero? ? @floating : shape(@selected)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# What OSC3 reads. The 8580 delays the triangle and sawtooth shapers
|
|
168
|
+
# by half a cycle, which OSC3 latches as a whole cycle late; pulse and
|
|
169
|
+
# noise still reach the lines on time.
|
|
170
|
+
def osc3
|
|
171
|
+
return output unless @tri_saw_delay && @selected.anybits?(0x3)
|
|
172
|
+
|
|
173
|
+
shape(@selected, @delayed_sawtooth, @delayed_triangle)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def sawtooth = @accumulator >> 12
|
|
177
|
+
|
|
178
|
+
# The upper half of the ramp is folded back down, shifted left one bit
|
|
179
|
+
# to keep the full 12-bit range.
|
|
180
|
+
def triangle(selected = @selected)
|
|
181
|
+
folded = inverted?(selected) ? @accumulator ^ 0xffffff : @accumulator
|
|
182
|
+
(folded >> 11) & 0xfff
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Eight taps off the 23-bit LFSR, gathered into a 12-bit sample.
|
|
186
|
+
def noise
|
|
187
|
+
((@shift_register & 0x100000) >> 9) |
|
|
188
|
+
((@shift_register & 0x040000) >> 8) |
|
|
189
|
+
((@shift_register & 0x004000) >> 5) |
|
|
190
|
+
((@shift_register & 0x000800) >> 3) |
|
|
191
|
+
((@shift_register & 0x000200) >> 2) |
|
|
192
|
+
((@shift_register & 0x000020) << 1) |
|
|
193
|
+
((@shift_register & 0x000004) << 3) |
|
|
194
|
+
((@shift_register & 0x000001) << 4)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
private
|
|
198
|
+
|
|
199
|
+
def use_model(model)
|
|
200
|
+
@topbit_feedback = model != :mos8580
|
|
201
|
+
@pulse_noise_read = PULSE_NOISE_READ.fetch(model)
|
|
202
|
+
@pulse_noise_write = PULSE_NOISE_WRITE.fetch(model)
|
|
203
|
+
@combined = Combined.tables(model)
|
|
204
|
+
@shift_register_reset_delay = SHIFT_REGISTER_RESET_DELAY.fetch(model)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def shape(selected, saw = sawtooth, tri = triangle(selected))
|
|
208
|
+
case selected
|
|
209
|
+
when 0x1 then tri
|
|
210
|
+
when 0x2 then saw
|
|
211
|
+
when 0x4 then @pulse
|
|
212
|
+
when 0x8 then noise
|
|
213
|
+
else combined(selected, saw, tri)
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# A low pulse grounds every line. Noise with pulse alone loses its
|
|
218
|
+
# lowest lines; noise with triangle or sawtooth is ANDed over the rest
|
|
219
|
+
# of the mix.
|
|
220
|
+
def combined(selected, saw, tri)
|
|
221
|
+
return 0x000 if selected.anybits?(0x4) && @pulse.zero?
|
|
222
|
+
return noise & @pulse_noise_read if selected == 0xc
|
|
223
|
+
|
|
224
|
+
rest = selected & 0x7
|
|
225
|
+
value = case rest
|
|
226
|
+
when 0x1 then tri
|
|
227
|
+
when 0x2 then saw
|
|
228
|
+
when 0x4 then 0xfff
|
|
229
|
+
else @combined[rest][rest == 0x5 ? tri : saw]
|
|
230
|
+
end
|
|
231
|
+
selected.anybits?(0x8) ? value & noise : value
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def compare_pulse(phase = @accumulator >> 12) = (@pulse = @test || phase >= @pulse_width ? 0xfff : 0x000)
|
|
235
|
+
|
|
236
|
+
# More than one bit set in the selection.
|
|
237
|
+
def combined?(selected) = selected & (selected - 1) != 0
|
|
238
|
+
|
|
239
|
+
# The one point in the cycle where the waveform selector drives the DAC:
|
|
240
|
+
# either it latches a fresh value, or nothing drives the line and the
|
|
241
|
+
# charge already on it drains a little further.
|
|
242
|
+
def latch_output
|
|
243
|
+
value = output
|
|
244
|
+
if @tri_saw_delay
|
|
245
|
+
@delayed_sawtooth = sawtooth
|
|
246
|
+
@delayed_triangle = triangle
|
|
247
|
+
end
|
|
248
|
+
if @selected.zero?
|
|
249
|
+
drain_floating(1)
|
|
250
|
+
return
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
@floating = value
|
|
254
|
+
@floating_ttl = FLOATING_OUTPUT_TTL
|
|
255
|
+
feed_back(value) if combined?(@selected) && !@test
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
# A zero on the shared output lines travels back into the oscillator:
|
|
259
|
+
# through the sawtooth switch it clears the accumulator MSB on the next
|
|
260
|
+
# cycle, and with noise selected it lands in the LFSR, where a bit
|
|
261
|
+
# pulled low can never come back. The 8580 buffers the top bit behind a
|
|
262
|
+
# flip-flop before the sawtooth switch, so only the LFSR sees it. In the
|
|
263
|
+
# first phase of a shift the register bits float, so nothing is pulled
|
|
264
|
+
# down: the output is latched instead, for the second phase to write.
|
|
265
|
+
def feed_back(value)
|
|
266
|
+
@accumulator &= ~MSB if @topbit_feedback && @selected.anybits?(0x2) && value.nobits?(0x800)
|
|
267
|
+
write_shift_register(write_back(@selected, value)) if @selected.anybits?(0x8) && @shift_pipeline != 1
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
# A rise of bit 19 starts a shift that takes two more cycles
|
|
271
|
+
# (SID/noisewriteback's noise_writeback_test2, after libresidfp's shift
|
|
272
|
+
# pipeline). The first phase latches the output, and the second writes
|
|
273
|
+
# it over the taps before the register shifts.
|
|
274
|
+
def advance
|
|
275
|
+
previous = @accumulator
|
|
276
|
+
@accumulator = (previous + @frequency) & 0xffffff
|
|
277
|
+
@msb_rising = @accumulator & ~previous & MSB != 0
|
|
278
|
+
if @accumulator & ~previous & 0x080000 != 0
|
|
279
|
+
@shift_pipeline = 2
|
|
280
|
+
elsif @shift_pipeline != 0 && (@shift_pipeline -= 1).zero?
|
|
281
|
+
write_back_shift
|
|
282
|
+
shift_noise
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
# Bit 0 feeds back bits 22 and 17, with the test bit forcing bit 22 high.
|
|
287
|
+
def shift_noise(forced = 0)
|
|
288
|
+
bit0 = ((@shift_register >> 22) | forced) ^ (@shift_register >> 17)
|
|
289
|
+
@shift_register = ((@shift_register << 1) & 0x7fffff) | (bit0 & 0x1)
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
# TriXOR = !Saw & ((!V3 & Ring) ^ bit23), where V3 is the modulating
|
|
293
|
+
# voice's MSB (SID/ringmod).
|
|
294
|
+
def inverted?(selected)
|
|
295
|
+
return false if selected & 0x2 != 0
|
|
296
|
+
|
|
297
|
+
msb = @accumulator & MSB != 0
|
|
298
|
+
return msb unless @ring
|
|
299
|
+
|
|
300
|
+
msb == (@sync_source.accumulator & MSB != 0)
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
end
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "badline/chips/sid/waveform"
|
|
4
|
+
require "badline/chips/sid/envelope"
|
|
5
|
+
require "badline/chips/sid/voice"
|
|
6
|
+
require "badline/chips/sid/filter"
|
|
7
|
+
require "badline/chips/sid/decimator"
|
|
8
|
+
require "badline/chips/sid/catch_up"
|
|
9
|
+
require "badline/chips/sid/keyed_parts"
|
|
10
|
+
|
|
11
|
+
module Badline
|
|
12
|
+
module Chips
|
|
13
|
+
# SID (Sound Interface Device) chip, in either the 6581 or the 8580
|
|
14
|
+
# revision.
|
|
15
|
+
#
|
|
16
|
+
# $D400-$D418 - Voices, filter and volume - write only
|
|
17
|
+
# $D419-$D41A - POTX/POTY paddle inputs - read only
|
|
18
|
+
# $D41B-$D41C - Voice 3 oscillator/envelope - read only
|
|
19
|
+
# $D41D-$D41F - Unconnected
|
|
20
|
+
#
|
|
21
|
+
# The register file mirrors every 32 bytes up to $D7FF. A second or
|
|
22
|
+
# third SID, which only the SID player fits, is built `at` another
|
|
23
|
+
# address and decodes just the 32 bytes there.
|
|
24
|
+
#
|
|
25
|
+
# Reading a write-only or unconnected register returns the last byte the
|
|
26
|
+
# SID saw on the data bus. That value fades to $00 as the capacitance
|
|
27
|
+
# holding it drains. Paddles and the 1351 mouse attach as a pots source
|
|
28
|
+
# responding to #pot_x and #pot_y; with none attached the lines read $FF.
|
|
29
|
+
#
|
|
30
|
+
# Three voices feed the filter and the master volume; #output and #sample
|
|
31
|
+
# read out the mixed result, and #record collects it at an audio rate for
|
|
32
|
+
# #drain_samples. The DSP is clocked lazily and catches up when something
|
|
33
|
+
# asks for its state.
|
|
34
|
+
#
|
|
35
|
+
# The 6581 drives its voices well above ground, so the mix carries a large
|
|
36
|
+
# DC offset that the RC network on the C64 board filters out.
|
|
37
|
+
class SID
|
|
38
|
+
include Addressable
|
|
39
|
+
include CatchUp
|
|
40
|
+
|
|
41
|
+
VOICES = 3
|
|
42
|
+
|
|
43
|
+
# Cycles the data bus holds a value, measured through SID/bitfade.
|
|
44
|
+
BUS_TTL = { mos6581: 0x1d00, mos8580: 0xa2000 }.freeze
|
|
45
|
+
|
|
46
|
+
# Scales the filter's 20-bit mix down to a signed 16-bit sample, as
|
|
47
|
+
# reSID 0.16 does: three voices at full swing and volume 15 span the
|
|
48
|
+
# whole range, on either chip.
|
|
49
|
+
SAMPLE_DIVISOR = ((0xfff * 0xff) >> 7) * 3 * 15 * 2 / (2**16)
|
|
50
|
+
|
|
51
|
+
# Writes the DSP queues between catch-ups. A full queue catches up
|
|
52
|
+
# there and then, so no write loses its timing.
|
|
53
|
+
DEFERRED_WRITES = 0x400
|
|
54
|
+
|
|
55
|
+
# Cycles the filter integrates in one step while synthesizing, after
|
|
56
|
+
# reSID's delta_t_flt. 1 makes the audio exact, at a per-cycle cost.
|
|
57
|
+
FILTER_CHUNK = 4
|
|
58
|
+
|
|
59
|
+
attr_accessor :pots
|
|
60
|
+
attr_reader :model
|
|
61
|
+
|
|
62
|
+
def initialize(model: :mos6581, pots: nil, filter_chunk: FILTER_CHUNK, at: 0xd400)
|
|
63
|
+
addressable_at(at, length: at == 0xd400 ? 2**10 : 2**5)
|
|
64
|
+
@model = model
|
|
65
|
+
@pots = pots
|
|
66
|
+
@bus_ttl_reset = BUS_TTL.fetch(model)
|
|
67
|
+
@filter = Filter.new(model:)
|
|
68
|
+
@synthesizing = false
|
|
69
|
+
@stepped = @synced = false
|
|
70
|
+
@pending_cycles = 0
|
|
71
|
+
@deferred_writes = []
|
|
72
|
+
@decimator = nil
|
|
73
|
+
@samples = []
|
|
74
|
+
@voice_samples = nil
|
|
75
|
+
@filter_chunk = filter_chunk
|
|
76
|
+
@voices = Voice.linked(VOICES, model:)
|
|
77
|
+
@voice1, @voice2, @voice3 = @voices
|
|
78
|
+
@waveform1, @waveform2, @waveform3 = @voices.map(&:waveform)
|
|
79
|
+
reset!
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Switches the chip, its filter and its voices to the other model's
|
|
83
|
+
# values. The cycles already passed run on the old model first, and the
|
|
84
|
+
# running state carries over.
|
|
85
|
+
def model=(model)
|
|
86
|
+
catch_up
|
|
87
|
+
@model = model
|
|
88
|
+
@bus_ttl_reset = BUS_TTL.fetch(model)
|
|
89
|
+
@filter.model = model
|
|
90
|
+
@voices.each { |voice| voice.model = model }
|
|
91
|
+
update_span_rules
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# The RES line clears the registers, the data bus, the filter and the
|
|
95
|
+
# voices, all but their accumulators. Recording carries on across it.
|
|
96
|
+
def reset!
|
|
97
|
+
catch_up
|
|
98
|
+
@registers = Memory.new(length: 2**5)
|
|
99
|
+
@bus_value = 0x00
|
|
100
|
+
@bus_ttl = 0
|
|
101
|
+
@voices.each(&:reset!)
|
|
102
|
+
@filter.reset
|
|
103
|
+
update_span_rules
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# The DSP only counts cycles as they pass. Whatever asks for its state
|
|
107
|
+
# catches it up, a span at a time: each span fast-forwards the voices
|
|
108
|
+
# and ends on one whole cycle, so everything the CPU can read stays
|
|
109
|
+
# exact. The filter only runs once something wants audio.
|
|
110
|
+
def synthesizing? = @synthesizing
|
|
111
|
+
|
|
112
|
+
def synthesize!
|
|
113
|
+
return if @synthesizing
|
|
114
|
+
|
|
115
|
+
@synthesizing = true
|
|
116
|
+
update_span_rules
|
|
117
|
+
catch_up
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Starts collecting the output, averaged down to `rate` samples a
|
|
121
|
+
# second, for #drain_samples. `filter_chunk` overrides the one the SID
|
|
122
|
+
# was built with, for a machine that built its own. `clock_hz` is the
|
|
123
|
+
# rate the SID's cycles are taken to run at.
|
|
124
|
+
def record(rate:, filter_chunk: @filter_chunk, clock_hz: Region::PAL.clock_hz)
|
|
125
|
+
synthesize!
|
|
126
|
+
catch_up
|
|
127
|
+
@filter_chunk = filter_chunk
|
|
128
|
+
@decimator = Decimator.new(clock_hz:, rate:)
|
|
129
|
+
@samples = []
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Also keeps each voice's own output, before the filter and the volume,
|
|
133
|
+
# as each recorded sample closes, for #drain_voice_samples.
|
|
134
|
+
def record_voices!
|
|
135
|
+
@voice_samples = [] if @voice_samples.nil?
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# The voices' outputs since the last drain, three to a sample, in voice
|
|
139
|
+
# order, or nothing unless #record_voices! asked for them.
|
|
140
|
+
def drain_voice_samples
|
|
141
|
+
return [] if @voice_samples.nil?
|
|
142
|
+
|
|
143
|
+
catch_up
|
|
144
|
+
samples = @voice_samples
|
|
145
|
+
@voice_samples = []
|
|
146
|
+
samples
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# The samples recorded since the last drain.
|
|
150
|
+
def drain_samples
|
|
151
|
+
catch_up
|
|
152
|
+
samples = @samples
|
|
153
|
+
@samples = []
|
|
154
|
+
samples
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def voices
|
|
158
|
+
catch_up
|
|
159
|
+
@voices
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Runs the DSP up to the current cycle.
|
|
163
|
+
def catch_up! = catch_up
|
|
164
|
+
|
|
165
|
+
# The byte the data bus holds and the cycles until it fades.
|
|
166
|
+
def bus_state = [@bus_value, @bus_ttl]
|
|
167
|
+
|
|
168
|
+
def restore_bus(value, ttl)
|
|
169
|
+
@bus_value = value
|
|
170
|
+
@bus_ttl = ttl
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def filter
|
|
174
|
+
catch_up
|
|
175
|
+
@filter
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# Voice 3's oscillator and envelope, the only synthesis state the CPU
|
|
179
|
+
# can see. Programs poll OSC3 with the noise waveform selected for
|
|
180
|
+
# random numbers, and ENV3 to time hard restarts.
|
|
181
|
+
def osc3
|
|
182
|
+
catch_up
|
|
183
|
+
@waveform3.osc3 >> 4
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def env3
|
|
187
|
+
catch_up
|
|
188
|
+
@voice3.envelope.env3
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def output
|
|
192
|
+
synthesize!
|
|
193
|
+
catch_up
|
|
194
|
+
@filter.output
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def sample
|
|
198
|
+
output
|
|
199
|
+
current_sample
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def cycle!
|
|
203
|
+
age_bus if @bus_ttl != 0
|
|
204
|
+
@pending_cycles += 1
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def peek(addr)
|
|
208
|
+
case offset_of(addr) % (2**5)
|
|
209
|
+
when 0x19 then latch(pots ? pots.pot_x : 0xff)
|
|
210
|
+
when 0x1a then latch(pots ? pots.pot_y : 0xff)
|
|
211
|
+
when 0x1b then latch(osc3)
|
|
212
|
+
when 0x1c then latch(env3)
|
|
213
|
+
else @bus_value
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def poke(addr, value)
|
|
218
|
+
reg = offset_of(addr) % (2**5)
|
|
219
|
+
write_register(reg, value) if reg <= 0x18
|
|
220
|
+
latch(value)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# Register contents as written, for save states and debugging.
|
|
224
|
+
def register(reg) = @registers.peek(reg)
|
|
225
|
+
|
|
226
|
+
private
|
|
227
|
+
|
|
228
|
+
def latch(value)
|
|
229
|
+
@bus_ttl = @bus_ttl_reset
|
|
230
|
+
@bus_value = value
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def age_bus
|
|
234
|
+
@bus_ttl -= 1
|
|
235
|
+
@bus_value = 0x00 if @bus_ttl.zero?
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def write_register(reg, value)
|
|
239
|
+
@registers.poke(reg, value)
|
|
240
|
+
catch_up if @deferred_writes.length == DEFERRED_WRITES * 3
|
|
241
|
+
@deferred_writes.push(@pending_cycles, reg, value)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def apply_write(reg, value)
|
|
245
|
+
reg < 0x15 ? write_voice(reg, value) : @filter.write(reg, value)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def write_voice(reg, value)
|
|
249
|
+
voice = @voices[reg / 7]
|
|
250
|
+
case reg % 7
|
|
251
|
+
when 0 then voice.waveform.frequency_low = value
|
|
252
|
+
when 1 then voice.waveform.frequency_high = value
|
|
253
|
+
when 2 then voice.waveform.pulse_width_low = value
|
|
254
|
+
when 3 then voice.waveform.pulse_width_high = value
|
|
255
|
+
when 4
|
|
256
|
+
voice.control = value
|
|
257
|
+
update_span_rules
|
|
258
|
+
when 5 then voice.envelope.attack_decay = value
|
|
259
|
+
when 6 then voice.envelope.sustain_release = value
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
end
|