badline 0.12.1 → 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 (565) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -1
  3. data/CLAUDE.md +86 -38
  4. data/CONTRIBUTING.md +4 -3
  5. data/README.md +9 -6
  6. data/doc/library.md +9 -9
  7. data/doc/media.md +2 -1
  8. data/doc/pinned-behaviour.md +134 -105
  9. data/doc/snapshot-format.md +1047 -0
  10. data/doc/snapshots.md +73 -43
  11. data/lib/badline/audio/bare_player.rb +53 -20
  12. data/lib/badline/audio/cli.rb +6 -6
  13. data/lib/badline/audio/jukebox.rb +2 -2
  14. data/lib/badline/audio/machine_player.rb +16 -10
  15. data/lib/badline/{media → audio}/queue.rb +1 -1
  16. data/lib/badline/audio/queued_tune.rb +6 -6
  17. data/lib/badline/audio/renderer.rb +33 -22
  18. data/lib/badline/audio/stereo.rb +1 -1
  19. data/lib/badline/c128/banks.rb +6 -3
  20. data/lib/badline/c128/bus/keyed_state.rb +45 -0
  21. data/lib/badline/c128/bus.rb +35 -20
  22. data/lib/badline/c128/color_lines.rb +2 -2
  23. data/lib/badline/c128/cpu.rb +1 -1
  24. data/lib/badline/c128/drives.rb +14 -34
  25. data/lib/badline/c128/fast_serial.rb +5 -5
  26. data/lib/badline/c128/keyed_modules.rb +117 -0
  27. data/lib/badline/c128/keyed_state.rb +91 -0
  28. data/lib/badline/c128/keys.rb +9 -0
  29. data/lib/badline/c128/mmu.rb +9 -8
  30. data/lib/badline/c128/mmu_pages.rb +21 -1
  31. data/lib/badline/c128/modes.rb +21 -11
  32. data/lib/badline/c128/z80.rb +2 -2
  33. data/lib/badline/c128/z80_turns.rb +1 -1
  34. data/lib/badline/c128.rb +21 -16
  35. data/lib/badline/c64/attachments.rb +42 -0
  36. data/lib/badline/c64/banked_ram/banking.rb +32 -0
  37. data/lib/badline/c64/banked_ram/plus256k.rb +64 -0
  38. data/lib/badline/c64/banked_ram/plus60k.rb +47 -0
  39. data/lib/badline/c64/banked_ram/unexpanded.rb +30 -0
  40. data/lib/badline/c64/banked_ram.rb +23 -0
  41. data/lib/badline/c64/bus/debug_register.rb +32 -0
  42. data/lib/badline/c64/bus/extra_sids.rb +32 -0
  43. data/lib/badline/c64/bus/fittings.rb +40 -0
  44. data/lib/badline/c64/bus/keyed_state.rb +41 -0
  45. data/lib/badline/c64/bus/pla.rb +149 -0
  46. data/lib/badline/c64/bus/roms.rb +41 -0
  47. data/lib/badline/c64/bus/sid_slots.rb +44 -0
  48. data/lib/badline/c64/bus.rb +219 -0
  49. data/lib/badline/c64/cartridge/action_replay.rb +115 -0
  50. data/lib/badline/c64/cartridge/atomic_power.rb +26 -0
  51. data/lib/badline/c64/cartridge/bank.rb +83 -0
  52. data/lib/badline/c64/cartridge/comal80.rb +52 -0
  53. data/lib/badline/c64/cartridge/dinamic.rb +36 -0
  54. data/lib/badline/c64/cartridge/easy_flash.rb +132 -0
  55. data/lib/badline/c64/cartridge/epyx_fastload.rb +73 -0
  56. data/lib/badline/c64/cartridge/final_cartridge3.rb +79 -0
  57. data/lib/badline/c64/cartridge/flash.rb +279 -0
  58. data/lib/badline/c64/cartridge/freezer.rb +35 -0
  59. data/lib/badline/c64/cartridge/fun_play.rb +40 -0
  60. data/lib/badline/c64/cartridge/g_mod2.rb +64 -0
  61. data/lib/badline/c64/cartridge/game_system.rb +42 -0
  62. data/lib/badline/c64/cartridge/geo_ram.rb +65 -0
  63. data/lib/badline/c64/cartridge/kcs_power.rb +69 -0
  64. data/lib/badline/c64/cartridge/keyed_state.rb +393 -0
  65. data/lib/badline/c64/cartridge/mach5.rb +34 -0
  66. data/lib/badline/c64/cartridge/magic_desk.rb +32 -0
  67. data/lib/badline/c64/cartridge/ocean.rb +37 -0
  68. data/lib/badline/c64/cartridge/pagefox.rb +60 -0
  69. data/lib/badline/c64/cartridge/retro_replay.rb +278 -0
  70. data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
  71. data/lib/badline/c64/cartridge/rgcd.rb +50 -0
  72. data/lib/badline/c64/cartridge/simons_basic.rb +37 -0
  73. data/lib/badline/c64/cartridge/standard.rb +17 -0
  74. data/lib/badline/c64/cartridge/super_games.rb +40 -0
  75. data/lib/badline/c64/cartridge/westermann.rb +32 -0
  76. data/lib/badline/c64/cartridge/zaxxon.rb +52 -0
  77. data/lib/badline/c64/cartridge.rb +232 -0
  78. data/lib/badline/c64/color_memory.rb +27 -0
  79. data/lib/badline/{computer → c64}/common.rb +2 -2
  80. data/lib/badline/{computer → c64}/kernal_traps.rb +39 -36
  81. data/lib/badline/c64/keyed_modules.rb +111 -0
  82. data/lib/badline/c64/keyed_state.rb +68 -0
  83. data/lib/badline/c64/reu/dma.rb +271 -0
  84. data/lib/badline/c64/reu/keyed_state.rb +140 -0
  85. data/lib/badline/c64/reu/ram.rb +94 -0
  86. data/lib/badline/c64/reu/trigger.rb +34 -0
  87. data/lib/badline/c64/reu.rb +289 -0
  88. data/lib/badline/c64/true_drives.rb +120 -0
  89. data/lib/badline/{computer.rb → c64.rb} +24 -15
  90. data/lib/badline/chips/cia/fast_forward.rb +62 -0
  91. data/lib/badline/chips/cia/interrupt_register.rb +128 -0
  92. data/lib/badline/chips/cia/keyed_parts.rb +213 -0
  93. data/lib/badline/chips/cia/serial.rb +246 -0
  94. data/lib/badline/chips/cia/time_of_day.rb +210 -0
  95. data/lib/badline/chips/cia/timer.rb +188 -0
  96. data/lib/badline/chips/cia.rb +281 -0
  97. data/lib/badline/chips/cpu/addressing.rb +133 -0
  98. data/lib/badline/chips/cpu/boundary.rb +56 -0
  99. data/lib/badline/chips/cpu/core.rb +183 -0
  100. data/lib/badline/chips/cpu/instruction.rb +338 -0
  101. data/lib/badline/chips/cpu/instruction_set/arithmetic.rb +118 -0
  102. data/lib/badline/chips/cpu/instruction_set/bitwise.rb +130 -0
  103. data/lib/badline/chips/cpu/instruction_set/branch.rb +83 -0
  104. data/lib/badline/chips/cpu/instruction_set/flag.rb +67 -0
  105. data/lib/badline/chips/cpu/instruction_set/illegal.rb +274 -0
  106. data/lib/badline/chips/cpu/instruction_set/inc_dec.rb +73 -0
  107. data/lib/badline/chips/cpu/instruction_set/stack.rb +56 -0
  108. data/lib/badline/chips/cpu/instruction_set/transfer.rb +141 -0
  109. data/lib/badline/chips/cpu/instruction_set.rb +59 -0
  110. data/lib/badline/chips/cpu/interrupts.rb +108 -0
  111. data/lib/badline/chips/cpu/keyed_state.rb +177 -0
  112. data/lib/badline/chips/cpu/microcode.rb +195 -0
  113. data/lib/badline/chips/cpu/operations.rb +90 -0
  114. data/lib/badline/chips/cpu/port.rb +133 -0
  115. data/lib/badline/chips/cpu/stack_operations.rb +84 -0
  116. data/lib/badline/chips/cpu/traps.rb +23 -0
  117. data/lib/badline/chips/cpu.rb +17 -0
  118. data/lib/badline/chips/sid/catch_up.rb +122 -0
  119. data/lib/badline/chips/sid/decimator.rb +68 -0
  120. data/lib/badline/chips/sid/envelope.rb +236 -0
  121. data/lib/badline/chips/sid/filter.rb +227 -0
  122. data/lib/badline/chips/sid/keyed_parts.rb +286 -0
  123. data/lib/badline/chips/sid/voice.rb +69 -0
  124. data/lib/badline/chips/sid/waveform/combined.rb +128 -0
  125. data/lib/badline/chips/sid/waveform/fast_forward.rb +107 -0
  126. data/lib/badline/chips/sid/waveform/noise_writeback.rb +124 -0
  127. data/lib/badline/chips/sid/waveform.rb +305 -0
  128. data/lib/badline/chips/sid.rb +264 -0
  129. data/lib/badline/chips/ted/beam.rb +119 -0
  130. data/lib/badline/chips/ted/timers.rb +66 -0
  131. data/lib/badline/chips/ted.rb +143 -0
  132. data/lib/badline/chips/tia.rb +49 -0
  133. data/lib/badline/chips/vdc/keyed_parts.rb +105 -0
  134. data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
  135. data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -13
  136. data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -17
  137. data/lib/badline/{c128 → chips}/vdc/window.rb +1 -10
  138. data/lib/badline/{c128 → chips}/vdc.rb +6 -31
  139. data/lib/badline/chips/via/control_lines.rb +109 -0
  140. data/lib/badline/chips/via/fast_forward.rb +55 -0
  141. data/lib/badline/chips/via/interrupt_register.rb +60 -0
  142. data/lib/badline/chips/via/keyed_parts.rb +163 -0
  143. data/lib/badline/chips/via/shift_register.rb +168 -0
  144. data/lib/badline/chips/via/timer1.rb +120 -0
  145. data/lib/badline/chips/via/timer2.rb +117 -0
  146. data/lib/badline/chips/via.rb +267 -0
  147. data/lib/badline/chips/vic/bank.rb +135 -0
  148. data/lib/badline/chips/vic/border_mask.rb +78 -0
  149. data/lib/badline/chips/vic/collisions.rb +106 -0
  150. data/lib/badline/chips/vic/color_patches.rb +38 -0
  151. data/lib/badline/chips/vic/display_state.rb +168 -0
  152. data/lib/badline/chips/vic/graphics_mode.rb +166 -0
  153. data/lib/badline/chips/vic/graphics_shifter.rb +183 -0
  154. data/lib/badline/chips/vic/keyed_parts.rb +228 -0
  155. data/lib/badline/chips/vic/keyed_sprites.rb +225 -0
  156. data/lib/badline/chips/vic/keyed_state.rb +102 -0
  157. data/lib/badline/chips/vic/register_log.rb +65 -0
  158. data/lib/badline/chips/vic/registers.rb +188 -0
  159. data/lib/badline/chips/vic/sequencer.rb +275 -0
  160. data/lib/badline/chips/vic/sequencer_output.rb +118 -0
  161. data/lib/badline/chips/vic/sprite/internal_bus.rb +59 -0
  162. data/lib/badline/chips/vic/sprite/shifter.rb +148 -0
  163. data/lib/badline/chips/vic/sprite/timing.rb +58 -0
  164. data/lib/badline/chips/vic/sprite.rb +337 -0
  165. data/lib/badline/chips/vic/sprites.rb +281 -0
  166. data/lib/badline/chips/vic.rb +787 -0
  167. data/lib/badline/chips/vic_i/keyed_parts.rb +142 -0
  168. data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +2 -30
  169. data/lib/badline/chips/vic_i/sound/output.rb +85 -0
  170. data/lib/badline/chips/vic_i/sound.rb +227 -0
  171. data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
  172. data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +6 -6
  173. data/lib/badline/chips/z80/arithmetic.rb +119 -0
  174. data/lib/badline/chips/z80/bit_page.rb +57 -0
  175. data/lib/badline/chips/z80/block_io.rb +60 -0
  176. data/lib/badline/chips/z80/block_transfers.rb +61 -0
  177. data/lib/badline/chips/z80/bus_cycles.rb +113 -0
  178. data/lib/badline/chips/z80/core.rb +115 -0
  179. data/lib/badline/chips/z80/exchanges.rb +52 -0
  180. data/lib/badline/chips/z80/extended_page.rb +91 -0
  181. data/lib/badline/chips/z80/flags.rb +39 -0
  182. data/lib/badline/chips/z80/interrupt_acceptance.rb +48 -0
  183. data/lib/badline/chips/z80/jumps.rb +84 -0
  184. data/lib/badline/chips/z80/keyed_state.rb +73 -0
  185. data/lib/badline/chips/z80/loads.rb +100 -0
  186. data/lib/badline/chips/z80/main_page.rb +136 -0
  187. data/lib/badline/chips/z80/registers.rb +122 -0
  188. data/lib/badline/chips/z80/shifts.rb +66 -0
  189. data/lib/badline/chips/z80.rb +13 -0
  190. data/lib/badline/chips.rb +10 -0
  191. data/lib/badline/core.rb +13 -32
  192. data/lib/badline/drives/datasette/keyed_state.rb +38 -0
  193. data/lib/badline/drives/datasette.rb +173 -0
  194. data/lib/badline/drives/engine/core.rb +152 -0
  195. data/lib/badline/drives/engine/fast_serial.rb +75 -0
  196. data/lib/badline/drives/engine/idle.rb +127 -0
  197. data/lib/badline/drives/engine/idle_cpu.rb +30 -0
  198. data/lib/badline/drives/engine/orbit.rb +81 -0
  199. data/lib/badline/drives/engine/serial_lines.rb +72 -0
  200. data/lib/badline/drives/engine/sleep.rb +114 -0
  201. data/lib/badline/drives/engine/vias.rb +86 -0
  202. data/lib/badline/drives/engine/watch.rb +152 -0
  203. data/lib/badline/drives/engine.rb +11 -0
  204. data/lib/badline/drives/model1541/bus.rb +75 -0
  205. data/lib/badline/drives/model1541/byte_ready.rb +50 -0
  206. data/lib/badline/drives/model1541/cpu.rb +13 -0
  207. data/lib/badline/drives/model1541/disk.rb +318 -0
  208. data/lib/badline/drives/model1541/disk_via.rb +38 -0
  209. data/lib/badline/drives/model1541/gcr.rb +59 -0
  210. data/lib/badline/drives/model1541/keyed_state.rb +251 -0
  211. data/lib/badline/drives/model1541/mechanism.rb +313 -0
  212. data/lib/badline/drives/model1541/rotation.rb +123 -0
  213. data/lib/badline/drives/model1541/sector_reader.rb +78 -0
  214. data/lib/badline/drives/model1541/serial_port.rb +20 -0
  215. data/lib/badline/drives/model1541/track.rb +100 -0
  216. data/lib/badline/drives/model1541.rb +80 -0
  217. data/lib/badline/drives/model1571/bus.rb +100 -0
  218. data/lib/badline/drives/model1571/cpu.rb +13 -0
  219. data/lib/badline/drives/model1571/keyed_state.rb +108 -0
  220. data/lib/badline/drives/model1571/serial_port.rb +39 -0
  221. data/lib/badline/drives/model1571/serial_via.rb +27 -0
  222. data/lib/badline/drives/model1571/wd1770.rb +108 -0
  223. data/lib/badline/drives/model1571.rb +141 -0
  224. data/lib/badline/drives/model1581/bus.rb +126 -0
  225. data/lib/badline/drives/model1581/cpu.rb +13 -0
  226. data/lib/badline/drives/model1581/disk.rb +133 -0
  227. data/lib/badline/drives/model1581/keyed_state.rb +280 -0
  228. data/lib/badline/drives/model1581/mechanism.rb +98 -0
  229. data/lib/badline/drives/model1581/serial_port.rb +54 -0
  230. data/lib/badline/drives/model1581/slot.rb +61 -0
  231. data/lib/badline/drives/model1581/track.rb +102 -0
  232. data/lib/badline/drives/model1581/track_bytes.rb +77 -0
  233. data/lib/badline/drives/model1581/wd1772/registers.rb +91 -0
  234. data/lib/badline/drives/model1581/wd1772/sector_writes.rb +75 -0
  235. data/lib/badline/drives/model1581/wd1772/sectors.rb +152 -0
  236. data/lib/badline/drives/model1581/wd1772/stepping.rb +111 -0
  237. data/lib/badline/drives/model1581/wd1772/tracks.rb +127 -0
  238. data/lib/badline/drives/model1581/wd1772/turn.rb +75 -0
  239. data/lib/badline/drives/model1581/wd1772.rb +216 -0
  240. data/lib/badline/drives/model1581.rb +206 -0
  241. data/lib/badline/drives/serial_bus.rb +161 -0
  242. data/lib/badline/drives.rb +8 -0
  243. data/lib/badline/frontend/app.rb +3 -3
  244. data/lib/badline/frontend/boot.rb +4 -4
  245. data/lib/badline/frontend/controls.rb +19 -3
  246. data/lib/badline/frontend/drive_led.rb +44 -21
  247. data/lib/badline/frontend/machine_window.rb +3 -1
  248. data/lib/badline/frontend/menu/menu_dialogs.rb +2 -2
  249. data/lib/badline/frontend/player/filter_view.rb +1 -1
  250. data/lib/badline/frontend/player/player_controller.rb +2 -2
  251. data/lib/badline/frontend/player/player_screen.rb +1 -0
  252. data/lib/badline/frontend/player/theme.rb +7 -7
  253. data/lib/badline/frontend/snapshots.rb +12 -1
  254. data/lib/badline/frontend/timeline.rb +30 -12
  255. data/lib/badline/input/control_ports.rb +78 -0
  256. data/lib/badline/input/joystick.rb +27 -0
  257. data/lib/badline/input/keyboard.rb +114 -0
  258. data/lib/badline/input/matrix_typist.rb +98 -0
  259. data/lib/badline/input.rb +4 -0
  260. data/lib/badline/kernal_trap/chrout.rb +45 -0
  261. data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
  262. data/lib/badline/kernal_trap/dos/channel.rb +156 -0
  263. data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -26
  264. data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -10
  265. data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
  266. data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -9
  267. data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -19
  268. data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
  269. data/lib/badline/kernal_trap/{drive.rb → dos.rb} +9 -27
  270. data/lib/badline/kernal_trap/file_routine.rb +4 -4
  271. data/lib/badline/kernal_trap/keyed_state.rb +150 -0
  272. data/lib/badline/kernal_trap/layout.rb +75 -11
  273. data/lib/badline/kernal_trap/load.rb +19 -21
  274. data/lib/badline/kernal_trap/routine.rb +12 -0
  275. data/lib/badline/kernal_trap/save.rb +12 -22
  276. data/lib/badline/kernal_trap/serial.rb +8 -24
  277. data/lib/badline/kernal_trap.rb +3 -2
  278. data/lib/badline/machine/clocking.rb +1 -1
  279. data/lib/badline/machine/keyboard_buffer.rb +49 -0
  280. data/lib/badline/machine/settling.rb +29 -0
  281. data/lib/badline/machine.rb +10 -7
  282. data/lib/badline/media/boot_disk.rb +14 -2
  283. data/lib/badline/media/extensions.rb +10 -0
  284. data/lib/badline/media/true_drive.rb +1 -1
  285. data/lib/badline/media/tune.rb +2 -2
  286. data/lib/badline/media.rb +3 -3
  287. data/lib/badline/memory.rb +3 -6
  288. data/lib/badline/model.rb +1 -1
  289. data/lib/badline/options/family.rb +5 -2
  290. data/lib/badline/options/help.rb +42 -16
  291. data/lib/badline/options/table.rb +2 -0
  292. data/lib/badline/options/validation.rb +2 -0
  293. data/lib/badline/options.rb +6 -1
  294. data/lib/badline/plus4/acia.rb +45 -0
  295. data/lib/badline/plus4/bus.rb +312 -0
  296. data/lib/badline/plus4/cpu.rb +10 -0
  297. data/lib/badline/plus4/cpu_port.rb +93 -0
  298. data/lib/badline/plus4/keyboard_port.rb +51 -0
  299. data/lib/badline/plus4/model.rb +38 -0
  300. data/lib/badline/plus4/user_port.rb +31 -0
  301. data/lib/badline/plus4.rb +164 -0
  302. data/lib/badline/roms/README +44 -6
  303. data/lib/badline/roms/plus4/basic.rom +0 -0
  304. data/lib/badline/roms/plus4/function-high.rom +0 -0
  305. data/lib/badline/roms/plus4/function-low.rom +0 -0
  306. data/lib/badline/roms/plus4/kernal-ntsc.rom +0 -0
  307. data/lib/badline/roms/plus4/kernal-pal.rom +0 -0
  308. data/lib/badline/sdl.rb +1 -0
  309. data/lib/badline/{storage/sid_file.rb → sid_tune/file.rb} +3 -3
  310. data/lib/badline/{storage → sid_tune}/hvsc.rb +7 -7
  311. data/lib/badline/{storage → sid_tune}/song_lengths.rb +2 -2
  312. data/lib/badline/{storage → sid_tune}/stil/credit.rb +1 -1
  313. data/lib/badline/{storage → sid_tune}/stil.rb +3 -3
  314. data/lib/badline/sid_tune.rb +6 -0
  315. data/lib/badline/snapshot/c128_setup.rb +32 -0
  316. data/lib/badline/snapshot/c64_setup.rb +83 -0
  317. data/lib/badline/snapshot/container.rb +4 -0
  318. data/lib/badline/snapshot/field_doc/markdown.rb +112 -0
  319. data/lib/badline/snapshot/field_doc.rb +109 -0
  320. data/lib/badline/snapshot/image.rb +132 -46
  321. data/lib/badline/snapshot/keyed/cursor.rb +40 -0
  322. data/lib/badline/snapshot/keyed/modules.rb +66 -0
  323. data/lib/badline/snapshot/keyed/reader.rb +188 -0
  324. data/lib/badline/snapshot/keyed/recorder.rb +88 -0
  325. data/lib/badline/snapshot/keyed/report.rb +26 -0
  326. data/lib/badline/snapshot/keyed/writer.rb +55 -0
  327. data/lib/badline/snapshot/keyed.rb +64 -0
  328. data/lib/badline/snapshot/machine_state.rb +17 -64
  329. data/lib/badline/snapshot/storage_setup.rb +63 -0
  330. data/lib/badline/snapshot/vic20_setup.rb +28 -0
  331. data/lib/badline/snapshot/vice/c64_mem.rb +1 -1
  332. data/lib/badline/snapshot/vice/restore.rb +1 -1
  333. data/lib/badline/snapshot/vice/reu1764.rb +3 -3
  334. data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
  335. data/lib/badline/snapshot/vice.rb +13 -35
  336. data/lib/badline/snapshot.rb +44 -22
  337. data/lib/badline/storage/crt_file.rb +3 -1
  338. data/lib/badline/storage/d64_image.rb +0 -2
  339. data/lib/badline/storage/d71_image.rb +0 -2
  340. data/lib/badline/storage/d81_image.rb +0 -2
  341. data/lib/badline/storage/disk_image.rb +3 -6
  342. data/lib/badline/storage/g64_image.rb +10 -5
  343. data/lib/badline/storage/host_directory.rb +0 -5
  344. data/lib/badline/storage/t64.rb +2 -8
  345. data/lib/badline/storage/tap.rb +43 -15
  346. data/lib/badline/storage/unavailable.rb +1 -1
  347. data/lib/badline/storage.rb +0 -37
  348. data/lib/badline/support/c128_checkpoint.rb +39 -0
  349. data/lib/badline/support/checkpoint.rb +108 -0
  350. data/lib/badline/support/vic20_checkpoint.rb +38 -0
  351. data/lib/badline/support.rb +5 -0
  352. data/lib/badline/version.rb +1 -1
  353. data/lib/badline/vic20/attachments.rb +8 -5
  354. data/lib/badline/vic20/bus/keyed_state.rb +52 -0
  355. data/lib/badline/vic20/bus.rb +2 -25
  356. data/lib/badline/vic20/cpu.rb +1 -1
  357. data/lib/badline/vic20/keyed_modules.rb +73 -0
  358. data/lib/badline/vic20/keyed_state.rb +45 -0
  359. data/lib/badline/vic20/port_wiring.rb +4 -4
  360. data/lib/badline/vic20/user_via_ports.rb +2 -2
  361. data/lib/badline/vic20.rb +22 -17
  362. data/lib/badline.rb +1 -0
  363. metadata +271 -228
  364. data/lib/badline/address_bus/extra_sids.rb +0 -30
  365. data/lib/badline/address_bus/fittings.rb +0 -38
  366. data/lib/badline/address_bus/pla.rb +0 -147
  367. data/lib/badline/address_bus/roms.rb +0 -39
  368. data/lib/badline/address_bus/saved_state.rb +0 -66
  369. data/lib/badline/address_bus/sid_slots.rb +0 -42
  370. data/lib/badline/address_bus.rb +0 -216
  371. data/lib/badline/c128/bus_state.rb +0 -53
  372. data/lib/badline/c128/saved_state.rb +0 -143
  373. data/lib/badline/cartridge/action_replay.rb +0 -126
  374. data/lib/badline/cartridge/atomic_power.rb +0 -24
  375. data/lib/badline/cartridge/bank.rb +0 -81
  376. data/lib/badline/cartridge/comal80.rb +0 -50
  377. data/lib/badline/cartridge/dinamic.rb +0 -34
  378. data/lib/badline/cartridge/easy_flash.rb +0 -145
  379. data/lib/badline/cartridge/epyx_fastload.rb +0 -79
  380. data/lib/badline/cartridge/final_cartridge3.rb +0 -89
  381. data/lib/badline/cartridge/flash.rb +0 -306
  382. data/lib/badline/cartridge/freezer.rb +0 -33
  383. data/lib/badline/cartridge/fun_play.rb +0 -38
  384. data/lib/badline/cartridge/g_mod2.rb +0 -74
  385. data/lib/badline/cartridge/game_system.rb +0 -40
  386. data/lib/badline/cartridge/geo_ram.rb +0 -79
  387. data/lib/badline/cartridge/kcs_power.rb +0 -75
  388. data/lib/badline/cartridge/mach5.rb +0 -32
  389. data/lib/badline/cartridge/magic_desk.rb +0 -30
  390. data/lib/badline/cartridge/ocean.rb +0 -35
  391. data/lib/badline/cartridge/pagefox.rb +0 -68
  392. data/lib/badline/cartridge/retro_replay.rb +0 -320
  393. data/lib/badline/cartridge/rex_utility.rb +0 -29
  394. data/lib/badline/cartridge/rgcd.rb +0 -58
  395. data/lib/badline/cartridge/simons_basic.rb +0 -35
  396. data/lib/badline/cartridge/standard.rb +0 -15
  397. data/lib/badline/cartridge/super_games.rb +0 -48
  398. data/lib/badline/cartridge/westermann.rb +0 -30
  399. data/lib/badline/cartridge/zaxxon.rb +0 -66
  400. data/lib/badline/cartridge.rb +0 -303
  401. data/lib/badline/checkpoint.rb +0 -98
  402. data/lib/badline/chrout_trap.rb +0 -43
  403. data/lib/badline/cia/fast_forward.rb +0 -60
  404. data/lib/badline/cia/interrupt_register.rb +0 -143
  405. data/lib/badline/cia/serial.rb +0 -275
  406. data/lib/badline/cia/state.rb +0 -47
  407. data/lib/badline/cia/timer.rb +0 -206
  408. data/lib/badline/cia.rb +0 -279
  409. data/lib/badline/color_memory.rb +0 -25
  410. data/lib/badline/computer/attachments.rb +0 -88
  411. data/lib/badline/computer/saved_state.rb +0 -117
  412. data/lib/badline/computer/true_drives.rb +0 -69
  413. data/lib/badline/control_ports.rb +0 -76
  414. data/lib/badline/cpu/addressing.rb +0 -131
  415. data/lib/badline/cpu/boundary.rb +0 -54
  416. data/lib/badline/cpu/core.rb +0 -165
  417. data/lib/badline/cpu/microcode.rb +0 -177
  418. data/lib/badline/cpu/operations.rb +0 -88
  419. data/lib/badline/cpu/saved_state.rb +0 -115
  420. data/lib/badline/cpu/stack_operations.rb +0 -82
  421. data/lib/badline/cpu.rb +0 -10
  422. data/lib/badline/cpu_port.rb +0 -112
  423. data/lib/badline/datasette.rb +0 -161
  424. data/lib/badline/debug_register.rb +0 -28
  425. data/lib/badline/drive/core.rb +0 -147
  426. data/lib/badline/drive/fast_serial.rb +0 -73
  427. data/lib/badline/drive/idle.rb +0 -125
  428. data/lib/badline/drive/idle_cpu.rb +0 -28
  429. data/lib/badline/drive/orbit.rb +0 -79
  430. data/lib/badline/drive/serial_lines.rb +0 -73
  431. data/lib/badline/drive/sleep.rb +0 -112
  432. data/lib/badline/drive/vias.rb +0 -84
  433. data/lib/badline/drive/watch.rb +0 -150
  434. data/lib/badline/drive.rb +0 -11
  435. data/lib/badline/drive1541/bus.rb +0 -86
  436. data/lib/badline/drive1541/byte_ready.rb +0 -48
  437. data/lib/badline/drive1541/cpu.rb +0 -11
  438. data/lib/badline/drive1541/disk.rb +0 -315
  439. data/lib/badline/drive1541/disk_state.rb +0 -86
  440. data/lib/badline/drive1541/disk_via.rb +0 -36
  441. data/lib/badline/drive1541/gcr.rb +0 -57
  442. data/lib/badline/drive1541/mechanism.rb +0 -313
  443. data/lib/badline/drive1541/mechanism_state.rb +0 -68
  444. data/lib/badline/drive1541/rotation.rb +0 -121
  445. data/lib/badline/drive1541/sector_reader.rb +0 -76
  446. data/lib/badline/drive1541/serial_port.rb +0 -18
  447. data/lib/badline/drive1541/track.rb +0 -98
  448. data/lib/badline/drive1541.rb +0 -111
  449. data/lib/badline/drive1571/bus.rb +0 -111
  450. data/lib/badline/drive1571/cpu.rb +0 -11
  451. data/lib/badline/drive1571/serial_port.rb +0 -37
  452. data/lib/badline/drive1571/serial_via.rb +0 -25
  453. data/lib/badline/drive1571/wd1770.rb +0 -120
  454. data/lib/badline/drive1571.rb +0 -175
  455. data/lib/badline/drive1581/bus.rb +0 -137
  456. data/lib/badline/drive1581/cpu.rb +0 -11
  457. data/lib/badline/drive1581/disk.rb +0 -135
  458. data/lib/badline/drive1581/disk_state.rb +0 -87
  459. data/lib/badline/drive1581/mechanism.rb +0 -117
  460. data/lib/badline/drive1581/serial_port.rb +0 -52
  461. data/lib/badline/drive1581/slot.rb +0 -78
  462. data/lib/badline/drive1581/track.rb +0 -100
  463. data/lib/badline/drive1581/track_bytes.rb +0 -75
  464. data/lib/badline/drive1581/wd1772/registers.rb +0 -89
  465. data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
  466. data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
  467. data/lib/badline/drive1581/wd1772/state.rb +0 -66
  468. data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
  469. data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
  470. data/lib/badline/drive1581/wd1772/turn.rb +0 -73
  471. data/lib/badline/drive1581/wd1772.rb +0 -216
  472. data/lib/badline/drive1581.rb +0 -233
  473. data/lib/badline/iec_bus.rb +0 -159
  474. data/lib/badline/instruction.rb +0 -334
  475. data/lib/badline/instruction_set/arithmetic.rb +0 -114
  476. data/lib/badline/instruction_set/bitwise.rb +0 -126
  477. data/lib/badline/instruction_set/branch.rb +0 -79
  478. data/lib/badline/instruction_set/flag.rb +0 -63
  479. data/lib/badline/instruction_set/illegal.rb +0 -270
  480. data/lib/badline/instruction_set/inc_dec.rb +0 -69
  481. data/lib/badline/instruction_set/stack.rb +0 -52
  482. data/lib/badline/instruction_set/transfer.rb +0 -137
  483. data/lib/badline/instruction_set.rb +0 -55
  484. data/lib/badline/interrupts.rb +0 -104
  485. data/lib/badline/joystick.rb +0 -25
  486. data/lib/badline/kernal_trap/channel.rb +0 -181
  487. data/lib/badline/keyboard.rb +0 -112
  488. data/lib/badline/keyboard_buffer.rb +0 -33
  489. data/lib/badline/ram_expansion/banking.rb +0 -30
  490. data/lib/badline/ram_expansion/plus256k.rb +0 -54
  491. data/lib/badline/ram_expansion/plus60k.rb +0 -43
  492. data/lib/badline/ram_expansion/unexpanded.rb +0 -28
  493. data/lib/badline/ram_expansion.rb +0 -21
  494. data/lib/badline/reu/dma/saved_state.rb +0 -50
  495. data/lib/badline/reu/dma.rb +0 -273
  496. data/lib/badline/reu/ram.rb +0 -107
  497. data/lib/badline/reu/saved_state.rb +0 -80
  498. data/lib/badline/reu/trigger.rb +0 -32
  499. data/lib/badline/reu.rb +0 -289
  500. data/lib/badline/sid/catch_up.rb +0 -120
  501. data/lib/badline/sid/decimator.rb +0 -64
  502. data/lib/badline/sid/envelope/state.rb +0 -68
  503. data/lib/badline/sid/envelope.rb +0 -239
  504. data/lib/badline/sid/filter.rb +0 -263
  505. data/lib/badline/sid/voice.rb +0 -77
  506. data/lib/badline/sid/waveform/combined.rb +0 -126
  507. data/lib/badline/sid/waveform/fast_forward.rb +0 -105
  508. data/lib/badline/sid/waveform/noise_writeback.rb +0 -122
  509. data/lib/badline/sid/waveform/state.rb +0 -66
  510. data/lib/badline/sid/waveform.rb +0 -305
  511. data/lib/badline/sid.rb +0 -303
  512. data/lib/badline/snapshot/setup.rb +0 -75
  513. data/lib/badline/snapshot/state.rb +0 -189
  514. data/lib/badline/time_of_day.rb +0 -228
  515. data/lib/badline/traps.rb +0 -19
  516. data/lib/badline/via/control_lines.rb +0 -122
  517. data/lib/badline/via/fast_forward.rb +0 -53
  518. data/lib/badline/via/interrupt_register.rb +0 -67
  519. data/lib/badline/via/shift_register.rb +0 -180
  520. data/lib/badline/via/state.rb +0 -42
  521. data/lib/badline/via/timer1.rb +0 -131
  522. data/lib/badline/via/timer2.rb +0 -133
  523. data/lib/badline/via.rb +0 -266
  524. data/lib/badline/vic/bank.rb +0 -133
  525. data/lib/badline/vic/border_mask.rb +0 -86
  526. data/lib/badline/vic/collisions.rb +0 -115
  527. data/lib/badline/vic/color_patches.rb +0 -47
  528. data/lib/badline/vic/display_state.rb +0 -185
  529. data/lib/badline/vic/graphics_mode.rb +0 -164
  530. data/lib/badline/vic/graphics_shifter.rb +0 -207
  531. data/lib/badline/vic/register_log.rb +0 -81
  532. data/lib/badline/vic/registers.rb +0 -195
  533. data/lib/badline/vic/sequencer.rb +0 -275
  534. data/lib/badline/vic/sequencer_output.rb +0 -116
  535. data/lib/badline/vic/sequencer_state.rb +0 -89
  536. data/lib/badline/vic/sprite/internal_bus.rb +0 -68
  537. data/lib/badline/vic/sprite/saved_state.rb +0 -64
  538. data/lib/badline/vic/sprite/shifter.rb +0 -146
  539. data/lib/badline/vic/sprite/timing.rb +0 -56
  540. data/lib/badline/vic/sprite.rb +0 -337
  541. data/lib/badline/vic/sprites.rb +0 -282
  542. data/lib/badline/vic/sprites_state.rb +0 -57
  543. data/lib/badline/vic.rb +0 -853
  544. data/lib/badline/vic20/saved_state.rb +0 -124
  545. data/lib/badline/vic20/sound/output.rb +0 -83
  546. data/lib/badline/vic20/sound.rb +0 -233
  547. data/lib/badline/vic20/vic/saved_state.rb +0 -55
  548. data/lib/badline/z80/arithmetic.rb +0 -117
  549. data/lib/badline/z80/bit_page.rb +0 -55
  550. data/lib/badline/z80/block_io.rb +0 -58
  551. data/lib/badline/z80/block_transfers.rb +0 -59
  552. data/lib/badline/z80/bus_cycles.rb +0 -111
  553. data/lib/badline/z80/core.rb +0 -113
  554. data/lib/badline/z80/exchanges.rb +0 -50
  555. data/lib/badline/z80/extended_page.rb +0 -89
  556. data/lib/badline/z80/flags.rb +0 -37
  557. data/lib/badline/z80/interrupt_acceptance.rb +0 -46
  558. data/lib/badline/z80/jumps.rb +0 -82
  559. data/lib/badline/z80/loads.rb +0 -98
  560. data/lib/badline/z80/main_page.rb +0 -134
  561. data/lib/badline/z80/registers.rb +0 -120
  562. data/lib/badline/z80/saved_state.rb +0 -69
  563. data/lib/badline/z80/shifts.rb +0 -64
  564. data/lib/badline/z80.rb +0 -11
  565. /data/lib/badline/snapshot/{fields.rb → vice/fields.rb} +0 -0
