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
|
@@ -1,306 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Cartridge
|
|
5
|
-
# A Flash chip's state, for a snapshot.
|
|
6
|
-
module FlashState
|
|
7
|
-
STATES = %i[read program_setup autoselect programming erase_window erasing suspended chip_erase
|
|
8
|
-
program_error].freeze
|
|
9
|
-
|
|
10
|
-
# The array, the command state, a timed operation's end on the
|
|
11
|
-
# machine's clock, and the windows handed out so far, which load_state
|
|
12
|
-
# builds anew.
|
|
13
|
-
def save_state(out)
|
|
14
|
-
out.blob(@data).int(STATES.index(@state)).int(STATES.index(@base_state)).int(@cycle).int(@toggle)
|
|
15
|
-
out.optional_int(@done_at).optional_int(@programmed).optional_int(@remaining)
|
|
16
|
-
out.boolean(!@erasing_sectors.nil?)
|
|
17
|
-
out.ints(@erasing_sectors) if @erasing_sectors
|
|
18
|
-
out.ints(@windows.keys).ints(@status_windows.keys)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def load_state(input)
|
|
22
|
-
input.blob_into(@data)
|
|
23
|
-
@state = STATES.fetch(input.int).to_sym
|
|
24
|
-
@base_state = STATES.fetch(input.int).to_sym
|
|
25
|
-
@cycle = input.int
|
|
26
|
-
@toggle = input.int
|
|
27
|
-
@done_at = input.optional_int
|
|
28
|
-
@programmed = input.optional_int
|
|
29
|
-
@remaining = input.optional_int
|
|
30
|
-
@erasing_sectors = nil
|
|
31
|
-
@erasing_sectors = input.ints if input.boolean?
|
|
32
|
-
rebuild_windows(input.ints, input.ints)
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# An AMD 29F0x0 flash chip, driven through the JEDEC command set in the
|
|
37
|
-
# AMD datasheets. Each command opens with two unlock cycles, $AA to the
|
|
38
|
-
# first unlock address and $55 to the second, and a third write picks
|
|
39
|
-
# the command:
|
|
40
|
-
#
|
|
41
|
-
# $90 autoselect: offset 0 reads the manufacturer, 1 the device and 2
|
|
42
|
-
# the sector protection, until a reset
|
|
43
|
-
# $F0 reset to reading the array, which a lone $F0 also does
|
|
44
|
-
# $A0 byte program: the next write clears bits of the array, which
|
|
45
|
-
# only an erase sets again
|
|
46
|
-
# $80 erase, after two more unlock cycles: $10 to the first unlock
|
|
47
|
-
# address erases the chip, and $30 to a sector erases the sector.
|
|
48
|
-
# Further sectors can follow within the 50 us window.
|
|
49
|
-
#
|
|
50
|
-
# While a program or erase runs, a read returns status: DQ7 the
|
|
51
|
-
# complement of the programmed bit (0 while erasing), DQ6 toggling on
|
|
52
|
-
# every read, DQ5 set when a program failed and DQ3 set once an erase
|
|
53
|
-
# has left its window. $B0 suspends a sector erase and $30 resumes it.
|
|
54
|
-
#
|
|
55
|
-
# The cartridge reads the array through windows, and the chip swaps
|
|
56
|
-
# them for status windows while it is busy or in autoselect.
|
|
57
|
-
class Flash
|
|
58
|
-
Model = Data.define(:size, :sector_size, :unlock1, :unlock2, :unlock_mask, :manufacturer, :device)
|
|
59
|
-
|
|
60
|
-
AM29F040 = Model.new(size: 0x80000, sector_size: 0x10000, unlock1: 0x5555, unlock2: 0x2aaa,
|
|
61
|
-
unlock_mask: 0x7fff, manufacturer: 0x01, device: 0xa4)
|
|
62
|
-
AM29F040B = Model.new(size: 0x80000, sector_size: 0x10000, unlock1: 0x555, unlock2: 0x2aa,
|
|
63
|
-
unlock_mask: 0x7ff, manufacturer: 0x01, device: 0xa4)
|
|
64
|
-
AM29F010 = Model.new(size: 0x20000, sector_size: 0x4000, unlock1: 0x5555, unlock2: 0x2aaa,
|
|
65
|
-
unlock_mask: 0x7fff, manufacturer: 0x01, device: 0x20)
|
|
66
|
-
|
|
67
|
-
# The datasheet's typical times, in cycles at 1 MHz.
|
|
68
|
-
PROGRAM_CYCLES = 7
|
|
69
|
-
ERASE_WINDOW_CYCLES = 50
|
|
70
|
-
SECTOR_ERASE_CYCLES = 1_000_000
|
|
71
|
-
CHIP_ERASE_CYCLES = 8_000_000
|
|
72
|
-
|
|
73
|
-
# The array, read directly while the chip reads it.
|
|
74
|
-
class Window
|
|
75
|
-
def initialize(flash, base)
|
|
76
|
-
@flash = flash
|
|
77
|
-
@data = flash.data
|
|
78
|
-
@base = base
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def peek(addr)
|
|
82
|
-
@data[@base | (addr & 0x1fff)]
|
|
83
|
-
end
|
|
84
|
-
alias [] peek
|
|
85
|
-
|
|
86
|
-
def poke(addr, value)
|
|
87
|
-
@flash.write(@base | (addr & 0x1fff), value)
|
|
88
|
-
end
|
|
89
|
-
alias []= poke
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
# Reads through the chip, for its status and autoselect codes.
|
|
93
|
-
class StatusWindow < Window
|
|
94
|
-
def peek(addr)
|
|
95
|
-
@flash.read(@base | (addr & 0x1fff))
|
|
96
|
-
end
|
|
97
|
-
alias [] peek
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
include FlashState
|
|
101
|
-
|
|
102
|
-
attr_reader :data, :state
|
|
103
|
-
attr_writer :clock
|
|
104
|
-
|
|
105
|
-
def initialize(data, model: AM29F040B, clock: -> { 0 })
|
|
106
|
-
@model = model
|
|
107
|
-
@data = data + ([0xff] * (model.size - data.length))
|
|
108
|
-
@clock = clock
|
|
109
|
-
@windows = {}
|
|
110
|
-
@status_windows = {}
|
|
111
|
-
@on_change = nil
|
|
112
|
-
@state = :read
|
|
113
|
-
@base_state = :read
|
|
114
|
-
@cycle = 0
|
|
115
|
-
@toggle = 0
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
# Called when the chip starts or stops answering reads from the array.
|
|
119
|
-
def on_change(&block)
|
|
120
|
-
@on_change = block
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
def window(base)
|
|
124
|
-
if array_mode?
|
|
125
|
-
@windows[base] ||= Window.new(self, base)
|
|
126
|
-
else
|
|
127
|
-
@status_windows[base] ||= StatusWindow.new(self, base)
|
|
128
|
-
end
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
# Hands out new windows at the bases given, as #window would have.
|
|
132
|
-
def rebuild_windows(bases, status_bases)
|
|
133
|
-
@windows = {}
|
|
134
|
-
@status_windows = {}
|
|
135
|
-
bases.each { |base| @windows[base] = Window.new(self, base) }
|
|
136
|
-
status_bases.each { |base| @status_windows[base] = StatusWindow.new(self, base) }
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
def array_mode?
|
|
140
|
-
@state == :read || @state == :program_setup
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
def read(offset)
|
|
144
|
-
settle
|
|
145
|
-
case @state
|
|
146
|
-
when :read then @data[offset]
|
|
147
|
-
when :autoselect then autoselect_code(offset)
|
|
148
|
-
when :suspended then suspended_read(offset)
|
|
149
|
-
else status
|
|
150
|
-
end
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
def write(offset, value)
|
|
154
|
-
settle
|
|
155
|
-
case @state
|
|
156
|
-
when :program_setup then program(offset, value)
|
|
157
|
-
when :erase_window then extend_erase(offset, value)
|
|
158
|
-
when :erasing then suspend if value == 0xb0
|
|
159
|
-
when :suspended then resume if value == 0x30
|
|
160
|
-
when :program_error then enter(:read, base: :read) if value == 0xf0
|
|
161
|
-
when :programming, :chip_erase then nil
|
|
162
|
-
else command(offset, value)
|
|
163
|
-
end
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
private
|
|
167
|
-
|
|
168
|
-
def command(offset, value)
|
|
169
|
-
if value == 0xf0
|
|
170
|
-
@cycle = 0
|
|
171
|
-
return enter(:read, base: :read)
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
address = offset & @model.unlock_mask
|
|
175
|
-
@cycle = case @cycle
|
|
176
|
-
when 0, 3 then address == @model.unlock1 && value == 0xaa ? @cycle + 1 : 0
|
|
177
|
-
when 1, 4 then address == @model.unlock2 && value == 0x55 ? @cycle + 1 : 0
|
|
178
|
-
when 2 then command_cycle(address, value)
|
|
179
|
-
when 5 then erase_command(offset, address, value)
|
|
180
|
-
end
|
|
181
|
-
end
|
|
182
|
-
|
|
183
|
-
def command_cycle(address, value)
|
|
184
|
-
return 0 unless address == @model.unlock1
|
|
185
|
-
|
|
186
|
-
case value
|
|
187
|
-
when 0x90 then enter(:autoselect, base: :autoselect)
|
|
188
|
-
when 0xa0 then @state = :program_setup
|
|
189
|
-
when 0x80 then return 3
|
|
190
|
-
end
|
|
191
|
-
0
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
def erase_command(offset, address, value)
|
|
195
|
-
if value == 0x10 && address == @model.unlock1
|
|
196
|
-
start_busy(:chip_erase, CHIP_ERASE_CYCLES)
|
|
197
|
-
elsif value == 0x30
|
|
198
|
-
@erasing_sectors = [sector(offset)]
|
|
199
|
-
start_busy(:erase_window, ERASE_WINDOW_CYCLES)
|
|
200
|
-
end
|
|
201
|
-
0
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
def program(offset, value)
|
|
205
|
-
@programmed = value
|
|
206
|
-
@data[offset] &= value
|
|
207
|
-
if @data[offset] == value
|
|
208
|
-
start_busy(:programming, PROGRAM_CYCLES)
|
|
209
|
-
else
|
|
210
|
-
enter(:program_error)
|
|
211
|
-
end
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
def extend_erase(offset, value)
|
|
215
|
-
case value
|
|
216
|
-
when 0x30
|
|
217
|
-
@erasing_sectors |= [sector(offset)]
|
|
218
|
-
@done_at = now + ERASE_WINDOW_CYCLES
|
|
219
|
-
when 0xb0
|
|
220
|
-
@remaining = @erasing_sectors.length * SECTOR_ERASE_CYCLES
|
|
221
|
-
enter(:suspended)
|
|
222
|
-
else
|
|
223
|
-
@erasing_sectors = nil
|
|
224
|
-
enter(@base_state)
|
|
225
|
-
end
|
|
226
|
-
end
|
|
227
|
-
|
|
228
|
-
def suspend
|
|
229
|
-
@remaining = @done_at - now
|
|
230
|
-
enter(:suspended)
|
|
231
|
-
end
|
|
232
|
-
|
|
233
|
-
def resume
|
|
234
|
-
start_busy(:erasing, @remaining)
|
|
235
|
-
end
|
|
236
|
-
|
|
237
|
-
# Moves a timed operation on once the clock has passed its end.
|
|
238
|
-
def settle
|
|
239
|
-
return unless @done_at && now >= @done_at
|
|
240
|
-
|
|
241
|
-
case @state
|
|
242
|
-
when :erase_window
|
|
243
|
-
start_busy(:erasing, @done_at - now + (@erasing_sectors.length * SECTOR_ERASE_CYCLES))
|
|
244
|
-
settle
|
|
245
|
-
when :erasing
|
|
246
|
-
@erasing_sectors.each { |s| @data.fill(0xff, s * @model.sector_size, @model.sector_size) }
|
|
247
|
-
@erasing_sectors = nil
|
|
248
|
-
finish
|
|
249
|
-
when :chip_erase
|
|
250
|
-
@data.fill(0xff)
|
|
251
|
-
finish
|
|
252
|
-
else
|
|
253
|
-
finish
|
|
254
|
-
end
|
|
255
|
-
end
|
|
256
|
-
|
|
257
|
-
def finish
|
|
258
|
-
@done_at = nil
|
|
259
|
-
enter(@base_state)
|
|
260
|
-
end
|
|
261
|
-
|
|
262
|
-
def start_busy(state, cycles)
|
|
263
|
-
@done_at = now + cycles
|
|
264
|
-
@programmed = 0xff unless state == :programming
|
|
265
|
-
enter(state)
|
|
266
|
-
end
|
|
267
|
-
|
|
268
|
-
def enter(state, base: @base_state)
|
|
269
|
-
was_array = array_mode?
|
|
270
|
-
@state = state
|
|
271
|
-
@base_state = base
|
|
272
|
-
@done_at = nil unless %i[programming erase_window erasing chip_erase].include?(state)
|
|
273
|
-
@on_change&.call if was_array != array_mode?
|
|
274
|
-
end
|
|
275
|
-
|
|
276
|
-
def status
|
|
277
|
-
@toggle ^= 0x40
|
|
278
|
-
value = (~@programmed & 0x80) | @toggle
|
|
279
|
-
value |= 0x20 if @state == :program_error
|
|
280
|
-
value |= 0x08 if @state == :erasing || @state == :chip_erase
|
|
281
|
-
value
|
|
282
|
-
end
|
|
283
|
-
|
|
284
|
-
def suspended_read(offset)
|
|
285
|
-
@erasing_sectors.include?(sector(offset)) ? 0x80 : @data[offset]
|
|
286
|
-
end
|
|
287
|
-
|
|
288
|
-
def autoselect_code(offset)
|
|
289
|
-
case offset & 0x43
|
|
290
|
-
when 0 then @model.manufacturer
|
|
291
|
-
when 1 then @model.device
|
|
292
|
-
when 2 then 0x00
|
|
293
|
-
else @data[offset]
|
|
294
|
-
end
|
|
295
|
-
end
|
|
296
|
-
|
|
297
|
-
def sector(offset)
|
|
298
|
-
offset / @model.sector_size
|
|
299
|
-
end
|
|
300
|
-
|
|
301
|
-
def now
|
|
302
|
-
@clock.call
|
|
303
|
-
end
|
|
304
|
-
end
|
|
305
|
-
end
|
|
306
|
-
end
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Cartridge
|
|
5
|
-
# The freeze button of a freezer cartridge. A press pulls NMI, and the
|
|
6
|
-
# computer calls #freeze! once the CPU has pushed the return address and
|
|
7
|
-
# status of the interrupt, so the vector fetch that follows reads the
|
|
8
|
-
# cartridge ROM in Ultimax mode. The cartridge lets go of NMI when its
|
|
9
|
-
# software acknowledges the freeze.
|
|
10
|
-
module Freezer
|
|
11
|
-
def freezer? = true
|
|
12
|
-
|
|
13
|
-
def press_button
|
|
14
|
-
@button = true
|
|
15
|
-
self.nmi = true if freeze_allowed?
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def release_button
|
|
19
|
-
@button = false
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
private
|
|
23
|
-
|
|
24
|
-
def freeze_allowed?
|
|
25
|
-
true
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def button_pressed?
|
|
29
|
-
@button == true
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Cartridge
|
|
5
|
-
# Fun Play / Power Play: up to 16 8K banks. A write to I/O 1 selects the
|
|
6
|
-
# bank from bits 3-5 and 0, and either 8K mode ($00 in bits 7, 6, 2 and 1)
|
|
7
|
-
# or no ROM ($86 in those bits).
|
|
8
|
-
class FunPlay < Cartridge
|
|
9
|
-
def poke(addr, value)
|
|
10
|
-
return if addr > 0xdeff
|
|
11
|
-
|
|
12
|
-
@roml = bank(@banks, self.class.bank_number(value))
|
|
13
|
-
case value & 0xc6
|
|
14
|
-
when 0x00 then self.mode = :rom8k
|
|
15
|
-
when 0x86 then self.mode = :off
|
|
16
|
-
end
|
|
17
|
-
changed!
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
# The CRT file numbers each bank by the register value that selects it.
|
|
21
|
-
def reset
|
|
22
|
-
poke(0xde00, 0)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def self.bank_number(value)
|
|
26
|
-
((value >> 3) & 0x07) | ((value & 0x01) << 3)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
private
|
|
30
|
-
|
|
31
|
-
def install_chips(chips)
|
|
32
|
-
@banks = []
|
|
33
|
-
chips.each { |chip| @banks[self.class.bank_number(chip.bank)] = rom_bank(chip.data) }
|
|
34
|
-
reset
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Cartridge
|
|
5
|
-
# GMod2: an Am29F040 flash chip of 64 8K banks at ROML. A write to I/O 1
|
|
6
|
-
# selects the bank from bits 0-5. Bit 6 selects the EEPROM, which
|
|
7
|
-
# switches the ROM out, and bits 6 and 7 together enable flash writes:
|
|
8
|
-
# the cartridge then asserts Ultimax on write cycles only, so reads see
|
|
9
|
-
# the C64's memory and writes to $E000-$FFFF reach the flash. The EEPROM
|
|
10
|
-
# isn't emulated.
|
|
11
|
-
class GMod2 < Cartridge
|
|
12
|
-
BANKS = 64
|
|
13
|
-
|
|
14
|
-
attr_reader :flash
|
|
15
|
-
|
|
16
|
-
def clock=(clock)
|
|
17
|
-
super
|
|
18
|
-
@flash.clock = clock
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def poke(addr, value)
|
|
22
|
-
return if addr > 0xdeff
|
|
23
|
-
|
|
24
|
-
@bank = value & 0x3f
|
|
25
|
-
@flash_writes = value.allbits?(0xc0)
|
|
26
|
-
self.mode = value.anybits?(0x40) ? :off : :rom8k
|
|
27
|
-
select_bank
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def romh_writes
|
|
31
|
-
@roml if @flash_writes
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# Reset selects the first bank in 8K mode, and leaves the flash as it
|
|
35
|
-
# is.
|
|
36
|
-
def reset
|
|
37
|
-
@bank = 0
|
|
38
|
-
@flash_writes = false
|
|
39
|
-
self.mode = :rom8k
|
|
40
|
-
select_bank
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
private
|
|
44
|
-
|
|
45
|
-
def select_bank
|
|
46
|
-
@roml = @flash.window(@bank * BANK_SIZE)
|
|
47
|
-
changed!
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def save_mapper(out)
|
|
51
|
-
out.int(@bank).boolean(@flash_writes)
|
|
52
|
-
@flash.save_state(out)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def load_mapper(input)
|
|
56
|
-
@bank = input.int
|
|
57
|
-
@flash_writes = input.boolean?
|
|
58
|
-
@flash.load_state(input)
|
|
59
|
-
@roml = @flash.window(@bank * BANK_SIZE)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def install_chips(chips)
|
|
63
|
-
data = Array.new(BANKS * BANK_SIZE, 0xff)
|
|
64
|
-
chips.each do |chip|
|
|
65
|
-
bytes = chip.data.first(BANK_SIZE)
|
|
66
|
-
data[(chip.bank & 0x3f) * BANK_SIZE, bytes.length] = bytes
|
|
67
|
-
end
|
|
68
|
-
@flash = Flash.new(data, model: Flash::AM29F040)
|
|
69
|
-
@flash.on_change { select_bank }
|
|
70
|
-
reset
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
end
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Cartridge
|
|
5
|
-
# C64 Game System / System 3: up to 64 8K banks. Any access to
|
|
6
|
-
# $DE00-$DEFF selects the bank from the low six address bits; the data
|
|
7
|
-
# is ignored.
|
|
8
|
-
class GameSystem < Cartridge
|
|
9
|
-
def readable_io_pages
|
|
10
|
-
[0xde]
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def peek(addr)
|
|
14
|
-
select(addr) if addr < 0xdf00
|
|
15
|
-
open_bus(addr)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def poke(addr, _value)
|
|
19
|
-
select(addr) if addr < 0xdf00
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def reset
|
|
23
|
-
select(0)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
private
|
|
27
|
-
|
|
28
|
-
def select(addr)
|
|
29
|
-
@roml = bank(@banks, addr & 0x3f)
|
|
30
|
-
changed!
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def install_chips(chips)
|
|
34
|
-
@banks = banks_from(chips).first
|
|
35
|
-
self.mode = :rom8k
|
|
36
|
-
reset
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Cartridge
|
|
5
|
-
# GEO-RAM: a RAM expansion on the expansion port, seen through a 256-byte
|
|
6
|
-
# window at $DE00-$DEFF. Two write-only registers pick the page the
|
|
7
|
-
# window shows: $DFFE selects one of the 64 pages of a 16K block, and
|
|
8
|
-
# $DFFF selects the block. As in VICE, the registers answer at every
|
|
9
|
-
# address from $DF80 up, even for $DFFE and odd for $DFFF, and the block
|
|
10
|
-
# number wraps at the number of blocks the RAM holds. Reads of I/O 2 are
|
|
11
|
-
# open bus. It leaves EXROM and GAME high, and RES clears both
|
|
12
|
-
# registers.
|
|
13
|
-
class GeoRAM < Cartridge
|
|
14
|
-
SIZES = [64, 128, 256, 512, 1024, 2048, 4096].freeze
|
|
15
|
-
BLOCK_SIZE = 0x4000
|
|
16
|
-
PAGE_MASK = 0x3f
|
|
17
|
-
|
|
18
|
-
attr_reader :size
|
|
19
|
-
|
|
20
|
-
# size is the RAM in kilobytes.
|
|
21
|
-
def initialize(size: 512)
|
|
22
|
-
raise ArgumentError, "Unsupported GEO-RAM size #{size}K" unless SIZES.include?(size)
|
|
23
|
-
|
|
24
|
-
@size = size
|
|
25
|
-
@block_mask = ((size * 1024) / BLOCK_SIZE) - 1
|
|
26
|
-
super(Storage::CRTFile::Image.new(hardware_type: nil, subtype: 0, exrom: 1, game: 1,
|
|
27
|
-
name: "GEO-RAM", chips: []))
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def readable_io_pages
|
|
31
|
-
[0xde]
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def peek(addr)
|
|
35
|
-
@ram_data[@window + (addr & 0xff)]
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def poke(addr, value)
|
|
39
|
-
if addr <= 0xdeff
|
|
40
|
-
@ram_data[@window + (addr & 0xff)] = value
|
|
41
|
-
elsif addr >= 0xdf80
|
|
42
|
-
if addr.odd?
|
|
43
|
-
@block = value & @block_mask
|
|
44
|
-
else
|
|
45
|
-
@page = value & PAGE_MASK
|
|
46
|
-
end
|
|
47
|
-
@window = (@block * BLOCK_SIZE) + (@page * 0x100)
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def reset
|
|
52
|
-
@block = @page = @window = 0
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
# A GEO-RAM is built from its size alone.
|
|
56
|
-
def save_setup(out)
|
|
57
|
-
out.int(GEO_RAM_SETUP).int(@size)
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
private
|
|
61
|
-
|
|
62
|
-
def save_mapper(out)
|
|
63
|
-
out.blob(@ram_data).int(@block).int(@page).int(@window)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def load_mapper(input)
|
|
67
|
-
input.blob_into(@ram_data)
|
|
68
|
-
@block = input.int
|
|
69
|
-
@page = input.int
|
|
70
|
-
@window = input.int
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def install_chips(_chips)
|
|
74
|
-
@ram_data = Array.new(@size * 1024, 0)
|
|
75
|
-
reset
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
end
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Cartridge
|
|
5
|
-
# The KCS Power Cartridge: 16K of ROM, 128 bytes of RAM and a freeze
|
|
6
|
-
# button. It boots in 16K mode, and any access to I/O 1 sets the lines
|
|
7
|
-
# from address bit 1 and the direction:
|
|
8
|
-
#
|
|
9
|
-
# read, bit 1 clear 8K
|
|
10
|
-
# read, bit 1 set off
|
|
11
|
-
# write, bit 1 clear 16K
|
|
12
|
-
# write, bit 1 set Ultimax
|
|
13
|
-
#
|
|
14
|
-
# A read of I/O 1 returns the second last page of ROML. I/O 2 holds the
|
|
15
|
-
# RAM in its lower half, and the upper half reads the EXROM line in bit 7
|
|
16
|
-
# and GAME in bit 6, which the freezer checks to find the mode it
|
|
17
|
-
# interrupted. A freeze switches to Ultimax and lets go of NMI.
|
|
18
|
-
class KCSPower < Cartridge
|
|
19
|
-
include Freezer
|
|
20
|
-
|
|
21
|
-
IO1_ROM_PAGE = 0x1e00
|
|
22
|
-
|
|
23
|
-
def readable_io_pages
|
|
24
|
-
[0xde, 0xdf]
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def peek(addr)
|
|
28
|
-
if addr < 0xdf00
|
|
29
|
-
select_mode(addr.anybits?(0x02) ? :off : :rom8k)
|
|
30
|
-
@roml.peek(IO1_ROM_PAGE | (addr & 0xff))
|
|
31
|
-
elsif addr.anybits?(0x80)
|
|
32
|
-
(@exrom << 7) | (@game << 6) | (open_bus(addr) & 0x3f)
|
|
33
|
-
else
|
|
34
|
-
@io_ram[addr & 0x7f]
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def poke(addr, value)
|
|
39
|
-
if addr < 0xdf00
|
|
40
|
-
select_mode(addr.anybits?(0x02) ? :ultimax : :rom16k)
|
|
41
|
-
elsif addr.nobits?(0x80)
|
|
42
|
-
@io_ram[addr & 0x7f] = value
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def reset
|
|
47
|
-
self.nmi = false
|
|
48
|
-
select_mode(:rom16k)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def freeze!
|
|
52
|
-
self.nmi = false
|
|
53
|
-
select_mode(:ultimax)
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
private
|
|
57
|
-
|
|
58
|
-
def save_mapper(out)
|
|
59
|
-
out.blob(@io_ram)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def load_mapper(input)
|
|
63
|
-
input.blob_into(@io_ram)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def install_chips(chips)
|
|
67
|
-
roml, romh = banks_from(chips)
|
|
68
|
-
@roml = roml.first || EMPTY_BANK
|
|
69
|
-
@romh = romh.first || EMPTY_BANK
|
|
70
|
-
@io_ram = Array.new(0x80, 0xff)
|
|
71
|
-
reset
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
end
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Cartridge
|
|
5
|
-
# 8K. Writing I/O 1 switches the ROM in, writing I/O 2 switches it out.
|
|
6
|
-
# Both I/O pages read the last 512 bytes of the ROM.
|
|
7
|
-
class Mach5 < Cartridge
|
|
8
|
-
def readable_io_pages
|
|
9
|
-
[0xde, 0xdf]
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def peek(addr)
|
|
13
|
-
@roml.peek(addr)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def poke(addr, _value)
|
|
17
|
-
select_mode(addr < 0xdf00 ? :rom8k : :off)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def reset
|
|
21
|
-
select_mode(:rom8k)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
private
|
|
25
|
-
|
|
26
|
-
def install_chips(chips)
|
|
27
|
-
@roml = banks_from(chips).first.compact.first || EMPTY_BANK
|
|
28
|
-
reset
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Cartridge
|
|
5
|
-
# Magic Desk: up to 128 8K banks. A write to I/O 1 selects the bank from
|
|
6
|
-
# bits 0-6, masked to the size of the ROM and at least four banks, and
|
|
7
|
-
# switches the ROM out with bit 7.
|
|
8
|
-
class MagicDesk < Cartridge
|
|
9
|
-
def poke(addr, value)
|
|
10
|
-
return if addr > 0xdeff
|
|
11
|
-
|
|
12
|
-
@exrom = value.anybits?(0x80) ? 1 : 0
|
|
13
|
-
@roml = bank(@banks, value & @bank_mask)
|
|
14
|
-
changed!
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def reset
|
|
18
|
-
poke(0xde00, 0)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
private
|
|
22
|
-
|
|
23
|
-
def install_chips(chips)
|
|
24
|
-
@banks = banks_from(chips).first
|
|
25
|
-
@bank_mask = (bank_mask(@banks) | 0x03) & 0x7f
|
|
26
|
-
reset
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|