badline 0.13.0 → 0.15.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 +72 -1
- data/CLAUDE.md +42 -12
- data/CONTRIBUTING.md +4 -3
- data/README.md +76 -13
- data/doc/media.md +2 -1
- data/doc/pinned-behaviour.md +174 -0
- data/doc/snapshot-format.md +1197 -0
- data/doc/snapshots.md +90 -40
- data/lib/badline/audio/bare_player.rb +46 -17
- data/lib/badline/audio/machine_player.rb +6 -10
- data/lib/badline/audio/renderer.rb +32 -21
- data/lib/badline/c128/banks.rb +7 -6
- data/lib/badline/c128/bus/keyed_state.rb +45 -0
- data/lib/badline/c128/bus.rb +36 -4
- data/lib/badline/c128/drives.rb +6 -25
- 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 +27 -0
- data/lib/badline/c128/modes.rb +19 -9
- data/lib/badline/c128/z80_turns.rb +1 -1
- data/lib/badline/c128.rb +8 -8
- data/lib/badline/c64/attachments.rb +0 -44
- data/lib/badline/c64/banked_ram/plus256k.rb +18 -10
- data/lib/badline/c64/banked_ram/plus60k.rb +8 -6
- data/lib/badline/c64/banked_ram/unexpanded.rb +2 -2
- data/lib/badline/c64/bus/debug_register.rb +32 -0
- data/lib/badline/c64/bus/extra_sids.rb +80 -0
- data/lib/badline/c64/bus/keyed_state.rb +41 -0
- data/lib/badline/c64/bus.rb +3 -1
- data/lib/badline/c64/cartridge/action_replay.rb +6 -15
- data/lib/badline/c64/cartridge/comal80.rb +1 -0
- data/lib/badline/c64/cartridge/dinamic.rb +3 -1
- data/lib/badline/c64/cartridge/easy_flash.rb +0 -15
- data/lib/badline/c64/cartridge/epyx_fastload.rb +0 -8
- data/lib/badline/c64/cartridge/final_cartridge3.rb +1 -12
- data/lib/badline/c64/cartridge/flash.rb +3 -3
- data/lib/badline/c64/cartridge/fun_play.rb +2 -1
- data/lib/badline/c64/cartridge/g_mod2.rb +0 -12
- data/lib/badline/c64/cartridge/game_system.rb +2 -1
- data/lib/badline/c64/cartridge/geo_ram.rb +0 -16
- data/lib/badline/c64/cartridge/kcs_power.rb +0 -8
- data/lib/badline/c64/cartridge/keyed_state.rb +514 -0
- data/lib/badline/c64/cartridge/magic_desk.rb +2 -1
- data/lib/badline/c64/cartridge/ocean.rb +1 -0
- data/lib/badline/c64/cartridge/pagefox.rb +1 -10
- data/lib/badline/c64/cartridge/retro_replay.rb +0 -8
- data/lib/badline/c64/cartridge/rgcd.rb +2 -11
- data/lib/badline/c64/cartridge/super_games.rb +3 -12
- data/lib/badline/c64/cartridge/zaxxon.rb +1 -16
- data/lib/badline/c64/cartridge.rb +4 -30
- data/lib/badline/c64/kernal_traps.rb +28 -25
- data/lib/badline/c64/keyed_modules.rb +115 -0
- data/lib/badline/c64/keyed_state.rb +68 -0
- data/lib/badline/c64/reu/dma.rb +0 -4
- data/lib/badline/c64/reu/keyed_state.rb +140 -0
- data/lib/badline/c64/reu/ram.rb +0 -15
- data/lib/badline/c64/reu.rb +1 -3
- data/lib/badline/c64/true_drives.rb +56 -5
- data/lib/badline/c64.rb +7 -3
- data/lib/badline/chips/cia/interrupt_register.rb +0 -17
- data/lib/badline/chips/cia/keyed_parts.rb +213 -0
- data/lib/badline/chips/cia/serial.rb +0 -4
- data/lib/badline/chips/cia/time_of_day.rb +0 -22
- data/lib/badline/chips/cia/timer.rb +0 -20
- data/lib/badline/chips/cia.rb +2 -2
- data/lib/badline/chips/cpu/core.rb +18 -2
- data/lib/badline/chips/cpu/keyed_state.rb +177 -0
- data/lib/badline/chips/cpu/microcode.rb +16 -0
- data/lib/badline/chips/cpu/port.rb +20 -3
- data/lib/badline/chips/cpu.rb +5 -0
- data/lib/badline/chips/sid/decimator.rb +10 -8
- data/lib/badline/chips/sid/envelope.rb +1 -6
- data/lib/badline/chips/sid/filter.rb +0 -14
- data/lib/badline/chips/sid/keyed_parts.rb +286 -0
- data/lib/badline/chips/sid/voice.rb +0 -10
- data/lib/badline/chips/sid/waveform.rb +0 -2
- data/lib/badline/chips/sid.rb +1 -2
- data/lib/badline/chips/ted/beam.rb +118 -0
- data/lib/badline/chips/ted/fetches.rb +199 -0
- data/lib/badline/chips/ted/keyed_state.rb +156 -0
- data/lib/badline/chips/ted/modes.rb +134 -0
- data/lib/badline/chips/ted/palette.rb +43 -0
- data/lib/badline/chips/ted/picture.rb +182 -0
- data/lib/badline/chips/ted/sound/output.rb +86 -0
- data/lib/badline/chips/ted/sound.rb +284 -0
- data/lib/badline/chips/ted/timers.rb +66 -0
- data/lib/badline/chips/ted.rb +190 -0
- data/lib/badline/chips/tia.rb +61 -0
- data/lib/badline/chips/vdc/keyed_parts.rb +105 -0
- data/lib/badline/chips/vdc/painter.rb +0 -12
- data/lib/badline/chips/vdc/raster.rb +0 -16
- data/lib/badline/chips/vdc/window.rb +0 -9
- data/lib/badline/chips/vdc.rb +1 -2
- data/lib/badline/chips/via/control_lines.rb +0 -15
- data/lib/badline/chips/via/interrupt_register.rb +0 -9
- data/lib/badline/chips/via/keyed_parts.rb +163 -0
- data/lib/badline/chips/via/shift_register.rb +0 -14
- data/lib/badline/chips/via/timer1.rb +0 -13
- data/lib/badline/chips/via/timer2.rb +0 -18
- data/lib/badline/chips/via.rb +1 -2
- data/lib/badline/chips/vic/border_mask.rb +0 -10
- data/lib/badline/chips/vic/collisions.rb +0 -11
- data/lib/badline/chips/vic/color_patches.rb +0 -11
- data/lib/badline/chips/vic/display_state.rb +0 -19
- data/lib/badline/chips/vic/graphics_shifter.rb +0 -4
- 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 +0 -18
- data/lib/badline/chips/vic/registers.rb +0 -9
- data/lib/badline/chips/vic/sequencer.rb +0 -2
- data/lib/badline/chips/vic/sprite/internal_bus.rb +0 -11
- data/lib/badline/chips/vic/sprite.rb +0 -2
- data/lib/badline/chips/vic/sprites.rb +0 -3
- data/lib/badline/chips/vic.rb +6 -2
- data/lib/badline/chips/vic_i/keyed_parts.rb +142 -0
- data/lib/badline/chips/vic_i/painter.rb +0 -4
- data/lib/badline/chips/vic_i/sound.rb +38 -46
- data/lib/badline/chips/vic_i.rb +2 -2
- data/lib/badline/chips/z80/core.rb +2 -2
- data/lib/badline/chips/z80/keyed_state.rb +73 -0
- data/lib/badline/chips.rb +10 -0
- data/lib/badline/core.rb +4 -21
- data/lib/badline/drives/datasette/keyed_state.rb +43 -0
- data/lib/badline/drives/datasette.rb +62 -12
- data/lib/badline/drives/engine/core.rb +3 -0
- data/lib/badline/drives/engine/serial_lines.rb +4 -7
- data/lib/badline/drives/model1541/bus.rb +0 -13
- data/lib/badline/drives/model1541/disk.rb +9 -8
- data/lib/badline/drives/model1541/keyed_state.rb +251 -0
- data/lib/badline/drives/model1541/mechanism.rb +0 -2
- data/lib/badline/drives/model1541.rb +1 -2
- data/lib/badline/drives/model1571/bus.rb +0 -13
- data/lib/badline/drives/model1571/keyed_state.rb +108 -0
- data/lib/badline/drives/model1571/wd1770.rb +0 -14
- data/lib/badline/drives/model1571.rb +1 -2
- data/lib/badline/drives/model1581/bus.rb +0 -13
- data/lib/badline/drives/model1581/disk.rb +0 -4
- data/lib/badline/drives/model1581/keyed_state.rb +280 -0
- data/lib/badline/drives/model1581/mechanism.rb +0 -21
- data/lib/badline/drives/model1581/slot.rb +0 -18
- data/lib/badline/drives/model1581/wd1772.rb +0 -2
- data/lib/badline/drives/model1581.rb +2 -2
- data/lib/badline/drives.rb +8 -0
- data/lib/badline/frontend/app.rb +3 -3
- data/lib/badline/frontend/boot.rb +4 -2
- data/lib/badline/frontend/controls.rb +25 -5
- data/lib/badline/frontend/drive_led.rb +44 -21
- data/lib/badline/frontend/keys.rb +14 -2
- data/lib/badline/frontend/media_slots.rb +11 -1
- data/lib/badline/frontend/menu/menu_dialogs.rb +4 -3
- data/lib/badline/frontend/menu/menu_media.rb +13 -3
- data/lib/badline/frontend/menu/menu_pages.rb +8 -8
- data/lib/badline/frontend/menu/menu_ports.rb +13 -1
- data/lib/badline/frontend/screen.rb +33 -12
- data/lib/badline/frontend/screens.rb +2 -1
- data/lib/badline/frontend/snapshots.rb +12 -1
- data/lib/badline/frontend/sound.rb +4 -4
- data/lib/badline/frontend/timeline.rb +43 -12
- data/lib/badline/input/matrix_typist.rb +98 -0
- data/lib/badline/input.rb +1 -0
- data/lib/badline/kernal_trap/chrout.rb +45 -0
- data/lib/badline/kernal_trap/dos/channel.rb +0 -27
- data/lib/badline/kernal_trap/dos/channels.rb +0 -25
- data/lib/badline/kernal_trap/dos/memory.rb +0 -9
- data/lib/badline/kernal_trap/dos/status.rb +0 -8
- data/lib/badline/kernal_trap/dos/write_file.rb +0 -18
- data/lib/badline/kernal_trap/dos.rb +0 -19
- 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 +14 -16
- data/lib/badline/kernal_trap/routine.rb +12 -0
- data/lib/badline/kernal_trap/save.rb +8 -18
- data/lib/badline/kernal_trap/serial.rb +1 -17
- data/lib/badline/kernal_trap.rb +2 -0
- data/lib/badline/machine/keyboard_buffer.rb +49 -0
- data/lib/badline/machine/settling.rb +29 -0
- data/lib/badline/machine.rb +29 -6
- data/lib/badline/media/boot_disk.rb +14 -2
- data/lib/badline/media/extensions.rb +10 -0
- data/lib/badline/media/plus4_media.rb +68 -0
- data/lib/badline/media/program.rb +20 -6
- data/lib/badline/media.rb +33 -12
- data/lib/badline/memory.rb +3 -6
- data/lib/badline/options/family.rb +6 -2
- data/lib/badline/options/help.rb +66 -16
- data/lib/badline/options/table.rb +17 -2
- data/lib/badline/options/validation.rb +26 -2
- data/lib/badline/options.rb +42 -9
- data/lib/badline/plus4/acia.rb +45 -0
- data/lib/badline/plus4/bus.rb +375 -0
- data/lib/badline/plus4/cassette_sense.rb +21 -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 +76 -0
- data/lib/badline/plus4/keyed_modules.rb +99 -0
- data/lib/badline/plus4/keyed_parts.rb +143 -0
- data/lib/badline/plus4/keyed_state.rb +41 -0
- data/lib/badline/plus4/model.rb +38 -0
- data/lib/badline/plus4/user_port.rb +31 -0
- data/lib/badline/plus4.rb +240 -0
- data/lib/badline/roms/README +38 -0
- 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/snapshot/c128_setup.rb +9 -20
- data/lib/badline/snapshot/c64_setup.rb +28 -24
- data/lib/badline/snapshot/container.rb +6 -0
- data/lib/badline/snapshot/field_doc/markdown.rb +113 -0
- data/lib/badline/snapshot/field_doc.rb +148 -0
- data/lib/badline/snapshot/image.rb +143 -28
- 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/plus4_setup.rb +39 -0
- data/lib/badline/snapshot/storage_setup.rb +29 -34
- data/lib/badline/snapshot/vic20_setup.rb +6 -15
- data/lib/badline/snapshot/vice/reu1764.rb +2 -2
- data/lib/badline/snapshot/vice.rb +7 -31
- data/lib/badline/snapshot.rb +48 -20
- data/lib/badline/storage/crt_file.rb +3 -1
- data/lib/badline/storage/g64_image.rb +9 -4
- data/lib/badline/storage/tap.rb +57 -20
- data/lib/badline/support/checkpoint.rb +3 -2
- data/lib/badline/support/plus4_checkpoint.rb +42 -0
- data/lib/badline/version.rb +1 -1
- data/lib/badline/vic20/attachments.rb +3 -0
- data/lib/badline/vic20/bus/keyed_state.rb +52 -0
- data/lib/badline/vic20/bus.rb +1 -2
- data/lib/badline/vic20/keyed_modules.rb +73 -0
- data/lib/badline/vic20/keyed_state.rb +45 -0
- data/lib/badline/vic20.rb +5 -5
- data/lib/badline.rb +1 -0
- metadata +75 -42
- data/lib/badline/c128/bus/saved_state.rb +0 -53
- data/lib/badline/c128/saved_state.rb +0 -117
- data/lib/badline/c64/bus/saved_state.rb +0 -68
- data/lib/badline/c64/cartridge/flash/saved_state.rb +0 -40
- data/lib/badline/c64/cartridge/retro_replay/saved_state.rb +0 -47
- data/lib/badline/c64/cartridge/saved_state.rb +0 -63
- data/lib/badline/c64/reu/dma/saved_state.rb +0 -52
- data/lib/badline/c64/reu/saved_state.rb +0 -55
- data/lib/badline/c64/saved_state.rb +0 -112
- data/lib/badline/chips/cia/saved_state.rb +0 -49
- data/lib/badline/chips/cia/serial/saved_state.rb +0 -45
- data/lib/badline/chips/cpu/saved_state.rb +0 -117
- data/lib/badline/chips/sid/envelope/saved_state.rb +0 -70
- data/lib/badline/chips/sid/filter/saved_state.rb +0 -42
- data/lib/badline/chips/sid/saved_state.rb +0 -52
- data/lib/badline/chips/sid/waveform/saved_state.rb +0 -68
- data/lib/badline/chips/vdc/saved_state.rb +0 -36
- data/lib/badline/chips/via/saved_state.rb +0 -44
- data/lib/badline/chips/vic/graphics_shifter/saved_state.rb +0 -40
- data/lib/badline/chips/vic/saved_state.rb +0 -82
- data/lib/badline/chips/vic/sequencer/saved_state.rb +0 -91
- data/lib/badline/chips/vic/sprite/saved_state.rb +0 -66
- data/lib/badline/chips/vic/sprites/saved_state.rb +0 -59
- data/lib/badline/chips/vic_i/painter/saved_state.rb +0 -40
- data/lib/badline/chips/vic_i/saved_state.rb +0 -55
- data/lib/badline/chips/z80/saved_state.rb +0 -71
- data/lib/badline/chrout_trap.rb +0 -43
- data/lib/badline/debug_register.rb +0 -28
- data/lib/badline/drives/datasette/saved_state.rb +0 -37
- data/lib/badline/drives/model1541/disk/saved_state.rb +0 -88
- data/lib/badline/drives/model1541/mechanism/saved_state.rb +0 -72
- data/lib/badline/drives/model1541/saved_state.rb +0 -44
- data/lib/badline/drives/model1571/saved_state.rb +0 -47
- data/lib/badline/drives/model1581/disk/saved_state.rb +0 -89
- data/lib/badline/drives/model1581/saved_state.rb +0 -42
- data/lib/badline/drives/model1581/wd1772/saved_state.rb +0 -68
- data/lib/badline/keyboard_buffer.rb +0 -33
- data/lib/badline/snapshot/setup.rb +0 -31
- data/lib/badline/snapshot/state.rb +0 -179
- data/lib/badline/vic20/bus/saved_state.rb +0 -35
- data/lib/badline/vic20/saved_state.rb +0 -110
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
module Drives
|
|
5
|
-
class Model1581
|
|
6
|
-
class WD1772
|
|
7
|
-
# Saving and restoring the WD1772 for a snapshot: its registers and
|
|
8
|
-
# lines, and the command running, down to the byte it is at.
|
|
9
|
-
module SavedState
|
|
10
|
-
def save_state(out)
|
|
11
|
-
[@now, @due, @phase, @command, @track, @sector, @data, @status, @steps, @count, @after_spin_up, @mode,
|
|
12
|
-
@deadline, @id_at, @found, @index, @crc, @write_id, @size].each { |value| out.int(value) }
|
|
13
|
-
[@type1, @drq, @intrq, @motor_on, @inward, @crc_good, @gate_open, @late,
|
|
14
|
-
@settling].each { |flag| out.boolean(flag) }
|
|
15
|
-
out.ints(@bytes).ints(@syncs.map { |sync| sync ? 1 : 0 })
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def load_state(input)
|
|
19
|
-
load_registers(input)
|
|
20
|
-
load_command(input)
|
|
21
|
-
load_flags(input)
|
|
22
|
-
@bytes = input.ints
|
|
23
|
-
@syncs = input.ints.map { |sync| sync == 1 }
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
private
|
|
27
|
-
|
|
28
|
-
def load_registers(input)
|
|
29
|
-
@now = input.int
|
|
30
|
-
@due = input.int
|
|
31
|
-
@phase = input.int
|
|
32
|
-
@command = input.int
|
|
33
|
-
@track = input.int
|
|
34
|
-
@sector = input.int
|
|
35
|
-
@data = input.int
|
|
36
|
-
@status = input.int
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def load_command(input)
|
|
40
|
-
@steps = input.int
|
|
41
|
-
@count = input.int
|
|
42
|
-
@after_spin_up = input.int
|
|
43
|
-
@mode = input.int
|
|
44
|
-
@deadline = input.int
|
|
45
|
-
@id_at = input.int
|
|
46
|
-
@found = input.int
|
|
47
|
-
@index = input.int
|
|
48
|
-
@crc = input.int
|
|
49
|
-
@write_id = input.int
|
|
50
|
-
@size = input.int
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def load_flags(input)
|
|
54
|
-
@type1 = input.boolean?
|
|
55
|
-
@drq = input.boolean?
|
|
56
|
-
@intrq = input.boolean?
|
|
57
|
-
@motor_on = input.boolean?
|
|
58
|
-
@inward = input.boolean?
|
|
59
|
-
@crc_good = input.boolean?
|
|
60
|
-
@gate_open = input.boolean?
|
|
61
|
-
@late = input.boolean?
|
|
62
|
-
@settling = input.boolean?
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
end
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
module KeyboardBuffer
|
|
5
|
-
ADDRESS = 0x0277
|
|
6
|
-
COUNT = 0xc6
|
|
7
|
-
CAPACITY = 10
|
|
8
|
-
|
|
9
|
-
def type_text(text)
|
|
10
|
-
codes = text.bytes.map { |b| ascii_to_petscii(b) }
|
|
11
|
-
on_init { @pending_keys = codes }
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
private
|
|
15
|
-
|
|
16
|
-
def feed_keyboard
|
|
17
|
-
return unless ram.peek(COUNT).zero?
|
|
18
|
-
|
|
19
|
-
chunk = @pending_keys.shift(CAPACITY)
|
|
20
|
-
ram.write(ADDRESS, chunk)
|
|
21
|
-
ram.poke(COUNT, chunk.length)
|
|
22
|
-
@pending_keys = nil if @pending_keys.empty?
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def ascii_to_petscii(byte)
|
|
26
|
-
case byte
|
|
27
|
-
when 0x61..0x7a then byte - 0x20
|
|
28
|
-
when 0x41..0x5a then byte + 0x80
|
|
29
|
-
else byte
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "badline/snapshot/c64_setup"
|
|
4
|
-
require "badline/snapshot/vic20_setup"
|
|
5
|
-
require "badline/snapshot/c128_setup"
|
|
6
|
-
|
|
7
|
-
module Badline
|
|
8
|
-
module Snapshot
|
|
9
|
-
# How the machine a State was taken of was built, so a machine to
|
|
10
|
-
# restore it into can be built first. A State starts with its family's
|
|
11
|
-
# marker, the stamp (StateWriter#stamp) and the family's setup:
|
|
12
|
-
# C64Setup, Vic20Setup or C128Setup. Each reads its setup from a State
|
|
13
|
-
# (.from) or from the fields after the stamp (.read), writes it
|
|
14
|
-
# (#write), builds a machine that way at power-on (#build) and names it
|
|
15
|
-
# (#to_s).
|
|
16
|
-
module Setup
|
|
17
|
-
# The setup of the family whose marker the State starts with.
|
|
18
|
-
def self.read(state)
|
|
19
|
-
family = StateReader.new(state).string
|
|
20
|
-
return Vic20Setup.from(state) if family == Vic20Setup::MARKER
|
|
21
|
-
return C128Setup.from(state) if family == C128Setup::MARKER
|
|
22
|
-
|
|
23
|
-
C64Setup.from(state)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
# A new machine, built as the one a State was taken of, at that
|
|
27
|
-
# state.
|
|
28
|
-
def self.restored(state) = read(state).build.apply_state(state)
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
module Snapshot
|
|
5
|
-
# A file that isn't a snapshot badline reads, is cut short, or holds a
|
|
6
|
-
# state that doesn't line up with the machine reading it.
|
|
7
|
-
class FormatError < StandardError; end
|
|
8
|
-
|
|
9
|
-
# A machine's state, held in memory: the Integers each chip writes in
|
|
10
|
-
# turn, and the byte strings for memories, names and paths. Booleans
|
|
11
|
-
# are written as 0 and 1. C64#snapshot takes one and
|
|
12
|
-
# C64#restore puts it back.
|
|
13
|
-
class State
|
|
14
|
-
# The layout the chips write their fields in. It goes up whenever a
|
|
15
|
-
# save_state writes something else, so a State in another layout
|
|
16
|
-
# fails before anything is read into a machine. A State only reads in
|
|
17
|
-
# the layout and the badline version that wrote it.
|
|
18
|
-
SCHEMA = 10
|
|
19
|
-
|
|
20
|
-
attr_reader :values, :strings
|
|
21
|
-
|
|
22
|
-
def initialize(values, strings)
|
|
23
|
-
@values = values
|
|
24
|
-
@strings = strings
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def ==(other)
|
|
28
|
-
other.is_a?(State) && values == other.values && strings == other.strings
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# Writes a State. Each chip's save_state writes its fields through one
|
|
33
|
-
# of these, and its load_state reads them back from a StateReader in
|
|
34
|
-
# the same order.
|
|
35
|
-
class StateWriter
|
|
36
|
-
attr_reader :state
|
|
37
|
-
|
|
38
|
-
def initialize
|
|
39
|
-
@values = []
|
|
40
|
-
@strings = []
|
|
41
|
-
@state = State.new(@values, @strings)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def int(value)
|
|
45
|
-
raise TypeError, "not an Integer: #{value.inspect}" unless value.is_a?(Integer)
|
|
46
|
-
|
|
47
|
-
@values << value.to_i
|
|
48
|
-
self
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def boolean(value)
|
|
52
|
-
@values << (value ? 1 : 0)
|
|
53
|
-
self
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def optional_int(value)
|
|
57
|
-
return boolean(false) if value.nil?
|
|
58
|
-
|
|
59
|
-
boolean(true).int(value)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def ints(values)
|
|
63
|
-
int(values.length)
|
|
64
|
-
values.each { |value| int(value) }
|
|
65
|
-
self
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def booleans(values)
|
|
69
|
-
int(values.length)
|
|
70
|
-
values.each { |value| boolean(value) }
|
|
71
|
-
self
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
# Bytes, 0 to 255 each, kept as one string.
|
|
75
|
-
def blob(values)
|
|
76
|
-
@strings << values.pack("C*")
|
|
77
|
-
self
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def string(value)
|
|
81
|
-
@strings << value.to_s.b
|
|
82
|
-
self
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def optional_string(value)
|
|
86
|
-
return boolean(false) if value.nil?
|
|
87
|
-
|
|
88
|
-
boolean(true).string(value)
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
# A name a reader checks for, so a state that has gone out of step
|
|
92
|
-
# fails there instead of loading the wrong fields.
|
|
93
|
-
def marker(name) = string(name)
|
|
94
|
-
|
|
95
|
-
# The State's layout and the badline version writing it, which a
|
|
96
|
-
# reader checks first (StateReader#check_stamp).
|
|
97
|
-
def stamp = int(State::SCHEMA).string(VERSION)
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
# Reads a State back in the order a StateWriter wrote it.
|
|
101
|
-
#
|
|
102
|
-
# A detached reader restores a machine that opens no host file and
|
|
103
|
-
# writes none, for a copy the machine runs on its own: a disk image
|
|
104
|
-
# comes from the bytes the state holds, write-protected, a directory
|
|
105
|
-
# device 8 serves is left out, and a true drive's disk keeps the
|
|
106
|
-
# state's tracks without its image file.
|
|
107
|
-
class StateReader
|
|
108
|
-
def initialize(state, detached: false)
|
|
109
|
-
@values = state.values
|
|
110
|
-
@strings = state.strings
|
|
111
|
-
@value = 0
|
|
112
|
-
@string = 0
|
|
113
|
-
@detached = detached
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def detached? = @detached
|
|
117
|
-
|
|
118
|
-
def int
|
|
119
|
-
raise FormatError, "the state ends early, at value #{@value}" if @value >= @values.length
|
|
120
|
-
|
|
121
|
-
value = @values[@value]
|
|
122
|
-
@value += 1
|
|
123
|
-
value
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def boolean?
|
|
127
|
-
value = int
|
|
128
|
-
raise FormatError, "expected a boolean in the state, found #{value}" unless value.between?(0, 1)
|
|
129
|
-
|
|
130
|
-
value == 1
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
def optional_int = boolean? ? int : nil
|
|
134
|
-
|
|
135
|
-
def ints = Array.new(int) { int }
|
|
136
|
-
|
|
137
|
-
def booleans = Array.new(int) { boolean? }
|
|
138
|
-
|
|
139
|
-
# Reads into an existing array, in place, so whatever else holds it
|
|
140
|
-
# sees the values.
|
|
141
|
-
def ints_into(array) = array.replace(ints)
|
|
142
|
-
|
|
143
|
-
def booleans_into(array) = array.replace(booleans)
|
|
144
|
-
|
|
145
|
-
def blob = string.bytes
|
|
146
|
-
|
|
147
|
-
def blob_into(array) = array.replace(blob)
|
|
148
|
-
|
|
149
|
-
def string
|
|
150
|
-
raise FormatError, "the state ends early, at string #{@string}" if @string >= @strings.length
|
|
151
|
-
|
|
152
|
-
value = @strings[@string]
|
|
153
|
-
@string += 1
|
|
154
|
-
value
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
def optional_string = boolean? ? string : nil
|
|
158
|
-
|
|
159
|
-
def marker(name)
|
|
160
|
-
found = string
|
|
161
|
-
raise FormatError, "expected #{name} in the state, found #{found[0, 20].inspect}" unless found == name
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
# Fails unless the State was written in this layout by this badline
|
|
165
|
-
# version.
|
|
166
|
-
def check_stamp
|
|
167
|
-
schema = int
|
|
168
|
-
version = string
|
|
169
|
-
return if schema == State::SCHEMA && version == VERSION
|
|
170
|
-
|
|
171
|
-
raise FormatError, "the state was written by badline #{version.inspect} in layout #{schema}, " \
|
|
172
|
-
"and this is badline #{VERSION}, layout #{State::SCHEMA}"
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
# Whether every value and string has been read.
|
|
176
|
-
def finished? = @value == @values.length && @string == @strings.length
|
|
177
|
-
end
|
|
178
|
-
end
|
|
179
|
-
end
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
class Vic20
|
|
5
|
-
class Bus
|
|
6
|
-
# The bus's state for a snapshot.
|
|
7
|
-
module SavedState
|
|
8
|
-
# The RAM, the colour RAM, the byte each side's data lines hold and the
|
|
9
|
-
# cartridge's ROM chips, for a snapshot. The expansion blocks are how
|
|
10
|
-
# the machine was built.
|
|
11
|
-
def save_state(out)
|
|
12
|
-
out.marker("VIC20 BUS")
|
|
13
|
-
@ram.save_state(out)
|
|
14
|
-
out.blob(@color_ram.cells).int(@data).int(@video_data).int(@roms.length)
|
|
15
|
-
@roms.each do |rom|
|
|
16
|
-
out.int(rom.start)
|
|
17
|
-
rom.save_state(out)
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def load_state(input)
|
|
22
|
-
input.marker("VIC20 BUS")
|
|
23
|
-
@ram.load_state(input)
|
|
24
|
-
input.blob_into(@color_ram.cells)
|
|
25
|
-
@data = input.int
|
|
26
|
-
@video_data = input.int
|
|
27
|
-
chips = Array.new(input.int) { [input.int, input.blob] }
|
|
28
|
-
@roms = []
|
|
29
|
-
chips.each { |chip| @roms << ROM.new(chip[1], length: chip[1].length, start: chip[0]) }
|
|
30
|
-
map_pages
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "badline/snapshot/vic20_setup"
|
|
4
|
-
|
|
5
|
-
module Badline
|
|
6
|
-
class Vic20
|
|
7
|
-
# How the machine a State from #snapshot was taken of was built.
|
|
8
|
-
def self.setup(state) = Snapshot::Vic20Setup.from(state)
|
|
9
|
-
|
|
10
|
-
# A new machine, built as the one a State from #snapshot was taken of,
|
|
11
|
-
# at that state.
|
|
12
|
-
def self.restored(state) = setup(state).build.apply_state(state)
|
|
13
|
-
|
|
14
|
-
# The whole machine's state for a snapshot, as C64's: the
|
|
15
|
-
# machine's own latches, the bus with its RAM and cartridge ROM, the
|
|
16
|
-
# VIC with its sound, both VIAs, the CPU, the datasette and its tape,
|
|
17
|
-
# the disk device 8 serves through the traps, and a true 1541. The
|
|
18
|
-
# serial lines go back into the bus from the restored VIAs. What the
|
|
19
|
-
# host holds stays out: the keyboard, the joystick, RESTORE, the traps
|
|
20
|
-
# and callbacks, whether the display renders, whether the sound
|
|
21
|
-
# records, and whether the datasette records.
|
|
22
|
-
module SavedState
|
|
23
|
-
# How many more on_init handlers the machine a State was taken of had
|
|
24
|
-
# yet to run than this one has. Nil until the machine is restored.
|
|
25
|
-
attr_reader :init_handlers_lost
|
|
26
|
-
|
|
27
|
-
def snapshot
|
|
28
|
-
out = Snapshot::StateWriter.new
|
|
29
|
-
save_state(out)
|
|
30
|
-
out.state
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# Takes the machine back to a State from #snapshot, trying it on a new
|
|
34
|
-
# machine first, so one that fails leaves this machine as it was.
|
|
35
|
-
# Raises Snapshot::FormatError for a state of another machine or RAM
|
|
36
|
-
# expansion.
|
|
37
|
-
def restore(state)
|
|
38
|
-
check_setup(Vic20.setup(state))
|
|
39
|
-
Vic20.restored(state)
|
|
40
|
-
apply_state(state)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# Puts a State into the machine without trying it on a new one first.
|
|
44
|
-
def apply_state(state)
|
|
45
|
-
input = Snapshot::StateReader.new(state)
|
|
46
|
-
load_state(input)
|
|
47
|
-
raise Snapshot::FormatError, "the state goes on past the machine" unless input.finished?
|
|
48
|
-
|
|
49
|
-
self
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def save_state(out)
|
|
53
|
-
out.marker(Snapshot::Vic20Setup::MARKER).stamp
|
|
54
|
-
Snapshot::Vic20Setup.new(ram: @ram_configuration).write(out)
|
|
55
|
-
out.int(@cycles).boolean(@nmi_asserted).boolean(!@pending_keys.nil?)
|
|
56
|
-
out.ints(@pending_keys) if @pending_keys
|
|
57
|
-
out.int(@cycles <= @init_threshold ? @init_handlers.length : 0)
|
|
58
|
-
@bus.save_state(out)
|
|
59
|
-
@vic.save_state(out)
|
|
60
|
-
@sound.save_state(out)
|
|
61
|
-
@via1.save_state(out)
|
|
62
|
-
@via2.save_state(out)
|
|
63
|
-
@cpu.save_state(out)
|
|
64
|
-
@datasette.save_state(out)
|
|
65
|
-
save_trap_dos(out)
|
|
66
|
-
save_drive1541(out)
|
|
67
|
-
save_drive1581(out)
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def load_state(input)
|
|
71
|
-
input.marker(Snapshot::Vic20Setup::MARKER)
|
|
72
|
-
input.check_stamp
|
|
73
|
-
check_setup(Snapshot::Vic20Setup.read(input))
|
|
74
|
-
@cycles = input.int
|
|
75
|
-
@nmi_asserted = input.boolean?
|
|
76
|
-
@pending_keys = nil
|
|
77
|
-
@pending_keys = input.ints if input.boolean?
|
|
78
|
-
@init_handlers_lost = [input.int - @init_handlers.length, 0].max
|
|
79
|
-
@bus.load_state(input)
|
|
80
|
-
@vic.load_state(input)
|
|
81
|
-
@sound.load_state(input)
|
|
82
|
-
@via1.load_state(input)
|
|
83
|
-
@via2.load_state(input)
|
|
84
|
-
@cpu.load_state(input)
|
|
85
|
-
via_written
|
|
86
|
-
@datasette.load_state(input)
|
|
87
|
-
load_trap_dos(input)
|
|
88
|
-
load_drive1541(input)
|
|
89
|
-
load_drive1581(input)
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
private
|
|
93
|
-
|
|
94
|
-
# A true 1541 on the serial bus, with its device number.
|
|
95
|
-
def save_drive1541(out)
|
|
96
|
-
out.boolean(!@drive1541.nil?)
|
|
97
|
-
return unless @drive1541
|
|
98
|
-
|
|
99
|
-
out.int(@drive1541.device)
|
|
100
|
-
@drive1541.save_state(out)
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def check_setup(setup)
|
|
104
|
-
return if setup.ram == @ram_configuration
|
|
105
|
-
|
|
106
|
-
raise Snapshot::FormatError, "the state is of a VIC-20 with #{setup.ram} RAM, not #{@ram_configuration}"
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
end
|