data/doc/snapshots.md CHANGED
@@ -28,44 +28,72 @@ and `$XDG_DATA_HOME/badline` or `~/.local/share/badline` elsewhere.
28
28
 
29
29
  Both executables do this, and both open a `.vsf` given as the media,
30
30
  in a machine built as the saved one was, whatever `--model` says.
31
- `--save-snapshot FILE` saves one to `FILE` after the last frame. A
32
- snapshot that fails to open leaves the machine running as it was.
31
+ `--save-snapshot FILE` saves one to `FILE` after the last frame, and
32
+ `--vice` adds VICE's modules to it (see [VICE](#vice)). A snapshot that
33
+ fails to open leaves the machine running as it was.
34
+
35
+ ## Which snapshots load
36
+
37
+ Snapshots from badline 0.14.0 on load in that version and every later
38
+ one. Each part of the machine is saved as named fields, so a later
39
+ badline skips a field it no longer needs, and a field an earlier one
40
+ didn't save starts as it does when the machine is switched on. What a
41
+ restore leaves out or changes is printed, such as a module missing from
42
+ the file. [snapshot-format.md](snapshot-format.md) lists every field.
43
+
44
+ Snapshots from badline 0.13 and earlier are refused, with a message
45
+ naming the version that saved them, which still opens them. No snapshot
46
+ loaded across releases before 0.14.0, and none converts.
33
47
 
