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
@@ -56,18 +56,6 @@ module Badline
56
56
  [0, 0, shown.clamp(1, @width), (frame_lines - sync_lines).clamp(1, @height)]
57
57
  end
58
58
 
59
- # The display's size and the window's start addresses. The display
60
- # starts again cleared, to be painted while the VDC renders.
61
- def save_state(out)
62
- out.int(@width).int(@height)
63
- @window.save_state(out)
64
- end
65
-
66
- def load_state(input)
67
- resize(input.int, input.int)
68
- @window.load_state(input)
69
- end
70
-
71
59
  def clear_dirty_lines!
72
60
  @dirty_lines.fill(false)
73
61
  end
@@ -30,22 +30,6 @@ module Badline
30
30
  # Outside the displayed rows, as status bit 5 reads.
31
31
  def vertical_blank? = @adjusting || @row >= @registers[6]
32
32
 
33
- def save_state(out)
34
- out.int(@frame).int(@row).int(@row_line).boolean(@adjusting).int(@frame_line).int(@frame_lines)
35
- out.int(@sync_start).int(@sync_lines)
36
- end
37
-
38
- def load_state(input)
39
- @frame = input.int
40
- @row = input.int
41
- @row_line = input.int
42
- @adjusting = input.boolean?
43
- @frame_line = input.int
44
- @frame_lines = input.int
45
- @sync_start = input.int
46
- @sync_lines = input.int
47
- end
48
-
49
33
  def end_line(render)
50
34
  paint_line if render
51
35
  @frame_line += 1
@@ -57,15 +57,6 @@ module Badline
57
57
  @attribute_start = (regs[20] << 8) | regs[21]
58
58
  end
59
59
 
60
- def save_state(out)
61
- out.int(@display_start).int(@attribute_start)
62
- end
63
-
64
- def load_state(input)
65
- @display_start = input.int
66
- @attribute_start = input.int
67
- end
68
-
69
60
  def paint(line, row, row_line, frame)
70
61
  regs = @registers
71
62
  lay_out_cell
@@ -4,7 +4,7 @@ require "badline/chips/vdc/memory"
4
4
  require "badline/chips/vdc/window"
5
5
  require "badline/chips/vdc/painter"
6
6
  require "badline/chips/vdc/raster"
7
- require "badline/chips/vdc/saved_state"
7
+ require "badline/chips/vdc/keyed_parts"
8
8
 
9
9
  module Badline
10
10
  module Chips
@@ -34,7 +34,6 @@ module Badline
34
34
  # fills or two per byte it copies.
35
35
  class VDC
36
36
  include Addressable
37
- include SavedState
38
37
 
39
38
  STATUS_READY = 0x80
40
39
  STATUS_VBLANK = 0x20
@@ -56,21 +56,6 @@ module Badline
56
56
 
57
57
  def active_c1_edge?(high) = high == @control.anybits?(0x01)
58
58
 
59
- # The lines' levels and mode. Which flags they set, and whether reads
60
- # handshake, are the port's wiring.
61
- def save_state(out)
62
- out.int(@control).boolean(@c1_high).boolean(@c2_high).boolean(@handshake_low).int(@pulse).boolean(@c2_output)
63
- end
64
-
65
- def load_state(input)
66
- @control = input.int
67
- @c1_high = input.boolean?
68
- @c2_high = input.boolean?
69
- @handshake_low = input.boolean?
70
- @pulse = input.int
71
- @c2_output = input.boolean?
72
- end
73
-
74
59
  # Everything the lines hold, for comparing them at two points.
75
60
  def state = [@control, @c1_high, @c2_high, @handshake_low, @pulse, @c2_output]
76
61
 
@@ -25,15 +25,6 @@ module Badline
25
25
  @enable = 0x00
26
26
  end
27
27
 
28
- def save_state(out)
29
- out.int(@flags).int(@enable)
30
- end
31
-
32
- def load_state(input)
33
- @flags = input.int
34
- @enable = input.int
35
- end
36
-
37
28
  def set(bits)
38
29
  @flags |= bits
39
30
  end
