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.
Files changed (286) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +72 -1
  3. data/CLAUDE.md +42 -12
  4. data/CONTRIBUTING.md +4 -3
  5. data/README.md +76 -13
  6. data/doc/media.md +2 -1
  7. data/doc/pinned-behaviour.md +174 -0
  8. data/doc/snapshot-format.md +1197 -0
  9. data/doc/snapshots.md +90 -40
  10. data/lib/badline/audio/bare_player.rb +46 -17
  11. data/lib/badline/audio/machine_player.rb +6 -10
  12. data/lib/badline/audio/renderer.rb +32 -21
  13. data/lib/badline/c128/banks.rb +7 -6
  14. data/lib/badline/c128/bus/keyed_state.rb +45 -0
  15. data/lib/badline/c128/bus.rb +36 -4
  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 +27 -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/extra_sids.rb +80 -0
  31. data/lib/badline/c64/bus/keyed_state.rb +41 -0
  32. data/lib/badline/c64/bus.rb +3 -1
  33. data/lib/badline/c64/cartridge/action_replay.rb +6 -15
  34. data/lib/badline/c64/cartridge/comal80.rb +1 -0
  35. data/lib/badline/c64/cartridge/dinamic.rb +3 -1
  36. data/lib/badline/c64/cartridge/easy_flash.rb +0 -15
  37. data/lib/badline/c64/cartridge/epyx_fastload.rb +0 -8
  38. data/lib/badline/c64/cartridge/final_cartridge3.rb +1 -12
  39. data/lib/badline/c64/cartridge/flash.rb +3 -3
  40. data/lib/badline/c64/cartridge/fun_play.rb +2 -1
  41. data/lib/badline/c64/cartridge/g_mod2.rb +0 -12
  42. data/lib/badline/c64/cartridge/game_system.rb +2 -1
  43. data/lib/badline/c64/cartridge/geo_ram.rb +0 -16
  44. data/lib/badline/c64/cartridge/kcs_power.rb +0 -8
  45. data/lib/badline/c64/cartridge/keyed_state.rb +514 -0
  46. data/lib/badline/c64/cartridge/magic_desk.rb +2 -1
  47. data/lib/badline/c64/cartridge/ocean.rb +1 -0
  48. data/lib/badline/c64/cartridge/pagefox.rb +1 -10
  49. data/lib/badline/c64/cartridge/retro_replay.rb +0 -8
  50. data/lib/badline/c64/cartridge/rgcd.rb +2 -11
  51. data/lib/badline/c64/cartridge/super_games.rb +3 -12
  52. data/lib/badline/c64/cartridge/zaxxon.rb +1 -16
  53. data/lib/badline/c64/cartridge.rb +4 -30
  54. data/lib/badline/c64/kernal_traps.rb +28 -25
  55. data/lib/badline/c64/keyed_modules.rb +115 -0
  56. data/lib/badline/c64/keyed_state.rb +68 -0
  57. data/lib/badline/c64/reu/dma.rb +0 -4
  58. data/lib/badline/c64/reu/keyed_state.rb +140 -0
  59. data/lib/badline/c64/reu/ram.rb +0 -15
  60. data/lib/badline/c64/reu.rb +1 -3
  61. data/lib/badline/c64/true_drives.rb +56 -5
  62. data/lib/badline/c64.rb +7 -3
  63. data/lib/badline/chips/cia/interrupt_register.rb +0 -17
  64. data/lib/badline/chips/cia/keyed_parts.rb +213 -0
  65. data/lib/badline/chips/cia/serial.rb +0 -4
  66. data/lib/badline/chips/cia/time_of_day.rb +0 -22
  67. data/lib/badline/chips/cia/timer.rb +0 -20
  68. data/lib/badline/chips/cia.rb +2 -2
  69. data/lib/badline/chips/cpu/core.rb +18 -2
  70. data/lib/badline/chips/cpu/keyed_state.rb +177 -0
  71. data/lib/badline/chips/cpu/microcode.rb +16 -0
  72. data/lib/badline/chips/cpu/port.rb +20 -3
  73. data/lib/badline/chips/cpu.rb +5 -0
  74. data/lib/badline/chips/sid/decimator.rb +10 -8
  75. data/lib/badline/chips/sid/envelope.rb +1 -6
  76. data/lib/badline/chips/sid/filter.rb +0 -14
  77. data/lib/badline/chips/sid/keyed_parts.rb +286 -0
  78. data/lib/badline/chips/sid/voice.rb +0 -10
  79. data/lib/badline/chips/sid/waveform.rb +0 -2
  80. data/lib/badline/chips/sid.rb +1 -2
  81. data/lib/badline/chips/ted/beam.rb +118 -0
  82. data/lib/badline/chips/ted/fetches.rb +199 -0
  83. data/lib/badline/chips/ted/keyed_state.rb +156 -0
  84. data/lib/badline/chips/ted/modes.rb +134 -0
  85. data/lib/badline/chips/ted/palette.rb +43 -0
  86. data/lib/badline/chips/ted/picture.rb +182 -0
  87. data/lib/badline/chips/ted/sound/output.rb +86 -0
  88. data/lib/badline/chips/ted/sound.rb +284 -0
  89. data/lib/badline/chips/ted/timers.rb +66 -0
  90. data/lib/badline/chips/ted.rb +190 -0
  91. data/lib/badline/chips/tia.rb +61 -0
  92. data/lib/badline/chips/vdc/keyed_parts.rb +105 -0
  93. data/lib/badline/chips/vdc/painter.rb +0 -12
  94. data/lib/badline/chips/vdc/raster.rb +0 -16
  95. data/lib/badline/chips/vdc/window.rb +0 -9
  96. data/lib/badline/chips/vdc.rb +1 -2
  97. data/lib/badline/chips/via/control_lines.rb +0 -15
  98. data/lib/badline/chips/via/interrupt_register.rb +0 -9
  99. data/lib/badline/chips/via/keyed_parts.rb +163 -0
  100. data/lib/badline/chips/via/shift_register.rb +0 -14
  101. data/lib/badline/chips/via/timer1.rb +0 -13
  102. data/lib/badline/chips/via/timer2.rb +0 -18
  103. data/lib/badline/chips/via.rb +1 -2
  104. data/lib/badline/chips/vic/border_mask.rb +0 -10
  105. data/lib/badline/chips/vic/collisions.rb +0 -11
  106. data/lib/badline/chips/vic/color_patches.rb +0 -11
  107. data/lib/badline/chips/vic/display_state.rb +0 -19
  108. data/lib/badline/chips/vic/graphics_shifter.rb +0 -4
  109. data/lib/badline/chips/vic/keyed_parts.rb +228 -0
  110. data/lib/badline/chips/vic/keyed_sprites.rb +225 -0
  111. data/lib/badline/chips/vic/keyed_state.rb +102 -0
  112. data/lib/badline/chips/vic/register_log.rb +0 -18
  113. data/lib/badline/chips/vic/registers.rb +0 -9
  114. data/lib/badline/chips/vic/sequencer.rb +0 -2
  115. data/lib/badline/chips/vic/sprite/internal_bus.rb +0 -11
  116. data/lib/badline/chips/vic/sprite.rb +0 -2
  117. data/lib/badline/chips/vic/sprites.rb +0 -3
  118. data/lib/badline/chips/vic.rb +6 -2
  119. data/lib/badline/chips/vic_i/keyed_parts.rb +142 -0
  120. data/lib/badline/chips/vic_i/painter.rb +0 -4
  121. data/lib/badline/chips/vic_i/sound.rb +38 -46
  122. data/lib/badline/chips/vic_i.rb +2 -2
  123. data/lib/badline/chips/z80/core.rb +2 -2
  124. data/lib/badline/chips/z80/keyed_state.rb +73 -0
  125. data/lib/badline/chips.rb +10 -0
  126. data/lib/badline/core.rb +4 -21
  127. data/lib/badline/drives/datasette/keyed_state.rb +43 -0
  128. data/lib/badline/drives/datasette.rb +62 -12
  129. data/lib/badline/drives/engine/core.rb +3 -0
  130. data/lib/badline/drives/engine/serial_lines.rb +4 -7
  131. data/lib/badline/drives/model1541/bus.rb +0 -13
  132. data/lib/badline/drives/model1541/disk.rb +9 -8
  133. data/lib/badline/drives/model1541/keyed_state.rb +251 -0
  134. data/lib/badline/drives/model1541/mechanism.rb +0 -2
  135. data/lib/badline/drives/model1541.rb +1 -2
  136. data/lib/badline/drives/model1571/bus.rb +0 -13
  137. data/lib/badline/drives/model1571/keyed_state.rb +108 -0
  138. data/lib/badline/drives/model1571/wd1770.rb +0 -14
  139. data/lib/badline/drives/model1571.rb +1 -2
  140. data/lib/badline/drives/model1581/bus.rb +0 -13
  141. data/lib/badline/drives/model1581/disk.rb +0 -4
  142. data/lib/badline/drives/model1581/keyed_state.rb +280 -0
  143. data/lib/badline/drives/model1581/mechanism.rb +0 -21
  144. data/lib/badline/drives/model1581/slot.rb +0 -18
  145. data/lib/badline/drives/model1581/wd1772.rb +0 -2
  146. data/lib/badline/drives/model1581.rb +2 -2
  147. data/lib/badline/drives.rb +8 -0
  148. data/lib/badline/frontend/app.rb +3 -3
  149. data/lib/badline/frontend/boot.rb +4 -2
  150. data/lib/badline/frontend/controls.rb +25 -5
  151. data/lib/badline/frontend/drive_led.rb +44 -21
  152. data/lib/badline/frontend/keys.rb +14 -2
  153. data/lib/badline/frontend/media_slots.rb +11 -1
  154. data/lib/badline/frontend/menu/menu_dialogs.rb +4 -3
  155. data/lib/badline/frontend/menu/menu_media.rb +13 -3
  156. data/lib/badline/frontend/menu/menu_pages.rb +8 -8
  157. data/lib/badline/frontend/menu/menu_ports.rb +13 -1
  158. data/lib/badline/frontend/screen.rb +33 -12
  159. data/lib/badline/frontend/screens.rb +2 -1
  160. data/lib/badline/frontend/snapshots.rb +12 -1
  161. data/lib/badline/frontend/sound.rb +4 -4
  162. data/lib/badline/frontend/timeline.rb +43 -12
  163. data/lib/badline/input/matrix_typist.rb +98 -0
  164. data/lib/badline/input.rb +1 -0
  165. data/lib/badline/kernal_trap/chrout.rb +45 -0
  166. data/lib/badline/kernal_trap/dos/channel.rb +0 -27
  167. data/lib/badline/kernal_trap/dos/channels.rb +0 -25
  168. data/lib/badline/kernal_trap/dos/memory.rb +0 -9
  169. data/lib/badline/kernal_trap/dos/status.rb +0 -8
  170. data/lib/badline/kernal_trap/dos/write_file.rb +0 -18
  171. data/lib/badline/kernal_trap/dos.rb +0 -19
  172. data/lib/badline/kernal_trap/file_routine.rb +4 -4
  173. data/lib/badline/kernal_trap/keyed_state.rb +150 -0
  174. data/lib/badline/kernal_trap/layout.rb +75 -11
  175. data/lib/badline/kernal_trap/load.rb +14 -16
  176. data/lib/badline/kernal_trap/routine.rb +12 -0
  177. data/lib/badline/kernal_trap/save.rb +8 -18
  178. data/lib/badline/kernal_trap/serial.rb +1 -17
  179. data/lib/badline/kernal_trap.rb +2 -0
  180. data/lib/badline/machine/keyboard_buffer.rb +49 -0
  181. data/lib/badline/machine/settling.rb +29 -0
  182. data/lib/badline/machine.rb +29 -6
  183. data/lib/badline/media/boot_disk.rb +14 -2
  184. data/lib/badline/media/extensions.rb +10 -0
  185. data/lib/badline/media/plus4_media.rb +68 -0
  186. data/lib/badline/media/program.rb +20 -6
  187. data/lib/badline/media.rb +33 -12
  188. data/lib/badline/memory.rb +3 -6
  189. data/lib/badline/options/family.rb +6 -2
  190. data/lib/badline/options/help.rb +66 -16
  191. data/lib/badline/options/table.rb +17 -2
  192. data/lib/badline/options/validation.rb +26 -2
  193. data/lib/badline/options.rb +42 -9
  194. data/lib/badline/plus4/acia.rb +45 -0
  195. data/lib/badline/plus4/bus.rb +375 -0
  196. data/lib/badline/plus4/cassette_sense.rb +21 -0
  197. data/lib/badline/plus4/cpu.rb +10 -0
  198. data/lib/badline/plus4/cpu_port.rb +93 -0
  199. data/lib/badline/plus4/keyboard_port.rb +76 -0
  200. data/lib/badline/plus4/keyed_modules.rb +99 -0
  201. data/lib/badline/plus4/keyed_parts.rb +143 -0
  202. data/lib/badline/plus4/keyed_state.rb +41 -0
  203. data/lib/badline/plus4/model.rb +38 -0
  204. data/lib/badline/plus4/user_port.rb +31 -0
  205. data/lib/badline/plus4.rb +240 -0
  206. data/lib/badline/roms/README +38 -0
  207. data/lib/badline/roms/plus4/basic.rom +0 -0
  208. data/lib/badline/roms/plus4/function-high.rom +0 -0
  209. data/lib/badline/roms/plus4/function-low.rom +0 -0
  210. data/lib/badline/roms/plus4/kernal-ntsc.rom +0 -0
  211. data/lib/badline/roms/plus4/kernal-pal.rom +0 -0
  212. data/lib/badline/snapshot/c128_setup.rb +9 -20
  213. data/lib/badline/snapshot/c64_setup.rb +28 -24
  214. data/lib/badline/snapshot/container.rb +6 -0
  215. data/lib/badline/snapshot/field_doc/markdown.rb +113 -0
  216. data/lib/badline/snapshot/field_doc.rb +148 -0
  217. data/lib/badline/snapshot/image.rb +143 -28
  218. data/lib/badline/snapshot/keyed/cursor.rb +40 -0
  219. data/lib/badline/snapshot/keyed/modules.rb +66 -0
  220. data/lib/badline/snapshot/keyed/reader.rb +188 -0
  221. data/lib/badline/snapshot/keyed/recorder.rb +88 -0
  222. data/lib/badline/snapshot/keyed/report.rb +26 -0
  223. data/lib/badline/snapshot/keyed/writer.rb +55 -0
  224. data/lib/badline/snapshot/keyed.rb +64 -0
  225. data/lib/badline/snapshot/machine_state.rb +17 -64
  226. data/lib/badline/snapshot/plus4_setup.rb +39 -0
  227. data/lib/badline/snapshot/storage_setup.rb +29 -34
  228. data/lib/badline/snapshot/vic20_setup.rb +6 -15
  229. data/lib/badline/snapshot/vice/reu1764.rb +2 -2
  230. data/lib/badline/snapshot/vice.rb +7 -31
  231. data/lib/badline/snapshot.rb +48 -20
  232. data/lib/badline/storage/crt_file.rb +3 -1
  233. data/lib/badline/storage/g64_image.rb +9 -4
  234. data/lib/badline/storage/tap.rb +57 -20
  235. data/lib/badline/support/checkpoint.rb +3 -2
  236. data/lib/badline/support/plus4_checkpoint.rb +42 -0
  237. data/lib/badline/version.rb +1 -1
  238. data/lib/badline/vic20/attachments.rb +3 -0
  239. data/lib/badline/vic20/bus/keyed_state.rb +52 -0
  240. data/lib/badline/vic20/bus.rb +1 -2
  241. data/lib/badline/vic20/keyed_modules.rb +73 -0
  242. data/lib/badline/vic20/keyed_state.rb +45 -0
  243. data/lib/badline/vic20.rb +5 -5
  244. data/lib/badline.rb +1 -0
  245. metadata +75 -42
  246. data/lib/badline/c128/bus/saved_state.rb +0 -53
  247. data/lib/badline/c128/saved_state.rb +0 -117
  248. data/lib/badline/c64/bus/saved_state.rb +0 -68
  249. data/lib/badline/c64/cartridge/flash/saved_state.rb +0 -40
  250. data/lib/badline/c64/cartridge/retro_replay/saved_state.rb +0 -47
  251. data/lib/badline/c64/cartridge/saved_state.rb +0 -63
  252. data/lib/badline/c64/reu/dma/saved_state.rb +0 -52
  253. data/lib/badline/c64/reu/saved_state.rb +0 -55
  254. data/lib/badline/c64/saved_state.rb +0 -112
  255. data/lib/badline/chips/cia/saved_state.rb +0 -49
  256. data/lib/badline/chips/cia/serial/saved_state.rb +0 -45
  257. data/lib/badline/chips/cpu/saved_state.rb +0 -117
  258. data/lib/badline/chips/sid/envelope/saved_state.rb +0 -70
  259. data/lib/badline/chips/sid/filter/saved_state.rb +0 -42
  260. data/lib/badline/chips/sid/saved_state.rb +0 -52
  261. data/lib/badline/chips/sid/waveform/saved_state.rb +0 -68
  262. data/lib/badline/chips/vdc/saved_state.rb +0 -36
  263. data/lib/badline/chips/via/saved_state.rb +0 -44
  264. data/lib/badline/chips/vic/graphics_shifter/saved_state.rb +0 -40
  265. data/lib/badline/chips/vic/saved_state.rb +0 -82
  266. data/lib/badline/chips/vic/sequencer/saved_state.rb +0 -91
  267. data/lib/badline/chips/vic/sprite/saved_state.rb +0 -66
  268. data/lib/badline/chips/vic/sprites/saved_state.rb +0 -59
  269. data/lib/badline/chips/vic_i/painter/saved_state.rb +0 -40
  270. data/lib/badline/chips/vic_i/saved_state.rb +0 -55
  271. data/lib/badline/chips/z80/saved_state.rb +0 -71
  272. data/lib/badline/chrout_trap.rb +0 -43
  273. data/lib/badline/debug_register.rb +0 -28
  274. data/lib/badline/drives/datasette/saved_state.rb +0 -37
  275. data/lib/badline/drives/model1541/disk/saved_state.rb +0 -88
  276. data/lib/badline/drives/model1541/mechanism/saved_state.rb +0 -72
  277. data/lib/badline/drives/model1541/saved_state.rb +0 -44
  278. data/lib/badline/drives/model1571/saved_state.rb +0 -47
  279. data/lib/badline/drives/model1581/disk/saved_state.rb +0 -89
  280. data/lib/badline/drives/model1581/saved_state.rb +0 -42
  281. data/lib/badline/drives/model1581/wd1772/saved_state.rb +0 -68
  282. data/lib/badline/keyboard_buffer.rb +0 -33
  283. data/lib/badline/snapshot/setup.rb +0 -31
  284. data/lib/badline/snapshot/state.rb +0 -179
  285. data/lib/badline/vic20/bus/saved_state.rb +0 -35
  286. 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 snapshot
181
- # names them by: the mapper's banks, or nothing for a mapper whose
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 (ChroutTrap).
39
+ # Records what the KERNAL prints through CHROUT (KernalTrap::Chrout).
40
40
  def capture_output
41
- @capture_output ||= ChroutTrap.new(cpu:, bus: trap_bus, layout: trap_layout).tap do |trap|
42
- cpu.install_trap(ChroutTrap::ADDRESS) { trap.call }
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
@@ -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
@@ -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
@@ -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/saved_state"
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
- # A true 1541 on the serial bus, with its device number.
59
- def load_drive1541(input)
60
- return detach_drive1541 unless input.boolean?
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
- device = input.int
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.load_state(input)
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/saved_state"
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