34
48
  ## From Ruby
35
49
 
36
50
  `computer.save_snapshot(path)` saves, `computer.restore_snapshot(path)`
37
51
  takes a machine back to a snapshot, and `Badline::Snapshot.load(path)`
38
52
  builds a new machine as the saved one was built and restores it.
39
- `computer.snapshot` and `computer.restore(state)` do the same in memory,
40
- without a file. A restore that fails leaves the machine as it was.
53
+ `computer.snapshot` returns a `Badline::Snapshot::Image` in memory,
54
+ without a file, and `computer.restore(image)` takes the machine back to
55
+ it; `image.load` builds a new machine from it. A restore that fails
56
+ leaves the machine as it was. `computer.export_snapshot(path)` saves with
57
+ VICE's modules too.
58
+
59
+ Saving first runs the machine on to the next instruction boundary, and
60
+ to the end of an REU transfer under way, so it advances the machine by a
61
+ few cycles: usually under a hundred, and up to about 262,000 for an REU
62
+ swapping 64K. `computer.cycles` afterwards says where it was saved. A
63
+ save straight after another runs no cycles and writes the same file. In
64
+ the window this happens between frames, and the cycles fold into the
65
+ next frame. `computer.snapshot` in memory saves the same way.
41
66
 
42
67
  ## What a snapshot holds