@@ -0,0 +1,163 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Chips
5
+ class VIA
6
+ class Timer1
7
+ # Timer 1's fields in a keyed snapshot module, under `prefix`.
8
+ module KeyedState
9
+ def save_fields(out, prefix)
10
+ out.int("#{prefix}counter", @counter).int("#{prefix}latch", @latch).bool("#{prefix}hold", @hold)
11
+ out.bool("#{prefix}reload", @reload).bool("#{prefix}armed", @armed).bool("#{prefix}pb7", @pb7)
12
+ end
13
+
14
+ def load_fields(input, prefix)
15
+ @counter = input.word("#{prefix}counter", @counter)
16
+ @latch = input.word("#{prefix}latch", @latch)
17
+ @hold = input.bool("#{prefix}hold", @hold)
18
+ @reload = input.bool("#{prefix}reload", @reload)
19
+ @armed = input.bool("#{prefix}armed", @armed)
20
+ @pb7 = input.bool("#{prefix}pb7", @pb7)
21
+ end
22
+ end
23
+
24
+ include KeyedState
25
+ end
26
+
27
+ class Timer2
28
+ # Timer 2's fields in a keyed snapshot module, under `prefix`.
29
+ module KeyedState
30
+ def save_fields(out, prefix)
31
+ out.int("#{prefix}counter", @counter).int("#{prefix}latch_low", @latch_low).bool("#{prefix}hold", @hold)
32
+ out.bool("#{prefix}low_reload", @low_reload).bool("#{prefix}armed", @armed)
33
+ out.bool("#{prefix}low_underflowed", @low_underflowed).bool("#{prefix}count_pulses", @count_pulses)
34
+ out.bool("#{prefix}counting_pulses", @counting_pulses)
35
+ end
36
+
37
+ def load_fields(input, prefix)
38
+ @counter = input.word("#{prefix}counter", @counter)
39
+ @latch_low = input.byte("#{prefix}latch_low", @latch_low)
40
+ @hold = input.bool("#{prefix}hold", @hold)
41
+ @low_reload = input.bool("#{prefix}low_reload", @low_reload)
42
+ @armed = input.bool("#{prefix}armed", @armed)
43
+ @low_underflowed = input.bool("#{prefix}low_underflowed", @low_underflowed)
44
+ @count_pulses = input.bool("#{prefix}count_pulses", @count_pulses)
45
+ @counting_pulses = input.bool("#{prefix}counting_pulses", @counting_pulses)
46
+ end
47
+ end
48
+
49
+ include KeyedState
50
+ end
51
+
52
+ class ShiftRegister
53
+ # The shift register's fields in a keyed snapshot module, under
54
+ # `prefix`.
55
+ module KeyedState
56
+ def save_fields(out, prefix)
57
+ out.int("#{prefix}mode", @mode).int("#{prefix}data", @data).int("#{prefix}bits", @bits)
58
+ out.int("#{prefix}delay", @delay).bool("#{prefix}clock", @clock).bool("#{prefix}cb2", @cb2)
59
+ out.bool("#{prefix}cb2_input", @cb2_input)
60
+ end
61
+
62
+ def load_fields(input, prefix)
63
+ @mode = input.masked("#{prefix}mode", @mode, 0x07)
64
+ @data = input.byte("#{prefix}data", @data)
65
+ @bits = input.int("#{prefix}bits", @bits)
66
+ @delay = input.int("#{prefix}delay", @delay)
67
+ @clock = input.bool("#{prefix}clock", @clock)
68
+ @cb2 = input.bool("#{prefix}cb2", @cb2)
69
+ @cb2_input = input.bool("#{prefix}cb2_input", @cb2_input)
70
+ end
71
+ end
72
+
73
+ include KeyedState
74
+ end
75
+
76
+ class InterruptRegister
77
+ # The flags and the enable mask, under `prefix`.
78
+ module KeyedState
79
+ def save_fields(out, prefix)
80
+ out.int("#{prefix}flags", @flags).int("#{prefix}enable", @enable)
81
+ end
82
+
83
+ def load_fields(input, prefix)
84
+ @flags = input.masked("#{prefix}flags", @flags, 0x7f)
85
+ @enable = input.masked("#{prefix}enable", @enable, 0x7f)
86
+ end
87
+ end
88
+
89
+ include KeyedState
90
+ end
91
+
92
+ class ControlLines
93
+ # A pair of control lines' fields, under `prefix`.
94
+ module KeyedState
95
+ def save_fields(out, prefix)
96
+ out.int("#{prefix}control", @control).bool("#{prefix}c1_high", @c1_high).bool("#{prefix}c2_high", @c2_high)
97
+ out.bool("#{prefix}handshake_low", @handshake_low).int("#{prefix}pulse", @pulse)
98
+ out.bool("#{prefix}c2_output", @c2_output)
99
+ end
100
+
101
+ def load_fields(input, prefix)
102
+ @control = input.masked("#{prefix}control", @control, 0x0f)
103
+ @c1_high = input.bool("#{prefix}c1_high", @c1_high)
104
+ @c2_high = input.bool("#{prefix}c2_high", @c2_high)
105
+ @handshake_low = input.bool("#{prefix}handshake_low", @handshake_low)
106
+ @pulse = input.int("#{prefix}pulse", @pulse)
107
+ @c2_output = input.bool("#{prefix}c2_output", @c2_output)
108
+ end
109
+ end
110
+
111
+ include KeyedState
112
+ end
113
+
114
+ # The VIA's fields in a keyed snapshot module (Snapshot::Keyed): the
115
+ # registers and PB6, and its parts under t1., t2., sr., ifr., ca. and
116
+ # cb. Whether the shift register clocks off timer 2 comes from the
117
+ # ACR on load. The peripheral restores its own state.
118
+ module KeyedState
119
+ def save_fields(out)
120
+ out.int("ora", @ora).int("orb", @orb).int("ddra", @ddra).int("ddrb", @ddrb).int("latch_a", @latch_a)
121
+ out.int("latch_b", @latch_b).int("acr", @acr).int("pcr", @pcr).bool("pb6_high", @pb6_high)
122
+ @t1.save_fields(out, "t1.")
123
+ @t2.save_fields(out, "t2.")
124
+ @shift_register.save_fields(out, "sr.")
125
+ @ifr.save_fields(out, "ifr.")
126
+ @ca.save_fields(out, "ca.")
127
+ @cb.save_fields(out, "cb.")
128
+ out
129
+ end
130
+
131
+ def load_fields(input)
132
+ @ora = input.byte("ora", @ora)
133
+ @orb = input.byte("orb", @orb)
134
+ @ddra = input.byte("ddra", @ddra)
135
+ @ddrb = input.byte("ddrb", @ddrb)
136
+ @latch_a = input.byte("latch_a", @latch_a)
137
+ @latch_b = input.byte("latch_b", @latch_b)
138
+ @acr = input.byte("acr", @acr)
139
+ @pcr = input.byte("pcr", @pcr)
140
+ @pb6_high = input.bool("pb6_high", @pb6_high)
141
+ load_part_fields(input)
142
+ end
143
+
144
+ def restored!
145
+ @sr_uses_t2 = [1, 4, 5].include?((@acr >> 2) & 0x07)
146
+ end
147
+
148
+ private
149
+
150
+ def load_part_fields(input)
151
+ @t1.load_fields(input, "t1.")
152
+ @t2.load_fields(input, "t2.")
153
+ @shift_register.load_fields(input, "sr.")
154
+ @ifr.load_fields(input, "ifr.")
155
+ @ca.load_fields(input, "ca.")
156
+ @cb.load_fields(input, "cb.")
157
+ end
158
+ end
159
+
160
+ include KeyedState
161
+ end
162
+ end
163
+ end
@@ -81,20 +81,6 @@ module Badline
81
81
  # changes it from cycle to cycle.
