badline 0.12.0 → 0.13.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 +25 -0
- data/CLAUDE.md +59 -31
- data/README.md +1 -1
- data/doc/library.md +9 -9
- data/doc/pinned-behaviour.md +105 -105
- data/doc/snapshots.md +1 -4
- data/lib/badline/audio/bare_player.rb +4 -4
- data/lib/badline/audio/cli.rb +6 -6
- data/lib/badline/audio/jukebox.rb +2 -2
- data/lib/badline/audio/machine_player.rb +2 -2
- data/lib/badline/{media → audio}/queue.rb +1 -1
- data/lib/badline/audio/queued_tune.rb +6 -6
- data/lib/badline/audio/renderer.rb +5 -5
- data/lib/badline/audio/stereo.rb +1 -1
- data/lib/badline/c128/{bus_state.rb → bus/saved_state.rb} +6 -6
- data/lib/badline/c128/bus.rb +30 -51
- data/lib/badline/c128/color_lines.rb +2 -2
- data/lib/badline/c128/cpu.rb +1 -1
- data/lib/badline/c128/drives.rb +10 -11
- data/lib/badline/c128/fast_serial.rb +5 -5
- data/lib/badline/c128/mmu_pages.rb +1 -1
- data/lib/badline/c128/modes.rb +2 -2
- data/lib/badline/c128/saved_state.rb +21 -47
- data/lib/badline/c128/z80.rb +2 -2
- data/lib/badline/c128.rb +18 -72
- data/lib/badline/{computer → c64}/attachments.rb +16 -47
- data/lib/badline/c64/banked_ram/banking.rb +32 -0
- data/lib/badline/c64/banked_ram/plus256k.rb +56 -0
- data/lib/badline/c64/banked_ram/plus60k.rb +45 -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/extra_sids.rb +32 -0
- data/lib/badline/c64/bus/fittings.rb +40 -0
- data/lib/badline/c64/bus/pla.rb +149 -0
- data/lib/badline/c64/bus/roms.rb +41 -0
- data/lib/badline/c64/bus/saved_state.rb +68 -0
- data/lib/badline/c64/bus/sid_slots.rb +44 -0
- data/lib/badline/c64/bus.rb +218 -0
- data/lib/badline/c64/cartridge/action_replay.rb +128 -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 +147 -0
- data/lib/badline/c64/cartridge/epyx_fastload.rb +81 -0
- data/lib/badline/c64/cartridge/final_cartridge3.rb +91 -0
- data/lib/badline/c64/cartridge/flash/saved_state.rb +40 -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 +76 -0
- data/lib/badline/c64/cartridge/game_system.rb +42 -0
- data/lib/badline/c64/cartridge/geo_ram.rb +81 -0
- data/lib/badline/c64/cartridge/kcs_power.rb +77 -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 +70 -0
- data/lib/badline/c64/cartridge/retro_replay/saved_state.rb +47 -0
- data/lib/badline/c64/cartridge/retro_replay.rb +286 -0
- data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
- data/lib/badline/c64/cartridge/rgcd.rb +60 -0
- data/lib/badline/c64/cartridge/saved_state.rb +63 -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 +50 -0
- data/lib/badline/c64/cartridge/westermann.rb +32 -0
- data/lib/badline/c64/cartridge/zaxxon.rb +68 -0
- data/lib/badline/c64/cartridge.rb +258 -0
- data/lib/badline/c64/color_memory.rb +27 -0
- data/lib/badline/c64/common.rb +34 -0
- data/lib/badline/c64/kernal_traps.rb +89 -0
- data/lib/badline/c64/reu/dma/saved_state.rb +52 -0
- data/lib/badline/c64/reu/dma.rb +275 -0
- data/lib/badline/c64/reu/ram.rb +109 -0
- data/lib/badline/c64/reu/saved_state.rb +55 -0
- data/lib/badline/c64/reu/trigger.rb +34 -0
- data/lib/badline/c64/reu.rb +291 -0
- data/lib/badline/{computer → c64}/saved_state.rb +13 -18
- data/lib/badline/{computer → c64}/true_drives.rb +20 -31
- data/lib/badline/{computer.rb → c64.rb} +22 -80
- data/lib/badline/chips/cia/fast_forward.rb +62 -0
- data/lib/badline/chips/cia/interrupt_register.rb +145 -0
- data/lib/badline/chips/cia/saved_state.rb +49 -0
- data/lib/badline/chips/cia/serial/saved_state.rb +45 -0
- data/lib/badline/chips/cia/serial.rb +250 -0
- data/lib/badline/chips/cia/time_of_day.rb +232 -0
- data/lib/badline/chips/cia/timer.rb +208 -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 +167 -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/microcode.rb +179 -0
- data/lib/badline/chips/cpu/operations.rb +90 -0
- data/lib/badline/chips/cpu/port.rb +116 -0
- data/lib/badline/chips/cpu/saved_state.rb +117 -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 +12 -0
- data/lib/badline/chips/sid/catch_up.rb +122 -0
- data/lib/badline/chips/sid/decimator.rb +66 -0
- data/lib/badline/chips/sid/envelope/saved_state.rb +70 -0
- data/lib/badline/chips/sid/envelope.rb +241 -0
- data/lib/badline/chips/sid/filter/saved_state.rb +42 -0
- data/lib/badline/chips/sid/filter.rb +241 -0
- data/lib/badline/chips/sid/saved_state.rb +52 -0
- data/lib/badline/chips/sid/voice.rb +79 -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/saved_state.rb +68 -0
- data/lib/badline/chips/sid/waveform.rb +307 -0
- data/lib/badline/chips/sid.rb +265 -0
- data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
- data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -1
- data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -1
- data/lib/badline/chips/vdc/saved_state.rb +36 -0
- data/lib/badline/{c128 → chips}/vdc/window.rb +1 -1
- data/lib/badline/{c128 → chips}/vdc.rb +7 -31
- data/lib/badline/chips/via/control_lines.rb +124 -0
- data/lib/badline/chips/via/fast_forward.rb +55 -0
- data/lib/badline/chips/via/interrupt_register.rb +69 -0
- data/lib/badline/chips/via/saved_state.rb +44 -0
- data/lib/badline/chips/via/shift_register.rb +182 -0
- data/lib/badline/chips/via/timer1.rb +133 -0
- data/lib/badline/chips/via/timer2.rb +135 -0
- data/lib/badline/chips/via.rb +268 -0
- data/lib/badline/chips/vic/bank.rb +135 -0
- data/lib/badline/chips/vic/border_mask.rb +88 -0
- data/lib/badline/chips/vic/collisions.rb +117 -0
- data/lib/badline/chips/vic/color_patches.rb +49 -0
- data/lib/badline/chips/vic/display_state.rb +187 -0
- data/lib/badline/chips/vic/graphics_mode.rb +166 -0
- data/lib/badline/chips/vic/graphics_shifter/saved_state.rb +40 -0
- data/lib/badline/chips/vic/graphics_shifter.rb +187 -0
- data/lib/badline/chips/vic/register_log.rb +83 -0
- data/lib/badline/chips/vic/registers.rb +197 -0
- data/lib/badline/chips/vic/saved_state.rb +82 -0
- data/lib/badline/chips/vic/sequencer/saved_state.rb +91 -0
- data/lib/badline/chips/vic/sequencer.rb +277 -0
- data/lib/badline/chips/vic/sequencer_output.rb +118 -0
- data/lib/badline/chips/vic/sprite/internal_bus.rb +70 -0
- data/lib/badline/chips/vic/sprite/saved_state.rb +66 -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 +339 -0
- data/lib/badline/chips/vic/sprites/saved_state.rb +59 -0
- data/lib/badline/chips/vic/sprites.rb +284 -0
- data/lib/badline/chips/vic.rb +783 -0
- data/lib/badline/chips/vic_i/painter/saved_state.rb +40 -0
- data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +6 -30
- data/lib/badline/{vic20/vic → chips/vic_i}/saved_state.rb +2 -2
- data/lib/badline/chips/vic_i/sound/output.rb +85 -0
- data/lib/badline/chips/vic_i/sound.rb +235 -0
- data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
- data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +5 -5
- 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/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/saved_state.rb +71 -0
- data/lib/badline/chips/z80/shifts.rb +66 -0
- data/lib/badline/chips/z80.rb +13 -0
- data/lib/badline/core.rb +27 -29
- data/lib/badline/drives/datasette/saved_state.rb +37 -0
- data/lib/badline/drives/datasette.rb +140 -0
- data/lib/badline/drives/engine/core.rb +149 -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 +75 -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 +88 -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/saved_state.rb +88 -0
- data/lib/badline/drives/model1541/disk.rb +317 -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/mechanism/saved_state.rb +72 -0
- data/lib/badline/drives/model1541/mechanism.rb +315 -0
- data/lib/badline/drives/model1541/rotation.rb +123 -0
- data/lib/badline/drives/model1541/saved_state.rb +44 -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 +81 -0
- data/lib/badline/drives/model1571/bus.rb +113 -0
- data/lib/badline/drives/model1571/cpu.rb +13 -0
- data/lib/badline/drives/model1571/saved_state.rb +47 -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 +122 -0
- data/lib/badline/drives/model1571.rb +142 -0
- data/lib/badline/drives/model1581/bus.rb +139 -0
- data/lib/badline/drives/model1581/cpu.rb +13 -0
- data/lib/badline/drives/model1581/disk/saved_state.rb +89 -0
- data/lib/badline/drives/model1581/disk.rb +137 -0
- data/lib/badline/drives/model1581/mechanism.rb +119 -0
- data/lib/badline/drives/model1581/saved_state.rb +42 -0
- data/lib/badline/drives/model1581/serial_port.rb +54 -0
- data/lib/badline/drives/model1581/slot.rb +79 -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/saved_state.rb +68 -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 +218 -0
- data/lib/badline/drives/model1581.rb +206 -0
- data/lib/badline/drives/serial_bus.rb +161 -0
- data/lib/badline/frontend/boot.rb +10 -61
- data/lib/badline/frontend/machine_window.rb +3 -1
- 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/timeline.rb +3 -3
- 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.rb +3 -0
- data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
- data/lib/badline/kernal_trap/dos/channel.rb +183 -0
- data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
- data/lib/badline/kernal_trap/{drive.rb → dos.rb} +11 -10
- data/lib/badline/kernal_trap/{file.rb → file_routine.rb} +1 -1
- data/lib/badline/kernal_trap/load.rb +6 -6
- data/lib/badline/kernal_trap/save.rb +5 -5
- data/lib/badline/kernal_trap/serial.rb +7 -7
- data/lib/badline/kernal_trap.rb +2 -3
- data/lib/badline/machine/clocking.rb +50 -0
- data/lib/badline/machine.rb +63 -7
- data/lib/badline/media/boot_disk.rb +2 -2
- data/lib/badline/media/disk_list.rb +3 -3
- data/lib/badline/media/disk_set.rb +1 -1
- data/lib/badline/media/extensions.rb +33 -0
- data/lib/badline/media/program.rb +28 -0
- data/lib/badline/media/true_drive.rb +4 -3
- data/lib/badline/media/tune.rb +35 -0
- data/lib/badline/media/vic20_cartridge.rb +1 -7
- data/lib/badline/media/vic20_media.rb +38 -80
- data/lib/badline/media.rb +84 -81
- data/lib/badline/model.rb +1 -1
- data/lib/badline/options/event.rb +3 -1
- data/lib/badline/roms/README +6 -6
- 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 +43 -0
- data/lib/badline/snapshot/c64_setup.rb +79 -0
- data/lib/badline/snapshot/image.rb +5 -25
- data/lib/badline/snapshot/machine_state.rb +10 -2
- data/lib/badline/snapshot/setup.rb +22 -66
- data/lib/badline/snapshot/state.rb +8 -17
- data/lib/badline/snapshot/storage_setup.rb +68 -0
- data/lib/badline/snapshot/vic20_setup.rb +37 -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 +1 -1
- data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
- data/lib/badline/snapshot/vice.rb +7 -5
- data/lib/badline/snapshot.rb +13 -12
- data/lib/badline/storage/d64_image.rb +15 -9
- data/lib/badline/storage/d71_image.rb +0 -2
- data/lib/badline/storage/d81_image.rb +0 -2
- data/lib/badline/storage/disk_image/writing.rb +2 -2
- data/lib/badline/storage/disk_image.rb +3 -6
- data/lib/badline/storage/g64_image.rb +2 -2
- data/lib/badline/storage/host_directory.rb +0 -5
- data/lib/badline/storage/t64.rb +2 -8
- 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 +11 -81
- data/lib/badline/vic20/bus/saved_state.rb +35 -0
- data/lib/badline/vic20/bus.rb +3 -25
- data/lib/badline/vic20/cpu.rb +1 -1
- data/lib/badline/vic20/port_wiring.rb +4 -4
- data/lib/badline/vic20/saved_state.rb +16 -60
- data/lib/badline/vic20/user_via_ports.rb +2 -2
- data/lib/badline/vic20.rb +20 -51
- metadata +250 -221
- 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 -72
- data/lib/badline/address_bus/sid_slots.rb +0 -42
- data/lib/badline/address_bus.rb +0 -235
- 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/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/kernal_traps.rb +0 -29
- 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/cycleable.rb +0 -38
- data/lib/badline/datasette.rb +0 -161
- 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 -318
- data/lib/badline/drive1541/disk_state.rb +0 -94
- 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/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/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 -852
- data/lib/badline/vic20/sound/output.rb +0 -83
- data/lib/badline/vic20/sound.rb +0 -233
- 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,149 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
class C64
|
|
5
|
+
class Bus
|
|
6
|
+
# The C64's PLA: what each page of the CPU's view maps to, from the
|
|
7
|
+
# CPU port's LORAM, HIRAM and CHAREN lines and the cartridge's EXROM
|
|
8
|
+
# and GAME. The bus that includes it supplies the page tables, the
|
|
9
|
+
# ROMs, the chips, #map_ram_pages, which lays out the RAM that the
|
|
10
|
+
# ROMs, the cartridge and I/O map over, and #map_io_pages, which lays
|
|
11
|
+
# out the chips at $D000-$DFFF, with #map_cartridge_io for I/O 1 and 2.
|
|
12
|
+
module PLA
|
|
13
|
+
# A chip's registers seen at another page, which reads and writes
|
|
14
|
+
# them as at the page the chip starts at.
|
|
15
|
+
class Mirror
|
|
16
|
+
def initialize(chip, start)
|
|
17
|
+
@chip = chip
|
|
18
|
+
@start = start
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def peek(addr) = @chip.peek(@start | (addr & 0xff))
|
|
22
|
+
def poke(addr, value) = @chip.poke(@start | (addr & 0xff), value)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def map_pla_pages
|
|
28
|
+
map_ram_pages
|
|
29
|
+
@ultimax ? map_ultimax_pages : map_banked_pages
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def map_banked_pages
|
|
33
|
+
map_rom_overlays
|
|
34
|
+
map_cartridge_ram
|
|
35
|
+
@write_pages.fill(@cartridge.romh_writes, 0xe0, 0x20) if @cartridge&.romh_writes
|
|
36
|
+
|
|
37
|
+
if io?
|
|
38
|
+
map_io_pages
|
|
39
|
+
elsif character?
|
|
40
|
+
@read_pages.fill(character_rom, 0xd0, 0x10)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Ultimax mode ignores the $01 lines: 4K of RAM, ROML/ROMH windows,
|
|
45
|
+
# I/O always visible and open address space everywhere else. The ROML
|
|
46
|
+
# and ROMH selects fire on writes as well, so cartridge RAM or flash in
|
|
47
|
+
# either window takes the writes there. The MAX has 2K of RAM, and is
|
|
48
|
+
# in Ultimax mode with no cartridge too.
|
|
49
|
+
def map_ultimax_pages
|
|
50
|
+
first = @board == :max ? 0x08 : 0x10
|
|
51
|
+
@read_pages.fill(@open_bus, first, 0x100 - first)
|
|
52
|
+
@write_pages.fill(@open_bus, first, 0x100 - first)
|
|
53
|
+
map_ultimax_cartridge if @cartridge
|
|
54
|
+
map_io_pages
|
|
55
|
+
map_max_io if @board == :max
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def map_ultimax_cartridge
|
|
59
|
+
@read_pages.fill(@cartridge.roml, 0x80, 0x20) if @cartridge.roml
|
|
60
|
+
map_ultimax_writes(@cartridge.roml, 0x80)
|
|
61
|
+
@read_pages.fill(@cartridge.romh, 0xe0, 0x20) if @cartridge.romh
|
|
62
|
+
map_ultimax_writes(@cartridge.romh, 0xe0)
|
|
63
|
+
map_ultimax_a000
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def map_ultimax_writes(bank, first_page)
|
|
67
|
+
@write_pages.fill(bank, first_page, 0x20) if bank.respond_to?(:poke)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def map_ultimax_a000
|
|
71
|
+
return unless (window = @cartridge.ultimax_a000)
|
|
72
|
+
|
|
73
|
+
@read_pages.fill(window, 0xa0, 0x20)
|
|
74
|
+
@write_pages.fill(window, 0xa0, 0x20)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# The MAX has no CIA 2 and no I/O 2: CIA 1 answers all through
|
|
78
|
+
# $DC00-$DFFF, but for the I/O 1 page a cartridge takes.
|
|
79
|
+
def map_max_io
|
|
80
|
+
@cia1_mirror ||= Mirror.new(cia1, 0xdc00)
|
|
81
|
+
(0xdd..0xdf).each { |page| @read_pages[page] = @write_pages[page] = @cia1_mirror }
|
|
82
|
+
return unless @cartridge
|
|
83
|
+
|
|
84
|
+
@write_pages[0xde] = @cartridge
|
|
85
|
+
@read_pages[0xde] = @cartridge if @cartridge.readable_io_pages.include?(0xde)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# EXROM and GAME select the cartridge whether or not it has a chip
|
|
89
|
+
# there, and an empty socket leaves the bus floating.
|
|
90
|
+
def map_rom_overlays
|
|
91
|
+
@read_pages.fill(@cartridge.roml || @open_bus, 0x80, 0x20) if roml?
|
|
92
|
+
if romh?
|
|
93
|
+
@read_pages.fill(@cartridge.romh || @open_bus, 0xa0, 0x20)
|
|
94
|
+
elsif basic?
|
|
95
|
+
@read_pages.fill(basic_rom, 0xa0, 0x20)
|
|
96
|
+
end
|
|
97
|
+
@read_pages.fill(kernal_rom, 0xe0, 0x20) if kernal?
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Cartridge RAM in the ROML or ROMH window decodes writes itself,
|
|
101
|
+
# whatever the $01 lines say.
|
|
102
|
+
def map_cartridge_ram
|
|
103
|
+
return unless @cartridge&.exrom&.zero?
|
|
104
|
+
|
|
105
|
+
map_cartridge_ram_bank(@cartridge.roml, 0x80)
|
|
106
|
+
map_cartridge_ram_bank(@cartridge.romh, 0xa0) if @cartridge.game.zero?
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def map_cartridge_ram_bank(bank, first_page)
|
|
110
|
+
@write_pages.fill(bank, first_page, 0x20) if bank.is_a?(Cartridge::RAMBank)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def map_cartridge_io
|
|
114
|
+
@write_pages.fill(@cartridge, 0xde, 2)
|
|
115
|
+
@cartridge.readable_io_pages.each { |p| @read_pages[p] = @cartridge }
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def basic?
|
|
119
|
+
io_port.kernal? && io_port.basic? && game_high?
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def game_high?
|
|
123
|
+
@cartridge.nil? || @cartridge.game == 1
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def roml?
|
|
127
|
+
@cartridge&.exrom&.zero? && io_port.kernal? && io_port.basic?
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def romh?
|
|
131
|
+
@cartridge&.exrom&.zero? && @cartridge.game.zero? && io_port.kernal?
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# In 16K mode LORAM alone leaves $d000 as RAM, where it still maps I/O.
|
|
135
|
+
def character?
|
|
136
|
+
(io_port.kernal? || (io_port.basic? && game_high?)) && !io_port.io?
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def io?
|
|
140
|
+
(io_port.basic? || io_port.kernal?) && io_port.io?
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def kernal?
|
|
144
|
+
io_port.kernal?
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
class C64
|
|
5
|
+
class Bus
|
|
6
|
+
# The BASIC, character and KERNAL ROMs, and which KERNAL is fitted.
|
|
7
|
+
module ROMs
|
|
8
|
+
# The KERNAL ROMs a machine can be fitted with, by name: the C64's,
|
|
9
|
+
# the SX-64's, the PET 64's and the C64GS's. The C64GS's is a 16K
|
|
10
|
+
# image of its BASIC and its KERNAL, and fits both.
|
|
11
|
+
KERNALS = {
|
|
12
|
+
c64: "kernal.rom", sx64: "kernal-sx64.rom", pet64: "kernal-pet64.rom", gs: "c64gs.rom"
|
|
13
|
+
}.freeze
|
|
14
|
+
|
|
15
|
+
attr_reader :basic_rom, :character_rom, :kernal_rom, :kernal
|
|
16
|
+
|
|
17
|
+
# Fits the KERNAL ROM KERNALS names `name`, in place of the one before,
|
|
18
|
+
# with the BASIC of a 16K image or else the C64's.
|
|
19
|
+
def kernal=(name)
|
|
20
|
+
raise ArgumentError, "no KERNAL named #{name}" unless KERNALS.key?(name)
|
|
21
|
+
|
|
22
|
+
@kernal = name
|
|
23
|
+
data = ROM.read(KERNALS[name])
|
|
24
|
+
basic = data.length == 0x4000 ? data[0, 0x2000] : ROM.read("basic.rom")
|
|
25
|
+
@basic_rom = ROM.new(basic, length: 0x2000, start: 0xa000)
|
|
26
|
+
@kernal_rom = ROM.new(data[-0x2000, 0x2000], length: 0x2000, start: 0xe000)
|
|
27
|
+
update_overlays!
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def load_roms
|
|
33
|
+
@basic_rom = ROM.load("basic.rom", 0xa000)
|
|
34
|
+
@character_rom = ROM.load("character.rom", 0xd000)
|
|
35
|
+
@kernal = :c64
|
|
36
|
+
@kernal_rom = ROM.load(KERNALS[:c64], 0xe000)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
class C64
|
|
5
|
+
class Bus
|
|
6
|
+
# The bus's state for a snapshot: the CPU port, the RAM, colour RAM and
|
|
7
|
+
# a RAM expansion, the cartridge, the datasette and the chips.
|
|
8
|
+
module SavedState
|
|
9
|
+
# The RAM expansion fitted, or an Unexpanded stand-in.
|
|
10
|
+
attr_reader :ram_expansion
|
|
11
|
+
|
|
12
|
+
# Takes the cartridge out of the expansion port, as a restore does for
|
|
13
|
+
# a state without one.
|
|
14
|
+
def detach_cartridge
|
|
15
|
+
@cartridge = nil
|
|
16
|
+
update_overlays!
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# The 6510 port's direction and output registers, and the charge left
|
|
20
|
+
# on its floating bits.
|
|
21
|
+
def port_state = [@cpu_port.ddr, @cpu_port.data, @cpu_port.floating]
|
|
22
|
+
|
|
23
|
+
# Sets the port as port_state reads it, as a snapshot restores it,
|
|
24
|
+
# leaving the RAM under $00 and $01 alone.
|
|
25
|
+
def restore_port(ddr, out, floating)
|
|
26
|
+
@cpu_port.restore(ddr, out, floating)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# The machine's memory and everything on the bus but the keyboard, the
|
|
30
|
+
# joysticks and the pot devices, which the host holds. A cartridge is
|
|
31
|
+
# already in the port, built from its setup (C64#load_state).
|
|
32
|
+
def save_state(out)
|
|
33
|
+
out.marker("BUS")
|
|
34
|
+
out.int(@cpu_port.ddr).int(@cpu_port.data).int(@cpu_port.floating)
|
|
35
|
+
@ram.save_state(out)
|
|
36
|
+
@color_ram.save_state(out)
|
|
37
|
+
@ram_expansion.save_state(out)
|
|
38
|
+
@cartridge&.save_state(out)
|
|
39
|
+
@datasette.save_state(out)
|
|
40
|
+
@vic.save_state(out)
|
|
41
|
+
@cia1.save_state(out)
|
|
42
|
+
@cia2.save_state(out)
|
|
43
|
+
@sid.save_state(out)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def load_state(input)
|
|
47
|
+
input.marker("BUS")
|
|
48
|
+
ddr = input.int
|
|
49
|
+
port_out = input.int
|
|
50
|
+
floating = input.int
|
|
51
|
+
@ram.load_state(input)
|
|
52
|
+
@color_ram.load_state(input)
|
|
53
|
+
@ram_expansion.load_state(input)
|
|
54
|
+
@cartridge&.load_state(input)
|
|
55
|
+
@datasette.load_state(input)
|
|
56
|
+
@cpu_port.load(ddr, port_out, floating)
|
|
57
|
+
update_overlays!
|
|
58
|
+
@vic.load_state(input)
|
|
59
|
+
@cia1.load_state(input)
|
|
60
|
+
@cia2.load_state(input)
|
|
61
|
+
@sid.load_state(input)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
include SavedState
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
class C64
|
|
5
|
+
class Bus
|
|
6
|
+
# Stands in for a page of I/O that a second or third SID shares: each 32
|
|
7
|
+
# bytes of it go to the SID placed there, or else to the first SID's
|
|
8
|
+
# mirrors in `$d400-$d7ff`, and to the open bus in I/O 1 and 2.
|
|
9
|
+
class SIDSlots
|
|
10
|
+
attr_reader :page
|
|
11
|
+
|
|
12
|
+
def initialize(page, first, open_bus)
|
|
13
|
+
@page = page
|
|
14
|
+
@io = page >= 0xde
|
|
15
|
+
@first = first
|
|
16
|
+
@open_bus = open_bus
|
|
17
|
+
@sids = []
|
|
18
|
+
@slots = Array.new(8, -1)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def place(sid)
|
|
22
|
+
@slots[(sid.start >> 5) & 7] = @sids.size
|
|
23
|
+
@sids << sid
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def peek(addr)
|
|
27
|
+
index = @slots[(addr >> 5) & 7]
|
|
28
|
+
return @sids[index].peek(addr) unless index.negative?
|
|
29
|
+
|
|
30
|
+
@io ? @open_bus.peek(addr) : @first.peek(addr)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def poke(addr, value)
|
|
34
|
+
index = @slots[(addr >> 5) & 7]
|
|
35
|
+
if !index.negative?
|
|
36
|
+
@sids[index].poke(addr, value)
|
|
37
|
+
elsif !@io
|
|
38
|
+
@first.poke(addr, value)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "badline/c64/bus/saved_state"
|
|
4
|
+
require "badline/c64/bus/sid_slots"
|
|
5
|
+
require "badline/c64/bus/extra_sids"
|
|
6
|
+
require "badline/c64/bus/pla"
|
|
7
|
+
require "badline/c64/bus/roms"
|
|
8
|
+
require "badline/c64/bus/fittings"
|
|
9
|
+
|
|
10
|
+
module Badline
|
|
11
|
+
# Memory layout:
|
|
12
|
+
#
|
|
13
|
+
# 0x0000-0x00FF - Page 0 - Zeropage
|
|
14
|
+
# 0x0100-0x01FF - Page 1 - Stack
|
|
15
|
+
# 0x0200-0x02FF - Page 2 - OS/BASIC pointers
|
|
16
|
+
# 0x0300-0x03FF - Page 3 - OS/BASIC pointers
|
|
17
|
+
# 0x0400-0x07FF - Page 4-7 - Screen memory
|
|
18
|
+
# 0x0800-0x9FFF - Page 8-159 - BASIC program storage area
|
|
19
|
+
# 0xA000-0xBFFF - Page 160-191 - Machine code program storage (ROM overlay)
|
|
20
|
+
# 0xC000-0xCFFF - Page 192-207 - Machine code program storage
|
|
21
|
+
# 0xD000-0xD3FF - Page 208-211 - VIC II registers
|
|
22
|
+
# 0xD400-0xD7FF - Page 212-215 - SID registers
|
|
23
|
+
# 0xD800-0xDBFF - Page 216-219 - Color memory
|
|
24
|
+
# 0xDC00-0xDCFF - Page 220 - CIA 1
|
|
25
|
+
# 0xDD00-0xDDFF - Page 221 - CIA 2
|
|
26
|
+
# 0xDE00-0xDEFF - Page 222 - I/O 1
|
|
27
|
+
# 0xDF00-0xDFFF - Page 223 - I/O 2
|
|
28
|
+
# 0xE000-0xFFFF - Page 224-255 - Machine code program storage (ROM overlay)
|
|
29
|
+
|
|
30
|
+
class C64
|
|
31
|
+
# Overlays:
|
|
32
|
+
#
|
|
33
|
+
# 0x8000-0x9FFF - Cartridge ROM (low) - 8kb
|
|
34
|
+
# 0xA000-0xBFFF - BASIC ROM / Cartridge ROM (high) - 8kb
|
|
35
|
+
# 0xD000-0xDFFF - Character ROM / I/O - 4kb
|
|
36
|
+
# 0xE000-0xFFFF - KERNAL ROM / Cartridge ROM (high) - 8kb
|
|
37
|
+
class Bus
|
|
38
|
+
include Addressable
|
|
39
|
+
include PLA
|
|
40
|
+
include ExtraSIDs
|
|
41
|
+
include ROMs
|
|
42
|
+
include Fittings
|
|
43
|
+
|
|
44
|
+
# I/O 1 and 2, and the Ultimax holes, with nothing on the bus. A read
|
|
45
|
+
# picks up the byte the VIC fetched in the preceding phi1 half-cycle,
|
|
46
|
+
# and a write goes nowhere.
|
|
47
|
+
class OpenBus
|
|
48
|
+
def initialize(vic)
|
|
49
|
+
@vic = vic
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def peek(_addr) = @vic.phi1_data
|
|
53
|
+
def poke(_addr, _value); end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# The 6510's port pins with pull-ups, and the floating ones (CPU::Port).
|
|
57
|
+
PORT_PULLUPS = 0b0001_0111
|
|
58
|
+
PORT_FLOATING = 0b1100_1000
|
|
59
|
+
|
|
60
|
+
# RAM powers on in runs of $00 $00 $FF $FF $FF $FF $00 $00, inverted in
|
|
61
|
+
# the second and fourth 16K: a C64C (ASSY 250469 R4) from
|
|
62
|
+
# C64/raminitpattern/readme.txt, without its occasional random bytes.
|
|
63
|
+
# See doc/pinned-behaviour.md.
|
|
64
|
+
RAM_POWER_ON = Array.new(2**16) { |addr| (((addr + 2) / 4) ^ (addr / 0x4000)).odd? ? 0xff : 0x00 }.freeze
|
|
65
|
+
|
|
66
|
+
attr_reader :io_port, :ram,
|
|
67
|
+
:vic, :sid, :color_ram, :cia1, :cia2, :keyboard, :joystick1, :joystick2,
|
|
68
|
+
:control_ports, :cartridge, :ultimax, :phi1_ultimax, :datasette, :region, :video_ram, :reu
|
|
69
|
+
|
|
70
|
+
# ram_expansion fits a +60K (:plus60k) or +256K (:plus256k).
|
|
71
|
+
def initialize(sid_model: :mos6581, cia_model: :mos6526, vic_model: :mos6569, region: Region::PAL,
|
|
72
|
+
ram_expansion: nil)
|
|
73
|
+
@region = region
|
|
74
|
+
@board = :c64
|
|
75
|
+
@ram = Memory.new(RAM_POWER_ON, length: 2**16, start: 0)
|
|
76
|
+
@ram_expansion = BankedRAM.build(ram_expansion, @ram) { update_overlays! }
|
|
77
|
+
@cartridge = @reu = nil
|
|
78
|
+
@debug_register = nil
|
|
79
|
+
|
|
80
|
+
load_roms
|
|
81
|
+
|
|
82
|
+
@keyboard = Input::Keyboard.new
|
|
83
|
+
@joystick1 = Input::Joystick.new
|
|
84
|
+
@joystick2 = Input::Joystick.new
|
|
85
|
+
@control_ports = Input::ControlPorts.new(keyboard: @keyboard, joystick1: @joystick1, joystick2: @joystick2)
|
|
86
|
+
@vic = Chips::VIC.new(model: vic_model, region:)
|
|
87
|
+
@cia1 = Chips::CIA.new(start: 0xdc00, peripheral: @control_ports, model: cia_model, region:)
|
|
88
|
+
@cia2 = Chips::CIA.new(start: 0xdd00, model: cia_model, region:)
|
|
89
|
+
@control_ports.port_a_source = @cia1
|
|
90
|
+
@cia1.on_port_b4_change { |high| @vic.lightpen_level(high) }
|
|
91
|
+
@sid = Chips::SID.new(model: sid_model, pots: @control_ports)
|
|
92
|
+
@sid_slots = []
|
|
93
|
+
|
|
94
|
+
@datasette = Drives::Datasette.new
|
|
95
|
+
@datasette.on_flag { @cia1.flag! }
|
|
96
|
+
@datasette.on_sense_change { @cpu_port.refresh }
|
|
97
|
+
|
|
98
|
+
@color_ram = ColorMemory.new(@vic)
|
|
99
|
+
@vic.vic_bank.connect(cia2: @cia2, color_ram: @color_ram)
|
|
100
|
+
@vic.vic_bank.map_character_rom(character_rom)
|
|
101
|
+
@open_bus = OpenBus.new(@vic)
|
|
102
|
+
@cpu_off_bus = false
|
|
103
|
+
|
|
104
|
+
@cpu_port = Chips::CPU::Port.new(@datasette, pullups: PORT_PULLUPS, floating: PORT_FLOATING)
|
|
105
|
+
@cpu_port.on_change { update_overlays! }
|
|
106
|
+
@io_port = @cpu_port.status
|
|
107
|
+
|
|
108
|
+
@read_pages = Array.new(256)
|
|
109
|
+
@write_pages = Array.new(256)
|
|
110
|
+
update_overlays!
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def attach_cartridge(cartridge)
|
|
114
|
+
@cartridge = cartridge
|
|
115
|
+
cartridge.connect(ram: @ram, open_bus: @open_bus)
|
|
116
|
+
cartridge.on_change { update_overlays! }
|
|
117
|
+
update_overlays!
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# An REU takes I/O 2 unless a cartridge claims it, and watches writes
|
|
121
|
+
# to $FF00 for the one that starts an armed transfer.
|
|
122
|
+
def attach_reu(reu)
|
|
123
|
+
@reu = reu
|
|
124
|
+
update_overlays!
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def power_on!
|
|
128
|
+
@ram.clear!(RAM_POWER_ON)
|
|
129
|
+
@ram_expansion.power_on!
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# The RES line clears the 6510 port's direction and output registers,
|
|
133
|
+
# and a RAM expansion's bank register. The port's floating bits keep
|
|
134
|
+
# their charge.
|
|
135
|
+
def reset!
|
|
136
|
+
@ram_expansion.reset!
|
|
137
|
+
@cpu_port.reset!
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def disable_overlays!
|
|
141
|
+
poke(0, 0x2f)
|
|
142
|
+
poke(1, 0)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def install_debug_register(&)
|
|
146
|
+
@debug_register = DebugRegister.new(@sid, &)
|
|
147
|
+
update_overlays!
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def peek(addr)
|
|
151
|
+
return @cpu_port.ddr if addr.zero?
|
|
152
|
+
return @io_port.value if addr == 0x01
|
|
153
|
+
|
|
154
|
+
@read_pages[addr >> 8].peek(addr)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# A write to $00 or $01 goes to the port, but the RAM below is still
|
|
158
|
+
# write-enabled, and takes whatever is left on the bus: the byte the VIC
|
|
159
|
+
# fetched in the phi1 half of the cycle.
|
|
160
|
+
def poke(addr, value)
|
|
161
|
+
if addr < 0x02
|
|
162
|
+
@ram.poke(addr, @vic.phi1_data)
|
|
163
|
+
addr.zero? ? @cpu_port.write_ddr(value) : @cpu_port.write_data(value)
|
|
164
|
+
elsif !@cpu_off_bus
|
|
165
|
+
@write_pages[addr >> 8].poke(addr, value)
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Runs a CPU cycle with the CPU off the bus, as an REU's /DMA line
|
|
170
|
+
# holds it: a write it makes reaches nothing but its own port.
|
|
171
|
+
def cycle_cpu_off_bus(cpu)
|
|
172
|
+
@cpu_off_bus = true
|
|
173
|
+
cpu.cycle!
|
|
174
|
+
@cpu_off_bus = false
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def inspect
|
|
178
|
+
"#<#{self.class.name} port=#{format('0x%02x', @io_port.value)} " \
|
|
179
|
+
"cartridge=#{@cartridge ? @cartridge.class.name : 'none'} " \
|
|
180
|
+
"ultimax=#{@ultimax}>"
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
private
|
|
184
|
+
|
|
185
|
+
# Banking changes only on $01 writes and cartridge line/bank changes,
|
|
186
|
+
# so reads and writes dispatch through per-page handler tables instead
|
|
187
|
+
# of range checks.
|
|
188
|
+
def update_overlays!
|
|
189
|
+
max = @board == :max
|
|
190
|
+
@ultimax = max || (@cartridge ? @cartridge.ultimax? : false)
|
|
191
|
+
@phi1_ultimax = max || (@cartridge ? @cartridge.phi1_ultimax? : false)
|
|
192
|
+
@video_ram = @ram_expansion.video_ram
|
|
193
|
+
@vic.vic_bank.map(@video_ram, phi1_ultimax: @phi1_ultimax, ultimax: @ultimax, romh: @cartridge&.romh)
|
|
194
|
+
|
|
195
|
+
map_pla_pages
|
|
196
|
+
@write_pages[0xff] = @reu.trigger.wrap(@write_pages[0xff]) if @reu
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def map_ram_pages
|
|
200
|
+
@ram_expansion.map(@read_pages, @write_pages)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def map_io_pages
|
|
204
|
+
{
|
|
205
|
+
vic => 0xd0..0xd3, sid => 0xd4..0xd7, color_ram => 0xd8..0xdb,
|
|
206
|
+
cia1 => 0xdc..0xdc, cia2 => 0xdd..0xdd, @open_bus => 0xde..0xdf
|
|
207
|
+
}.each do |chip, pages|
|
|
208
|
+
pages.each { |p| @read_pages[p] = @write_pages[p] = chip }
|
|
209
|
+
end
|
|
210
|
+
@ram_expansion.map_io(@read_pages, @write_pages)
|
|
211
|
+
@read_pages[0xd7] = @write_pages[0xd7] = @debug_register if @debug_register
|
|
212
|
+
@read_pages[0xdf] = @write_pages[0xdf] = @reu if @reu
|
|
213
|
+
map_cartridge_io if @cartridge
|
|
214
|
+
map_extra_sids unless @sid_slots.empty?
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
class C64
|
|
5
|
+
class Cartridge
|
|
6
|
+
# Action Replay v4.2 to v6: four 8K ROM banks and 8K of RAM. A write to
|
|
7
|
+
# I/O 1 sets the control register:
|
|
8
|
+
#
|
|
9
|
+
# bit 0 pulls GAME low
|
|
10
|
+
# bit 1 releases EXROM
|
|
11
|
+
# bit 2 switches the register off until the next freeze or reset
|
|
12
|
+
# bits 3-4 ROM bank
|
|
13
|
+
# bit 5 RAM instead of ROM at ROML and I/O 2
|
|
14
|
+
# bit 6 acknowledges a freeze and lets go of NMI
|
|
15
|
+
#
|
|
16
|
+
# I/O 2 shows the last page of the RAM or of the ROM bank. The register
|
|
17
|
+
# doesn't decode R/W, so a read of I/O 1 writes whatever is on the bus
|
|
18
|
+
# into it. RAM with only EXROM released ($22) selects the cartridge RAM
|
|
19
|
+
# and the C64's together at ROML. A freeze switches the cartridge back
|
|
20
|
+
# on, in Ultimax mode with the RAM at ROML and the first bank at ROMH.
|
|
21
|
+
class ActionReplay < Cartridge
|
|
22
|
+
include Freezer
|
|
23
|
+
|
|
24
|
+
CONTROL_MODES = %i[rom8k rom16k off ultimax].freeze
|
|
25
|
+
IO2_PAGE = 0x1f00
|
|
26
|
+
|
|
27
|
+
def connect(ram:, open_bus:)
|
|
28
|
+
super
|
|
29
|
+
@through.backing = ram
|
|
30
|
+
@contended.backing = ram
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def readable_io_pages
|
|
34
|
+
[0xde, 0xdf]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def peek(addr)
|
|
38
|
+
return open_bus(addr) unless @active
|
|
39
|
+
return io2_peek(addr) if addr >= 0xdf00
|
|
40
|
+
|
|
41
|
+
open_bus(addr).tap { |value| control(value) }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def poke(addr, value)
|
|
45
|
+
return unless @active
|
|
46
|
+
|
|
47
|
+
if addr < 0xdf00
|
|
48
|
+
control(value)
|
|
49
|
+
elsif @io2_ram
|
|
50
|
+
@ram_data[IO2_PAGE | (addr & 0xff)] = value
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def reset
|
|
55
|
+
@active = true
|
|
56
|
+
self.nmi = false
|
|
57
|
+
control(0)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def freeze!
|
|
61
|
+
@active = true
|
|
62
|
+
@rom = bank(@rom_banks, 0)
|
|
63
|
+
select(:ultimax, @isolated, io2_ram: true)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
def save_mapper(out)
|
|
69
|
+
super
|
|
70
|
+
out.int(window_index(@rom, windows)).boolean(@active).boolean(@io2_ram).blob(@ram_data)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def load_mapper(input)
|
|
74
|
+
super
|
|
75
|
+
@rom = window_at(input.int, windows)
|
|
76
|
+
@active = input.boolean?
|
|
77
|
+
@io2_ram = input.boolean?
|
|
78
|
+
input.blob_into(@ram_data)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def windows = [@through, @isolated, @contended, *@rom_banks, EMPTY_BANK]
|
|
82
|
+
|
|
83
|
+
def io2_peek(addr)
|
|
84
|
+
@io2_ram ? @ram_data[IO2_PAGE | (addr & 0xff)] : @rom.peek(addr)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def control(value)
|
|
88
|
+
self.nmi = false if value.anybits?(0x40)
|
|
89
|
+
@rom = bank(@rom_banks, (value >> 3) & 0x03)
|
|
90
|
+
configure(value)
|
|
91
|
+
@active = false if value.anybits?(0x04)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def configure(value)
|
|
95
|
+
return select(:rom8k, @contended, io2_ram: true) if (value & 0x23) == 0x22
|
|
96
|
+
|
|
97
|
+
configure_standard(value)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def configure_standard(value)
|
|
101
|
+
mode = CONTROL_MODES[value & 0x03]
|
|
102
|
+
if value.anybits?(0x20)
|
|
103
|
+
select(mode, mode == :ultimax ? @isolated : @through, io2_ram: true)
|
|
104
|
+
else
|
|
105
|
+
select(mode, @rom, io2_ram: false)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def select(mode, roml, io2_ram:, romh: @rom)
|
|
110
|
+
self.mode = mode
|
|
111
|
+
@roml = roml
|
|
112
|
+
@romh = romh
|
|
113
|
+
@io2_ram = io2_ram
|
|
114
|
+
changed!
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def install_chips(chips)
|
|
118
|
+
@rom_banks = banks_from(chips).first
|
|
119
|
+
@ram_data = Array.new(BANK_SIZE, 0)
|
|
120
|
+
@through = RAMBank.new(@ram_data)
|
|
121
|
+
@isolated = RAMBank.new(@ram_data)
|
|
122
|
+
@contended = ContendedRAM.new(@ram_data)
|
|
123
|
+
reset
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
class C64
|
|
5
|
+
class Cartridge
|
|
6
|
+
# Atomic Power, sold as Nordic Power: an Action Replay 5 with one more
|
|
7
|
+
# configuration. RAM with only EXROM released and bits 2, 6 and 7 clear
|
|
8
|
+
# ($22) selects 16K mode with the ROM bank at ROML and the RAM at ROMH
|
|
9
|
+
# and I/O 2. Writes to that RAM don't reach the C64's. The VIC never
|
|
10
|
+
# sees Ultimax mode.
|
|
11
|
+
class AtomicPower < ActionReplay
|
|
12
|
+
def phi1_ultimax?
|
|
13
|
+
false
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def configure(value)
|
|
19
|
+
return select(:rom16k, @rom, romh: @isolated, io2_ram: true) if (value & 0xe7) == 0x22
|
|
20
|
+
|
|
21
|
+
configure_standard(value)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|