43
68
 
44
- A snapshot holds the machine as it was on the cycle it was saved: the
45
- chips down to the instruction step and the pixel pipeline, the RAM and
69
+ A snapshot holds the machine as it was at the instruction boundary it
70
+ was saved at: the chips down to the pixel pipeline, the RAM and
46
71
  any +60K or +256K expansion, the cartridge with its RAM and flash, a
47
72
  GEO-RAM, a true 1541 with its RAM, its VIAs and the disk under the head,
48
73
  a disk or directory mounted through the traps with its open channels,
49
74
  and the tape with its place on it. A restored machine runs on exactly
50
75
  as the saved one would have.
51
76
 
52
- A tape, a `.t64` archive and a disk image mounted through the traps come
53
- back with their contents from the snapshot, so they need no file to
54
- restore. A true drive's disk opens again from its image's path, with its
55
- tracks as the drive last saw them. When that file is gone, the disk
56
- comes back from the tracks alone, write-protected. A directory mounted
57
- as device 8 opens again from its path. What the host holds stays the
77
+ A tape, a `.t64` archive, a disk image mounted through the traps and a
78
+ true drive's disk come back with their contents from the snapshot, so
79
+ they need no file to restore. A true drive's disk holds its image as last
80
+ written to its file, with the tracks the drive has written since, and
81
+ writes back to that file while it is there. When the file is gone, the
82
+ disk comes back write-protected. A directory mounted as device 8 opens
83
+ again from its path. What the host holds stays the
58
84
  host's: the keyboard, the joysticks, the mouse and paddles, sound, and