82
82
  def clocking? = @bits.nonzero? && internal_clock?
83
83
 
84
- def save_state(out)
85
- out.int(@mode).int(@data).int(@bits).int(@delay).boolean(@clock).boolean(@cb2).boolean(@cb2_input)
86
- end
87
-
88
- def load_state(input)
89
- @mode = input.int
90
- @data = input.int
91
- @bits = input.int
92
- @delay = input.int
93
- @clock = input.boolean?
94
- @cb2 = input.boolean?
95
- @cb2_input = input.boolean?
96
- end
97
-
98
84
  # Everything the register holds, for comparing it at two points.
99
85
  def state = [@mode, @data, @bits, @delay, @clock, @cb2, @cb2_input]
100
86
 
@@ -93,19 +93,6 @@ module Badline
93
93
  @counter = @reload ? 0xffff : @latch - phase + 1
94
94
  end
95
95
 
96
- def save_state(out)
97
- out.int(@counter).int(@latch).boolean(@hold).boolean(@reload).boolean(@armed).boolean(@pb7)
98
- end
99
-
100
- def load_state(input)
101
- @counter = input.int
102
- @latch = input.int
103
- @hold = input.boolean?
104
- @reload = input.boolean?
105
- @armed = input.boolean?
106
- @pb7 = input.boolean?
107
- end
108
-
109
96
  # What the counter and PB7 don't hold, for comparing the timer at two
110
97
  # points.
111
98
  def state = [@latch, @armed]
@@ -85,24 +85,6 @@ module Badline
85
85
  @low_underflowed = @counter.allbits?(0xff)
86
86
  end
87
87
 
88
- def save_state(out)
89
- out.int(@counter).int(@latch_low)
90
- [@hold, @low_reload, @armed, @low_underflowed, @count_pulses, @counting_pulses].each do |flag|
91
- out.boolean(flag)
92
- end
93
- end
94
-
95
- def load_state(input)
96
- @counter = input.int
97
- @latch_low = input.int
98
- @hold = input.boolean?
99
- @low_reload = input.boolean?
100
- @armed = input.boolean?
101
- @low_underflowed = input.boolean?
102
- @count_pulses = input.boolean?
103
- @counting_pulses = input.boolean?
104
- end
105
-
106
88
  # What the counter and the low byte's underflow don't hold, for
