badline 0.13.0 → 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.
Files changed (254) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +49 -1
  3. data/CLAUDE.md +27 -7
  4. data/CONTRIBUTING.md +4 -3
  5. data/README.md +8 -5
  6. data/doc/media.md +2 -1
  7. data/doc/pinned-behaviour.md +29 -0
  8. data/doc/snapshot-format.md +1047 -0
  9. data/doc/snapshots.md +72 -39
  10. data/lib/badline/audio/bare_player.rb +50 -17
  11. data/lib/badline/audio/machine_player.rb +15 -9
  12. data/lib/badline/audio/renderer.rb +32 -21
  13. data/lib/badline/c128/banks.rb +6 -3
  14. data/lib/badline/c128/bus/keyed_state.rb +45 -0
  15. data/lib/badline/c128/bus.rb +17 -3
  16. data/lib/badline/c128/drives.rb +6 -25
  17. data/lib/badline/c128/keyed_modules.rb +117 -0
  18. data/lib/badline/c128/keyed_state.rb +91 -0
  19. data/lib/badline/c128/keys.rb +9 -0
  20. data/lib/badline/c128/mmu.rb +9 -8
  21. data/lib/badline/c128/mmu_pages.rb +20 -0
  22. data/lib/badline/c128/modes.rb +19 -9
  23. data/lib/badline/c128/z80_turns.rb +1 -1
  24. data/lib/badline/c128.rb +8 -8
  25. data/lib/badline/c64/attachments.rb +0 -44
  26. data/lib/badline/c64/banked_ram/plus256k.rb +18 -10
  27. data/lib/badline/c64/banked_ram/plus60k.rb +8 -6
  28. data/lib/badline/c64/banked_ram/unexpanded.rb +2 -2
  29. data/lib/badline/c64/bus/debug_register.rb +32 -0
  30. data/lib/badline/c64/bus/keyed_state.rb +41 -0
  31. data/lib/badline/c64/bus.rb +2 -1
  32. data/lib/badline/c64/cartridge/action_replay.rb +0 -13
  33. data/lib/badline/c64/cartridge/easy_flash.rb +0 -15
  34. data/lib/badline/c64/cartridge/epyx_fastload.rb +0 -8
  35. data/lib/badline/c64/cartridge/final_cartridge3.rb +0 -12
  36. data/lib/badline/c64/cartridge/flash.rb +3 -3
  37. data/lib/badline/c64/cartridge/g_mod2.rb +0 -12
  38. data/lib/badline/c64/cartridge/geo_ram.rb +0 -16
  39. data/lib/badline/c64/cartridge/kcs_power.rb +0 -8
  40. data/lib/badline/c64/cartridge/keyed_state.rb +393 -0
  41. data/lib/badline/c64/cartridge/pagefox.rb +0 -10
  42. data/lib/badline/c64/cartridge/retro_replay.rb +0 -8
  43. data/lib/badline/c64/cartridge/rgcd.rb +0 -10
  44. data/lib/badline/c64/cartridge/super_games.rb +0 -10
  45. data/lib/badline/c64/cartridge/zaxxon.rb +0 -16
  46. data/lib/badline/c64/cartridge.rb +1 -27
  47. data/lib/badline/c64/kernal_traps.rb +28 -25
  48. data/lib/badline/c64/keyed_modules.rb +111 -0
  49. data/lib/badline/c64/keyed_state.rb +68 -0
  50. data/lib/badline/c64/reu/dma.rb +0 -4
  51. data/lib/badline/c64/reu/keyed_state.rb +140 -0
  52. data/lib/badline/c64/reu/ram.rb +0 -15
  53. data/lib/badline/c64/reu.rb +1 -3
  54. data/lib/badline/c64/true_drives.rb +56 -5
  55. data/lib/badline/c64.rb +7 -3
  56. data/lib/badline/chips/cia/interrupt_register.rb +0 -17
  57. data/lib/badline/chips/cia/keyed_parts.rb +213 -0
  58. data/lib/badline/chips/cia/serial.rb +0 -4
  59. data/lib/badline/chips/cia/time_of_day.rb +0 -22
  60. data/lib/badline/chips/cia/timer.rb +0 -20
  61. data/lib/badline/chips/cia.rb +2 -2
  62. data/lib/badline/chips/cpu/core.rb +18 -2
  63. data/lib/badline/chips/cpu/keyed_state.rb +177 -0
  64. data/lib/badline/chips/cpu/microcode.rb +16 -0
  65. data/lib/badline/chips/cpu/port.rb +20 -3
  66. data/lib/badline/chips/cpu.rb +5 -0
  67. data/lib/badline/chips/sid/decimator.rb +10 -8
  68. data/lib/badline/chips/sid/envelope.rb +1 -6
  69. data/lib/badline/chips/sid/filter.rb +0 -14
  70. data/lib/badline/chips/sid/keyed_parts.rb +286 -0
  71. data/lib/badline/chips/sid/voice.rb +0 -10
  72. data/lib/badline/chips/sid/waveform.rb +0 -2
  73. data/lib/badline/chips/sid.rb +1 -2
  74. data/lib/badline/chips/ted/beam.rb +119 -0
  75. data/lib/badline/chips/ted/timers.rb +66 -0
  76. data/lib/badline/chips/ted.rb +143 -0
  77. data/lib/badline/chips/tia.rb +49 -0
  78. data/lib/badline/chips/vdc/keyed_parts.rb +105 -0
  79. data/lib/badline/chips/vdc/painter.rb +0 -12
  80. data/lib/badline/chips/vdc/raster.rb +0 -16
  81. data/lib/badline/chips/vdc/window.rb +0 -9
  82. data/lib/badline/chips/vdc.rb +1 -2
  83. data/lib/badline/chips/via/control_lines.rb +0 -15
  84. data/lib/badline/chips/via/interrupt_register.rb +0 -9
  85. data/lib/badline/chips/via/keyed_parts.rb +163 -0
  86. data/lib/badline/chips/via/shift_register.rb +0 -14
  87. data/lib/badline/chips/via/timer1.rb +0 -13
  88. data/lib/badline/chips/via/timer2.rb +0 -18
  89. data/lib/badline/chips/via.rb +1 -2
  90. data/lib/badline/chips/vic/border_mask.rb +0 -10
  91. data/lib/badline/chips/vic/collisions.rb +0 -11
  92. data/lib/badline/chips/vic/color_patches.rb +0 -11
  93. data/lib/badline/chips/vic/display_state.rb +0 -19
  94. data/lib/badline/chips/vic/graphics_shifter.rb +0 -4
  95. data/lib/badline/chips/vic/keyed_parts.rb +228 -0
  96. data/lib/badline/chips/vic/keyed_sprites.rb +225 -0
  97. data/lib/badline/chips/vic/keyed_state.rb +102 -0
  98. data/lib/badline/chips/vic/register_log.rb +0 -18
  99. data/lib/badline/chips/vic/registers.rb +0 -9
  100. data/lib/badline/chips/vic/sequencer.rb +0 -2
  101. data/lib/badline/chips/vic/sprite/internal_bus.rb +0 -11
  102. data/lib/badline/chips/vic/sprite.rb +0 -2
  103. data/lib/badline/chips/vic/sprites.rb +0 -3
  104. data/lib/badline/chips/vic.rb +6 -2
  105. data/lib/badline/chips/vic_i/keyed_parts.rb +142 -0
  106. data/lib/badline/chips/vic_i/painter.rb +0 -4
  107. data/lib/badline/chips/vic_i/sound.rb +38 -46
  108. data/lib/badline/chips/vic_i.rb +2 -2
  109. data/lib/badline/chips/z80/core.rb +2 -2
  110. data/lib/badline/chips/z80/keyed_state.rb +73 -0
  111. data/lib/badline/chips.rb +10 -0
  112. data/lib/badline/core.rb +4 -21
  113. data/lib/badline/drives/datasette/keyed_state.rb +38 -0
  114. data/lib/badline/drives/datasette.rb +40 -7
  115. data/lib/badline/drives/engine/core.rb +3 -0
  116. data/lib/badline/drives/engine/serial_lines.rb +4 -7
  117. data/lib/badline/drives/model1541/bus.rb +0 -13
  118. data/lib/badline/drives/model1541/disk.rb +9 -8
  119. data/lib/badline/drives/model1541/keyed_state.rb +251 -0
  120. data/lib/badline/drives/model1541/mechanism.rb +0 -2
  121. data/lib/badline/drives/model1541.rb +1 -2
  122. data/lib/badline/drives/model1571/bus.rb +0 -13
  123. data/lib/badline/drives/model1571/keyed_state.rb +108 -0
  124. data/lib/badline/drives/model1571/wd1770.rb +0 -14
  125. data/lib/badline/drives/model1571.rb +1 -2
  126. data/lib/badline/drives/model1581/bus.rb +0 -13
  127. data/lib/badline/drives/model1581/disk.rb +0 -4
  128. data/lib/badline/drives/model1581/keyed_state.rb +280 -0
  129. data/lib/badline/drives/model1581/mechanism.rb +0 -21
  130. data/lib/badline/drives/model1581/slot.rb +0 -18
  131. data/lib/badline/drives/model1581/wd1772.rb +0 -2
  132. data/lib/badline/drives/model1581.rb +2 -2
  133. data/lib/badline/drives.rb +8 -0
  134. data/lib/badline/frontend/app.rb +3 -3
  135. data/lib/badline/frontend/boot.rb +1 -1
  136. data/lib/badline/frontend/controls.rb +19 -3
  137. data/lib/badline/frontend/drive_led.rb +44 -21
  138. data/lib/badline/frontend/menu/menu_dialogs.rb +2 -2
  139. data/lib/badline/frontend/snapshots.rb +12 -1
  140. data/lib/badline/frontend/timeline.rb +28 -10
  141. data/lib/badline/input/matrix_typist.rb +98 -0
  142. data/lib/badline/input.rb +1 -0
  143. data/lib/badline/kernal_trap/chrout.rb +45 -0
  144. data/lib/badline/kernal_trap/dos/channel.rb +0 -27
  145. data/lib/badline/kernal_trap/dos/channels.rb +0 -25
  146. data/lib/badline/kernal_trap/dos/memory.rb +0 -9
  147. data/lib/badline/kernal_trap/dos/status.rb +0 -8
  148. data/lib/badline/kernal_trap/dos/write_file.rb +0 -18
  149. data/lib/badline/kernal_trap/dos.rb +0 -19
  150. data/lib/badline/kernal_trap/file_routine.rb +4 -4
  151. data/lib/badline/kernal_trap/keyed_state.rb +150 -0
  152. data/lib/badline/kernal_trap/layout.rb +75 -11
  153. data/lib/badline/kernal_trap/load.rb +14 -16
  154. data/lib/badline/kernal_trap/routine.rb +12 -0
  155. data/lib/badline/kernal_trap/save.rb +8 -18
  156. data/lib/badline/kernal_trap/serial.rb +1 -17
  157. data/lib/badline/kernal_trap.rb +2 -0
  158. data/lib/badline/machine/keyboard_buffer.rb +49 -0
  159. data/lib/badline/machine/settling.rb +29 -0
  160. data/lib/badline/machine.rb +5 -2
  161. data/lib/badline/media/boot_disk.rb +14 -2
  162. data/lib/badline/media/extensions.rb +10 -0
  163. data/lib/badline/memory.rb +3 -6
  164. data/lib/badline/options/family.rb +5 -2
  165. data/lib/badline/options/help.rb +42 -16
  166. data/lib/badline/options/table.rb +2 -0
  167. data/lib/badline/options/validation.rb +2 -0
  168. data/lib/badline/options.rb +6 -1
  169. data/lib/badline/plus4/acia.rb +45 -0
  170. data/lib/badline/plus4/bus.rb +312 -0
  171. data/lib/badline/plus4/cpu.rb +10 -0
  172. data/lib/badline/plus4/cpu_port.rb +93 -0
  173. data/lib/badline/plus4/keyboard_port.rb +51 -0
  174. data/lib/badline/plus4/model.rb +38 -0
  175. data/lib/badline/plus4/user_port.rb +31 -0
  176. data/lib/badline/plus4.rb +164 -0
  177. data/lib/badline/roms/README +38 -0
  178. data/lib/badline/roms/plus4/basic.rom +0 -0
  179. data/lib/badline/roms/plus4/function-high.rom +0 -0
  180. data/lib/badline/roms/plus4/function-low.rom +0 -0
  181. data/lib/badline/roms/plus4/kernal-ntsc.rom +0 -0
  182. data/lib/badline/roms/plus4/kernal-pal.rom +0 -0
  183. data/lib/badline/snapshot/c128_setup.rb +9 -20
  184. data/lib/badline/snapshot/c64_setup.rb +28 -24
  185. data/lib/badline/snapshot/container.rb +4 -0
  186. data/lib/badline/snapshot/field_doc/markdown.rb +112 -0
  187. data/lib/badline/snapshot/field_doc.rb +109 -0
  188. data/lib/badline/snapshot/image.rb +134 -28
  189. data/lib/badline/snapshot/keyed/cursor.rb +40 -0
  190. data/lib/badline/snapshot/keyed/modules.rb +66 -0
  191. data/lib/badline/snapshot/keyed/reader.rb +188 -0
  192. data/lib/badline/snapshot/keyed/recorder.rb +88 -0
  193. data/lib/badline/snapshot/keyed/report.rb +26 -0
  194. data/lib/badline/snapshot/keyed/writer.rb +55 -0
  195. data/lib/badline/snapshot/keyed.rb +64 -0
  196. data/lib/badline/snapshot/machine_state.rb +17 -64
  197. data/lib/badline/snapshot/storage_setup.rb +29 -34
  198. data/lib/badline/snapshot/vic20_setup.rb +6 -15
  199. data/lib/badline/snapshot/vice/reu1764.rb +2 -2
  200. data/lib/badline/snapshot/vice.rb +7 -31
  201. data/lib/badline/snapshot.rb +43 -20
  202. data/lib/badline/storage/crt_file.rb +3 -1
  203. data/lib/badline/storage/g64_image.rb +8 -3
  204. data/lib/badline/storage/tap.rb +43 -15
  205. data/lib/badline/version.rb +1 -1
  206. data/lib/badline/vic20/attachments.rb +3 -0
  207. data/lib/badline/vic20/bus/keyed_state.rb +52 -0
  208. data/lib/badline/vic20/bus.rb +1 -2
  209. data/lib/badline/vic20/keyed_modules.rb +73 -0
  210. data/lib/badline/vic20/keyed_state.rb +45 -0
  211. data/lib/badline/vic20.rb +5 -5
  212. data/lib/badline.rb +1 -0
  213. metadata +61 -42
  214. data/lib/badline/c128/bus/saved_state.rb +0 -53
  215. data/lib/badline/c128/saved_state.rb +0 -117
  216. data/lib/badline/c64/bus/saved_state.rb +0 -68
  217. data/lib/badline/c64/cartridge/flash/saved_state.rb +0 -40
  218. data/lib/badline/c64/cartridge/retro_replay/saved_state.rb +0 -47
  219. data/lib/badline/c64/cartridge/saved_state.rb +0 -63
  220. data/lib/badline/c64/reu/dma/saved_state.rb +0 -52
  221. data/lib/badline/c64/reu/saved_state.rb +0 -55
  222. data/lib/badline/c64/saved_state.rb +0 -112
  223. data/lib/badline/chips/cia/saved_state.rb +0 -49
  224. data/lib/badline/chips/cia/serial/saved_state.rb +0 -45
  225. data/lib/badline/chips/cpu/saved_state.rb +0 -117
  226. data/lib/badline/chips/sid/envelope/saved_state.rb +0 -70
  227. data/lib/badline/chips/sid/filter/saved_state.rb +0 -42
  228. data/lib/badline/chips/sid/saved_state.rb +0 -52
  229. data/lib/badline/chips/sid/waveform/saved_state.rb +0 -68
  230. data/lib/badline/chips/vdc/saved_state.rb +0 -36
  231. data/lib/badline/chips/via/saved_state.rb +0 -44
  232. data/lib/badline/chips/vic/graphics_shifter/saved_state.rb +0 -40
  233. data/lib/badline/chips/vic/saved_state.rb +0 -82
  234. data/lib/badline/chips/vic/sequencer/saved_state.rb +0 -91
  235. data/lib/badline/chips/vic/sprite/saved_state.rb +0 -66
  236. data/lib/badline/chips/vic/sprites/saved_state.rb +0 -59
  237. data/lib/badline/chips/vic_i/painter/saved_state.rb +0 -40
  238. data/lib/badline/chips/vic_i/saved_state.rb +0 -55
  239. data/lib/badline/chips/z80/saved_state.rb +0 -71
  240. data/lib/badline/chrout_trap.rb +0 -43
  241. data/lib/badline/debug_register.rb +0 -28
  242. data/lib/badline/drives/datasette/saved_state.rb +0 -37
  243. data/lib/badline/drives/model1541/disk/saved_state.rb +0 -88
  244. data/lib/badline/drives/model1541/mechanism/saved_state.rb +0 -72
  245. data/lib/badline/drives/model1541/saved_state.rb +0 -44
  246. data/lib/badline/drives/model1571/saved_state.rb +0 -47
  247. data/lib/badline/drives/model1581/disk/saved_state.rb +0 -89
  248. data/lib/badline/drives/model1581/saved_state.rb +0 -42
  249. data/lib/badline/drives/model1581/wd1772/saved_state.rb +0 -68
  250. data/lib/badline/keyboard_buffer.rb +0 -33
  251. data/lib/badline/snapshot/setup.rb +0 -31
  252. data/lib/badline/snapshot/state.rb +0 -179
  253. data/lib/badline/vic20/bus/saved_state.rb +0 -35
  254. data/lib/badline/vic20/saved_state.rb +0 -110