59
85
  blocks given to `on_init` that hadn't run yet, which a restore reports.
60
86
 
61
87
  Every model saves this way, PAL, NTSC, old NTSC and Drean alike, and so
62
- does a machine with an REU, with its RAM, its registers and a transfer
63
- part way through. A snapshot only restores in the badline version that
64
- wrote it, into a machine with the same chip models, region, RAM
65
- expansion, REU, KERNAL, datasette and board. One saved before badline
66
- recorded the KERNAL and the datasette restores as a machine with the
67
- C64's KERNAL and a datasette, and one saved before it recorded the board
68
- restores on a C64's.
88
+ does a machine with an REU, with its RAM and its registers. A snapshot
89
+ restores into a machine with the same chip models, region, RAM
90
+ expansion, REU, KERNAL, datasette and board.
91
+
92
+ Text typed with `type_text` that the machine hasn't taken yet, such as
93
+ autostart's `RUN`, carries over, and so do the keys a C128 is typing on
94
+ its key matrix. The VIC-II's line in progress carries over to a badline
95
+ that draws lines the same way. A later badline that draws them another
96
+ way starts the rest of that line afresh, and says so.
69
97
 
70
98
  ## The VIC-20
71
99
 
@@ -73,10 +101,10 @@ restores on a C64's.
73
101
  slots and pause menu page. A VIC-20 snapshot holds its RAM and colour
