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
|
@@ -27,15 +27,11 @@ require "badline/c64/cartridge/final_cartridge3"
|
|
|
27
27
|
require "badline/c64/cartridge/retro_replay"
|
|
28
28
|
require "badline/c64/cartridge/kcs_power"
|
|
29
29
|
require "badline/c64/cartridge/geo_ram"
|
|
30
|
-
require "badline/c64/cartridge/saved_state"
|
|
31
30
|
|
|
32
31
|
module Badline
|
|
33
32
|
class C64
|
|
34
33
|
class Cartridge
|
|
35
|
-
include SavedState
|
|
36
|
-
|
|
37
34
|
class UnsupportedTypeError < StandardError; end
|
|
38
|
-
|
|
39
35
|
ROMH_START = 0xa000
|
|
40
36
|
BANK_SIZE = 0x2000
|
|
41
37
|
|
|
@@ -70,22 +66,6 @@ module Badline
|
|
|
70
66
|
mapper_for(crt).new(crt, **)
|
|
71
67
|
end
|
|
72
68
|
|
|
73
|
-
# A cartridge built afresh from what save_setup wrote, before
|
|
74
|
-
# load_state puts its state in.
|
|
75
|
-
def from_setup(input)
|
|
76
|
-
return GeoRAM.new(size: input.int) if input.int == GEO_RAM_SETUP
|
|
77
|
-
|
|
78
|
-
crt = Storage::CRTFile.new(bytes: input.string)
|
|
79
|
-
mapper_for(crt).from_jumpers(crt, input)
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
# A cartridge from its image and what save_jumpers wrote: whether
|
|
83
|
-
# there are jumpers, then their settings on a mapper that has them.
|
|
84
|
-
def from_jumpers(crt, input)
|
|
85
|
-
input.boolean?
|
|
86
|
-
new(crt)
|
|
87
|
-
end
|
|
88
|
-
|
|
89
69
|
def mapper_for(crt)
|
|
90
70
|
HARDWARE_TYPES.fetch(crt.hardware_type) do
|
|
91
71
|
raise UnsupportedTypeError,
|
|
@@ -94,11 +74,6 @@ module Badline
|
|
|
94
74
|
end
|
|
95
75
|
end
|
|
96
76
|
|
|
97
|
-
# What save_setup writes first: a cartridge from a CRT image, or a
|
|
98
|
-
# GEO-RAM.
|
|
99
|
-
CRT_SETUP = 0
|
|
100
|
-
GEO_RAM_SETUP = 1
|
|
101
|
-
|
|
102
77
|
# Keeps the image it was built from, so a snapshot's machine can build
|
|
103
78
|
# the same cartridge before the snapshot's state goes into it.
|
|
104
79
|
def initialize(crt)
|
|
@@ -177,9 +152,9 @@ module Badline
|
|
|
177
152
|
|
|
178
153
|
private
|
|
179
154
|
|
|
180
|
-
# The banks and views ROML and ROMH can point at, which a
|
|
181
|
-
# names them by: the mapper's banks, or nothing for a mapper
|
|
182
|
-
# windows stay where install_chips put them.
|
|
155
|
+
# The banks and views ROML and ROMH can point at, which a 0.14.0
|
|
156
|
+
# snapshot names them by: the mapper's banks, or nothing for a mapper
|
|
157
|
+
# whose windows stay where install_chips put them.
|
|
183
158
|
def windows
|
|
184
159
|
[*@banks, EMPTY_BANK] if @banks
|
|
185
160
|
end
|
|
@@ -191,8 +166,6 @@ module Badline
|
|
|
191
166
|
raise(ArgumentError, "#{self.class.name}: a window that isn't among its banks")
|
|
192
167
|
end
|
|
193
168
|
|
|
194
|
-
def window_at(index, windows) = index.negative? ? nil : windows.fetch(index)
|
|
195
|
-
|
|
196
169
|
def nmi=(level)
|
|
197
170
|
return if @nmi == level
|
|
198
171
|
|
|
@@ -256,3 +229,4 @@ module Badline
|
|
|
256
229
|
end
|
|
257
230
|
end
|
|
258
231
|
end
|
|
232
|
+
require "badline/c64/cartridge/keyed_state"
|
|
@@ -36,13 +36,38 @@ module Badline
|
|
|
36
36
|
# traps, or an empty one.
|
|
37
37
|
def mounted_path = @dos.nil? ? "" : @dos.path
|
|
38
38
|
|
|
39
|
-
# Records what the KERNAL prints through CHROUT (
|
|
39
|
+
# Records what the KERNAL prints through CHROUT (KernalTrap::Chrout).
|
|
40
40
|
def capture_output
|
|
41
|
-
@capture_output ||=
|
|
42
|
-
cpu.install_trap(
|
|
41
|
+
@capture_output ||= KernalTrap::Chrout.new(cpu:, bus: trap_bus, layout: trap_layout).tap do |trap|
|
|
42
|
+
cpu.install_trap(KernalTrap::Chrout::ADDRESS) { trap.call }
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
+
# Device 8 through the KERNAL traps in a keyed snapshot module
|
|
47
|
+
# (BL-TRAPDOS): the storage under storage.*, the DOS, the serial
|
|
48
|
+
# trap under serial.* and the SAVE trap under save.*. Nothing mounted
|
|
49
|
+
# writes nothing.
|
|
50
|
+
def save_trap_dos_fields(out)
|
|
51
|
+
dos = @dos
|
|
52
|
+
return unless dos
|
|
53
|
+
|
|
54
|
+
Snapshot::StorageSetup.write_fields(dos.storage, out)
|
|
55
|
+
dos.save_fields(out)
|
|
56
|
+
@serial_trap&.save_fields(out, "serial.")
|
|
57
|
+
@save_trap&.save_fields(out, "save.")
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# `detached` mounts a disk image write-protected and no directory.
|
|
61
|
+
def load_trap_dos_fields(input, detached: false)
|
|
62
|
+
unmount
|
|
63
|
+
return if input.missing?
|
|
64
|
+
|
|
65
|
+
mount(Snapshot::StorageSetup.read_fields(input, detached:))
|
|
66
|
+
@dos&.load_fields(input)
|
|
67
|
+
@serial_trap&.load_fields(input, "serial.")
|
|
68
|
+
@save_trap&.load_fields(input, "save.")
|
|
69
|
+
end
|
|
70
|
+
|
|
46
71
|
private
|
|
47
72
|
|
|
48
73
|
def install_kernal_traps(layout)
|
|
@@ -62,28 +87,6 @@ module Badline
|
|
|
62
87
|
@serial_trap = nil
|
|
63
88
|
@save_trap = nil
|
|
64
89
|
end
|
|
65
|
-
|
|
66
|
-
# The disk device 8 serves through the traps, with the traps' own
|
|
67
|
-
# state: open channels, the drive's status and RAM, a SAVE under way.
|
|
68
|
-
def save_trap_dos(out)
|
|
69
|
-
out.boolean(!@dos.nil?)
|
|
70
|
-
return unless @dos
|
|
71
|
-
|
|
72
|
-
@dos.save_state(out)
|
|
73
|
-
@serial_trap.save_state(out)
|
|
74
|
-
@save_trap.save_state(out)
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def load_trap_dos(input)
|
|
78
|
-
return unmount unless input.boolean?
|
|
79
|
-
|
|
80
|
-
storage = Snapshot::StorageSetup.read(input)
|
|
81
|
-
unmount
|
|
82
|
-
mount(storage)
|
|
83
|
-
@dos.load_state(input)
|
|
84
|
-
@serial_trap.load_state(input)
|
|
85
|
-
@save_trap.load_state(input)
|
|
86
|
-
end
|
|
87
90
|
end
|
|
88
91
|
end
|
|
89
92
|
end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
class C64
|
|
5
|
+
# The whole machine as keyed snapshot modules (Snapshot::Keyed), in the
|
|
6
|
+
# order a load applies them: BL-MACHINE with the setup, the memories,
|
|
7
|
+
# the cartridge, the CPU with its port, the chips with any extra SIDs
|
|
8
|
+
# (Bus::ExtraSIDs), an REU, the datasette, device 8 through the traps
|
|
9
|
+
# and the true drives. A load
|
|
10
|
+
# reads the CPU's port before the chips, so the banks are mapped as the
|
|
11
|
+
# chips load, and the CPU's own fields after them. What each unit works
|
|
12
|
+
# out again from its fields comes last, once every unit is loaded.
|
|
13
|
+
module KeyedModules
|
|
14
|
+
def save_modules
|
|
15
|
+
bus = address_bus
|
|
16
|
+
sections = [Snapshot::Keyed.section("BL-MACHINE") { |out| save_machine_fields(out) },
|
|
17
|
+
Snapshot::Keyed.section("BL-RAM") { |out| bus.ram.save_fields(out, "ram") }]
|
|
18
|
+
expansion = bus.ram_expansion
|
|
19
|
+
sections << Snapshot::Keyed.section("BL-RAMEXP") { |out| expansion.save_fields(out) } if expansion.type
|
|
20
|
+
sections << Snapshot::Keyed.section("BL-COLORRAM") { |out| bus.color_ram.save_fields(out, "ram") }
|
|
21
|
+
cartridge = bus.cartridge
|
|
22
|
+
sections << Snapshot::Keyed.section("BL-CART") { |out| cartridge.save_fields(out) } if cartridge
|
|
23
|
+
save_chip_modules(sections, bus)
|
|
24
|
+
reu = @reu
|
|
25
|
+
sections << Snapshot::Keyed.section("BL-REU") { |out| reu.save_fields(out) } if reu
|
|
26
|
+
sections << Snapshot::Keyed.section("BL-TAPE") { |out| bus.datasette.save_fields(out) }
|
|
27
|
+
sections << Snapshot::Keyed.section("BL-TRAPDOS") { |out| save_trap_dos_fields(out) } if mounted?
|
|
28
|
+
save_drive_modules(sections)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Raises Snapshot::FormatError for the modules of a machine built
|
|
32
|
+
# another way.
|
|
33
|
+
def load_modules(modules)
|
|
34
|
+
machine = modules.machine
|
|
35
|
+
check_snapshot_setup(Snapshot::C64Setup.read_fields(machine))
|
|
36
|
+
load_machine_fields(machine)
|
|
37
|
+
bus = address_bus
|
|
38
|
+
bus.ram.load_fields(modules.required("BL-RAM"), "ram")
|
|
39
|
+
bus.ram_expansion.load_fields(modules.required("BL-RAMEXP")) if bus.ram_expansion.type
|
|
40
|
+
bus.color_ram.load_fields(modules.required("BL-COLORRAM"), "ram")
|
|
41
|
+
load_cartridge_module(modules.optional("BL-CART"))
|
|
42
|
+
cpu = modules.required("BL-CPU")
|
|
43
|
+
bus.load_port_fields(cpu)
|
|
44
|
+
bus.restored!
|
|
45
|
+
load_chip_modules(modules, cpu)
|
|
46
|
+
bus.datasette.load_fields(modules.required("BL-TAPE"))
|
|
47
|
+
load_trap_dos_module(modules)
|
|
48
|
+
load_drive_modules(modules)
|
|
49
|
+
modules_restored!
|
|
50
|
+
self
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def save_chip_modules(sections, bus)
|
|
56
|
+
sections << Snapshot::Keyed.section("BL-CPU") do |out|
|
|
57
|
+
@cpu.save_fields(out)
|
|
58
|
+
bus.save_port_fields(out)
|
|
59
|
+
end
|
|
60
|
+
sections << Snapshot::Keyed.section("BL-VIC") { |out| @vic.save_fields(out) }
|
|
61
|
+
sections << Snapshot::Keyed.section("BL-CIA1") { |out| @cia1.save_fields(out) }
|
|
62
|
+
sections << Snapshot::Keyed.section("BL-CIA2") { |out| @cia2.save_fields(out) }
|
|
63
|
+
sections << Snapshot::Keyed.section("BL-SID") { |out| @sid.save_fields(out) }
|
|
64
|
+
bus.save_extra_sid_modules(sections)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def load_chip_modules(modules, cpu)
|
|
68
|
+
@vic.load_fields(modules.required("BL-VIC"))
|
|
69
|
+
@cia1.load_fields(modules.required("BL-CIA1"))
|
|
70
|
+
@cia2.load_fields(modules.required("BL-CIA2"))
|
|
71
|
+
@sid.load_fields(modules.required("BL-SID"))
|
|
72
|
+
address_bus.load_extra_sid_modules(modules)
|
|
73
|
+
@reu&.load_fields(modules.required("BL-REU"))
|
|
74
|
+
@cpu.load_fields(cpu)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# The cartridge comes back built afresh from the CRT image the module
|
|
78
|
+
# holds, before its state goes in. No module means no cartridge.
|
|
79
|
+
def load_cartridge_module(input)
|
|
80
|
+
if input
|
|
81
|
+
cartridge = Cartridge.from_fields(input)
|
|
82
|
+
connect_cartridge(cartridge)
|
|
83
|
+
cartridge.load_fields(input)
|
|
84
|
+
elsif address_bus.cartridge
|
|
85
|
+
address_bus.detach_cartridge
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def load_trap_dos_module(modules)
|
|
90
|
+
input = modules.optional("BL-TRAPDOS")
|
|
91
|
+
input ? load_trap_dos_fields(input, detached: modules.detached?) : unmount
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def modules_restored!
|
|
95
|
+
@cpu.restored!
|
|
96
|
+
@vic.restored!
|
|
97
|
+
@cia1.restored!
|
|
98
|
+
@cia2.restored!
|
|
99
|
+
@sid.restored!
|
|
100
|
+
address_bus.extra_sids.each(&:restored!)
|
|
101
|
+
@reu&.restored!
|
|
102
|
+
machine_restored!
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def check_snapshot_setup(setup)
|
|
106
|
+
ours = Snapshot::C64Setup.of(address_bus)
|
|
107
|
+
return if setup == ours
|
|
108
|
+
|
|
109
|
+
raise Snapshot::FormatError, "the snapshot is of a machine with #{setup}, not #{ours}"
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
include KeyedModules
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
class C64
|
|
5
|
+
# The machine's own fields in a keyed snapshot module (Snapshot::Keyed,
|
|
6
|
+
# BL-MACHINE): the family, its setup by name, the cycle count, the NMI
|
|
7
|
+
# glue, the freezer's write count and the REU's hold on the bus, and the
|
|
8
|
+
# host's typing still to feed and on_init handlers still to run under
|
|
9
|
+
# host.*. The badline version that wrote it is written for reports and
|
|
10
|
+
# never read.
|
|
11
|
+
module KeyedState
|
|
12
|
+
# How many more on_init handlers the machine a snapshot was taken of had
|
|
13
|
+
# yet to run than this one has: they are the host's blocks, which a
|
|
14
|
+
# snapshot can't hold. Nil until the machine is restored.
|
|
15
|
+
attr_reader :init_handlers_lost
|
|
16
|
+
|
|
17
|
+
# Sets the machine's cycle count, for a snapshot from VICE, which
|
|
18
|
+
# counts from its own clock.
|
|
19
|
+
def resume_at(cycles)
|
|
20
|
+
@cycles = cycles
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Whether a snapshot saves now (Machine::Settling): the CPU between
|
|
24
|
+
# instructions or jammed, and no REU transfer under way.
|
|
25
|
+
def settled_for_snapshot? = (@cpu.boundary? || @cpu.jammed?) && !reu&.dma?
|
|
26
|
+
|
|
27
|
+
# The SID's deferred cycles and writes, run up to this cycle, and the
|
|
28
|
+
# VIC's sprite collisions latched up to the beam.
|
|
29
|
+
def settle_chips_for_snapshot
|
|
30
|
+
sid.catch_up!
|
|
31
|
+
@vic.fold_collisions!
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def save_machine_fields(out)
|
|
35
|
+
out.text("family", "c64").text("written_by", VERSION)
|
|
36
|
+
Snapshot::C64Setup.of(address_bus).write_fields(out)
|
|
37
|
+
out.int("cycles", @cycles).bool("nmi_asserted", @nmi_asserted).bool("cartridge_nmi", @cartridge_nmi)
|
|
38
|
+
out.bool("restore_pulse", @restore_pulse).bool("freezing", @freezing).int("freeze_writes", @freeze_writes)
|
|
39
|
+
out.bool("dma", @dma)
|
|
40
|
+
pending = @pending_keys
|
|
41
|
+
out.ints("host.pending_keys", pending) if pending
|
|
42
|
+
out.int("host.init_pending", booting? ? @init_handlers.length : 0)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def load_machine_fields(input)
|
|
46
|
+
@cycles = input.int("cycles", @cycles)
|
|
47
|
+
@nmi_asserted = input.bool("nmi_asserted", @nmi_asserted)
|
|
48
|
+
@cartridge_nmi = input.bool("cartridge_nmi", @cartridge_nmi)
|
|
49
|
+
@restore_pulse = input.bool("restore_pulse", @restore_pulse)
|
|
50
|
+
@freezing = input.bool("freezing", @freezing)
|
|
51
|
+
@freeze_writes = input.int("freeze_writes", @freeze_writes)
|
|
52
|
+
@dma = input.bool("dma", @dma)
|
|
53
|
+
pending = input.ints("host.pending_keys", [])
|
|
54
|
+
@pending_keys = pending.empty? ? nil : pending.dup
|
|
55
|
+
@init_handlers_lost = [input.int("host.init_pending", 0) - @init_handlers.length, 0].max
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# The REU's IRQ line and the serial bus's lines from CIA 2, once the
|
|
59
|
+
# chips are loaded.
|
|
60
|
+
def machine_restored!
|
|
61
|
+
@reu_irq = @reu.nil? ? false : @reu.irq?
|
|
62
|
+
push_serial_lines
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
include KeyedState
|
|
67
|
+
end
|
|
68
|
+
end
|
data/lib/badline/c64/reu/dma.rb
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "badline/c64/reu/dma/saved_state"
|
|
4
|
-
|
|
5
3
|
module Badline
|
|
6
4
|
class C64
|
|
7
5
|
class REU
|
|
@@ -11,8 +9,6 @@ module Badline
|
|
|
11
9
|
# After a write it goes on through the first BA-low cycle and stops at
|
|
12
10
|
# the second. See doc/pinned-behaviour.md, REU DMA.
|
|
13
11
|
class DMA
|
|
14
|
-
include SavedState
|
|
15
|
-
|
|
16
12
|
# Transfer types, as the command register's bottom two bits give
|
|
17
13
|
# them.
|
|
18
14
|
STASH = 0
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
class C64
|
|
5
|
+
class REU
|
|
6
|
+
class DMA
|
|
7
|
+
# The kinds of transfer, by name.
|
|
8
|
+
TYPE_NAMES = %w[stash fetch swap verify].freeze
|
|
9
|
+
|
|
10
|
+
# A transfer's fields in a keyed snapshot module, under `prefix`.
|
|
11
|
+
# Before the first transfer, the fields it sets on starting are
|
|
12
|
+
# absent.
|
|
13
|
+
module KeyedState
|
|
14
|
+
def save_fields(out, prefix)
|
|
15
|
+
out.int("#{prefix}c64", @c64).int("#{prefix}expansion", @expansion).int("#{prefix}length", @length)
|
|
16
|
+
out.int("#{prefix}events", @events)
|
|
17
|
+
type = @type
|
|
18
|
+
out.text("#{prefix}type", TYPE_NAMES.fetch(type)) unless type.nil?
|
|
19
|
+
out.optional_int("#{prefix}c64_step", @c64_step).optional_int("#{prefix}expansion_step", @expansion_step)
|
|
20
|
+
out.optional_int("#{prefix}last", @last).optional_int("#{prefix}ba_low_after_writes", @ba_low_after_writes)
|
|
21
|
+
out.optional_int("#{prefix}swap_byte", @swap_byte).optional_int("#{prefix}held_read", @held_read)
|
|
22
|
+
save_flag_fields(out, prefix)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def load_fields(input, prefix)
|
|
26
|
+
@c64 = input.word("#{prefix}c64", @c64)
|
|
27
|
+
@expansion = input.int("#{prefix}expansion", @expansion)
|
|
28
|
+
@length = input.int("#{prefix}length", @length)
|
|
29
|
+
@events = input.int("#{prefix}events", @events)
|
|
30
|
+
type = input.choice("#{prefix}type", TYPE_NAMES + ["none"], "none")
|
|
31
|
+
@type = type == "none" ? nil : TYPE_NAMES.index(type)
|
|
32
|
+
@c64_step = input.optional_int("#{prefix}c64_step")
|
|
33
|
+
@expansion_step = input.optional_int("#{prefix}expansion_step")
|
|
34
|
+
@last = input.optional_int("#{prefix}last")
|
|
35
|
+
@ba_low_after_writes = input.optional_int("#{prefix}ba_low_after_writes")
|
|
36
|
+
@swap_byte = input.optional_int("#{prefix}swap_byte")
|
|
37
|
+
@held_read = input.optional_int("#{prefix}held_read")
|
|
38
|
+
load_flag_fields(input, prefix)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def save_flag_fields(out, prefix)
|
|
44
|
+
out.bool("#{prefix}holding", @holding).bool("#{prefix}waiting", @waiting)
|
|
45
|
+
out.bool("#{prefix}stopped_after_write", @stopped_after_write)
|
|
46
|
+
out.bool("#{prefix}swap_write_due", @swap_write_due).bool("#{prefix}swap_read_again", @swap_read_again)
|
|
47
|
+
out.bool("#{prefix}moved_all", @moved_all).bool("#{prefix}extra_cycle", @extra_cycle)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def load_flag_fields(input, prefix)
|
|
51
|
+
@holding = input.bool("#{prefix}holding", @holding)
|
|
52
|
+
@waiting = input.bool("#{prefix}waiting", @waiting)
|
|
53
|
+
@stopped_after_write = input.bool("#{prefix}stopped_after_write", @stopped_after_write)
|
|
54
|
+
@swap_write_due = input.bool("#{prefix}swap_write_due", @swap_write_due)
|
|
55
|
+
@swap_read_again = input.bool("#{prefix}swap_read_again", @swap_read_again)
|
|
56
|
+
@moved_all = input.bool("#{prefix}moved_all", @moved_all)
|
|
57
|
+
@extra_cycle = input.bool("#{prefix}extra_cycle", @extra_cycle)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
include KeyedState
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
class RAM
|
|
65
|
+
# The data latch and each bank the REC has touched, as bank<N>; a
|
|
66
|
+
# bank left out holds its power-on contents.
|
|
67
|
+
module KeyedState
|
|
68
|
+
def save_fields(out)
|
|
69
|
+
out.int("latch", @latch)
|
|
70
|
+
@banks.each_with_index { |bank, number| out.bytes("bank#{number}", bank) unless bank.empty? }
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def load_fields(input)
|
|
74
|
+
@latch = input.byte("latch", @latch)
|
|
75
|
+
@banks.each_index do |number|
|
|
76
|
+
@banks[number] = input.bytes("bank#{number}", "".b).bytes
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
include KeyedState
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# The REU's fields in a keyed snapshot module (Snapshot::Keyed): the
|
|
85
|
+
# REC's registers and the values its counters start from, an armed or
|
|
86
|
+
# running transfer, the transfer under dma.*, and the RAM. The IRQ
|
|
87
|
+
# line comes from the status register on load.
|
|
88
|
+
module KeyedState
|
|
89
|
+
# The REU's size in K, which the machine's setup names.
|
|
90
|
+
def size_kb = @size_kb
|
|
91
|
+
|
|
92
|
+
def save_fields(out)
|
|
93
|
+
out.int("status", @status).int("command", @command).int("c64", @c64).int("c64_start", @c64_start)
|
|
94
|
+
out.int("expansion", @expansion).int("expansion_start", @expansion_start).int("bank", @bank)
|
|
95
|
+
out.int("bank_start", @bank_start).int("length", @length).int("length_start", @length_start)
|
|
96
|
+
out.int("interrupt_mask", @interrupt_mask).int("address_control", @address_control)
|
|
97
|
+
out.bool("armed", @armed).bool("requested", @requested).bool("running", @running)
|
|
98
|
+
out.bool("ba_was_low", @ba_was_low)
|
|
99
|
+
@dma.save_fields(out, "dma.")
|
|
100
|
+
@ram.save_fields(out)
|
|
101
|
+
out
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def load_fields(input)
|
|
105
|
+
load_register_fields(input)
|
|
106
|
+
@armed = input.bool("armed", @armed)
|
|
107
|
+
@requested = input.bool("requested", @requested)
|
|
108
|
+
@running = input.bool("running", @running)
|
|
109
|
+
@ba_was_low = input.bool("ba_was_low", @ba_was_low)
|
|
110
|
+
@dma.load_fields(input, "dma.")
|
|
111
|
+
@ram.load_fields(input)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Without calling back into the machine, which reads the line again.
|
|
115
|
+
def restored!
|
|
116
|
+
@irq = @status.anybits?(INTERRUPT_PENDING)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
private
|
|
120
|
+
|
|
121
|
+
def load_register_fields(input)
|
|
122
|
+
@status = input.byte("status", @status)
|
|
123
|
+
@command = input.byte("command", @command)
|
|
124
|
+
@c64 = input.word("c64", @c64)
|
|
125
|
+
@c64_start = input.word("c64_start", @c64_start)
|
|
126
|
+
@expansion = input.word("expansion", @expansion)
|
|
127
|
+
@expansion_start = input.word("expansion_start", @expansion_start)
|
|
128
|
+
@bank = input.byte("bank", @bank)
|
|
129
|
+
@bank_start = input.byte("bank_start", @bank_start)
|
|
130
|
+
@length = input.word("length", @length)
|
|
131
|
+
@length_start = input.word("length_start", @length_start)
|
|
132
|
+
@interrupt_mask = input.byte("interrupt_mask", @interrupt_mask)
|
|
133
|
+
@address_control = input.byte("address_control", @address_control)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
include KeyedState
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
data/lib/badline/c64/reu/ram.rb
CHANGED
|
@@ -38,21 +38,6 @@ module Badline
|
|
|
38
38
|
bank(addr >> 16)[addr & 0xffff] = value if addr < @size
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
# The latch, and each 64K bank the REC has touched. A bank it hasn't
|
|
42
|
-
# keeps its power-on contents until it does.
|
|
43
|
-
def save_state(out)
|
|
44
|
-
out.int(@latch)
|
|
45
|
-
@banks.each do |bank|
|
|
46
|
-
out.boolean(!bank.empty?)
|
|
47
|
-
out.blob(bank) unless bank.empty?
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def load_state(input)
|
|
52
|
-
@latch = input.int
|
|
53
|
-
@banks.each_index { |number| @banks[number] = input.boolean? ? input.blob : [] }
|
|
54
|
-
end
|
|
55
|
-
|
|
56
41
|
# Every byte, as one string, with a bank the REC hasn't touched at
|
|
57
42
|
# its power-on contents.
|
|
58
43
|
def contents
|
data/lib/badline/c64/reu.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require "badline/c64/reu/ram"
|
|
4
4
|
require "badline/c64/reu/dma"
|
|
5
5
|
require "badline/c64/reu/trigger"
|
|
6
|
-
require "badline/c64/reu/
|
|
6
|
+
require "badline/c64/reu/keyed_state"
|
|
7
7
|
|
|
8
8
|
module Badline
|
|
9
9
|
class C64
|
|
@@ -20,8 +20,6 @@ module Badline
|
|
|
20
20
|
# waits for the CPU's next read cycle with BA high, and C64 then
|
|
21
21
|
# clocks it through #dma_cycle! until it hands the bus back.
|
|
22
22
|
class REU
|
|
23
|
-
include SavedState
|
|
24
|
-
|
|
25
23
|
SIZES_KB = [128, 256, 512, 1024, 2048, 4096, 8192, 16_384].freeze
|
|
26
24
|
|
|
27
25
|
# The registers, by offset.
|
|
@@ -8,6 +8,9 @@ module Badline
|
|
|
8
8
|
module TrueDrives
|
|
9
9
|
include Drives::Model1581::Slot
|
|
10
10
|
|
|
11
|
+
# The true drive models a snapshot names.
|
|
12
|
+
DRIVE_MODELS = %w[1541 1571 1581].freeze
|
|
13
|
+
|
|
11
14
|
# Plugs in a Drives::Model1541, which then runs alongside the machine on its
|
|
12
15
|
# own clock and talks to it over the serial bus. The serial traps stop
|
|
13
16
|
# answering the drive's device number, so the KERNAL's TALK, LISTEN and
|
|
@@ -33,6 +36,35 @@ module Badline
|
|
|
33
36
|
Drives::Model1541.new.tap { |drive| attach_drive1541(drive) }
|
|
34
37
|
end
|
|
35
38
|
|
|
39
|
+
# The true drives as keyed snapshot modules, each named from its device
|
|
40
|
+
# number: BL-D8, BL-D8-CPU and so on for device 8.
|
|
41
|
+
def save_drive_modules(sections)
|
|
42
|
+
drive1541 = @drive1541
|
|
43
|
+
drive1541&.save_modules(sections, "BL-D#{drive1541.device}")
|
|
44
|
+
drive1581 = @drive1581
|
|
45
|
+
drive1581&.save_modules(sections, "BL-D#{drive1581.device}")
|
|
46
|
+
save_drive1571_modules(sections)
|
|
47
|
+
sections
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# The true drives a snapshot's modules hold, built afresh unless the
|
|
51
|
+
# same model is on the bus as the same device. A drive the snapshot
|
|
52
|
+
# doesn't have comes off the bus.
|
|
53
|
+
def load_drive_modules(modules)
|
|
54
|
+
models = []
|
|
55
|
+
8.upto(11) do |device|
|
|
56
|
+
input = modules.optional("BL-D#{device}")
|
|
57
|
+
next unless input
|
|
58
|
+
|
|
59
|
+
model = input.choice("model", DRIVE_MODELS, "1541")
|
|
60
|
+
load_drive_model(modules, input, device, model)
|
|
61
|
+
models << model
|
|
62
|
+
end
|
|
63
|
+
detach_drive1541 unless models.include?("1541")
|
|
64
|
+
detach_drive1581 unless models.include?("1581")
|
|
65
|
+
detach_drive1571 unless models.include?("1571")
|
|
66
|
+
end
|
|
67
|
+
|
|
36
68
|
# Unplugs the Drives::Model1541, leaving the serial bus with nothing on it.
|
|
37
69
|
def detach_drive1541
|
|
38
70
|
return unless @drive1541
|
|
@@ -55,15 +87,34 @@ module Badline
|
|
|
55
87
|
# for its DOS to boot before typing.
|
|
56
88
|
def drive1541_attached = nil
|
|
57
89
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
90
|
+
def load_drive_model(modules, input, device, model)
|
|
91
|
+
case model
|
|
92
|
+
when "1581" then load_drive1581_modules(modules, input, device)
|
|
93
|
+
when "1571" then load_drive1571_modules(modules, input, device)
|
|
94
|
+
else load_drive1541_modules(modules, input, device)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
61
97
|
|
|
62
|
-
|
|
98
|
+
def load_drive1541_modules(modules, input, device)
|
|
63
99
|
detach_drive1541 if @drive1541 && @drive1541.device != device
|
|
64
100
|
attach_drive1541(Drives::Model1541.new(device:)) unless @drive1541
|
|
65
|
-
@drive1541.
|
|
101
|
+
@drive1541.load_modules(modules, input, "BL-D#{device}")
|
|
66
102
|
end
|
|
103
|
+
|
|
104
|
+
def load_drive1581_modules(modules, input, device)
|
|
105
|
+
detach_drive1581 if @drive1581 && @drive1581.device != device
|
|
106
|
+
attach_drive1581(Drives::Model1581.new(device:)) unless @drive1581
|
|
107
|
+
@drive1581.load_modules(modules, input, "BL-D#{device}")
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# The C128D's 1571, which only the C128 has (C128::Drives).
|
|
111
|
+
def save_drive1571_modules(sections) = sections
|
|
112
|
+
|
|
113
|
+
def load_drive1571_modules(_modules, input, _device)
|
|
114
|
+
input.adjust("a 1571 doesn't plug into this machine, left out")
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def detach_drive1571 = nil
|
|
67
118
|
end
|
|
68
119
|
end
|
|
69
120
|
end
|
data/lib/badline/c64.rb
CHANGED
|
@@ -4,17 +4,18 @@ require "badline/c64/common"
|
|
|
4
4
|
require "badline/c64/true_drives"
|
|
5
5
|
require "badline/c64/attachments"
|
|
6
6
|
require "badline/c64/kernal_traps"
|
|
7
|
-
require "badline/c64/
|
|
7
|
+
require "badline/c64/keyed_state"
|
|
8
|
+
require "badline/c64/keyed_modules"
|
|
8
9
|
|
|
9
10
|
module Badline
|
|
10
11
|
class C64
|
|
11
12
|
include IntegerHelper
|
|
12
|
-
include KeyboardBuffer
|
|
13
|
+
include Machine::KeyboardBuffer
|
|
13
14
|
include Machine::Clocking
|
|
15
|
+
include Machine::Settling
|
|
14
16
|
include Common
|
|
15
17
|
include Attachments
|
|
16
18
|
include KernalTraps
|
|
17
|
-
include SavedState
|
|
18
19
|
|
|
19
20
|
attr_reader :address_bus, :cpu, :cycles, :drive1541
|
|
20
21
|
|
|
@@ -188,6 +189,9 @@ module Badline
|
|
|
188
189
|
# The KERNAL the traps stand in for (KernalTraps#mount).
|
|
189
190
|
def trap_layout = KernalTrap::C64_LAYOUT
|
|
190
191
|
|
|
192
|
+
# The KERNAL's keyboard buffer, which #type_text feeds.
|
|
193
|
+
def keyboard_buffer = Machine::KeyboardBuffer::C64_LAYOUT
|
|
194
|
+
|
|
191
195
|
def trap_bus = address_bus
|
|
192
196
|
|
|
193
197
|
def plug_reu(size_kb)
|
|
@@ -35,23 +35,6 @@ module Badline
|
|
|
35
35
|
|
|
36
36
|
def interrupted? = status.value >= 0x80
|
|
37
37
|
|
|
38
|
-
def save_state(out)
|
|
39
|
-
out.int(@mask.value).int(@status.value).int(@pending)
|
|
40
|
-
[@read, @read_last_cycle, @read_two_cycles_ago].each { |read| out.optional_int(read) }
|
|
41
|
-
out.boolean(@timer_b_bug).boolean(@quiet)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def load_state(input)
|
|
45
|
-
@mask.value = input.int
|
|
46
|
-
@status.value = input.int
|
|
47
|
-
@pending = input.int
|
|
48
|
-
@read = input.optional_int
|
|
49
|
-
@read_last_cycle = input.optional_int
|
|
50
|
-
@read_two_cycles_ago = input.optional_int
|
|
51
|
-
@timer_b_bug = input.boolean?
|
|
52
|
-
@quiet = input.boolean?
|
|
53
|
-
end
|
|
54
|
-
|
|
55
38
|
# Raises IR on this cycle.
|
|
56
39
|
def assert_now
|
|
57
40
|
status.interrupt = true
|