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
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Vic20
|
|
5
|
-
MARKER = "VIC20"
|
|
6
|
-
|
|
7
|
-
# The RAM expansion of the machine a State from #snapshot was taken
|
|
8
|
-
# of, a key of Bus::RAM_CONFIGURATIONS.
|
|
9
|
-
def self.setup(state)
|
|
10
|
-
input = Snapshot::StateReader.new(state)
|
|
11
|
-
input.marker(MARKER)
|
|
12
|
-
input.check_stamp
|
|
13
|
-
SavedState.read_ram(input)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# A new machine, built as the one a State from #snapshot was taken of,
|
|
17
|
-
# at that state.
|
|
18
|
-
def self.restored(state) = new(ram: setup(state)).apply_state(state)
|
|
19
|
-
|
|
20
|
-
# The whole machine's state for a snapshot, as Computer's: the
|
|
21
|
-
# machine's own latches, the bus with its RAM and cartridge ROM, the
|
|
22
|
-
# VIC with its sound, both VIAs, the CPU, the datasette and its tape,
|
|
23
|
-
# the disk device 8 serves through the traps, and a true 1541. The
|
|
24
|
-
# serial lines go back into the bus from the restored VIAs. What the
|
|
25
|
-
# host holds stays out: the keyboard, the joystick, RESTORE, the traps
|
|
26
|
-
# and callbacks, whether the display renders, whether the sound
|
|
27
|
-
# records, and whether the datasette records.
|
|
28
|
-
module SavedState
|
|
29
|
-
RAM_CONFIGURATIONS = Bus::RAM_CONFIGURATIONS.keys.freeze
|
|
30
|
-
|
|
31
|
-
def self.read_ram(input)
|
|
32
|
-
RAM_CONFIGURATIONS.fetch(input.int)
|
|
33
|
-
rescue IndexError
|
|
34
|
-
raise Snapshot::FormatError, "the state names a VIC-20 RAM expansion badline doesn't know"
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# How many more on_init handlers the machine a State was taken of had
|
|
38
|
-
# yet to run than this one has. Nil until the machine is restored.
|
|
39
|
-
attr_reader :init_handlers_lost
|
|
40
|
-
|
|
41
|
-
def snapshot
|
|
42
|
-
out = Snapshot::StateWriter.new
|
|
43
|
-
save_state(out)
|
|
44
|
-
out.state
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
# Takes the machine back to a State from #snapshot, trying it on a new
|
|
48
|
-
# machine first, so one that fails leaves this machine as it was.
|
|
49
|
-
# Raises Snapshot::FormatError for a state of another machine or RAM
|
|
50
|
-
# expansion.
|
|
51
|
-
def restore(state)
|
|
52
|
-
check_ram(Vic20.setup(state))
|
|
53
|
-
Vic20.restored(state)
|
|
54
|
-
apply_state(state)
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# Puts a State into the machine without trying it on a new one first.
|
|
58
|
-
def apply_state(state)
|
|
59
|
-
input = Snapshot::StateReader.new(state)
|
|
60
|
-
load_state(input)
|
|
61
|
-
raise Snapshot::FormatError, "the state goes on past the machine" unless input.finished?
|
|
62
|
-
|
|
63
|
-
self
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def save_state(out)
|
|
67
|
-
out.marker(MARKER).stamp
|
|
68
|
-
out.int(RAM_CONFIGURATIONS.index(@ram_configuration))
|
|
69
|
-
out.int(@cycles).boolean(@nmi_asserted).boolean(!@pending_keys.nil?)
|
|
70
|
-
out.ints(@pending_keys) if @pending_keys
|
|
71
|
-
out.int(@cycles <= @init_threshold ? @init_handlers.length : 0)
|
|
72
|
-
@bus.save_state(out)
|
|
73
|
-
@vic.save_state(out)
|
|
74
|
-
@sound.save_state(out)
|
|
75
|
-
@via1.save_state(out)
|
|
76
|
-
@via2.save_state(out)
|
|
77
|
-
@cpu.save_state(out)
|
|
78
|
-
@datasette.save_state(out)
|
|
79
|
-
save_trap_drive(out)
|
|
80
|
-
save_drive1541(out)
|
|
81
|
-
save_drive1581(out)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def load_state(input)
|
|
85
|
-
input.marker(MARKER)
|
|
86
|
-
input.check_stamp
|
|
87
|
-
check_ram(SavedState.read_ram(input))
|
|
88
|
-
@cycles = input.int
|
|
89
|
-
@nmi_asserted = input.boolean?
|
|
90
|
-
@pending_keys = nil
|
|
91
|
-
@pending_keys = input.ints if input.boolean?
|
|
92
|
-
@init_handlers_lost = [input.int - @init_handlers.length, 0].max
|
|
93
|
-
@bus.load_state(input)
|
|
94
|
-
@vic.load_state(input)
|
|
95
|
-
@sound.load_state(input)
|
|
96
|
-
@via1.load_state(input)
|
|
97
|
-
@via2.load_state(input)
|
|
98
|
-
@cpu.load_state(input)
|
|
99
|
-
via_written
|
|
100
|
-
@datasette.load_state(input)
|
|
101
|
-
load_trap_drive(input)
|
|
102
|
-
load_drive1541(input)
|
|
103
|
-
load_drive1581(input)
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
private
|
|
107
|
-
|
|
108
|
-
# A true 1541 on the serial bus, with its device number.
|
|
109
|
-
def save_drive1541(out)
|
|
110
|
-
out.boolean(!@drive1541.nil?)
|
|
111
|
-
return unless @drive1541
|
|
112
|
-
|
|
113
|
-
out.int(@drive1541.device)
|
|
114
|
-
@drive1541.save_state(out)
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
def check_ram(ram)
|
|
118
|
-
return if ram == @ram_configuration
|
|
119
|
-
|
|
120
|
-
raise Snapshot::FormatError, "the state is of a VIC-20 with #{ram} RAM, not #{@ram_configuration}"
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
end
|
|
124
|
-
end
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Vic20
|
|
5
|
-
class Sound
|
|
6
|
-
# The sound's level averaged over each sample of the audio rate, then
|
|
7
|
-
# through the machine's output stage: a one-pole low-pass at 1,420 Hz
|
|
8
|
-
# and a one-pole high-pass at 158 Hz, both run at the audio rate.
|
|
9
|
-
#
|
|
10
|
-
# The two corners are fitted to xvic's step response: a voice turned
|
|
11
|
-
# on at volume 15 rises and decays back to the line as those two RC
|
|
12
|
-
# stages do, within 6 parts in 11,000.
|
|
13
|
-
class Output
|
|
14
|
-
LOW_PASS_HZ = 1_420
|
|
15
|
-
HIGH_PASS_HZ = 158
|
|
16
|
-
|
|
17
|
-
# Scales the loudest level, four voices high at volume 15, to the
|
|
18
|
-
# top of a signed 16-bit sample.
|
|
19
|
-
SCALE = 32_767.0 / 570
|
|
20
|
-
|
|
21
|
-
attr_reader :samples
|
|
22
|
-
|
|
23
|
-
# `level` is the sound's level as the recording starts, which the
|
|
24
|
-
# stage takes as settled.
|
|
25
|
-
def initialize(clock_hz:, rate:, level:)
|
|
26
|
-
@clock_hz = clock_hz
|
|
27
|
-
@rate = rate
|
|
28
|
-
@remainder = 0
|
|
29
|
-
@window = next_window
|
|
30
|
-
@left = @window
|
|
31
|
-
@sum = 0
|
|
32
|
-
@low = @drift = level.to_f
|
|
33
|
-
@low_pass = 1.0 - Math.exp(-2.0 * Math::PI * LOW_PASS_HZ / rate)
|
|
34
|
-
@high_pass = 1.0 - Math.exp(-2.0 * Math::PI * HIGH_PASS_HZ / rate)
|
|
35
|
-
@samples = []
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
# Adds `cycles` cycles at `level`, closing every sample they finish.
|
|
39
|
-
def hold(level, cycles)
|
|
40
|
-
left = @left
|
|
41
|
-
while cycles >= left
|
|
42
|
-
@sum += level * left
|
|
43
|
-
cycles -= left
|
|
44
|
-
close
|
|
45
|
-
left = @left
|
|
46
|
-
end
|
|
47
|
-
@sum += level * cycles
|
|
48
|
-
@left = left - cycles
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
# The samples closed since the last drain.
|
|
52
|
-
def drain
|
|
53
|
-
samples = @samples
|
|
54
|
-
@samples = []
|
|
55
|
-
samples
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
private
|
|
59
|
-
|
|
60
|
-
def close
|
|
61
|
-
@low += @low_pass * (@sum.fdiv(@window) - @low)
|
|
62
|
-
@drift += @high_pass * (@low - @drift)
|
|
63
|
-
sample = ((@low - @drift) * SCALE).round
|
|
64
|
-
sample = 32_767 if sample > 32_767
|
|
65
|
-
sample = -32_768 if sample < -32_768
|
|
66
|
-
@samples << sample
|
|
67
|
-
@sum = 0
|
|
68
|
-
@window = next_window
|
|
69
|
-
@left = @window
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
# Each window is a whole number of cycles, and they add up to the
|
|
73
|
-
# clock's cycles over a second.
|
|
74
|
-
def next_window
|
|
75
|
-
@remainder += @clock_hz
|
|
76
|
-
cycles = @remainder / @rate
|
|
77
|
-
@remainder -= cycles * @rate
|
|
78
|
-
cycles
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
data/lib/badline/vic20/sound.rb
DELETED
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "badline/vic20/sound/output"
|
|
4
|
-
|
|
5
|
-
module Badline
|
|
6
|
-
class Vic20
|
|
7
|
-
# The VIC-I's sound: three square-wave voices, bass, alto and soprano at
|
|
8
|
-
# $900A-$900C, a noise voice at $900D, and the volume in $900E bits 0-3.
|
|
9
|
-
#
|
|
10
|
-
# Each voice has a 7-bit counter, ticked every 16, 8, 4 or 2 cycles from
|
|
11
|
-
# bass to noise. It counts up from the low 7 bits of its register, and
|
|
12
|
-
# on the tick it would reach 127 it reloads from the register instead.
|
|
13
|
-
# So a voice's counter comes round every 128 - ((value + 1) & 127)
|
|
14
|
-
# ticks, and the register's new value takes hold at the next reload.
|
|
15
|
-
#
|
|
16
|
-
# A tone voice's counter shifts an 8-bit shift register at each reload,
|
|
17
|
-
# bit 7 out and back into bit 0 inverted while bit 7 of the register
|
|
18
|
-
# enables the voice, and a zero while it doesn't. Bit 0 is the voice's
|
|
19
|
-
# output: a square wave of 16 shifts while the voice is on, which a
|
|
20
|
-
# voice turned off shifts out to silence.
|
|
21
|
-
#
|
|
22
|
-
# The noise voice's counter shifts a 16-bit LFSR instead, bit 0 in from
|
|
23
|
-
# the XOR of bits 3, 12, 14 and 15 while the voice is on and a one
|
|
24
|
-
# while it's off. Each time the LFSR's bit 0 rises, it shifts the noise
|
|
25
|
-
# voice's own 8-bit shift register, bit 7 back into bit 0, inverted
|
|
26
|
-
# while the voice is on. Its bit 0 is the voice's output while the voice
|
|
27
|
-
# is on, and it is silent while it's off.
|
|
28
|
-
#
|
|
29
|
-
# The output is the voices that are high, plus a little more, times the
|
|
30
|
-
# volume, so a volume write steps the output even with every voice off.
|
|
31
|
-
#
|
|
32
|
-
# The voices only run while #record collects the output: nothing the
|
|
33
|
-
# CPU reads depends on them. Until then a write only sets the register.
|
|
34
|
-
# While recording, the voices catch up to the current cycle whenever a
|
|
35
|
-
# write lands or the samples are drained, one shift at a time.
|
|
36
|
-
class Sound
|
|
37
|
-
VOICES = 4
|
|
38
|
-
NOISE = 3
|
|
39
|
-
|
|
40
|
-
# The cycles between ticks of each voice's counter.
|
|
41
|
-
DIVIDERS = [16, 8, 4, 2].freeze
|
|
42
|
-
|
|
43
|
-
# What a voice that is high adds to the output's level, and what the
|
|
44
|
-
# output carries with every voice low, before the volume.
|
|
45
|
-
VOICE_LEVEL = 9
|
|
46
|
-
IDLE_LEVEL = 2
|
|
47
|
-
|
|
48
|
-
attr_reader :volume
|
|
49
|
-
|
|
50
|
-
# `clock` answers the machine's cycles, `clock_hz` the rate they run at.
|
|
51
|
-
def initialize(clock, clock_hz)
|
|
52
|
-
@clock = clock
|
|
53
|
-
@clock_hz = clock_hz
|
|
54
|
-
@output = nil
|
|
55
|
-
@time = 0
|
|
56
|
-
@shift_registers = Array.new(VOICES, 0)
|
|
57
|
-
@next_shifts = Array.new(VOICES, 0)
|
|
58
|
-
@frequencies = Array.new(VOICES, 0)
|
|
59
|
-
@enabled = Array.new(VOICES, false)
|
|
60
|
-
power_on!
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def model = :mos6561
|
|
64
|
-
|
|
65
|
-
# The power-on state: every register clear and the tone voices' shift
|
|
66
|
-
# registers empty. The noise voice's LFSR and shift register start full
|
|
67
|
-
# of ones, as a noise voice left off fills them.
|
|
68
|
-
def power_on!
|
|
69
|
-
now = @clock.cycles
|
|
70
|
-
run_to(now)
|
|
71
|
-
@volume = 0
|
|
72
|
-
VOICES.times do |voice|
|
|
73
|
-
@frequencies[voice] = 0
|
|
74
|
-
@enabled[voice] = false
|
|
75
|
-
@shift_registers[voice] = 0
|
|
76
|
-
divider = DIVIDERS[voice]
|
|
77
|
-
@next_shifts[voice] = ((now / divider) + 128) * divider
|
|
78
|
-
end
|
|
79
|
-
@shift_registers[NOISE] = 0xff
|
|
80
|
-
@lfsr = 0xffff
|
|
81
|
-
@level = level_now
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# Starts collecting the output, averaged down to `rate` samples a
|
|
85
|
-
# second, for #drain_samples. `clock_hz` is the rate the cycles are
|
|
86
|
-
# taken to run at.
|
|
87
|
-
def record(rate:, clock_hz: @clock_hz)
|
|
88
|
-
now = @clock.cycles
|
|
89
|
-
run_to(now)
|
|
90
|
-
resume(now)
|
|
91
|
-
@output = Output.new(clock_hz:, rate:, level: @level)
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def recording? = !@output.nil?
|
|
95
|
-
|
|
96
|
-
# The samples recorded since the last drain.
|
|
97
|
-
def drain_samples
|
|
98
|
-
output = @output
|
|
99
|
-
return [] if output.nil?
|
|
100
|
-
|
|
101
|
-
run_to(@clock.cycles)
|
|
102
|
-
output.drain
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
# A write to $900A-$900E, which takes hold from the next cycle.
|
|
106
|
-
def write(register, value)
|
|
107
|
-
run_to(@clock.cycles + 1)
|
|
108
|
-
if register == 0x0e
|
|
109
|
-
@volume = value & 0x0f
|
|
110
|
-
else
|
|
111
|
-
voice = register - 0x0a
|
|
112
|
-
@frequencies[voice] = value & 0x7f
|
|
113
|
-
@enabled[voice] = value >= 0x80
|
|
114
|
-
end
|
|
115
|
-
@level = level_now
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
# The registers and the voices as they last ran, for a snapshot.
|
|
119
|
-
# Recording is the host's, and starts the voices again from the
|
|
120
|
-
# cycle it starts at.
|
|
121
|
-
def save_state(out)
|
|
122
|
-
run_to(@clock.cycles)
|
|
123
|
-
out.marker("VIC20 SOUND").int(@volume).ints(@frequencies).booleans(@enabled)
|
|
124
|
-
out.ints(@shift_registers).ints(@next_shifts).int(@lfsr).int(@level).int(@time)
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
def load_state(input)
|
|
128
|
-
input.marker("VIC20 SOUND")
|
|
129
|
-
@volume = input.int
|
|
130
|
-
input.ints_into(@frequencies)
|
|
131
|
-
input.booleans_into(@enabled)
|
|
132
|
-
input.ints_into(@shift_registers)
|
|
133
|
-
input.ints_into(@next_shifts)
|
|
134
|
-
@lfsr = input.int
|
|
135
|
-
@level = input.int
|
|
136
|
-
@time = input.int
|
|
137
|
-
resume(@clock.cycles) if recording?
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
# A voice's shift register as of the current cycle, while recording.
|
|
141
|
-
def shift_register(voice)
|
|
142
|
-
run_to(@clock.cycles)
|
|
143
|
-
@shift_registers[voice]
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
def lfsr
|
|
147
|
-
run_to(@clock.cycles)
|
|
148
|
-
@lfsr
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
private
|
|
152
|
-
|
|
153
|
-
# Moves each shift that the cycles since the voices last ran have
|
|
154
|
-
# passed to its next turn from `now`, keeping its phase.
|
|
155
|
-
def resume(now)
|
|
156
|
-
@time = now
|
|
157
|
-
VOICES.times do |voice|
|
|
158
|
-
due = @next_shifts[voice]
|
|
159
|
-
next if due >= now
|
|
160
|
-
|
|
161
|
-
interval = period(voice) * DIVIDERS[voice]
|
|
162
|
-
@next_shifts[voice] = due + ((now - due + interval - 1) / interval * interval)
|
|
163
|
-
end
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
# Runs the voices up to the start of cycle `target`, the output holding
|
|
167
|
-
# each level for the cycles it lasts.
|
|
168
|
-
def run_to(target)
|
|
169
|
-
time = @time
|
|
170
|
-
output = @output
|
|
171
|
-
return if output.nil? || target <= time
|
|
172
|
-
|
|
173
|
-
following = next_shift
|
|
174
|
-
while following < target
|
|
175
|
-
output.hold(@level, following - time)
|
|
176
|
-
time = following
|
|
177
|
-
shift_due(time)
|
|
178
|
-
@level = level_now
|
|
179
|
-
following = next_shift
|
|
180
|
-
end
|
|
181
|
-
output.hold(@level, target - time)
|
|
182
|
-
@time = target
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
def next_shift
|
|
186
|
-
shifts = @next_shifts
|
|
187
|
-
following = shifts[0]
|
|
188
|
-
following = shifts[1] if shifts[1] < following
|
|
189
|
-
following = shifts[2] if shifts[2] < following
|
|
190
|
-
following = shifts[3] if shifts[3] < following
|
|
191
|
-
following
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
def shift_due(time)
|
|
195
|
-
shifts = @next_shifts
|
|
196
|
-
VOICES.times do |voice|
|
|
197
|
-
next unless shifts[voice] == time
|
|
198
|
-
|
|
199
|
-
voice == NOISE ? step_noise : shift_tone(voice)
|
|
200
|
-
shifts[voice] = time + (period(voice) * DIVIDERS[voice])
|
|
201
|
-
end
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
def shift_tone(voice)
|
|
205
|
-
bits = @shift_registers[voice]
|
|
206
|
-
fill = @enabled[voice] && bits < 0x80 ? 1 : 0
|
|
207
|
-
@shift_registers[voice] = ((bits << 1) | fill) & 0xff
|
|
208
|
-
end
|
|
209
|
-
|
|
210
|
-
def step_noise
|
|
211
|
-
lfsr = @lfsr
|
|
212
|
-
enabled = @enabled[NOISE]
|
|
213
|
-
fill = enabled ? ((lfsr >> 3) ^ (lfsr >> 12) ^ (lfsr >> 14) ^ (lfsr >> 15)) & 1 : 1
|
|
214
|
-
@lfsr = ((lfsr << 1) | fill) & 0xffff
|
|
215
|
-
return unless fill == 1 && lfsr.even?
|
|
216
|
-
|
|
217
|
-
bits = @shift_registers[NOISE]
|
|
218
|
-
fill = (bits >> 7) ^ (enabled ? 1 : 0)
|
|
219
|
-
@shift_registers[NOISE] = ((bits << 1) | fill) & 0xff
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
# The ticks between two reloads of a voice's counter.
|
|
223
|
-
def period(voice) = 128 - ((@frequencies[voice] + 1) & 0x7f)
|
|
224
|
-
|
|
225
|
-
def level_now
|
|
226
|
-
registers = @shift_registers
|
|
227
|
-
high = (registers[0] & 1) + (registers[1] & 1) + (registers[2] & 1)
|
|
228
|
-
high += registers[NOISE] & 1 if @enabled[NOISE]
|
|
229
|
-
((high * VOICE_LEVEL) + IDLE_LEVEL) * @volume
|
|
230
|
-
end
|
|
231
|
-
end
|
|
232
|
-
end
|
|
233
|
-
end
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Vic20
|
|
5
|
-
class VIC
|
|
6
|
-
# The VIC's state for a snapshot: the registers and what they set, the
|
|
7
|
-
# raster, the text window and its fetches, and the picture with what
|
|
8
|
-
# each line fetched. The sound saves its own.
|
|
9
|
-
module SavedState
|
|
10
|
-
def save_state(out)
|
|
11
|
-
out.marker("VIC20 VIC")
|
|
12
|
-
out.ints(@registers).int(@rasterline).int(@column).int(@next_event)
|
|
13
|
-
[@origin_x, @origin_y, @columns, @rows, @char_shift, @screen_base, @char_base].each { |value| out.int(value) }
|
|
14
|
-
out.boolean(@window_open).boolean(@window_done)
|
|
15
|
-
[@row_start, @matrix, @char_line, @text_rows].each { |value| out.int(value) }
|
|
16
|
-
[@fetch_from, @fetch_to, @fetched, @slot, @code].each { |value| out.int(value) }
|
|
17
|
-
@painter.save_state(out)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def load_state(input)
|
|
21
|
-
input.marker("VIC20 VIC")
|
|
22
|
-
input.ints_into(@registers)
|
|
23
|
-
@rasterline = input.int
|
|
24
|
-
@column = input.int
|
|
25
|
-
@next_event = input.int
|
|
26
|
-
load_window(input)
|
|
27
|
-
@fetch_from = input.int
|
|
28
|
-
@fetch_to = input.int
|
|
29
|
-
@fetched = input.int
|
|
30
|
-
@slot = input.int
|
|
31
|
-
@code = input.int
|
|
32
|
-
@painter.load_state(input)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
private
|
|
36
|
-
|
|
37
|
-
def load_window(input)
|
|
38
|
-
@origin_x = input.int
|
|
39
|
-
@origin_y = input.int
|
|
40
|
-
@columns = input.int
|
|
41
|
-
@rows = input.int
|
|
42
|
-
@char_shift = input.int
|
|
43
|
-
@screen_base = input.int
|
|
44
|
-
@char_base = input.int
|
|
45
|
-
@window_open = input.boolean?
|
|
46
|
-
@window_done = input.boolean?
|
|
47
|
-
@row_start = input.int
|
|
48
|
-
@matrix = input.int
|
|
49
|
-
@char_line = input.int
|
|
50
|
-
@text_rows = input.int
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Z80
|
|
5
|
-
# The ALU's 8- and 16-bit arithmetic. Bits 5 and 3 of F come from the
|
|
6
|
-
# result, except for CP, which takes them from the operand, and the
|
|
7
|
-
# 16-bit operations, which take them from the high byte.
|
|
8
|
-
module Arithmetic
|
|
9
|
-
private
|
|
10
|
-
|
|
11
|
-
# The eight operations an opcode's bits 5-3 pick: ADD ADC SUB SBC AND
|
|
12
|
-
# XOR OR CP.
|
|
13
|
-
def alu(operation, value)
|
|
14
|
-
case operation
|
|
15
|
-
when 0 then add_a(value, 0)
|
|
16
|
-
when 1 then add_a(value, @f & CF)
|
|
17
|
-
when 2 then @a = subtract(value, 0)
|
|
18
|
-
when 3 then @a = subtract(value, @f & CF)
|
|
19
|
-
when 4 then logic(@a & value, HF)
|
|
20
|
-
when 5 then logic(@a ^ value, 0)
|
|
21
|
-
when 6 then logic(@a | value, 0)
|
|
22
|
-
else compare(value)
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def add_a(value, carry)
|
|
27
|
-
result = @a + value + carry
|
|
28
|
-
assign_flags(SZ53[result & 0xff] | (result >> 8) | ((@a ^ value ^ result) & HF) |
|
|
29
|
-
(((@a ^ value ^ 0x80) & (@a ^ result) & 0x80) >> 5))
|
|
30
|
-
@a = result & 0xff
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def subtract(value, carry)
|
|
34
|
-
result = @a - value - carry
|
|
35
|
-
assign_flags(SZ53[result & 0xff] | NF | ((result >> 8) & CF) | ((@a ^ value ^ result) & HF) |
|
|
36
|
-
(((@a ^ value) & (@a ^ result) & 0x80) >> 5))
|
|
37
|
-
result & 0xff
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def compare(value)
|
|
41
|
-
subtract(value, 0)
|
|
42
|
-
assign_flags((@f & ~XYF) | (value & XYF))
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def logic(result, half)
|
|
46
|
-
@a = result
|
|
47
|
-
assign_flags(SZ53P[result] | half)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def increment(value)
|
|
51
|
-
result = (value + 1) & 0xff
|
|
52
|
-
assign_flags((@f & CF) | SZ53[result] | (result == 0x80 ? PF : 0) | (result.nobits?(0x0f) ? HF : 0))
|
|
53
|
-
result
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def decrement(value)
|
|
57
|
-
result = (value - 1) & 0xff
|
|
58
|
-
assign_flags((@f & CF) | NF | SZ53[result] | (result == 0x7f ? PF : 0) | (value.nobits?(0x0f) ? HF : 0))
|
|
59
|
-
result
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def add16(left, right)
|
|
63
|
-
result = left + right
|
|
64
|
-
@wz = (left + 1) & 0xffff
|
|
65
|
-
assign_flags((@f & (SF | ZF | PF)) | ((result >> 8) & XYF) | (((left ^ right ^ result) >> 8) & HF) |
|
|
66
|
-
(result >> 16))
|
|
67
|
-
result & 0xffff
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def adc16(right)
|
|
71
|
-
left = hl
|
|
72
|
-
result = left + right + (@f & CF)
|
|
73
|
-
@wz = (left + 1) & 0xffff
|
|
74
|
-
self.hl = result & 0xffff
|
|
75
|
-
assign_flags(word_flags(result) | (((left ^ right ^ result) >> 8) & HF) |
|
|
76
|
-
(((left ^ right ^ 0x8000) & (left ^ result) & 0x8000) >> 13))
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def sbc16(right)
|
|
80
|
-
left = hl
|
|
81
|
-
result = left - right - (@f & CF)
|
|
82
|
-
@wz = (left + 1) & 0xffff
|
|
83
|
-
self.hl = result & 0xffff
|
|
84
|
-
assign_flags(word_flags(result) | NF | (((left ^ right ^ result) >> 8) & HF) |
|
|
85
|
-
(((left ^ right) & (left ^ result) & 0x8000) >> 13))
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def word_flags(result)
|
|
89
|
-
((result >> 8) & (SF | XYF)) | (result.nobits?(0xffff) ? ZF : 0) | ((result >> 16) & CF)
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def daa
|
|
93
|
-
low = @a & 0x0f
|
|
94
|
-
carry = @f.anybits?(CF) || @a > 0x99 ? CF : 0
|
|
95
|
-
correction = (carry.zero? ? 0 : 0x60) | (@f.anybits?(HF) || low > 9 ? 0x06 : 0)
|
|
96
|
-
subtracting = @f.anybits?(NF)
|
|
97
|
-
half = daa_half(low, subtracting)
|
|
98
|
-
@a = (subtracting ? @a - correction : @a + correction) & 0xff
|
|
99
|
-
assign_flags(SZ53P[@a] | (@f & NF) | carry | half)
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def daa_half(low, subtracting)
|
|
103
|
-
if subtracting
|
|
104
|
-
@f.anybits?(HF) && low < 6 ? HF : 0
|
|
105
|
-
else
|
|
106
|
-
low > 9 ? HF : 0
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def neg
|
|
111
|
-
value = @a
|
|
112
|
-
@a = 0
|
|
113
|
-
@a = subtract(value, 0)
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
end
|
data/lib/badline/z80/bit_page.rb
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Z80
|
|
5
|
-
# The CB page: rotates and shifts (quarter 0), BIT (1), RES (2) and SET
|
|
6
|
-
# (3) of the bit the row names, on the column's register or (HL). After
|
|
7
|
-
# DD or FD the operand is always (IX+d): the displacement comes before
|
|
8
|
-
# the opcode, and an opcode that names a register other than (HL) also
|
|
9
|
-
# copies the result into it.
|
|
10
|
-
module BitPage
|
|
11
|
-
private
|
|
12
|
-
|
|
13
|
-
def execute_bits(opcode)
|
|
14
|
-
operation = opcode >> 6
|
|
15
|
-
number = (opcode >> 3) & 7
|
|
16
|
-
index = opcode & 7
|
|
17
|
-
return bits_in_memory(operation, number, hl) if index == 6
|
|
18
|
-
|
|
19
|
-
value = register(index)
|
|
20
|
-
if operation == 1
|
|
21
|
-
bit(number, value, value)
|
|
22
|
-
else
|
|
23
|
-
set_register(index, bit_result(operation, number, value))
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def execute_index_bits
|
|
28
|
-
displaced
|
|
29
|
-
opcode = fetch_byte
|
|
30
|
-
@cycles += 2
|
|
31
|
-
result = bits_in_memory(opcode >> 6, (opcode >> 3) & 7, @wz)
|
|
32
|
-
index = opcode & 7
|
|
33
|
-
set_plain_register(index, result) unless index == 6 || (opcode >> 6) == 1
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def bits_in_memory(operation, number, address)
|
|
37
|
-
value = read_byte(address)
|
|
38
|
-
@cycles += 1
|
|
39
|
-
return bit(number, value, @wz >> 8) if operation == 1
|
|
40
|
-
|
|
41
|
-
result = bit_result(operation, number, value)
|
|
42
|
-
write_byte(address, result)
|
|
43
|
-
result
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def bit_result(operation, number, value)
|
|
47
|
-
case operation
|
|
48
|
-
when 0 then shift(number, value)
|
|
49
|
-
when 2 then value & ~(1 << number) & 0xff
|
|
50
|
-
else value | (1 << number)
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|