74
102
  RAM, a cartridge's ROM, the VIC with its picture and sound, both VIAs,
75
103
  the CPU, the tape with its place on it, the disk or directory device 8
76
- serves through the traps and a true 1541, and restores into a VIC-20
77
- with the same RAM expansion. Its file names its machine `VIC20`, as
78
- xvic's do, and holds only the `BADLINE` module, so xvic doesn't open
79
- it, and badline doesn't open xvic's. Restoring a
104
+ serves through the traps and a true 1541 or 1581, and restores into a
105
+ VIC-20 with the same RAM expansion. Its file names its machine `VIC20`,
106
+ as xvic's do, and holds only badline's modules, so xvic doesn't open it,
107
+ and badline doesn't open xvic's. Restoring a
80
108
  VIC-20 snapshot while a C64 runs, or a C64 one while a VIC-20 runs,
81
109
  swaps the machine in the window.
82
110
 
@@ -85,30 +113,32 @@ swaps the machine in the window.
85
113
  `badline c128` saves and restores the same way too. A C128 snapshot
86
114
  holds its 128K of RAM, both colour RAM banks, the CPU port, the MMU's
87
115
  registers and the page pointer writes it holds, the VIC-IIe, both CIAs,
88
- the SID, the VDC with its RAM and registers, the CPU, a cartridge, the
89
- tape, the disk device 8 serves through the traps and a true 1541, and
90
- restores into a C128 of the same model with the same SID, built for the
91
- same mode. The VDC's picture is left out and painted again while the
92
- window shows it, and the window shows the VIC-IIe after a restore. Its
93
- file names its machine `C128`, as x128's do, and holds only the
94
- `BADLINE` module, so x128 doesn't open it, and badline doesn't open
95
- x128's. Restoring a C128 snapshot while another machine runs swaps the
116
+ the SID, the VDC with its RAM and registers, the 8502 and the Z80, a
117
+ cartridge, the tape, the disk device 8 serves through the traps and a
118
+ true 1541, 1571 or 1581, and restores into a C128 of the same model with
119
+ the same SID, built for the same mode. The VDC's picture is left out and
120
+ painted again while the window shows it, and the window shows the
121
+ VIC-IIe after a restore. Its file names its machine `C128`, as x128's
122
+ do, and holds only badline's modules, so x128 doesn't open it, and
123
+ badline doesn't open x128's. Restoring a C128 snapshot while another machine runs swaps the
96
124
  machine in the window, as for the VIC-20.
97
125
 
98
126
  ## VICE
99
127
 
100
- Snapshots use VICE's `.vsf` format. badline writes VICE's modules for
101
- the CPU, RAM and CPU port, both CIAs, the SID and the VIC-II, and an
102
- REU's `REU1764`, plus the ones x64sc needs to open the file, with
103
- nothing else attached to the cartridge port, nothing on the tape or user
104
- ports and no true drive. The VIC-II module names the chip as VICE does:
105
- the 6569 or 8565 on PAL, the 6567R8 or 8562 on NTSC, the 6567R56A on old
106
- NTSC and the 6572 on PAL-N. A `BADLINE` module, which VICE skips, holds
107
- the whole machine, and badline restores its own snapshots from it.
108
-
109
- x64sc 3.10 opens badline's snapshots, taken at the end of the
110
- instruction the CPU was in, and of an REU transfer under way, as long
111
- as its VIC-II model matches: `-model c64`, `c64c`, `ntsc`, `newntsc`,
128
+ Snapshots use VICE's `.vsf` format, and badline's own modules are named
129
+ `BL-` and something, which VICE skips. A C64 snapshot saved with
130
+ `--vice`, or `computer.export_snapshot(path)`, also holds VICE's
131
+ modules for the CPU, RAM and CPU port, both CIAs, the SID and the
132
+ VIC-II, and an REU's `REU1764`, plus the ones x64sc needs to open the
133
+ file, with nothing else attached to the cartridge port, nothing on the
134
+ tape or user ports and no true drive. The VIC-II module names the chip
135
+ as VICE does: the 6569 or 8565 on PAL, the 6567R8 or 8562 on NTSC, the
136
+ 6567R56A on old NTSC and the 6572 on PAL-N. badline restores such a
137
+ snapshot from its own modules, and leaves VICE's alone.
138
+
139
+ x64sc 3.10 opens those snapshots, which are saved between
140
+ instructions with no REU transfer under way, as long as its VIC-II
141
+ model matches: `-model c64`, `c64c`, `ntsc`, `newntsc`,
112
142
  `oldntsc` or `drean`, as `--model` names the machine. It takes the REU
113
143
  from the snapshot, keeps its own drives and leaves out the cartridge,
114
144
  the other expansions and the tape. A program x64sc runs on from badline's
@@ -49,13 +49,13 @@ module Badline
49
49
  def initialize(tune, subtune: nil, sid_models: tune.sid_models)
50
50
  @tune = tune
51
51
  @subtune = (subtune || tune.start_subtune).clamp(1, tune.subtunes) - 1
52
- @bus = AddressBus.new(sid_model: sid_models[0])
52
+ @bus = C64::Bus.new(sid_model: sid_models[0])
53
53
  # The CPU port as the KERNAL leaves it, which a PSID tune expects.
54
54
  @bus.poke(0x00, 0x2f)
55
55
  @bus.poke(0x01, 0x37)
56
56
  @bus.poke(VIDEO_STANDARD, tune.ntsc? ? 0 : 1)
57
57
  @bus.cia1.timer_a_latch = tune.ntsc? ? NTSC_KERNAL_TIMER : KERNAL_TIMER
58
- @cpu = CPU.new(@bus)
58
+ @cpu = Chips::CPU.new(@bus)
59
59
  @sid = @bus.sid
60
60
  @stereo = Stereo.new(@bus, tune, sid_models)
61
61
  @extras = @stereo.extras
@@ -74,26 +74,41 @@ module Badline
74
74
  settle
75
75
  end
76
76
 
77
- # The rig between frames: the bus and its chips, the extra SIDs, the
78
- # CPU, and the call waiting for the idle loop.
79
- def save_state(out)
80
- out.marker("BARE PLAYER")
81
- @bus.save_state(out)
82
- @extras.each { |sid| sid.save_state(out) }
83
- @cpu.save_state(out)
84
- out.optional_int(@pending).int(@argument).boolean(@idle)
77
+ # The rig between frames as keyed snapshot modules: the call waiting
78
+ # for the idle loop in BL-PLAYER, the memories, the CPU and its port,
79
+ # the chips and the extra SIDs, as BL-SID2 and BL-SID3.
80
+ def save_modules
81
+ bus = @bus
82
+ cpu = @cpu
83
+ sections = [Snapshot::Keyed.section("BL-PLAYER") do |out|
84
+ out.optional_int("pending", @pending).int("argument", @argument).bool("idle", @idle)
85
+ end]
86
+ sections << Snapshot::Keyed.section("BL-RAM") { |out| bus.ram.save_fields(out, "ram") }
87
+ sections << Snapshot::Keyed.section("BL-COLORRAM") { |out| bus.color_ram.save_fields(out, "ram") }
88
+ sections << Snapshot::Keyed.section("BL-CPU") do |out|
89
+ cpu.save_fields(out)
90
+ bus.save_port_fields(out)
91
+ end
92
+ sections << Snapshot::Keyed.section("BL-VIC") { |out| bus.vic.save_fields(out) }
93
+ sections << Snapshot::Keyed.section("BL-CIA1") { |out| bus.cia1.save_fields(out) }
94
+ sections << Snapshot::Keyed.section("BL-CIA2") { |out| bus.cia2.save_fields(out) }
95
+ sections << Snapshot::Keyed.section("BL-SID") { |out| bus.sid.save_fields(out) }
96
+ @extras.each_with_index do |sid, index|
97
+ sections << Snapshot::Keyed.section("BL-SID#{index + 2}") { |out| sid.save_fields(out) }
98
+ end
99
+ sections
85
100
  end
86
101
 
87
- # Takes a rig that hasn't started to where #save_state found one, in
102
+ # Takes a rig that hasn't started to where #save_modules found one, in
88
103
  # place of #start.
