badline 0.12.1 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +66 -1
- data/CLAUDE.md +86 -38
- data/CONTRIBUTING.md +4 -3
- data/README.md +9 -6
- data/doc/library.md +9 -9
- data/doc/media.md +2 -1
- data/doc/pinned-behaviour.md +134 -105
- data/doc/snapshot-format.md +1047 -0
- data/doc/snapshots.md +73 -43
- data/lib/badline/audio/bare_player.rb +53 -20
- data/lib/badline/audio/cli.rb +6 -6
- data/lib/badline/audio/jukebox.rb +2 -2
- data/lib/badline/audio/machine_player.rb +16 -10
- data/lib/badline/{media → audio}/queue.rb +1 -1
- data/lib/badline/audio/queued_tune.rb +6 -6
- data/lib/badline/audio/renderer.rb +33 -22
- data/lib/badline/audio/stereo.rb +1 -1
- data/lib/badline/c128/banks.rb +6 -3
- data/lib/badline/c128/bus/keyed_state.rb +45 -0
- data/lib/badline/c128/bus.rb +35 -20
- data/lib/badline/c128/color_lines.rb +2 -2
- data/lib/badline/c128/cpu.rb +1 -1
- data/lib/badline/c128/drives.rb +14 -34
- data/lib/badline/c128/fast_serial.rb +5 -5
- data/lib/badline/c128/keyed_modules.rb +117 -0
- data/lib/badline/c128/keyed_state.rb +91 -0
- data/lib/badline/c128/keys.rb +9 -0
- data/lib/badline/c128/mmu.rb +9 -8
- data/lib/badline/c128/mmu_pages.rb +21 -1
- data/lib/badline/c128/modes.rb +21 -11
- data/lib/badline/c128/z80.rb +2 -2
- data/lib/badline/c128/z80_turns.rb +1 -1
- data/lib/badline/c128.rb +21 -16
- data/lib/badline/c64/attachments.rb +42 -0
- data/lib/badline/c64/banked_ram/banking.rb +32 -0
- data/lib/badline/c64/banked_ram/plus256k.rb +64 -0
- data/lib/badline/c64/banked_ram/plus60k.rb +47 -0
- data/lib/badline/c64/banked_ram/unexpanded.rb +30 -0
- data/lib/badline/c64/banked_ram.rb +23 -0
- data/lib/badline/c64/bus/debug_register.rb +32 -0
- data/lib/badline/c64/bus/extra_sids.rb +32 -0
- data/lib/badline/c64/bus/fittings.rb +40 -0
- data/lib/badline/c64/bus/keyed_state.rb +41 -0
- data/lib/badline/c64/bus/pla.rb +149 -0
- data/lib/badline/c64/bus/roms.rb +41 -0
- data/lib/badline/c64/bus/sid_slots.rb +44 -0
- data/lib/badline/c64/bus.rb +219 -0
- data/lib/badline/c64/cartridge/action_replay.rb +115 -0
- data/lib/badline/c64/cartridge/atomic_power.rb +26 -0
- data/lib/badline/c64/cartridge/bank.rb +83 -0
- data/lib/badline/c64/cartridge/comal80.rb +52 -0
- data/lib/badline/c64/cartridge/dinamic.rb +36 -0
- data/lib/badline/c64/cartridge/easy_flash.rb +132 -0
- data/lib/badline/c64/cartridge/epyx_fastload.rb +73 -0
- data/lib/badline/c64/cartridge/final_cartridge3.rb +79 -0
- data/lib/badline/c64/cartridge/flash.rb +279 -0
- data/lib/badline/c64/cartridge/freezer.rb +35 -0
- data/lib/badline/c64/cartridge/fun_play.rb +40 -0
- data/lib/badline/c64/cartridge/g_mod2.rb +64 -0
- data/lib/badline/c64/cartridge/game_system.rb +42 -0
- data/lib/badline/c64/cartridge/geo_ram.rb +65 -0
- data/lib/badline/c64/cartridge/kcs_power.rb +69 -0
- data/lib/badline/c64/cartridge/keyed_state.rb +393 -0
- data/lib/badline/c64/cartridge/mach5.rb +34 -0
- data/lib/badline/c64/cartridge/magic_desk.rb +32 -0
- data/lib/badline/c64/cartridge/ocean.rb +37 -0
- data/lib/badline/c64/cartridge/pagefox.rb +60 -0
- data/lib/badline/c64/cartridge/retro_replay.rb +278 -0
- data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
- data/lib/badline/c64/cartridge/rgcd.rb +50 -0
- data/lib/badline/c64/cartridge/simons_basic.rb +37 -0
- data/lib/badline/c64/cartridge/standard.rb +17 -0
- data/lib/badline/c64/cartridge/super_games.rb +40 -0
- data/lib/badline/c64/cartridge/westermann.rb +32 -0
- data/lib/badline/c64/cartridge/zaxxon.rb +52 -0
- data/lib/badline/c64/cartridge.rb +232 -0
- data/lib/badline/c64/color_memory.rb +27 -0
- data/lib/badline/{computer → c64}/common.rb +2 -2
- data/lib/badline/{computer → c64}/kernal_traps.rb +39 -36
- data/lib/badline/c64/keyed_modules.rb +111 -0
- data/lib/badline/c64/keyed_state.rb +68 -0
- data/lib/badline/c64/reu/dma.rb +271 -0
- data/lib/badline/c64/reu/keyed_state.rb +140 -0
- data/lib/badline/c64/reu/ram.rb +94 -0
- data/lib/badline/c64/reu/trigger.rb +34 -0
- data/lib/badline/c64/reu.rb +289 -0
- data/lib/badline/c64/true_drives.rb +120 -0
- data/lib/badline/{computer.rb → c64.rb} +24 -15
- data/lib/badline/chips/cia/fast_forward.rb +62 -0
- data/lib/badline/chips/cia/interrupt_register.rb +128 -0
- data/lib/badline/chips/cia/keyed_parts.rb +213 -0
- data/lib/badline/chips/cia/serial.rb +246 -0
- data/lib/badline/chips/cia/time_of_day.rb +210 -0
- data/lib/badline/chips/cia/timer.rb +188 -0
- data/lib/badline/chips/cia.rb +281 -0
- data/lib/badline/chips/cpu/addressing.rb +133 -0
- data/lib/badline/chips/cpu/boundary.rb +56 -0
- data/lib/badline/chips/cpu/core.rb +183 -0
- data/lib/badline/chips/cpu/instruction.rb +338 -0
- data/lib/badline/chips/cpu/instruction_set/arithmetic.rb +118 -0
- data/lib/badline/chips/cpu/instruction_set/bitwise.rb +130 -0
- data/lib/badline/chips/cpu/instruction_set/branch.rb +83 -0
- data/lib/badline/chips/cpu/instruction_set/flag.rb +67 -0
- data/lib/badline/chips/cpu/instruction_set/illegal.rb +274 -0
- data/lib/badline/chips/cpu/instruction_set/inc_dec.rb +73 -0
- data/lib/badline/chips/cpu/instruction_set/stack.rb +56 -0
- data/lib/badline/chips/cpu/instruction_set/transfer.rb +141 -0
- data/lib/badline/chips/cpu/instruction_set.rb +59 -0
- data/lib/badline/chips/cpu/interrupts.rb +108 -0
- data/lib/badline/chips/cpu/keyed_state.rb +177 -0
- data/lib/badline/chips/cpu/microcode.rb +195 -0
- data/lib/badline/chips/cpu/operations.rb +90 -0
- data/lib/badline/chips/cpu/port.rb +133 -0
- data/lib/badline/chips/cpu/stack_operations.rb +84 -0
- data/lib/badline/chips/cpu/traps.rb +23 -0
- data/lib/badline/chips/cpu.rb +17 -0
- data/lib/badline/chips/sid/catch_up.rb +122 -0
- data/lib/badline/chips/sid/decimator.rb +68 -0
- data/lib/badline/chips/sid/envelope.rb +236 -0
- data/lib/badline/chips/sid/filter.rb +227 -0
- data/lib/badline/chips/sid/keyed_parts.rb +286 -0
- data/lib/badline/chips/sid/voice.rb +69 -0
- data/lib/badline/chips/sid/waveform/combined.rb +128 -0
- data/lib/badline/chips/sid/waveform/fast_forward.rb +107 -0
- data/lib/badline/chips/sid/waveform/noise_writeback.rb +124 -0
- data/lib/badline/chips/sid/waveform.rb +305 -0
- data/lib/badline/chips/sid.rb +264 -0
- data/lib/badline/chips/ted/beam.rb +119 -0
- data/lib/badline/chips/ted/timers.rb +66 -0
- data/lib/badline/chips/ted.rb +143 -0
- data/lib/badline/chips/tia.rb +49 -0
- data/lib/badline/chips/vdc/keyed_parts.rb +105 -0
- data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
- data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -13
- data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -17
- data/lib/badline/{c128 → chips}/vdc/window.rb +1 -10
- data/lib/badline/{c128 → chips}/vdc.rb +6 -31
- data/lib/badline/chips/via/control_lines.rb +109 -0
- data/lib/badline/chips/via/fast_forward.rb +55 -0
- data/lib/badline/chips/via/interrupt_register.rb +60 -0
- data/lib/badline/chips/via/keyed_parts.rb +163 -0
- data/lib/badline/chips/via/shift_register.rb +168 -0
- data/lib/badline/chips/via/timer1.rb +120 -0
- data/lib/badline/chips/via/timer2.rb +117 -0
- data/lib/badline/chips/via.rb +267 -0
- data/lib/badline/chips/vic/bank.rb +135 -0
- data/lib/badline/chips/vic/border_mask.rb +78 -0
- data/lib/badline/chips/vic/collisions.rb +106 -0
- data/lib/badline/chips/vic/color_patches.rb +38 -0
- data/lib/badline/chips/vic/display_state.rb +168 -0
- data/lib/badline/chips/vic/graphics_mode.rb +166 -0
- data/lib/badline/chips/vic/graphics_shifter.rb +183 -0
- data/lib/badline/chips/vic/keyed_parts.rb +228 -0
- data/lib/badline/chips/vic/keyed_sprites.rb +225 -0
- data/lib/badline/chips/vic/keyed_state.rb +102 -0
- data/lib/badline/chips/vic/register_log.rb +65 -0
- data/lib/badline/chips/vic/registers.rb +188 -0
- data/lib/badline/chips/vic/sequencer.rb +275 -0
- data/lib/badline/chips/vic/sequencer_output.rb +118 -0
- data/lib/badline/chips/vic/sprite/internal_bus.rb +59 -0
- data/lib/badline/chips/vic/sprite/shifter.rb +148 -0
- data/lib/badline/chips/vic/sprite/timing.rb +58 -0
- data/lib/badline/chips/vic/sprite.rb +337 -0
- data/lib/badline/chips/vic/sprites.rb +281 -0
- data/lib/badline/chips/vic.rb +787 -0
- data/lib/badline/chips/vic_i/keyed_parts.rb +142 -0
- data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +2 -30
- data/lib/badline/chips/vic_i/sound/output.rb +85 -0
- data/lib/badline/chips/vic_i/sound.rb +227 -0
- data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
- data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +6 -6
- data/lib/badline/chips/z80/arithmetic.rb +119 -0
- data/lib/badline/chips/z80/bit_page.rb +57 -0
- data/lib/badline/chips/z80/block_io.rb +60 -0
- data/lib/badline/chips/z80/block_transfers.rb +61 -0
- data/lib/badline/chips/z80/bus_cycles.rb +113 -0
- data/lib/badline/chips/z80/core.rb +115 -0
- data/lib/badline/chips/z80/exchanges.rb +52 -0
- data/lib/badline/chips/z80/extended_page.rb +91 -0
- data/lib/badline/chips/z80/flags.rb +39 -0
- data/lib/badline/chips/z80/interrupt_acceptance.rb +48 -0
- data/lib/badline/chips/z80/jumps.rb +84 -0
- data/lib/badline/chips/z80/keyed_state.rb +73 -0
- data/lib/badline/chips/z80/loads.rb +100 -0
- data/lib/badline/chips/z80/main_page.rb +136 -0
- data/lib/badline/chips/z80/registers.rb +122 -0
- data/lib/badline/chips/z80/shifts.rb +66 -0
- data/lib/badline/chips/z80.rb +13 -0
- data/lib/badline/chips.rb +10 -0
- data/lib/badline/core.rb +13 -32
- data/lib/badline/drives/datasette/keyed_state.rb +38 -0
- data/lib/badline/drives/datasette.rb +173 -0
- data/lib/badline/drives/engine/core.rb +152 -0
- data/lib/badline/drives/engine/fast_serial.rb +75 -0
- data/lib/badline/drives/engine/idle.rb +127 -0
- data/lib/badline/drives/engine/idle_cpu.rb +30 -0
- data/lib/badline/drives/engine/orbit.rb +81 -0
- data/lib/badline/drives/engine/serial_lines.rb +72 -0
- data/lib/badline/drives/engine/sleep.rb +114 -0
- data/lib/badline/drives/engine/vias.rb +86 -0
- data/lib/badline/drives/engine/watch.rb +152 -0
- data/lib/badline/drives/engine.rb +11 -0
- data/lib/badline/drives/model1541/bus.rb +75 -0
- data/lib/badline/drives/model1541/byte_ready.rb +50 -0
- data/lib/badline/drives/model1541/cpu.rb +13 -0
- data/lib/badline/drives/model1541/disk.rb +318 -0
- data/lib/badline/drives/model1541/disk_via.rb +38 -0
- data/lib/badline/drives/model1541/gcr.rb +59 -0
- data/lib/badline/drives/model1541/keyed_state.rb +251 -0
- data/lib/badline/drives/model1541/mechanism.rb +313 -0
- data/lib/badline/drives/model1541/rotation.rb +123 -0
- data/lib/badline/drives/model1541/sector_reader.rb +78 -0
- data/lib/badline/drives/model1541/serial_port.rb +20 -0
- data/lib/badline/drives/model1541/track.rb +100 -0
- data/lib/badline/drives/model1541.rb +80 -0
- data/lib/badline/drives/model1571/bus.rb +100 -0
- data/lib/badline/drives/model1571/cpu.rb +13 -0
- data/lib/badline/drives/model1571/keyed_state.rb +108 -0
- data/lib/badline/drives/model1571/serial_port.rb +39 -0
- data/lib/badline/drives/model1571/serial_via.rb +27 -0
- data/lib/badline/drives/model1571/wd1770.rb +108 -0
- data/lib/badline/drives/model1571.rb +141 -0
- data/lib/badline/drives/model1581/bus.rb +126 -0
- data/lib/badline/drives/model1581/cpu.rb +13 -0
- data/lib/badline/drives/model1581/disk.rb +133 -0
- data/lib/badline/drives/model1581/keyed_state.rb +280 -0
- data/lib/badline/drives/model1581/mechanism.rb +98 -0
- data/lib/badline/drives/model1581/serial_port.rb +54 -0
- data/lib/badline/drives/model1581/slot.rb +61 -0
- data/lib/badline/drives/model1581/track.rb +102 -0
- data/lib/badline/drives/model1581/track_bytes.rb +77 -0
- data/lib/badline/drives/model1581/wd1772/registers.rb +91 -0
- data/lib/badline/drives/model1581/wd1772/sector_writes.rb +75 -0
- data/lib/badline/drives/model1581/wd1772/sectors.rb +152 -0
- data/lib/badline/drives/model1581/wd1772/stepping.rb +111 -0
- data/lib/badline/drives/model1581/wd1772/tracks.rb +127 -0
- data/lib/badline/drives/model1581/wd1772/turn.rb +75 -0
- data/lib/badline/drives/model1581/wd1772.rb +216 -0
- data/lib/badline/drives/model1581.rb +206 -0
- data/lib/badline/drives/serial_bus.rb +161 -0
- data/lib/badline/drives.rb +8 -0
- data/lib/badline/frontend/app.rb +3 -3
- data/lib/badline/frontend/boot.rb +4 -4
- data/lib/badline/frontend/controls.rb +19 -3
- data/lib/badline/frontend/drive_led.rb +44 -21
- data/lib/badline/frontend/machine_window.rb +3 -1
- data/lib/badline/frontend/menu/menu_dialogs.rb +2 -2
- data/lib/badline/frontend/player/filter_view.rb +1 -1
- data/lib/badline/frontend/player/player_controller.rb +2 -2
- data/lib/badline/frontend/player/player_screen.rb +1 -0
- data/lib/badline/frontend/player/theme.rb +7 -7
- data/lib/badline/frontend/snapshots.rb +12 -1
- data/lib/badline/frontend/timeline.rb +30 -12
- data/lib/badline/input/control_ports.rb +78 -0
- data/lib/badline/input/joystick.rb +27 -0
- data/lib/badline/input/keyboard.rb +114 -0
- data/lib/badline/input/matrix_typist.rb +98 -0
- data/lib/badline/input.rb +4 -0
- data/lib/badline/kernal_trap/chrout.rb +45 -0
- data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
- data/lib/badline/kernal_trap/dos/channel.rb +156 -0
- data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -26
- data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -10
- data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
- data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -9
- data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -19
- data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
- data/lib/badline/kernal_trap/{drive.rb → dos.rb} +9 -27
- data/lib/badline/kernal_trap/file_routine.rb +4 -4
- data/lib/badline/kernal_trap/keyed_state.rb +150 -0
- data/lib/badline/kernal_trap/layout.rb +75 -11
- data/lib/badline/kernal_trap/load.rb +19 -21
- data/lib/badline/kernal_trap/routine.rb +12 -0
- data/lib/badline/kernal_trap/save.rb +12 -22
- data/lib/badline/kernal_trap/serial.rb +8 -24
- data/lib/badline/kernal_trap.rb +3 -2
- data/lib/badline/machine/clocking.rb +1 -1
- data/lib/badline/machine/keyboard_buffer.rb +49 -0
- data/lib/badline/machine/settling.rb +29 -0
- data/lib/badline/machine.rb +10 -7
- data/lib/badline/media/boot_disk.rb +14 -2
- data/lib/badline/media/extensions.rb +10 -0
- data/lib/badline/media/true_drive.rb +1 -1
- data/lib/badline/media/tune.rb +2 -2
- data/lib/badline/media.rb +3 -3
- data/lib/badline/memory.rb +3 -6
- data/lib/badline/model.rb +1 -1
- data/lib/badline/options/family.rb +5 -2
- data/lib/badline/options/help.rb +42 -16
- data/lib/badline/options/table.rb +2 -0
- data/lib/badline/options/validation.rb +2 -0
- data/lib/badline/options.rb +6 -1
- data/lib/badline/plus4/acia.rb +45 -0
- data/lib/badline/plus4/bus.rb +312 -0
- data/lib/badline/plus4/cpu.rb +10 -0
- data/lib/badline/plus4/cpu_port.rb +93 -0
- data/lib/badline/plus4/keyboard_port.rb +51 -0
- data/lib/badline/plus4/model.rb +38 -0
- data/lib/badline/plus4/user_port.rb +31 -0
- data/lib/badline/plus4.rb +164 -0
- data/lib/badline/roms/README +44 -6
- data/lib/badline/roms/plus4/basic.rom +0 -0
- data/lib/badline/roms/plus4/function-high.rom +0 -0
- data/lib/badline/roms/plus4/function-low.rom +0 -0
- data/lib/badline/roms/plus4/kernal-ntsc.rom +0 -0
- data/lib/badline/roms/plus4/kernal-pal.rom +0 -0
- data/lib/badline/sdl.rb +1 -0
- data/lib/badline/{storage/sid_file.rb → sid_tune/file.rb} +3 -3
- data/lib/badline/{storage → sid_tune}/hvsc.rb +7 -7
- data/lib/badline/{storage → sid_tune}/song_lengths.rb +2 -2
- data/lib/badline/{storage → sid_tune}/stil/credit.rb +1 -1
- data/lib/badline/{storage → sid_tune}/stil.rb +3 -3
- data/lib/badline/sid_tune.rb +6 -0
- data/lib/badline/snapshot/c128_setup.rb +32 -0
- data/lib/badline/snapshot/c64_setup.rb +83 -0
- data/lib/badline/snapshot/container.rb +4 -0
- data/lib/badline/snapshot/field_doc/markdown.rb +112 -0
- data/lib/badline/snapshot/field_doc.rb +109 -0
- data/lib/badline/snapshot/image.rb +132 -46
- data/lib/badline/snapshot/keyed/cursor.rb +40 -0
- data/lib/badline/snapshot/keyed/modules.rb +66 -0
- data/lib/badline/snapshot/keyed/reader.rb +188 -0
- data/lib/badline/snapshot/keyed/recorder.rb +88 -0
- data/lib/badline/snapshot/keyed/report.rb +26 -0
- data/lib/badline/snapshot/keyed/writer.rb +55 -0
- data/lib/badline/snapshot/keyed.rb +64 -0
- data/lib/badline/snapshot/machine_state.rb +17 -64
- data/lib/badline/snapshot/storage_setup.rb +63 -0
- data/lib/badline/snapshot/vic20_setup.rb +28 -0
- data/lib/badline/snapshot/vice/c64_mem.rb +1 -1
- data/lib/badline/snapshot/vice/restore.rb +1 -1
- data/lib/badline/snapshot/vice/reu1764.rb +3 -3
- data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
- data/lib/badline/snapshot/vice.rb +13 -35
- data/lib/badline/snapshot.rb +44 -22
- data/lib/badline/storage/crt_file.rb +3 -1
- data/lib/badline/storage/d64_image.rb +0 -2
- data/lib/badline/storage/d71_image.rb +0 -2
- data/lib/badline/storage/d81_image.rb +0 -2
- data/lib/badline/storage/disk_image.rb +3 -6
- data/lib/badline/storage/g64_image.rb +10 -5
- data/lib/badline/storage/host_directory.rb +0 -5
- data/lib/badline/storage/t64.rb +2 -8
- data/lib/badline/storage/tap.rb +43 -15
- data/lib/badline/storage/unavailable.rb +1 -1
- data/lib/badline/storage.rb +0 -37
- data/lib/badline/support/c128_checkpoint.rb +39 -0
- data/lib/badline/support/checkpoint.rb +108 -0
- data/lib/badline/support/vic20_checkpoint.rb +38 -0
- data/lib/badline/support.rb +5 -0
- data/lib/badline/version.rb +1 -1
- data/lib/badline/vic20/attachments.rb +8 -5
- data/lib/badline/vic20/bus/keyed_state.rb +52 -0
- data/lib/badline/vic20/bus.rb +2 -25
- data/lib/badline/vic20/cpu.rb +1 -1
- data/lib/badline/vic20/keyed_modules.rb +73 -0
- data/lib/badline/vic20/keyed_state.rb +45 -0
- data/lib/badline/vic20/port_wiring.rb +4 -4
- data/lib/badline/vic20/user_via_ports.rb +2 -2
- data/lib/badline/vic20.rb +22 -17
- data/lib/badline.rb +1 -0
- metadata +271 -228
- data/lib/badline/address_bus/extra_sids.rb +0 -30
- data/lib/badline/address_bus/fittings.rb +0 -38
- data/lib/badline/address_bus/pla.rb +0 -147
- data/lib/badline/address_bus/roms.rb +0 -39
- data/lib/badline/address_bus/saved_state.rb +0 -66
- data/lib/badline/address_bus/sid_slots.rb +0 -42
- data/lib/badline/address_bus.rb +0 -216
- data/lib/badline/c128/bus_state.rb +0 -53
- data/lib/badline/c128/saved_state.rb +0 -143
- data/lib/badline/cartridge/action_replay.rb +0 -126
- data/lib/badline/cartridge/atomic_power.rb +0 -24
- data/lib/badline/cartridge/bank.rb +0 -81
- data/lib/badline/cartridge/comal80.rb +0 -50
- data/lib/badline/cartridge/dinamic.rb +0 -34
- data/lib/badline/cartridge/easy_flash.rb +0 -145
- data/lib/badline/cartridge/epyx_fastload.rb +0 -79
- data/lib/badline/cartridge/final_cartridge3.rb +0 -89
- data/lib/badline/cartridge/flash.rb +0 -306
- data/lib/badline/cartridge/freezer.rb +0 -33
- data/lib/badline/cartridge/fun_play.rb +0 -38
- data/lib/badline/cartridge/g_mod2.rb +0 -74
- data/lib/badline/cartridge/game_system.rb +0 -40
- data/lib/badline/cartridge/geo_ram.rb +0 -79
- data/lib/badline/cartridge/kcs_power.rb +0 -75
- data/lib/badline/cartridge/mach5.rb +0 -32
- data/lib/badline/cartridge/magic_desk.rb +0 -30
- data/lib/badline/cartridge/ocean.rb +0 -35
- data/lib/badline/cartridge/pagefox.rb +0 -68
- data/lib/badline/cartridge/retro_replay.rb +0 -320
- data/lib/badline/cartridge/rex_utility.rb +0 -29
- data/lib/badline/cartridge/rgcd.rb +0 -58
- data/lib/badline/cartridge/simons_basic.rb +0 -35
- data/lib/badline/cartridge/standard.rb +0 -15
- data/lib/badline/cartridge/super_games.rb +0 -48
- data/lib/badline/cartridge/westermann.rb +0 -30
- data/lib/badline/cartridge/zaxxon.rb +0 -66
- data/lib/badline/cartridge.rb +0 -303
- data/lib/badline/checkpoint.rb +0 -98
- data/lib/badline/chrout_trap.rb +0 -43
- data/lib/badline/cia/fast_forward.rb +0 -60
- data/lib/badline/cia/interrupt_register.rb +0 -143
- data/lib/badline/cia/serial.rb +0 -275
- data/lib/badline/cia/state.rb +0 -47
- data/lib/badline/cia/timer.rb +0 -206
- data/lib/badline/cia.rb +0 -279
- data/lib/badline/color_memory.rb +0 -25
- data/lib/badline/computer/attachments.rb +0 -88
- data/lib/badline/computer/saved_state.rb +0 -117
- data/lib/badline/computer/true_drives.rb +0 -69
- data/lib/badline/control_ports.rb +0 -76
- data/lib/badline/cpu/addressing.rb +0 -131
- data/lib/badline/cpu/boundary.rb +0 -54
- data/lib/badline/cpu/core.rb +0 -165
- data/lib/badline/cpu/microcode.rb +0 -177
- data/lib/badline/cpu/operations.rb +0 -88
- data/lib/badline/cpu/saved_state.rb +0 -115
- data/lib/badline/cpu/stack_operations.rb +0 -82
- data/lib/badline/cpu.rb +0 -10
- data/lib/badline/cpu_port.rb +0 -112
- data/lib/badline/datasette.rb +0 -161
- data/lib/badline/debug_register.rb +0 -28
- data/lib/badline/drive/core.rb +0 -147
- data/lib/badline/drive/fast_serial.rb +0 -73
- data/lib/badline/drive/idle.rb +0 -125
- data/lib/badline/drive/idle_cpu.rb +0 -28
- data/lib/badline/drive/orbit.rb +0 -79
- data/lib/badline/drive/serial_lines.rb +0 -73
- data/lib/badline/drive/sleep.rb +0 -112
- data/lib/badline/drive/vias.rb +0 -84
- data/lib/badline/drive/watch.rb +0 -150
- data/lib/badline/drive.rb +0 -11
- data/lib/badline/drive1541/bus.rb +0 -86
- data/lib/badline/drive1541/byte_ready.rb +0 -48
- data/lib/badline/drive1541/cpu.rb +0 -11
- data/lib/badline/drive1541/disk.rb +0 -315
- data/lib/badline/drive1541/disk_state.rb +0 -86
- data/lib/badline/drive1541/disk_via.rb +0 -36
- data/lib/badline/drive1541/gcr.rb +0 -57
- data/lib/badline/drive1541/mechanism.rb +0 -313
- data/lib/badline/drive1541/mechanism_state.rb +0 -68
- data/lib/badline/drive1541/rotation.rb +0 -121
- data/lib/badline/drive1541/sector_reader.rb +0 -76
- data/lib/badline/drive1541/serial_port.rb +0 -18
- data/lib/badline/drive1541/track.rb +0 -98
- data/lib/badline/drive1541.rb +0 -111
- data/lib/badline/drive1571/bus.rb +0 -111
- data/lib/badline/drive1571/cpu.rb +0 -11
- data/lib/badline/drive1571/serial_port.rb +0 -37
- data/lib/badline/drive1571/serial_via.rb +0 -25
- data/lib/badline/drive1571/wd1770.rb +0 -120
- data/lib/badline/drive1571.rb +0 -175
- data/lib/badline/drive1581/bus.rb +0 -137
- data/lib/badline/drive1581/cpu.rb +0 -11
- data/lib/badline/drive1581/disk.rb +0 -135
- data/lib/badline/drive1581/disk_state.rb +0 -87
- data/lib/badline/drive1581/mechanism.rb +0 -117
- data/lib/badline/drive1581/serial_port.rb +0 -52
- data/lib/badline/drive1581/slot.rb +0 -78
- data/lib/badline/drive1581/track.rb +0 -100
- data/lib/badline/drive1581/track_bytes.rb +0 -75
- data/lib/badline/drive1581/wd1772/registers.rb +0 -89
- data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
- data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
- data/lib/badline/drive1581/wd1772/state.rb +0 -66
- data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
- data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
- data/lib/badline/drive1581/wd1772/turn.rb +0 -73
- data/lib/badline/drive1581/wd1772.rb +0 -216
- data/lib/badline/drive1581.rb +0 -233
- data/lib/badline/iec_bus.rb +0 -159
- data/lib/badline/instruction.rb +0 -334
- data/lib/badline/instruction_set/arithmetic.rb +0 -114
- data/lib/badline/instruction_set/bitwise.rb +0 -126
- data/lib/badline/instruction_set/branch.rb +0 -79
- data/lib/badline/instruction_set/flag.rb +0 -63
- data/lib/badline/instruction_set/illegal.rb +0 -270
- data/lib/badline/instruction_set/inc_dec.rb +0 -69
- data/lib/badline/instruction_set/stack.rb +0 -52
- data/lib/badline/instruction_set/transfer.rb +0 -137
- data/lib/badline/instruction_set.rb +0 -55
- data/lib/badline/interrupts.rb +0 -104
- data/lib/badline/joystick.rb +0 -25
- data/lib/badline/kernal_trap/channel.rb +0 -181
- data/lib/badline/keyboard.rb +0 -112
- data/lib/badline/keyboard_buffer.rb +0 -33
- data/lib/badline/ram_expansion/banking.rb +0 -30
- data/lib/badline/ram_expansion/plus256k.rb +0 -54
- data/lib/badline/ram_expansion/plus60k.rb +0 -43
- data/lib/badline/ram_expansion/unexpanded.rb +0 -28
- data/lib/badline/ram_expansion.rb +0 -21
- data/lib/badline/reu/dma/saved_state.rb +0 -50
- data/lib/badline/reu/dma.rb +0 -273
- data/lib/badline/reu/ram.rb +0 -107
- data/lib/badline/reu/saved_state.rb +0 -80
- data/lib/badline/reu/trigger.rb +0 -32
- data/lib/badline/reu.rb +0 -289
- data/lib/badline/sid/catch_up.rb +0 -120
- data/lib/badline/sid/decimator.rb +0 -64
- data/lib/badline/sid/envelope/state.rb +0 -68
- data/lib/badline/sid/envelope.rb +0 -239
- data/lib/badline/sid/filter.rb +0 -263
- data/lib/badline/sid/voice.rb +0 -77
- data/lib/badline/sid/waveform/combined.rb +0 -126
- data/lib/badline/sid/waveform/fast_forward.rb +0 -105
- data/lib/badline/sid/waveform/noise_writeback.rb +0 -122
- data/lib/badline/sid/waveform/state.rb +0 -66
- data/lib/badline/sid/waveform.rb +0 -305
- data/lib/badline/sid.rb +0 -303
- data/lib/badline/snapshot/setup.rb +0 -75
- data/lib/badline/snapshot/state.rb +0 -189
- data/lib/badline/time_of_day.rb +0 -228
- data/lib/badline/traps.rb +0 -19
- data/lib/badline/via/control_lines.rb +0 -122
- data/lib/badline/via/fast_forward.rb +0 -53
- data/lib/badline/via/interrupt_register.rb +0 -67
- data/lib/badline/via/shift_register.rb +0 -180
- data/lib/badline/via/state.rb +0 -42
- data/lib/badline/via/timer1.rb +0 -131
- data/lib/badline/via/timer2.rb +0 -133
- data/lib/badline/via.rb +0 -266
- data/lib/badline/vic/bank.rb +0 -133
- data/lib/badline/vic/border_mask.rb +0 -86
- data/lib/badline/vic/collisions.rb +0 -115
- data/lib/badline/vic/color_patches.rb +0 -47
- data/lib/badline/vic/display_state.rb +0 -185
- data/lib/badline/vic/graphics_mode.rb +0 -164
- data/lib/badline/vic/graphics_shifter.rb +0 -207
- data/lib/badline/vic/register_log.rb +0 -81
- data/lib/badline/vic/registers.rb +0 -195
- data/lib/badline/vic/sequencer.rb +0 -275
- data/lib/badline/vic/sequencer_output.rb +0 -116
- data/lib/badline/vic/sequencer_state.rb +0 -89
- data/lib/badline/vic/sprite/internal_bus.rb +0 -68
- data/lib/badline/vic/sprite/saved_state.rb +0 -64
- data/lib/badline/vic/sprite/shifter.rb +0 -146
- data/lib/badline/vic/sprite/timing.rb +0 -56
- data/lib/badline/vic/sprite.rb +0 -337
- data/lib/badline/vic/sprites.rb +0 -282
- data/lib/badline/vic/sprites_state.rb +0 -57
- data/lib/badline/vic.rb +0 -853
- data/lib/badline/vic20/saved_state.rb +0 -124
- data/lib/badline/vic20/sound/output.rb +0 -83
- data/lib/badline/vic20/sound.rb +0 -233
- data/lib/badline/vic20/vic/saved_state.rb +0 -55
- data/lib/badline/z80/arithmetic.rb +0 -117
- data/lib/badline/z80/bit_page.rb +0 -55
- data/lib/badline/z80/block_io.rb +0 -58
- data/lib/badline/z80/block_transfers.rb +0 -59
- data/lib/badline/z80/bus_cycles.rb +0 -111
- data/lib/badline/z80/core.rb +0 -113
- data/lib/badline/z80/exchanges.rb +0 -50
- data/lib/badline/z80/extended_page.rb +0 -89
- data/lib/badline/z80/flags.rb +0 -37
- data/lib/badline/z80/interrupt_acceptance.rb +0 -46
- data/lib/badline/z80/jumps.rb +0 -82
- data/lib/badline/z80/loads.rb +0 -98
- data/lib/badline/z80/main_page.rb +0 -134
- data/lib/badline/z80/registers.rb +0 -120
- data/lib/badline/z80/saved_state.rb +0 -69
- data/lib/badline/z80/shifts.rb +0 -64
- data/lib/badline/z80.rb +0 -11
- /data/lib/badline/snapshot/{fields.rb → vice/fields.rb} +0 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class Z80
|
|
6
|
+
# The CB page: rotates and shifts (quarter 0), BIT (1), RES (2) and SET
|
|
7
|
+
# (3) of the bit the row names, on the column's register or (HL). After
|
|
8
|
+
# DD or FD the operand is always (IX+d): the displacement comes before
|
|
9
|
+
# the opcode, and an opcode that names a register other than (HL) also
|
|
10
|
+
# copies the result into it.
|
|
11
|
+
module BitPage
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def execute_bits(opcode)
|
|
15
|
+
operation = opcode >> 6
|
|
16
|
+
number = (opcode >> 3) & 7
|
|
17
|
+
index = opcode & 7
|
|
18
|
+
return bits_in_memory(operation, number, hl) if index == 6
|
|
19
|
+
|
|
20
|
+
value = register(index)
|
|
21
|
+
if operation == 1
|
|
22
|
+
bit(number, value, value)
|
|
23
|
+
else
|
|
24
|
+
set_register(index, bit_result(operation, number, value))
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def execute_index_bits
|
|
29
|
+
displaced
|
|
30
|
+
opcode = fetch_byte
|
|
31
|
+
@cycles += 2
|
|
32
|
+
result = bits_in_memory(opcode >> 6, (opcode >> 3) & 7, @wz)
|
|
33
|
+
index = opcode & 7
|
|
34
|
+
set_plain_register(index, result) unless index == 6 || (opcode >> 6) == 1
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def bits_in_memory(operation, number, address)
|
|
38
|
+
value = read_byte(address)
|
|
39
|
+
@cycles += 1
|
|
40
|
+
return bit(number, value, @wz >> 8) if operation == 1
|
|
41
|
+
|
|
42
|
+
result = bit_result(operation, number, value)
|
|
43
|
+
write_byte(address, result)
|
|
44
|
+
result
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def bit_result(operation, number, value)
|
|
48
|
+
case operation
|
|
49
|
+
when 0 then shift(number, value)
|
|
50
|
+
when 2 then value & ~(1 << number) & 0xff
|
|
51
|
+
else value | (1 << number)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class Z80
|
|
6
|
+
# INI, IND, OUTI, OUTD and their repeating forms. B counts the bytes
|
|
7
|
+
# and sets S, Z, 5 and 3. The byte's bit 7 sets N, and adding it to C
|
|
8
|
+
# plus or minus one for INI and IND, or to L for OUTI and OUTD, sets H
|
|
9
|
+
# and C on a carry out and P/V from the parity of its low 3 bits
|
|
10
|
+
# exclusive-ored with B.
|
|
11
|
+
module BlockIO
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def block_input(step, repeat)
|
|
15
|
+
@cycles += 1
|
|
16
|
+
port = bc
|
|
17
|
+
value = input(port)
|
|
18
|
+
@wz = (port + step) & 0xffff
|
|
19
|
+
@b = (@b - 1) & 0xff
|
|
20
|
+
write_byte(hl, value)
|
|
21
|
+
self.hl = (hl + step) & 0xffff
|
|
22
|
+
block_io_flags(value, value + ((@c + step) & 0xff), repeat)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def block_output(step, repeat)
|
|
26
|
+
@cycles += 1
|
|
27
|
+
value = read_byte(hl)
|
|
28
|
+
@b = (@b - 1) & 0xff
|
|
29
|
+
output(bc, value)
|
|
30
|
+
self.hl = (hl + step) & 0xffff
|
|
31
|
+
@wz = (bc + step) & 0xffff
|
|
32
|
+
block_io_flags(value, value + @l, repeat)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def block_io_flags(value, sum, repeat)
|
|
36
|
+
carry = sum > 0xff ? HF | CF : 0
|
|
37
|
+
assign_flags(SZ53[@b] | ((value >> 6) & NF) | carry | PARITY[(sum & 7) ^ @b])
|
|
38
|
+
return unless repeat && !@b.zero?
|
|
39
|
+
|
|
40
|
+
repeat_block
|
|
41
|
+
repeat_io_flags(value, carry)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def repeat_io_flags(value, carry)
|
|
45
|
+
flags = @f & ~HF
|
|
46
|
+
if carry.zero?
|
|
47
|
+
flags ^= PARITY[@b & 7] ^ PF
|
|
48
|
+
elsif value.anybits?(0x80)
|
|
49
|
+
flags ^= PARITY[(@b - 1) & 7] ^ PF
|
|
50
|
+
flags |= HF if @b.nobits?(0x0f)
|
|
51
|
+
else
|
|
52
|
+
flags ^= PARITY[(@b + 1) & 7] ^ PF
|
|
53
|
+
flags |= HF if @b.allbits?(0x0f)
|
|
54
|
+
end
|
|
55
|
+
assign_flags(flags)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class Z80
|
|
6
|
+
# LDI, LDD, CPI, CPD and their repeating forms. A repeating form that
|
|
7
|
+
# goes round again winds the program counter back to its ED and spends
|
|
8
|
+
# 5 T-states more, and bits 5 and 3 then come from the program
|
|
9
|
+
# counter's high byte.
|
|
10
|
+
module BlockTransfers
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
# ED A0-BB: the column picks LD, CP, IN or OUT, bit 3 counts down, and
|
|
14
|
+
# bit 4 repeats.
|
|
15
|
+
def block_operation(opcode)
|
|
16
|
+
step = opcode.nobits?(0x08) ? 1 : -1
|
|
17
|
+
repeat = opcode.anybits?(0x10)
|
|
18
|
+
case opcode & 3
|
|
19
|
+
when 0 then block_load(step, repeat)
|
|
20
|
+
when 1 then block_compare(step, repeat)
|
|
21
|
+
when 2 then block_input(step, repeat)
|
|
22
|
+
else block_output(step, repeat)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def block_load(step, repeat)
|
|
27
|
+
value = read_byte(hl)
|
|
28
|
+
write_byte(de, value)
|
|
29
|
+
@cycles += 2
|
|
30
|
+
self.hl = (hl + step) & 0xffff
|
|
31
|
+
self.de = (de + step) & 0xffff
|
|
32
|
+
self.bc = (bc - 1) & 0xffff
|
|
33
|
+
sum = value + @a
|
|
34
|
+
assign_flags((@f & (SF | ZF | CF)) | (sum & XF) | ((sum & 0x02) << 4) | (bc.zero? ? 0 : PF))
|
|
35
|
+
repeat_block if repeat && !bc.zero?
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def block_compare(step, repeat)
|
|
39
|
+
value = read_byte(hl)
|
|
40
|
+
@cycles += 5
|
|
41
|
+
result = (@a - value) & 0xff
|
|
42
|
+
half = (@a ^ value ^ result) & HF
|
|
43
|
+
adjusted = result - (half >> 4)
|
|
44
|
+
self.hl = (hl + step) & 0xffff
|
|
45
|
+
self.bc = (bc - 1) & 0xffff
|
|
46
|
+
@wz = (@wz + step) & 0xffff
|
|
47
|
+
assign_flags((@f & CF) | NF | half | (SZ53[result] & (SF | ZF)) | (adjusted & XF) | ((adjusted & 0x02) << 4) |
|
|
48
|
+
(bc.zero? ? 0 : PF))
|
|
49
|
+
repeat_block if repeat && !bc.zero? && !result.zero?
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def repeat_block
|
|
53
|
+
@cycles += 5
|
|
54
|
+
@pc = (@pc - 2) & 0xffff
|
|
55
|
+
@wz = (@pc + 1) & 0xffff
|
|
56
|
+
assign_flags((@f & ~XYF) | ((@pc >> 8) & XYF))
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class Z80
|
|
6
|
+
# The machine cycles that reach the bus. An opcode fetch (M1) takes 4
|
|
7
|
+
# T-states and refreshes a row of DRAM, which counts up the low 7 bits
|
|
8
|
+
# of R. A memory read or write takes 3, and an I/O read or write 4,
|
|
9
|
+
# one of them the wait state the Z80 inserts itself. Each calls the bus
|
|
10
|
+
# on its first T-state, and T-states the CPU spends inside lengthen
|
|
11
|
+
# the machine cycle before them.
|
|
12
|
+
module BusCycles
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def fetch_opcode
|
|
16
|
+
opcode = @bus.fetch(@pc)
|
|
17
|
+
@pc = (@pc + 1) & 0xffff
|
|
18
|
+
refresh
|
|
19
|
+
@cycles += 4
|
|
20
|
+
opcode
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# A halted CPU fetches from the address after HALT, again and again,
|
|
24
|
+
# and leaves the program counter there.
|
|
25
|
+
def idle_fetch
|
|
26
|
+
@bus.fetch(@pc)
|
|
27
|
+
refresh
|
|
28
|
+
@cycles += 4
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def refresh
|
|
32
|
+
@r = (@r & 0x80) | ((@r + 1) & 0x7f)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def read_byte(address)
|
|
36
|
+
value = @bus.read(address)
|
|
37
|
+
@cycles += 3
|
|
38
|
+
value
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def write_byte(address, value)
|
|
42
|
+
@bus.write(address, value)
|
|
43
|
+
@cycles += 3
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def read_word(address)
|
|
47
|
+
low = read_byte(address)
|
|
48
|
+
low | (read_byte((address + 1) & 0xffff) << 8)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def write_word(address, value)
|
|
52
|
+
write_byte(address, value & 0xff)
|
|
53
|
+
write_byte((address + 1) & 0xffff, value >> 8)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def input(port)
|
|
57
|
+
value = @bus.input(port)
|
|
58
|
+
@cycles += 4
|
|
59
|
+
value
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def output(port, value)
|
|
63
|
+
@bus.output(port, value)
|
|
64
|
+
@cycles += 4
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# The byte after the opcode.
|
|
68
|
+
def fetch_byte
|
|
69
|
+
value = read_byte(@pc)
|
|
70
|
+
@pc = (@pc + 1) & 0xffff
|
|
71
|
+
value
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def fetch_word
|
|
75
|
+
low = fetch_byte
|
|
76
|
+
low | (fetch_byte << 8)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def push(value)
|
|
80
|
+
@sp = (@sp - 1) & 0xffff
|
|
81
|
+
write_byte(@sp, value >> 8)
|
|
82
|
+
@sp = (@sp - 1) & 0xffff
|
|
83
|
+
write_byte(@sp, value & 0xff)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def pop
|
|
87
|
+
low = read_byte(@sp)
|
|
88
|
+
high = read_byte((@sp + 1) & 0xffff)
|
|
89
|
+
@sp = (@sp + 2) & 0xffff
|
|
90
|
+
low | (high << 8)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# The address of an (HL) operand, or of (IX+d), whose displacement is
|
|
94
|
+
# read from after the opcode and added in 5 T-states inside.
|
|
95
|
+
def operand_address
|
|
96
|
+
return hl if @prefix.zero?
|
|
97
|
+
|
|
98
|
+
displaced
|
|
99
|
+
@cycles += 5
|
|
100
|
+
@wz
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Reads the displacement of an (IX+d) or (IY+d) operand and leaves
|
|
104
|
+
# the address in WZ.
|
|
105
|
+
def displaced
|
|
106
|
+
offset = fetch_byte
|
|
107
|
+
offset -= 256 if offset > 127
|
|
108
|
+
@wz = (index_register + offset) & 0xffff
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "badline/chips/z80/flags"
|
|
4
|
+
require "badline/chips/z80/registers"
|
|
5
|
+
require "badline/chips/z80/bus_cycles"
|
|
6
|
+
require "badline/chips/z80/arithmetic"
|
|
7
|
+
require "badline/chips/z80/shifts"
|
|
8
|
+
require "badline/chips/z80/loads"
|
|
9
|
+
require "badline/chips/z80/exchanges"
|
|
10
|
+
require "badline/chips/z80/jumps"
|
|
11
|
+
require "badline/chips/z80/main_page"
|
|
12
|
+
require "badline/chips/z80/bit_page"
|
|
13
|
+
require "badline/chips/z80/extended_page"
|
|
14
|
+
require "badline/chips/z80/block_transfers"
|
|
15
|
+
require "badline/chips/z80/block_io"
|
|
16
|
+
require "badline/chips/z80/interrupt_acceptance"
|
|
17
|
+
require "badline/chips/z80/keyed_state"
|
|
18
|
+
|
|
19
|
+
module Badline
|
|
20
|
+
module Chips
|
|
21
|
+
class Z80
|
|
22
|
+
# The Z80 core, on whatever bus +bus+ is. The bus answers
|
|
23
|
+
# fetch(address) for an opcode fetch (M1), read(address) and
|
|
24
|
+
# write(address, value) for memory, input(port) and output(port, value)
|
|
25
|
+
# for I/O, and acknowledge for the byte a device puts on the data bus
|
|
26
|
+
# when the CPU takes a maskable interrupt.
|
|
27
|
+
#
|
|
28
|
+
# #step! runs one instruction, prefixes and all, or takes an interrupt,
|
|
29
|
+
# or idles one opcode fetch while halted. #cycles counts T-states, and
|
|
30
|
+
# each bus call happens while it holds the T-state its machine cycle
|
|
31
|
+
# starts on.
|
|
32
|
+
module Core
|
|
33
|
+
include Flags
|
|
34
|
+
include Registers
|
|
35
|
+
include BusCycles
|
|
36
|
+
include Arithmetic
|
|
37
|
+
include Shifts
|
|
38
|
+
include Loads
|
|
39
|
+
include Exchanges
|
|
40
|
+
include Jumps
|
|
41
|
+
include MainPage
|
|
42
|
+
include BitPage
|
|
43
|
+
include ExtendedPage
|
|
44
|
+
include BlockTransfers
|
|
45
|
+
include BlockIO
|
|
46
|
+
include InterruptAcceptance
|
|
47
|
+
include KeyedState
|
|
48
|
+
|
|
49
|
+
attr_reader :bus, :cycles, :nmi
|
|
50
|
+
attr_accessor :int
|
|
51
|
+
|
|
52
|
+
def initialize(bus)
|
|
53
|
+
@bus = bus
|
|
54
|
+
@cycles = 0
|
|
55
|
+
@a = @f = 0xff
|
|
56
|
+
@b = @c = @d = @e = @h = @l = 0xff
|
|
57
|
+
@af_alt = @bc_alt = @de_alt = @hl_alt = 0xffff
|
|
58
|
+
@ix = @iy = @sp = 0xffff
|
|
59
|
+
@wz = @q = @last_q = 0
|
|
60
|
+
@prefix = 0
|
|
61
|
+
@int = @nmi = @nmi_pending = false
|
|
62
|
+
reset!
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# The RESET line: the program counter, I, R and the interrupt mode go
|
|
66
|
+
# to 0, and interrupts are disabled.
|
|
67
|
+
def reset!
|
|
68
|
+
@pc = @i = @r = @im = 0
|
|
69
|
+
@iff1 = @iff2 = false
|
|
70
|
+
@halted = @after_ei = @after_ld_a_ir = false
|
|
71
|
+
@nmi_pending = false
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# The NMI line. Asserting it latches an interrupt, taken after the
|
|
75
|
+
# current instruction, and holding it does nothing more.
|
|
76
|
+
def nmi=(asserted)
|
|
77
|
+
@nmi_pending = true if asserted && !@nmi
|
|
78
|
+
@nmi = asserted
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# The WAIT line: a bus that holds it during an access lengthens that
|
|
82
|
+
# machine cycle by +states+ T-states.
|
|
83
|
+
def wait(states)
|
|
84
|
+
@cycles += states
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def step!
|
|
88
|
+
if @nmi_pending
|
|
89
|
+
take_nmi
|
|
90
|
+
elsif @int && @iff1 && !@after_ei
|
|
91
|
+
take_int
|
|
92
|
+
else
|
|
93
|
+
@after_ei = @after_ld_a_ir = false
|
|
94
|
+
@last_q = @q
|
|
95
|
+
@q = 0
|
|
96
|
+
@prefix = 0
|
|
97
|
+
@halted ? idle_fetch : execute(fetch_opcode)
|
|
98
|
+
end
|
|
99
|
+
nil
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def inspect
|
|
103
|
+
"Cycles: #{@cycles}, PC: #{hex(@pc)}, SP: #{hex(@sp)}, AF: #{hex(af)}, BC: #{hex(bc)}, " \
|
|
104
|
+
"DE: #{hex(de)}, HL: #{hex(hl)}, IX: #{hex(@ix)}, IY: #{hex(@iy)}"
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
private
|
|
108
|
+
|
|
109
|
+
def hex(value)
|
|
110
|
+
value.to_s(16).rjust(4, "0")
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class Z80
|
|
6
|
+
# EX AF,AF', EXX, EX DE,HL and EX (SP),HL. Only the last swaps IX or IY
|
|
7
|
+
# after a prefix.
|
|
8
|
+
module Exchanges
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def exchange_alternates
|
|
12
|
+
bc_alt = @bc_alt
|
|
13
|
+
de_alt = @de_alt
|
|
14
|
+
hl_alt = @hl_alt
|
|
15
|
+
@bc_alt = bc
|
|
16
|
+
@de_alt = de
|
|
17
|
+
@hl_alt = hl
|
|
18
|
+
self.bc = bc_alt
|
|
19
|
+
self.de = de_alt
|
|
20
|
+
self.hl = hl_alt
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def exchange_af
|
|
24
|
+
af_alt = @af_alt
|
|
25
|
+
@af_alt = af
|
|
26
|
+
self.af = af_alt
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def exchange_de_hl
|
|
30
|
+
d = @d
|
|
31
|
+
e = @e
|
|
32
|
+
@d = @h
|
|
33
|
+
@e = @l
|
|
34
|
+
@h = d
|
|
35
|
+
@l = e
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def exchange_stack_top
|
|
39
|
+
low = read_byte(@sp)
|
|
40
|
+
high = read_byte((@sp + 1) & 0xffff)
|
|
41
|
+
@cycles += 1
|
|
42
|
+
value = hl_or_index
|
|
43
|
+
write_byte((@sp + 1) & 0xffff, value >> 8)
|
|
44
|
+
write_byte(@sp, value & 0xff)
|
|
45
|
+
@cycles += 2
|
|
46
|
+
@wz = low | (high << 8)
|
|
47
|
+
self.hl_or_index = @wz
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class Z80
|
|
6
|
+
# The interrupt mode each of ED 46, 4E, 56, 5E, 66, 6E, 76 and 7E sets.
|
|
7
|
+
# 4E and 6E set mode 0 on the NMOS Z80.
|
|
8
|
+
INTERRUPT_MODES = [0, 0, 1, 2, 0, 0, 1, 2].freeze
|
|
9
|
+
|
|
10
|
+
# The ED page: its second quarter, the block instructions, and 8
|
|
11
|
+
# T-states of nothing for the rest.
|
|
12
|
+
module ExtendedPage
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def execute_extended(opcode)
|
|
16
|
+
case opcode >> 6
|
|
17
|
+
when 1 then extended_operation(opcode)
|
|
18
|
+
when 2 then block_operation(opcode) if (opcode & 0x24) == 0x20
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def extended_operation(opcode)
|
|
23
|
+
row = (opcode >> 3) & 7
|
|
24
|
+
case opcode & 7
|
|
25
|
+
when 0 then input_register(row)
|
|
26
|
+
when 1 then output_register(row)
|
|
27
|
+
when 2 then add_pair_with_carry(row)
|
|
28
|
+
when 3 then row.nobits?(1) ? store_word(pair(row >> 1)) : set_pair(row >> 1, load_word)
|
|
29
|
+
when 4 then neg
|
|
30
|
+
when 5 then return_from_interrupt
|
|
31
|
+
when 6 then @im = INTERRUPT_MODES[row]
|
|
32
|
+
else special_register(row)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# IN r,(C), and IN F,(C) at index 6, which sets the flags alone.
|
|
37
|
+
def input_register(index)
|
|
38
|
+
port = bc
|
|
39
|
+
value = input(port)
|
|
40
|
+
@wz = (port + 1) & 0xffff
|
|
41
|
+
assign_flags((@f & CF) | SZ53P[value])
|
|
42
|
+
set_register(index, value) unless index == 6
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# OUT (C),r, and at index 6 OUT (C),0.
|
|
46
|
+
def output_register(index)
|
|
47
|
+
port = bc
|
|
48
|
+
output(port, index == 6 ? 0 : register(index))
|
|
49
|
+
@wz = (port + 1) & 0xffff
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def add_pair_with_carry(row)
|
|
53
|
+
row.nobits?(1) ? sbc16(pair(row >> 1)) : adc16(pair(row >> 1))
|
|
54
|
+
@cycles += 7
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# RETN and RETI both restore IFF1 from IFF2.
|
|
58
|
+
def return_from_interrupt
|
|
59
|
+
@iff1 = @iff2
|
|
60
|
+
return_from_call
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# LD I,A, LD R,A, LD A,I, LD A,R, RRD and RLD, and two that do
|
|
64
|
+
# nothing.
|
|
65
|
+
def special_register(row)
|
|
66
|
+
case row
|
|
67
|
+
when 0 then @i = load_ir(@a)
|
|
68
|
+
when 1 then @r = load_ir(@a)
|
|
69
|
+
when 2 then @a = load_a_from_ir(@i)
|
|
70
|
+
when 3 then @a = load_a_from_ir(@r)
|
|
71
|
+
when 4 then rotate_digits(false)
|
|
72
|
+
when 5 then rotate_digits(true)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def load_ir(value)
|
|
77
|
+
@cycles += 1
|
|
78
|
+
value
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# P/V copies IFF2, and an interrupt taken next clears it again.
|
|
82
|
+
def load_a_from_ir(value)
|
|
83
|
+
@cycles += 1
|
|
84
|
+
assign_flags((@f & CF) | SZ53[value] | (@iff2 ? PF : 0))
|
|
85
|
+
@after_ld_a_ir = true
|
|
86
|
+
value
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class Z80
|
|
6
|
+
CF = 0x01
|
|
7
|
+
NF = 0x02
|
|
8
|
+
PF = 0x04
|
|
9
|
+
XF = 0x08
|
|
10
|
+
HF = 0x10
|
|
11
|
+
YF = 0x20
|
|
12
|
+
ZF = 0x40
|
|
13
|
+
SF = 0x80
|
|
14
|
+
|
|
15
|
+
# Bits 5 and 3, which most instructions copy from a result.
|
|
16
|
+
XYF = YF | XF
|
|
17
|
+
|
|
18
|
+
# S, Z, Y and X as a result byte sets them.
|
|
19
|
+
SZ53 = Array.new(256) { |v| (v & (SF | XYF)) | (v.zero? ? ZF : 0) }.freeze
|
|
20
|
+
|
|
21
|
+
# P/V as parity: set when a byte has an even number of bits set.
|
|
22
|
+
PARITY = Array.new(256) { |v| (0x6996 >> ((v ^ (v >> 4)) & 0x0f)).nobits?(1) ? PF : 0 }.freeze
|
|
23
|
+
|
|
24
|
+
SZ53P = Array.new(256) { |v| SZ53[v] | PARITY[v] }.freeze
|
|
25
|
+
|
|
26
|
+
# The flags, which the core keeps in F as the chip does. Every
|
|
27
|
+
# instruction that sets them through the ALU also latches them in Q,
|
|
28
|
+
# which SCF and CCF read on the next instruction.
|
|
29
|
+
module Flags
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def assign_flags(value)
|
|
33
|
+
@f = value
|
|
34
|
+
@q = value
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class Z80
|
|
6
|
+
# Taking NMI and INT between instructions. Either wakes a halted CPU,
|
|
7
|
+
# whose program counter already points past the HALT.
|
|
8
|
+
module InterruptAcceptance
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
# An opcode fetch whose byte is ignored, a T-state more, and a call
|
|
12
|
+
# to $0066. IFF2 keeps what IFF1 held, for RETN to restore.
|
|
13
|
+
def take_nmi
|
|
14
|
+
@nmi_pending = false
|
|
15
|
+
@halted = false
|
|
16
|
+
@iff1 = false
|
|
17
|
+
@bus.fetch(@pc)
|
|
18
|
+
refresh
|
|
19
|
+
@cycles += 5
|
|
20
|
+
push(@pc)
|
|
21
|
+
@pc = 0x66
|
|
22
|
+
@wz = 0x66
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# The acknowledge cycle, an M1 with two wait states, reads a byte
|
|
26
|
+
# from the device. Mode 0 runs it as an opcode, which is a RST in
|
|
27
|
+
# practice, mode 1 calls $0038, and mode 2 calls through the vector
|
|
28
|
+
# at I and that byte.
|
|
29
|
+
def take_int
|
|
30
|
+
@halted = false
|
|
31
|
+
@f &= ~PF if @after_ld_a_ir
|
|
32
|
+
@iff1 = @iff2 = false
|
|
33
|
+
@after_ld_a_ir = false
|
|
34
|
+
@prefix = 0
|
|
35
|
+
data = @bus.acknowledge
|
|
36
|
+
refresh
|
|
37
|
+
@cycles += 6
|
|
38
|
+
return execute(data) if @im.zero?
|
|
39
|
+
|
|
40
|
+
@cycles += 1
|
|
41
|
+
push(@pc)
|
|
42
|
+
@pc = @im == 1 ? 0x38 : read_word((@i << 8) | data)
|
|
43
|
+
@wz = @pc
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|