@@ -1,117 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "badline/snapshot/c128_setup"
4
-
5
- module Badline
6
- class C128
7
- # How the machine a State from #snapshot was taken of was built.
8
- def self.setup(state) = Snapshot::C128Setup.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, FAST and TEST as they last took hold, the bus with its RAM, the MMU, the chips and
16
- # the VDC, the CPU, the cartridge, the disk device 8 serves through the
17
- # traps and a true 1541. The serial lines go back into the bus from the
18
- # restored CIA 2. What the host holds stays out: the keyboard, the
19
- # joysticks, CAPS LOCK and 40/80 DISPLAY, the traps and callbacks, and
20
- # which chip renders.
21
- module SavedState
22
- # How many more on_init handlers the machine a State was taken of had
23
- # yet to run than this one has. Nil until the machine is restored.
24
- attr_reader :init_handlers_lost
25
-
26
- def snapshot
27
- out = Snapshot::StateWriter.new
28
- save_state(out)
29
- out.state
30
- end
31
-
32
- # Takes the machine back to a State from #snapshot, trying it on a new
33
- # machine first, so one that fails leaves this machine as it was.
34
- # Raises Snapshot::FormatError for a state of another model or SID.
35
- def restore(state)
36
- check_setup(C128.setup(state))
37
- C128.restored(state)
38
- apply_state(state)
39
- end
40
-
41
- # Puts a State into the machine without trying it on a new one first.
42
- def apply_state(state)
43
- input = Snapshot::StateReader.new(state)
44
- load_state(input)
45
- raise Snapshot::FormatError, "the state goes on past the machine" unless input.finished?
46
-
47
- self
48
- end
49
-
50
- def save_state(out)
51
- out.marker(Snapshot::C128Setup::MARKER).stamp
52
- snapshot_setup.write(out)
53
- out.int(@cycles).int(@clock_bits).boolean(@nmi_asserted).boolean(@cartridge_nmi).boolean(@restore_pulse)
54
- out.boolean(!@pending_keys.nil?)
55
- out.ints(@pending_keys) if @pending_keys
56
- out.int(@cycles <= init_threshold ? @init_handlers.length : 0)
57
- save_cartridge(out)
58
- @bus.save_state(out)
59
- @cpu.save_state(out)
60
- @z80.save_state(out)
61
- out.int(@z80_due).int(@chips_ahead).boolean(@cpu_reset_pending)
62
- save_trap_dos(out)
63
- save_serial_bus(out)
64
- end
65
-
66
- def load_state(input)
67
- input.marker(Snapshot::C128Setup::MARKER)
68
- input.check_stamp
69
- check_setup(Snapshot::C128Setup.read(input))
70
- @cycles = input.int
71
- @clock_bits = input.int
72
- @nmi_asserted = input.boolean?
73
- @cartridge_nmi = input.boolean?
74
- @restore_pulse = input.boolean?
75
- @pending_keys = nil
76
- @pending_keys = input.ints if input.boolean?
77
- @init_handlers_lost = [input.int - @init_handlers.length, 0].max
78
- load_cartridge(input)
79
- @cpu_reset_pending = false
80
- @bus.load_state(input)
81
- push_serial_lines
82
- @cpu.load_state(input)
83
- load_z80(input)
84
- load_trap_dos(input)
85
- load_serial_bus(input)
86
- push_fast_serial
87
- end
88
-
89
- private
90
-
91
- # The Z80 and which CPU has the bus. The bus, restored before it,
92
- # hands the bus to its CPU without resetting the 8502.
93
- def load_z80(input)
94
- @z80_running = @bus.z80?
95
- @z80.load_state(input)
96
- @z80_due = input.int
97
- @chips_ahead = input.int
98
- @cpu_reset_pending = input.boolean?
99
- @z80_turn = @z80_running || @chips_ahead.positive?
100
- end
101
-
102
- # How this machine was built.
103
- def snapshot_setup
104
- Snapshot::C128Setup.new(model: @model.name, sid_model: @sid.model, mode: @c64_built ? :c64 : :c128)
105
- end
106
-
107
- def check_setup(setup)
108
- ours = snapshot_setup
109
- return if setup == ours
110
-
111
- raise Snapshot::FormatError, "the state is of a #{setup}, not a #{ours}"
112
- end
113
- end
114
-
115
- include SavedState
116
- end
117
- end
@@ -1,68 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class C64
5
- class Bus
6
- # The bus's state for a snapshot: the CPU port, the RAM, colour RAM and
7
- # a RAM expansion, the cartridge, the datasette and the chips.
8
- module SavedState
9
- # The RAM expansion fitted, or an Unexpanded stand-in.
10
- attr_reader :ram_expansion
11
-
12
- # Takes the cartridge out of the expansion port, as a restore does for
13
- # a state without one.
14
- def detach_cartridge
15
- @cartridge = nil
16
- update_overlays!
17
- end
18
-
19
- # The 6510 port's direction and output registers, and the charge left
20
- # on its floating bits.
21
- def port_state = [@cpu_port.ddr, @cpu_port.data, @cpu_port.floating]
22
-
23
- # Sets the port as port_state reads it, as a snapshot restores it,
24
- # leaving the RAM under $00 and $01 alone.
25
- def restore_port(ddr, out, floating)
26
- @cpu_port.restore(ddr, out, floating)
27
- end
28
-
29
- # The machine's memory and everything on the bus but the keyboard, the
30
- # joysticks and the pot devices, which the host holds. A cartridge is
31
- # already in the port, built from its setup (C64#load_state).
32
- def save_state(out)
33
- out.marker("BUS")
34
- out.int(@cpu_port.ddr).int(@cpu_port.data).int(@cpu_port.floating)
35
- @ram.save_state(out)
36
- @color_ram.save_state(out)
37
- @ram_expansion.save_state(out)
38
- @cartridge&.save_state(out)
39
- @datasette.save_state(out)
40
- @vic.save_state(out)
41
- @cia1.save_state(out)
42
- @cia2.save_state(out)
43
- @sid.save_state(out)
44
- end
45
-
46
- def load_state(input)
47
- input.marker("BUS")
48
- ddr = input.int
49
- port_out = input.int
50
- floating = input.int
51
- @ram.load_state(input)
52
- @color_ram.load_state(input)
53
- @ram_expansion.load_state(input)
54
- @cartridge&.load_state(input)
55
- @datasette.load_state(input)
56
- @cpu_port.load(ddr, port_out, floating)
57
- update_overlays!
58
- @vic.load_state(input)
59
- @cia1.load_state(input)
60
- @cia2.load_state(input)
61
- @sid.load_state(input)
62
- end
63
- end
64
-
65
- include SavedState
66
- end
67
- end
68
- end
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class C64
5
- class Cartridge
6
- class Flash
7
- # A Flash chip's state, for a snapshot.
8
- module SavedState
9
- STATES = %i[read program_setup autoselect programming erase_window erasing suspended chip_erase
10
- program_error].freeze
11
-
12
- # The array, the command state, a timed operation's end on the
13
- # machine's clock, and the windows handed out so far, which load_state
14
- # builds anew.
15
- def save_state(out)
16
- out.blob(@data).int(STATES.index(@state)).int(STATES.index(@base_state)).int(@cycle).int(@toggle)
17
- out.optional_int(@done_at).optional_int(@programmed).optional_int(@remaining)
18
- out.boolean(!@erasing_sectors.nil?)
19
- out.ints(@erasing_sectors) if @erasing_sectors
20
- out.ints(@windows.keys).ints(@status_windows.keys)
21
- end
22
-
23
- def load_state(input)
24
- input.blob_into(@data)
25
- @state = STATES.fetch(input.int).to_sym
26
- @base_state = STATES.fetch(input.int).to_sym
27
- @cycle = input.int
28
- @toggle = input.int
29
- @done_at = input.optional_int
30
- @programmed = input.optional_int
31
- @remaining = input.optional_int
32
- @erasing_sectors = nil
33
- @erasing_sectors = input.ints if input.boolean?
34
- rebuild_windows(input.ints, input.ints)
35
- end
36
- end
37
- end
38
- end
39
- end
40
- end
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class C64
5
- class Cartridge
6
- class RetroReplay < Cartridge
7
- # A Retro Replay's registers, RAM and flash, for a snapshot.
8
- module SavedState
9
- private
10
-
11
- def save_jumpers(out)
12
- out.boolean(true).boolean(@flash_jumper).boolean(@bank_jumper)
13
- end
14
-
15
- def save_mapper(out)
16
- [@active, @frozen, @phi1_ultimax, @ram_enabled, @ram_at_a000, @allow_bank, @no_freeze, @reu_mapping,
17
- @write_once].each { |flag| out.boolean(flag) }
18
- out.int(@bank).int(RetroReplay::CONTROL_MODES.index(@config))
19
- @ram_data.each { |data| out.blob(data) }
20
- @flash.save_state(out)
21
- end
22
-
23
- def load_mapper(input)
24
- load_flags(input)
25
- @bank = input.int
26
- @config = RetroReplay::CONTROL_MODES.fetch(input.int)
27
- @ram_data.each { |data| input.blob_into(data) }
28
- @flash.load_state(input)
29
- map_windows
30
- end
31
-
32
- def load_flags(input)
33
- @active = input.boolean?
34
- @frozen = input.boolean?
35
- @phi1_ultimax = input.boolean?
36
- @ram_enabled = input.boolean?
37
- @ram_at_a000 = input.boolean?
38
- @allow_bank = input.boolean?
39
- @no_freeze = input.boolean?
40
- @reu_mapping = input.boolean?
41
- @write_once = input.boolean?
42
- end
43
- end
44
- end
45
- end
46
- end
47
- end
@@ -1,63 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class C64
5
- class Cartridge
6
- # A cartridge's state for a snapshot: the setup that builds it again and
7
- # the state that goes into it.
8
- module SavedState
9
- # What builds the same cartridge afresh (Cartridge.from_setup): the CRT
10
- # image it was built from, and the jumpers of a mapper that has them.
11
- def save_setup(out)
12
- out.int(CRT_SETUP).string(Storage::CRTFile.encode(@crt))
13
- save_jumpers(out)
14
- end
15
-
16
- # The lines, the pull on NMI, the button and the mapper's own state.
17
- # Loading sets them without calling back into the machine, which maps
18
- # the cartridge again afterwards.
19
- def save_state(out)
20
- out.marker("CARTRIDGE")
21
- out.int(@exrom).int(@game).boolean(@nmi).boolean(@button == true)
22
- save_mapper(out)
23
- end
24
-
25
- def load_state(input)
26
- input.marker("CARTRIDGE")
27
- @exrom = input.int
28
- @game = input.int
29
- @nmi = input.boolean?
30
- @button = input.boolean?
31
- load_mapper(input)
32
- end
33
-
34
- private
35
-
36
- def save_jumpers(out)
37
- out.boolean(false)
38
- end
39
-
40
- # The mapper's own state: where its windows point, for a mapper that
41
- # moves them, and whatever a mapper adds after calling super.
42
- def save_mapper(out)
43
- save_windows(out, windows) if windows
44
- end
45
-
46
- def load_mapper(input)
47
- load_windows(input, windows) if windows
48
- end
49
-
50
- # Where the ROML and ROMH windows point, as their places in `windows`,
51
- # the banks and views the mapper picks them from, or -1 for none.
52
- def save_windows(out, windows)
53
- out.int(window_index(@roml, windows)).int(window_index(@romh, windows))
54
- end
55
-
56
- def load_windows(input, windows)
57
- @roml = window_at(input.int, windows)
58
- @romh = window_at(input.int, windows)
59
- end
60
- end
61
- end
62
- end
63
- end
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class C64
5
- class REU
6
- class DMA
7
- # A transfer's state for a snapshot (REU::SavedState).
8
- module SavedState
9
- # Everything a transfer holds between cycles. Before the first
10
- # transfer, the fields it sets on starting are empty.
11
- def save_state(out)
12
- out.int(@c64).int(@expansion).int(@length).int(@events)
13
- [@type, @c64_step, @expansion_step, @last, @ba_low_after_writes, @swap_byte, @held_read].each do |value|
14
- out.optional_int(value)
15
- end
16
- [@holding, @waiting, @stopped_after_write, @swap_write_due, @swap_read_again, @moved_all,
17
- @extra_cycle].each do |flag|
18
- out.boolean(flag)
19
- end
20
- end
21
-
22
- def load_state(input)
23
- @c64 = input.int
24
- @expansion = input.int
25
- @length = input.int
26
- @events = input.int
27
- load_steps(input)
28
- @holding = input.boolean?
29
- @waiting = input.boolean?
30
- @stopped_after_write = input.boolean?
31
- @swap_write_due = input.boolean?
32
- @swap_read_again = input.boolean?
33
- @moved_all = input.boolean?
34
- @extra_cycle = input.boolean?
35
- end
36
-
37
- private
38
-
39
- def load_steps(input)
40
- @type = input.optional_int
41
- @c64_step = input.optional_int
42
- @expansion_step = input.optional_int
43
- @last = input.optional_int
44
- @ba_low_after_writes = input.optional_int
45
- @swap_byte = input.optional_int
46
- @held_read = input.optional_int
47
- end
48
- end
49
- end
50
- end
51
- end
52
- end
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class C64
5
- class REU
6
- # The REU's state for a snapshot: the REC's registers and the values
7
- # its counters start from, an armed or running transfer, the IRQ line,
8
- # the transfer's own state and the RAM. The size is the machine's
9
- # setup (Snapshot::C64Setup), so a restore finds an REU of the same size.
10
- module SavedState
11
- def size_kb = @size_kb
12
-
13
- def save_state(out)
14
- out.marker("REU")
15
- [@status, @command, @c64, @c64_start, @expansion, @expansion_start, @bank, @bank_start, @length,
16
- @length_start, @interrupt_mask, @address_control].each { |value| out.int(value) }
17
- out.boolean(@armed).boolean(@requested).boolean(@running).boolean(@irq).boolean(@ba_was_low)
18
- @dma.save_state(out)
19
- @ram.save_state(out)
20
- end
21
-
22
- # The IRQ line comes back as it was without calling back into the
23
- # machine, which reads it again afterwards.
24
- def load_state(input)
25
- input.marker("REU")
26
- load_registers(input)
27
- @armed = input.boolean?
28
- @requested = input.boolean?
29
- @running = input.boolean?
30
- @irq = input.boolean?
31
- @ba_was_low = input.boolean?
32
- @dma.load_state(input)
33
- @ram.load_state(input)
34
- end
35
-
36
- private
37
-
38
- def load_registers(input)
39
- @status = input.int
40
- @command = input.int
41
- @c64 = input.int
42
- @c64_start = input.int
43
- @expansion = input.int
44
- @expansion_start = input.int
45
- @bank = input.int
46
- @bank_start = input.int
47
- @length = input.int
48
- @length_start = input.int
49
- @interrupt_mask = input.int
50
- @address_control = input.int
51
- end
52
- end
53
- end
54
- end
55
- end
@@ -1,112 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class C64
5
- # The keyword arguments C64.new takes to build the machine a
6
- # State from #snapshot was taken of.
7
- def self.setup(state) = Snapshot::C64Setup.from(state)
8
-
9
- # A new machine, built as the one a State from #snapshot was taken of,
10
- # at that state. `detached` builds it without the host's files
11
- # (Snapshot::StateReader).
12
- def self.restored(state, detached: false) = setup(state).build.apply_state(state, detached:)
13
-
14
- # The whole machine's state for a snapshot: the machine's own latches,
15
- # the bus and its chips, the CPU, and what is attached to it
16
- # (Attachments).
17
- module SavedState
18
- # How many more on_init handlers the machine a State was taken of had
19
- # yet to run than this one has: they are the host's blocks, which a
20
- # State can't hold. Nil until the machine is restored.
21
- attr_reader :init_handlers_lost
22
-
23
- # The machine's whole state, in memory. #restore takes the machine, or
24
- # another built with the same chip models, region and RAM expansion,
25
- # back to it. The cartridge, the disk in device 8, a true 1541 and its
26
- # disk and the tape go in the state too. What the host holds stays
27
- # out: the keyboard, the joysticks and the pot devices, the traps and
28
- # callbacks, whether the display renders and whether the SID records.
29
- def snapshot
30
- out = Snapshot::StateWriter.new
31
- save_state(out)
32
- out.state
33
- end
34
-
35
- # Takes the machine back to a State from #snapshot. The machine keeps
36
- # its chips, its traps and its callbacks, and puts in the cartridge,
37
- # drives and tape the state has, taking out any it hasn't. Raises
38
- # Snapshot::FormatError for a state of a machine built another way.
39
- # The state goes into a new machine first, so one that fails leaves
40
- # this machine as it was.
41
- def restore(state)
42
- check_setup(C64.setup(state))
43
- C64.restored(state)
44
- apply_state(state)
45
- end
46
-
47
- # Puts a State into the machine without trying it on a new one
48
- # first, for a machine built for it (C64.restored): a state that
49
- # fails leaves the machine part restored. `detached` restores it
50
- # without the host's files (Snapshot::StateReader).
51
- def apply_state(state, detached: false)
52
- input = Snapshot::StateReader.new(state, detached:)
53
- load_state(input)
54
- raise Snapshot::FormatError, "the state goes on past the machine" unless input.finished?
55
-
56
- self
57
- end
58
-
59
- # Sets the machine's cycle count, for a snapshot from VICE, which
60
- # counts from its own clock.
61
- def resume_at(cycles)
62
- @cycles = cycles
63
- end
64
-
65
- def save_state(out)
66
- out.marker(Snapshot::C64Setup::MARKER).stamp
67
- Snapshot::C64Setup.of(address_bus).write(out)
68
- out.int(@cycles).boolean(@nmi_asserted).boolean(@cartridge_nmi).boolean(@restore_pulse).boolean(@freezing)
69
- out.int(@freeze_writes).boolean(!@pending_keys.nil?)
70
- out.ints(@pending_keys) if @pending_keys
71
- out.int(booting? ? @init_handlers.length : 0)
72
- save_cartridge(out)
73
- address_bus.save_state(out)
74
- @cpu.save_state(out)
75
- save_trap_dos(out)
76
- save_serial_bus(out)
77
- save_reu(out)
78
- end
79
-
80
- def load_state(input)
81
- input.marker(Snapshot::C64Setup::MARKER)
82
- input.check_stamp
83
- check_setup(Snapshot::C64Setup.read(input))
84
- @cycles = input.int
85
- @nmi_asserted = input.boolean?
86
- @cartridge_nmi = input.boolean?
87
- @restore_pulse = input.boolean?
88
- @freezing = input.boolean?
89
- @freeze_writes = input.int
90
- @pending_keys = nil
91
- @pending_keys = input.ints if input.boolean?
92
- @init_handlers_lost = [input.int - @init_handlers.length, 0].max
93
- load_cartridge(input)
94
- address_bus.load_state(input)
95
- push_serial_lines
96
- @cpu.load_state(input)
97
- load_trap_dos(input)
98
- load_serial_bus(input)
99
- load_reu(input)
100
- end
101
-
102
- private
103
-
104
- def check_setup(setup)
105
- ours = Snapshot::C64Setup.of(address_bus)
106
- return if setup == ours
107
-
108
- raise Snapshot::FormatError, "the state is of a machine with #{setup}, not #{ours}"
109
- end
110
- end
111
- end
112
- end
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- module Chips
5
- class CIA
6
- # A snapshot of the chip: everything it holds but its wiring, the ports,
7
- # the PB4 and CNT levels, the timers, the interrupt register, the serial
8
- # port and the TOD clock.
9
- module SavedState
10
- def save_state(out)
11
- out.marker("CIA")
12
- out.int(@data_port_a).int(@data_port_b).int(@data_dir_a).int(@data_dir_b)
13
- out.boolean(@port_b4_high).boolean(@port_b4_driven_high).boolean(@cnt_high).boolean(@cnt_rise)
14
- out.int(@control_a.value).int(@control_b.value)
15
- @ta.save_state(out)
16
- @tb.save_state(out)
17
- @icr.save_state(out)
18
- @serial.save_state(out)
19
- @tod.save_state(out)
20
- end
21
-
22
- def load_state(input)
23
- input.marker("CIA")
24
- @data_port_a = input.int
25
- @data_port_b = input.int
26
- @data_dir_a = input.int
27
- @data_dir_b = input.int
28
- @port_b4_high = input.boolean?
29
- @port_b4_driven_high = input.boolean?
30
- @cnt_high = input.boolean?
31
- @cnt_rise = input.boolean?
32
- @control_a.value = input.int
33
- @control_b.value = input.int
34
- load_parts(input)
35
- end
36
-
37
- private
38
-
39
- def load_parts(input)
40
- @ta.load_state(input)
41
- @tb.load_state(input)
42
- @icr.load_state(input)
43
- @serial.load_state(input)
44
- @tod.load_state(input)
45
- end
46
- end
47
- end
48
- end
49
- end
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- module Chips
5
- class CIA
6
- class Serial
7
- # The shift register's state for a snapshot.
8
- module SavedState
9
- def save_state(out)
10
- out.int(@data).int(@shift).int(@steps).optional_int(@empty_in).optional_int(@busy_in)
11
- out.boolean(@busy).boolean(@abandoned).optional_int(@pending).boolean(@underflow_high).boolean(@in_flight)
12
- out.int(@flight_up).int(@flight_down).boolean(@idle)
13
- [@cnt, @cnt_in, @sp_in, @sp_out].each { |level| out.boolean(level) }
14
- end
15
-
16
- def load_state(input)
17
- @data = input.int
18
- @shift = input.int
19
- @steps = input.int
20
- @empty_in = input.optional_int
21
- @busy_in = input.optional_int
22
- @busy = input.boolean?
23
- @abandoned = input.boolean?
24
- @pending = input.optional_int
25
- load_lines(input)
26
- end
27
-
28
- private
29
-
30
- def load_lines(input)
31
- @underflow_high = input.boolean?
32
- @in_flight = input.boolean?
33
- @flight_up = input.int
34
- @flight_down = input.int
35
- @idle = input.boolean?
36
- @cnt = input.boolean?
37
- @cnt_in = input.boolean?
38
- @sp_in = input.boolean?
39
- @sp_out = input.boolean?
40
- end
41
- end
42
- end
43
- end
44
- end
45
- end