89
- def load_state(input)
90
- input.marker("BARE PLAYER")
91
- @bus.load_state(input)
92
- @extras.each { |sid| sid.load_state(input) }
93
- @cpu.load_state(input)
94
- @pending = input.optional_int
95
- @argument = input.int
96
- @idle = input.boolean?
104
+ def load_modules(modules)
105
+ load_bus_modules(modules)
106
+ @cpu.load_fields(modules.required("BL-CPU"))
107
+ @cpu.restored!
108
+ player = modules.required("BL-PLAYER")
109
+ @pending = player.optional_int("pending")
110
+ @argument = player.int("argument", 0)
111
+ @idle = player.bool("idle", false)
97
112
  @stereo.synthesize!
98
113
  install_dispatch
99
114
  end
@@ -128,6 +143,24 @@ module Badline
128
143
  @bus.cia1.timer_a_latch + 1
129
144
  end
130
145
 
146
+ def load_bus_modules(modules)
147
+ bus = @bus
148
+ bus.ram.load_fields(modules.required("BL-RAM"), "ram")
149
+ bus.color_ram.load_fields(modules.required("BL-COLORRAM"), "ram")
150
+ bus.load_port_fields(modules.required("BL-CPU"))
151
+ bus.restored!
152
+ bus.vic.load_fields(modules.required("BL-VIC"))
153
+ bus.cia1.load_fields(modules.required("BL-CIA1"))
154
+ bus.cia2.load_fields(modules.required("BL-CIA2"))
155
+ @stereo.sids.each_with_index do |sid, index|
156
+ sid.load_fields(modules.required(index.zero? ? "BL-SID" : "BL-SID#{index + 1}"))
157
+ sid.restored!
158
+ end
159
+ bus.vic.restored!
160
+ bus.cia1.restored!
161
+ bus.cia2.restored!
162
+ end
163
+
131
164
  def stub_address = @stub_address ||= @tune.driver_address
132
165
 
133
166
  def idle_address = stub_address + 3
@@ -164,7 +197,7 @@ module Badline
164
197
 
165
198
  # Tunes live under the ROMs as often as not, so $01 has to bank out
166
199
  # whatever covers the routine about to run. An RSID tune banks itself,
167
- # and `SIDFile#bank_for` hands back nil for it.
200
+ # and `SIDTune::File#bank_for` hands back nil for it.
168
201
  def dispatch
169
202
  bank = @tune.bank_for(@pending)
170
203
  @bus.poke(0x01, bank) if bank
@@ -49,8 +49,8 @@ module Badline
49
49
  def queue
50
50
  @queue ||= begin
51
51
  paths = @options.tune_paths
52
- queue = Media::Queue.new(entries(paths, @options.subtune), all_parts: @options.all_subtunes?,
53
- build: ->(dropped) { entries(dropped) })
52
+ queue = Queue.new(entries(paths, @options.subtune), all_parts: @options.all_subtunes?,
53
+ build: ->(dropped) { entries(dropped) })
54
54
  raise Error, "no .sid tunes in #{paths.join(', ')}" if queue.empty? && !paths.empty?
55
55
 
56
56
  queue
@@ -77,7 +77,7 @@ module Badline
77
77
  # below the directories, the first starting on `subtune` if given.
78
78
  def entries(paths, subtune = nil)
79
79
  tunes = []
80
- Media::Queue.files(paths, ".sid").each do |path|
80
+ Queue.files(paths, ".sid").each do |path|
81
81
  tunes << QueuedTune.new(path, @options, subtune: tunes.empty? ? subtune : nil)
82
82
  end
83
83
  tunes
@@ -223,9 +223,9 @@ module Badline
223
223
  end
224
224
 
225
225
  def stil(entry)
226
- list = Storage::STIL.locate(entry.path)
227
- hvsc_path = list && Storage::HVSC.path(entry.path, list)
228
- hvsc_path && (@stil_lists[list] ||= Storage::STIL.new(list)).entry(hvsc_path)
226
+ list = SIDTune::STIL.locate(entry.path)
227
+ hvsc_path = list && SIDTune::HVSC.path(entry.path, list)
228
+ hvsc_path && (@stil_lists[list] ||= SIDTune::STIL.new(list)).entry(hvsc_path)
229
229
  end
230
230
 
231
231
  def progress(done, total)
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Badline
4
4
  module Audio
5
- # Plays a Media::Queue of tunes interactively: the console's keys step
5
+ # Plays a Audio::Queue of tunes interactively: the console's keys step
6
6
  # between tunes and between a tune's subtunes, seek within the subtune, pause,
7
7
  # turn the queue's shuffle, loop and all-subtunes modes on and off, and
8
8
  # quit, and the status line follows along. Seeking runs the subtune
@@ -10,7 +10,7 @@ module Badline
10
10
  # forward, and from the latest of its Checkpoints at or before there to
11
11
  # go back, or to go forward when that checkpoint is further on than
12
12
  # where the subtune is. A subtune that plays to its end moves on as
13
- # Media::Queue#advance says. It stops at the end of the queue, on q, or
13
+ # Audio::Queue#advance says. It stops at the end of the queue, on q, or
14
14
  # on Ctrl-C.
15
15
  #
16
16
  # `renderer` builds the renderer for an entry's subtune at the sink's
@@ -17,7 +17,7 @@ module Badline
17
17
  def initialize(tune, subtune: nil, sid_models: tune.sid_models)
18
18
  @tune = tune
19
19
  @subtune = subtune || tune.start_subtune
20
- @computer = Computer.new(sid_model: sid_models[0])
20
+ @computer = C64.new(sid_model: sid_models[0])
21
21
  @stereo = Stereo.new(@computer.address_bus, tune, sid_models)
22
22
  @extras = @stereo.extras
23
23
  @multi = !@extras.empty?
@@ -39,18 +39,24 @@ module Badline
39
39
 
40
40
  def clock_hz = @computer.region.clock_hz
41
41
 
42
- # The whole machine, as Computer#snapshot takes it, and the extra SIDs,
43
- # once it plays.
44
- def save_state(out)
45
- @computer.save_state(out)
46
- @extras.each { |sid| sid.save_state(out) }
42
+ # The whole machine as its keyed snapshot modules, as it stands between
43
+ # frames, and the extra SIDs as BL-SID2 and BL-SID3, once it plays.
44
+ def save_modules
45
+ sections = @computer.save_modules
46
+ @extras.each_with_index do |sid, index|
47
+ sections << Snapshot::Keyed.section("BL-SID#{index + 2}") { |out| sid.save_fields(out) }
48
+ end
49
+ sections
47
50
  end
48
51
 
49
- # Takes a machine that hasn't started to where #save_state found one,
52
+ # Takes a machine that hasn't started to where #save_modules found one,
50
53
  # in place of #start.
51
- def load_state(input)
52
- @computer.load_state(input)
53
- @extras.each { |sid| sid.load_state(input) }
54
+ def load_modules(modules)
55
+ @computer.load_modules(modules)
56
+ @extras.each_with_index do |sid, index|
57
+ sid.load_fields(modules.required("BL-SID#{index + 2}"))
58
+ sid.restored!
59
+ end
54
60
  @stereo.synthesize!
55
61
  @started = true
56
62
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Badline
4
- module Media
4
+ module Audio
5
5
  # An ordered list of media files to go through one at a time, such as
6
6
  # the tunes of a player. Each entry is a file and the part of it to
7
7
  # start on, counting from 1, out of the parts the file holds: a .sid
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Badline
4
4
  module Audio
5
- # A .sid tune in the player's Media::Queue, read only once the queue or
5
+ # A .sid tune in the player's Audio::Queue, read only once the queue or
6
6
  # the player first asks about it, so a queue of a whole collection
7
7
  # starts at once. Its subtunes, SID model and lengths follow the options:
8
8
  # --subtune picks the subtune to start on, --sid the model and --seconds the
@@ -11,7 +11,7 @@ module Badline
11
11
  #
12
12
  # A file that won't read as a tune, or lacks the subtune asked for, gets
13
13
  # an #error and a single subtune.
14
- class QueuedTune < Media::Queue::Entry
14
+ class QueuedTune < Queue::Entry
15
15
  def initialize(path, options, subtune: nil)
16
16
  super(path)
17
17
  @options = options
@@ -39,7 +39,7 @@ module Badline
39
39
  @error
40
40
  end
41
41
 
42
- def tune = @tune ||= Storage::SIDFile.new(path)
42
+ def tune = @tune ||= SIDTune::File.new(path)
43
43
 
44
44
  # Lets go of the tune's data, which #tune reads again if asked.
45
45
  def release = @tune = nil
@@ -71,7 +71,7 @@ module Badline
71
71
  @parts = tune.subtunes
72
72
  @part = @subtune || tune.start_subtune
73
73
  @error = "no subtune #{@part}: the tune has #{@parts}" if @part > @parts
74
- rescue Storage::SIDFile::FormatError => e
74
+ rescue SIDTune::File::FormatError => e
75
75
  @error = e.message