107
89
  # comparing the timer at two points.
108
90
  def state = [@latch_low, @armed, @hold, @low_reload, @count_pulses, @counting_pulses]
@@ -4,9 +4,9 @@ require "badline/chips/via/control_lines"
4
4
  require "badline/chips/via/fast_forward"
5
5
  require "badline/chips/via/interrupt_register"
6
6
  require "badline/chips/via/shift_register"
7
- require "badline/chips/via/saved_state"
8
7
  require "badline/chips/via/timer1"
9
8
  require "badline/chips/via/timer2"
9
+ require "badline/chips/via/keyed_parts"
10
10
 
11
11
  module Badline
12
12
  module Chips
@@ -20,7 +20,6 @@ module Badline
20
20
  class VIA
21
21
  include Addressable
22
22
  include FastForward
23
- include SavedState
24
23
 
25
24
  attr_reader :start, :peripheral, :shift_register, :acr, :pcr
26
25
 
@@ -28,16 +28,6 @@ module Badline
28
28
  @groups.fill(FULL)
29
29
  end
30
30
 
31
- def save_state(out)
32
- out.ints(@groups).booleans(@mask).blob(@snapshot)
33
- end
34
-
35
- def load_state(input)
36
- input.ints_into(@groups)
37
- input.booleans_into(@mask)
38
- input.blob_into(@snapshot)
39
- end
40
-
41
31
  def at?(pixel_x)
42
32
  case @groups[pixel_x >> 3]
43
33
  when FULL then true
@@ -37,17 +37,6 @@ module Badline
37
37
  @cleared_data = 0
38
38
  end
39
39
 
40
- def save_state(out)
41
- out.blob(@hits).int(@folded).int(@cleared_sprite).int(@cleared_data)
42
- end
43
-
44
- def load_state(input)
45
- input.blob_into(@hits)
46
- @folded = input.int
47
- @cleared_sprite = input.int
48
- @cleared_data = input.int
49
- end
50
-
51
40
  def start_line
52
41
  @folded = 0
53
42
  @cleared_sprite = carry(@cleared_sprite)
@@ -18,17 +18,6 @@ module Badline
18
18
 
19
19
  def clear = @patches.clear
20
20
 
21
- # Each patch as its four numbers: the boundary pixel, the register,
22
- # the old colour and the new.
23
- def save_state(out)
24
- out.int(@patches.length)
25
- @patches.each { |patch| out.ints(patch) }
26
- end
27
-
28
- def load_state(input)
29
- @patches.replace(Array.new(input.int) { input.ints })
30
- end
31
-
32
21
  def log(reg, old, value, boundary_x)
33
22
  @patches << [boundary_x, reg, @grey_dots ? GREY_DOT : old & 0x0f, value & 0x0f]
34
23
  end
@@ -79,25 +79,6 @@ module Badline
79
79
  @matched && column >= FETCH_FIRST && column <= DMA_LAST
80
80
  end
81
81
 
82
- def save_state(out)
83
- out.int(@vc_base).int(@vc).int(@vmli).int(@rc).boolean(@display).boolean(@bad_lines_enabled)
84
- out.boolean(@matched).optional_int(@ba).int(@line_bits).boolean(@den_line).boolean(@in_window)
85
- end
86
-
87
- def load_state(input)
88
- @vc_base = input.int
89
- @vc = input.int
90
- @vmli = input.int
91
- @rc = input.int
92
- @display = input.boolean?
93
- @bad_lines_enabled = input.boolean?
94
- @matched = input.boolean?
95
- @ba = input.optional_int
96
- @line_bits = input.int
97
- @den_line = input.boolean?
98
- @in_window = input.boolean?
99
- end
100
-
101
82
  def new_frame
102
83
  @vc_base = 0
103
84
  @bad_lines_enabled = false
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "badline/chips/vic/graphics_shifter/saved_state"
4
-
5
3
  module Badline
6
4
  module Chips
7
5
  class VIC
@@ -26,8 +24,6 @@ module Badline
26
24
  # invalid mode, it is still black into hi-res text, and so is a
27
25
  # background pixel into multicolour bitmap.
28
26
  class GraphicsShifter
29
- include SavedState
30
-
31
27
  ECM = 0b100
32
28
  ECM_BMM = 0b110
33
29
  MULTICOLOR_BITMAP = 0b011