76
76
  end
77
77
 
@@ -81,8 +81,8 @@ module Badline
81
81
  return @lengths if @lengths_read
82
82
 
83
83
  @lengths_read = true
84
- database = @options.songlengths || Storage::SongLengths.locate(path)
85
- @lengths = database && Storage::SongLengths.new(database).lengths(tune.md5)
84
+ database = @options.songlengths || SIDTune::SongLengths.locate(path)
85
+ @lengths = database && SIDTune::SongLengths.new(database).lengths(tune.md5)
86
86
  end
87
87
  end
88
88
  end
@@ -50,7 +50,7 @@ module Badline
50
50
  @subtune = subtune
51
51
  @rate = rate
52
52
  @sid_models = sid_models
53
- @filter_chunk = SID::FILTER_CHUNK
53
+ @filter_chunk = Chips::SID::FILTER_CHUNK
54
54
  @silent_samples = 0
55
55
  @level = 0
56
56
  @still = 0
@@ -136,17 +136,17 @@ module Badline
136
136
  # or before `cycles` if there is one, and returns the cycles into the
137
137
  # subtune it starts at.
138
138
  def start(cycles)
139
- state = @checkpoints&.latest(cycles)
140
- return start_afresh if state.nil?
139
+ sections = @checkpoints&.latest(cycles)
140
+ return start_afresh if sections.nil?
141
141
 
142
- input = Snapshot::StateReader.new(state)
143
- played = input.int
144
- resume(input)
142
+ modules = Snapshot::Keyed::Modules.new(sections)
143
+ audio = modules.required("BL-AUDIO")
144
+ restore_player(modules, audio)
145
145
  record
146
- player.stereo.sids.each { |sid| sid.load_recording(input) }
147
- @level = input.int
148
- @still = input.int
149
- played
146
+ player.stereo.sids.each_with_index { |sid, index| sid.load_recording_fields(audio, "sid#{index + 1}.rec.") }
147
+ @level = audio.int("level", 0)
148
+ @still = audio.int("still", 0)
149
+ audio.int("played", 0)
150
150
  end
151
151
 
152
152
  def start_afresh
@@ -157,13 +157,17 @@ module Badline
157
157
 
158
158
  def record = player.stereo.record(rate: @rate, filter_chunk: @filter_chunk, clock_hz: player.clock_hz)
159
159
 
160
- # Restores the player as it was, then puts back the SID models chosen
161
- # for this renderer.
162
- def resume(input)
160
+ # Restores the player as it was, on the SID models it was saved on,
161
+ # then puts back the SID models chosen for this renderer.
162
+ def restore_player(modules, audio)
163
163
  sids = player.stereo.sids
164
164
  chosen = sids.map(&:model)
165
- sids.each { |sid| refit(sid, Snapshot::Setup::SID_MODELS.fetch(input.int)) }
166
- player.load_state(input)
165
+ names = Snapshot::C64Setup::SID_MODELS.map(&:to_s)
166
+ sids.each_with_index do |sid, index|
167
+ name = audio.choice("sid#{index + 1}.model", names, sid.model.to_s)
168
+ refit(sid, Snapshot::C64Setup::SID_MODELS.find { |model| model.to_s == name } || sid.model)
169
+ end
170
+ player.load_modules(modules)
167
171
  sids.each_with_index { |sid, index| refit(sid, chosen[index]) }
168
172
  end
169
173
 
@@ -171,18 +175,25 @@ module Badline
171
175
  sid.model = model unless sid.model == model
172
176
  end
173
177
 
178
+ # The player's modules, after a BL-AUDIO module with the cycles into
179
+ # the subtune, each SID's model and how far its recording has got,
180
+ # and the silence count. The SIDs have caught up as the frame drained
181
+ # them, so they leave no samples behind.
174
182
  def save_checkpoint(played, clock_hz)
175
183
  checkpoints = @checkpoints
176
184
  return if checkpoints.nil? || !checkpoints.due?(played, clock_hz)
177
185
 
178
186
  sids = player.stereo.sids
179
- out = Snapshot::StateWriter.new
180
- out.int(played)
181
- sids.each { |sid| out.int(Snapshot::Setup::SID_MODELS.index(sid.model) || 0) }
182
- player.save_state(out)
183
- sids.each { |sid| sid.save_recording(out) }
184
- out.int(@level).int(@still)
185
- checkpoints.keep(played, out.state)
187
+ sections = player.save_modules
188
+ audio = Snapshot::Keyed.section("BL-AUDIO") do |out|
189
+ out.int("played", played)
190
+ sids.each_with_index do |sid, index|
191
+ out.text("sid#{index + 1}.model", sid.model.to_s)
192
+ sid.save_recording_fields(out, "sid#{index + 1}.rec.")
193
+ end
194
+ out.int("level", @level).int("still", @still)
195
+ end
196
+ checkpoints.keep(played, [audio, *sections])
186
197
  end
187
198
 
188
199
  # Counts the samples since the output last strayed more than QUIET
@@ -18,7 +18,7 @@ module Badline
18
18
  @sids = [bus.sid]
19
19
  @extras = []
20
20
  tune.sid_addresses.each do |address|
21
- sid = SID.new(model: models[@sids.size], at: address)
21
+ sid = Chips::SID.new(model: models[@sids.size], at: address)
22
22
  bus.add_sid(sid)
23
23
  @sids << sid
24
24
  @extras << sid
@@ -5,8 +5,8 @@ module Badline
5
5
  # The RAM the C128 KERNAL's bank numbers 0-15 reach, as its INDFET and
6
6
  # INDSTA reach it for LOAD, SAVE and the file name: the RAM bank of the
7
7
  # CR value the KERNAL's table at $F7F0 holds for the bank, with common
8
- # RAM in bank 0. The ROMs and I/O some of those CR values map are left
9
- # out.
8
+ # RAM in bank 0. The Bus lays the ROMs and I/O some of those CR values
9
+ # map over it.
10
10
  class Banks
11
11
  CONFIGURATIONS = 0xf7f0
12
12
 
@@ -18,6 +18,9 @@ module Badline
18
18
 
19
19
  def peek(bank, addr) = @ram.peek(physical(bank, addr))
20
20
 
21
+ # The CR value the KERNAL's table holds for the bank.
22
+ def configuration(bank) = @kernal_rom.peek(CONFIGURATIONS + (bank & 0x0f))
23
+
21
24
  def write(bank, addr, bytes)
22
25
  bytes.each_with_index { |byte, i| @ram.poke(physical(bank, (addr + i) & 0xffff), byte) }
23
26
  end
@@ -27,7 +30,7 @@ module Badline
27
30
  def physical(bank, addr)
28
31
  page = addr >> 8
29
32
  common = page < @mmu.common_low_pages || page >= @mmu.common_high_start
30
- ram_bank = common ? 0 : (@kernal_rom.peek(CONFIGURATIONS + (bank & 0x0f)) >> 6) & 0x01
33
+ ram_bank = common ? 0 : (configuration(bank) >> 6) & 0x01
31
34
  (ram_bank << 16) | addr
32
35
  end
33
36
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C128
5
+ class Bus
6
+ # The last access on the bus, which FAST mode's VIC and open bus read,
7
+ # in a keyed snapshot module (Snapshot::Keyed) under `prefix`, and
8
+ # what is worked out once the memories, the MMU and the chips are
9
+ # loaded: the banks each side sees and the keyboard's extra rows.
10
+ module KeyedState
11
+ def save_fields(out, prefix)
12
+ out.int("#{prefix}address", @address).int("#{prefix}data", @data)
13
+ end
14
+
15
+ def load_fields(input, prefix)
16
+ @address = input.word("#{prefix}address", @address)
17
+ @data = input.byte("#{prefix}data", @data)
18
+ end
19
+
20
+ # Both banks of colour RAM as bank0 and bank1.
21
+ def save_color_fields(out)
22
+ @color_lines.color_ram(0).save_fields(out, "bank0")
23
+ @color_lines.color_ram(1).save_fields(out, "bank1")
24
+ end
25
+
26
+ def load_color_fields(input)
27
+ @color_lines.color_ram(0).load_fields(input, "bank0")
28
+ @color_lines.color_ram(1).load_fields(input, "bank1")
29
+ end
30
+
31
+ # The 8502's port, as the C64's (C64::Bus::KeyedState).
32
+ def save_port_fields(out) = @cpu_port.save_fields(out, "port.")
33
+
34
+ def load_port_fields(input) = @cpu_port.load_fields(input, "port.")
35
+
36
+ def restored!
37
+ update_overlays!
38
+ @control_ports.extra_rows = 0xf8 | @vic.extra_keyboard_lines
39
+ end
40
+ end
41
+
42
+ include KeyedState
43
+ end
44
+ end
45
+ end