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
@@ -20,7 +20,7 @@ The character generator ROM.
20
20
  kernal-sx64.rom
21
21
  ---------------
22
22
  The SX-64's KERNAL, 251104-04. It boots with the SX-64's banner and
23
- colours, and loads from device 8 rather than tape. Computer.new(kernal:
23
+ colours, and loads from device 8 rather than tape. C64.new(kernal:
24
24
  :sx64) fits it, as --model sx64 does.
25
25
 
26
26
  Downloaded from
@@ -32,7 +32,7 @@ kernal-pet64.rom
32
32
  The KERNAL of the PET 64, 4064 and Educator 64, 901246-01. It boots
33
33
  with the "**** COMMODORE 4064 BASIC V2.0 ****" banner and a white
34
34
  cursor, and its interrupt routine keeps the border, background and
35
- sprite colours black unless bit 7 of $0286 is set. Computer.new(kernal:
35
+ sprite colours black unless bit 7 of $0286 is set. C64.new(kernal:
36
36
  :pet64) fits it, as --model pet64 does.
37
37
 
38
38
  Downloaded from
@@ -45,7 +45,7 @@ The C64GS's BASIC and KERNAL, 390852-01, 16 KB: BASIC for $A000-$BFFF
45
45
  followed by the KERNAL for $E000-$FFFF. Its BASIC is 901226-01's but
46
46
  for 30 unused bytes. Its KERNAL is 901227-03's with most changes in
47
47
  $F72C-$FC92, the cassette routines' place, and many jumps redirected to
48
- I/O error 5. Computer.new(kernal: :gs) fits both, as --model c64gs does.
48
+ I/O error 5. C64.new(kernal: :gs) fits both, as --model c64gs does.
49
49
 
50
50
  Downloaded from
51
51
  https://www.zimmers.net/anonftp/pub/cbm/firmware/computers/c64/64gs.390852-01.bin
@@ -54,7 +54,7 @@ MD5 049e657afafbdd802e8c6a4f88f3d730.
54
54
  dos1541.rom
55
55
  -----------
56
56
  The 1541 disk drive's DOS 2.6, 16 KB for $C000-$FFFF: 325302-01
57
- ($C000-$DFFF) followed by 901229-05 ($E000-$FFFF). Drive1541 loads it.
57
+ ($C000-$DFFF) followed by 901229-05 ($E000-$FFFF). Drives::Model1541 loads it.
58
58
 
59
59
  Both halves downloaded from
60
60
  https://www.zimmers.net/anonftp/pub/cbm/firmware/drives/new/1541/
@@ -64,7 +64,7 @@ SHA-1 ab16f56989b27d89babe5f89c5a8cb3da71a82f0.
64
64
  dos1571.rom
65
65
  -----------
66
66
  The 1571 disk drive's DOS 3.0, 310654-05, 32 KB for $8000-$FFFF.
67
- Drive1571 loads it.
67
+ Drives::Model1571 loads it.
68
68
 
69
69
  Downloaded from
70
70
  https://www.zimmers.net/anonftp/pub/cbm/firmware/drives/new/1571/1571-rom.310654-05.bin
@@ -73,7 +73,7 @@ SHA-1 f1be619c106641a685f6609e4d43d6fc9eac1e70.
73
73
  dos1581.rom
74
74
  -----------
75
75
  The 1581 disk drive's DOS, 318045-02, 32 KB for $8000-$FFFF.
76
- Drive1581 loads it.
76
+ Drives::Model1581 loads it.
77
77
 
78
78
  Downloaded from
79
79
  https://www.zimmers.net/anonftp/pub/cbm/firmware/drives/new/1581/1581-rom.318045-02.bin
@@ -132,3 +132,41 @@ c128/character.rom
132
132
  The character generator ROM, 390059-01 (characters.390059-01.bin),
133
133
  8 KB: the C64's set, the same as character.rom, followed by the C128's.
134
134
  SHA-1 29ed066d513f2d5c09ff26d9166ba23c2afb2b3f.
135
+
136
+ Commodore 264 series ROMs
137
+ =========================
138
+
139
+ Downloaded from
140
+ https://www.zimmers.net/anonftp/pub/cbm/firmware/computers/plus4/
141
+ for the Plus/4, the C16 and the C116, which share BASIC and the KERNAL.
142
+ Nothing maps them yet.
143
+
144
+ plus4/basic.rom
145
+ ---------------
146
+ BASIC 3.5, 318006-01 (basic.318006-01.bin), for $8000-$BFFF in ROM
147
+ bank 0.
148
+ SHA-1 161c96b4ad20f3a4f2321808e37a5ded26a135dd.
149
+
150
+ plus4/kernal-pal.rom
151
+ --------------------
152
+ The PAL KERNAL, 318004-05 (kernal.318004-05.bin), for $C000-$FFFF in
153
+ ROM bank 0, with the character set from $D000.
154
+ SHA-1 7c7e07f016391174a557e790c4ef1cbe33512cdb.
155
+
156
+ plus4/kernal-ntsc.rom
157
+ ---------------------
158
+ The NTSC KERNAL, 318005-05 (kernal.318005-05.bin), for $C000-$FFFF in
159
+ ROM bank 0.
160
+ SHA-1 a3d9e5be091b98de39a046ab167fb7632d053682.
161
+
162
+ plus4/function-low.rom
163
+ ----------------------
164
+ The Plus/4's 3-plus-1 function ROM, low half, 317053-01
165
+ (3-plus-1.317053-01.bin), for $8000-$BFFF in ROM bank 1.
166
+ SHA-1 3b69f6e7cb4c18bb08e203fb18b7dabfa853390f.
167
+
168
+ plus4/function-high.rom
169
+ -----------------------
170
+ The Plus/4's 3-plus-1 function ROM, high half, 317054-01
171
+ (3-plus-1.317054-01.bin), for $C000-$FFFF in ROM bank 1.
172
+ SHA-1 0ad7ac2db7da692d972e586ca0dfd747d82c7693.
Binary file
data/lib/badline/sdl.rb CHANGED
@@ -58,6 +58,7 @@ module Badline
58
58
  ffi_func :SDL_ClearQueuedAudio, [:uint32], :void
59
59
  ffi_func :SDL_PushEvent, [:ptr], :int
60
60
  ffi_func :SDL_GetKeyName, [:int], :str
61
+ ffi_func :SDL_StopTextInput, [], :void
61
62
 
62
63
  ffi_buffer :rect, 16
63
64
  ffi_write_i32 :rect_x, 0
@@ -3,10 +3,10 @@
3
3
  require "digest"
4
4
 
5
5
  module Badline
6
- module Storage
6
+ module SIDTune
7
7
  # PSID/RSID tunes: a memory image plus the addresses of the routines
8
8
  # that initialise it and produce one frame of music.
9
- class SIDFile
9
+ class File
10
10
  include IntegerHelper
11
11
 
12
12
  class FormatError < StandardError; end
@@ -147,7 +147,7 @@ module Badline
147
147
  attr_reader :format
148
148
 
149
149
  def initialize(path)
150
- @bytes = File.binread(path).bytes
150
+ @bytes = ::File.binread(path).bytes
151
151
  @format = @bytes[0, 4].pack("C*")
152
152
  raise FormatError, "Missing PSID or RSID signature" unless %w[PSID RSID].include?(@format)
153
153
  raise FormatError, "Truncated header" if truncated?
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Badline
4
- module Storage
4
+ module SIDTune
5
5
  # The layout of an HVSC collection: tunes in directories under its root,
6
6
  # and databases about them in `DOCUMENTS`. A tune's HVSC path is its path
7
7
  # from the root, as `/MUSICIANS/H/Hubbard_Rob/Commando.sid`.
@@ -10,15 +10,15 @@ module Badline
10
10
  # The named file in the DOCUMENTS directory of a collection above the
11
11
  # tune, or else of the one `$HVSC_BASE` points at.
12
12
  def document(tune_path, name)
13
- candidates(tune_path).map { |dir| File.join(dir, "DOCUMENTS", name) }
14
- .find { |path| File.file?(path) }
13
+ candidates(tune_path).map { |dir| ::File.join(dir, "DOCUMENTS", name) }
14
+ .find { |path| ::File.file?(path) }
15
15
  end
16
16
 
17
17
  # The tune's HVSC path in the collection that holds the document, or
18
18
  # nil when the tune lies outside it.
19
19
  def path(tune_path, document)
20
- root = File.dirname(File.expand_path(document), 2)
21
- tune = File.expand_path(tune_path)
20
+ root = ::File.dirname(::File.expand_path(document), 2)
21
+ tune = ::File.expand_path(tune_path)
22
22
  tune.start_with?("#{root}/") ? tune[root.length..] : nil
23
23
  end
24
24
 
@@ -26,10 +26,10 @@ module Badline
26
26
 
27
27
  def candidates(tune_path)
28
28
  dirs = []
29
- dir = File.dirname(File.expand_path(tune_path))
29
+ dir = ::File.dirname(::File.expand_path(tune_path))
30
30
  until dirs.last == dir
31
31
  dirs << dir
32
- dir = File.dirname(dir)
32
+ dir = ::File.dirname(dir)
33
33
  end
34
34
  base = ENV.fetch("HVSC_BASE", nil)
35
35
  dirs << base if base
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Badline
4
- module Storage
4
+ module SIDTune
5
5
  # HVSC's subtune length database. Each tune gets a comment naming its path
6
6
  # and a line keyed by the MD5 of the whole `.sid` file, holding one
7
7
  # `m:ss` time per subtune, optionally down to milliseconds:
@@ -23,7 +23,7 @@ module Badline
23
23
  # The tune's per-subtune lengths in seconds, or nil when it isn't listed.
24
24
  def lengths(md5)
25
25
  prefix = "#{md5.downcase}="
26
- File.foreach(@path) do |line|
26
+ ::File.foreach(@path) do |line|
27
27
  next unless line.start_with?(prefix)
28
28
 
29
29
  return line[prefix.length..].split.map { |time| seconds(time) }
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Badline
4
- module Storage
4
+ module SIDTune
5
5
  class STIL
6
6
  # A TITLE in a STIL entry, the tune a subtune covers, with the ARTIST
7
7
  # after it, and the stretch of the subtune it covers when the title
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "badline/storage/stil/credit"
3
+ require "badline/sid_tune/stil/credit"
4
4
 
5
5
  module Badline
6
- module Storage
6
+ module SIDTune
7
7
  # HVSC's SID Tune Information List, `DOCUMENTS/STIL.txt`: covers,
8
8
  # subtune names and composers' comments, keyed by each tune's HVSC path.
9
9
  # An entry holds fields for the whole file, then a block per subtune
@@ -89,7 +89,7 @@ module Badline
89
89
  def entry(hvsc_path) = entries[hvsc_path]
90
90
 
91
91
  def entries
92
- @entries ||= parse(Storage.latin1(File.binread(@path).bytes))
92
+ @entries ||= parse(Storage.latin1(::File.binread(@path).bytes))
93
93
  end
94
94
 
95
95
  private
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "badline/sid_tune/file"
4
+ require "badline/sid_tune/hvsc"
5
+ require "badline/sid_tune/song_lengths"
6
+ require "badline/sid_tune/stil"
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Snapshot
5
+ # How a C128 was built: its model's name, its SID's model and the
6
+ # mode it resets into, the arguments C128.new takes.
7
+ C128Setup = Data.define(:model, :sid_model, :mode)
8
+
9
+ class C128Setup
10
+ SID_MODELS = %i[mos6581 mos8580].freeze
11
+ MODES = %i[c64 c128].freeze
12
+
13
+ # The model, the SID and the mode by name, in a keyed snapshot module.
14
+ def write_fields(out)
15
+ out.text("model", model).text("sid_model", sid_model.to_s).text("mode", mode.to_s)
16
+ end
17
+
18
+ def self.read_fields(input)
19
+ model = input.choice("model", C128::Model::ALL.map(&:name), "c128")
20
+ sid = input.choice("sid_model", SID_MODELS.map(&:to_s), "mos6581")
21
+ mode = input.choice("mode", MODES.map(&:to_s), "c64")
22
+ new(model:, sid_model: SID_MODELS.find { |name| name.to_s == sid } || :mos6581,
23
+ mode: MODES.find { |name| name.to_s == mode } || :c64)
24
+ end
25
+
26
+ # A machine built this way, at power-on.
27
+ def build = C128.new(model:, sid_model:, mode:)
28
+
29
+ def to_s = [model, sid_model, mode].join(" with a ")
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Snapshot
5
+ # How a C64 was built: its VIC, CIA and SID models, its region, its
6
+ # RAM expansion, the size of its REU, its KERNAL, whether it has a
7
+ # datasette and its board, the arguments C64.new takes.
8
+ C64Setup = Data.define(:vic_model, :cia_model, :sid_model, :region, :ram_expansion, :reu, :kernal, :datasette,
9
+ :board)
10
+
11
+ class C64Setup
12
+ SID_MODELS = %i[mos6581 mos8580].freeze
13
+ REGIONS = [Region::PAL, Region::NTSC, Region::NTSC_OLD, Region::DREAN].freeze
14
+ RAM_EXPANSIONS = [:none, *C64::BankedRAM::TYPES.keys].freeze
15
+ KERNALS = C64::Bus::ROMs::KERNALS.keys.freeze
16
+ BOARDS = C64::Bus::Fittings::BOARDS
17
+
18
+ def self.of(address_bus)
19
+ new(vic_model: address_bus.vic.model, cia_model: address_bus.cia1.model, sid_model: address_bus.sid.model,
20
+ region: address_bus.region, ram_expansion: address_bus.ram_expansion.type, reu: address_bus.reu&.size_kb,
21
+ kernal: address_bus.kernal, datasette: address_bus.datasette.connected?, board: address_bus.board)
22
+ end
23
+
24
+ def self.ram_expansion(name) = name == :none ? nil : name
25
+
26
+ # An REU's size in K, written as 0 for none.
27
+ def self.reu(size_kb)
28
+ return nil if size_kb.zero?
29
+ return size_kb if C64::REU::SIZES_KB.include?(size_kb)
30
+
31
+ raise FormatError, "the snapshot names a #{size_kb}K REU, which badline doesn't build"
32
+ end
33
+
34
+ # The setup in a keyed snapshot module (Snapshot::Keyed), with each
35
+ # model, the region, the RAM expansion, the KERNAL and the board by
36
+ # name.
37
+ def write_fields(out)
38
+ out.text("vic_model", vic_model.to_s).text("cia_model", cia_model.to_s).text("sid_model", sid_model.to_s)
39
+ out.text("region", region.name.to_s).text("ram_expansion", (ram_expansion || :none).to_s)
40
+ out.int("reu_kb", reu || 0).text("kernal", kernal.to_s).bool("datasette", datasette)
41
+ out.text("board", board.to_s)
42
+ end
43
+
44
+ # The setup a keyed snapshot module names, a C64's at power-on for
45
+ # anything it leaves out or names that badline doesn't build.
46
+ def self.read_fields(input)
47
+ region = named(input, "region", REGIONS.map(&:name), :pal)
48
+ new(vic_model: named(input, "vic_model", Chips::VIC::MODELS, :mos6569),
49
+ cia_model: named(input, "cia_model", Chips::CIA::MODELS, :mos6526),
50
+ sid_model: named(input, "sid_model", SID_MODELS, :mos6581),
51
+ region: REGIONS.find { |each| each.name == region } || Region::PAL,
52
+ ram_expansion: ram_expansion(named(input, "ram_expansion", RAM_EXPANSIONS, :none)),
53
+ reu: reu(input.int("reu_kb", 0)), kernal: named(input, "kernal", KERNALS, :c64),
54
+ datasette: input.bool("datasette", true), board: named(input, "board", BOARDS, :c64))
55
+ end
56
+
57
+ # The Symbol of `names` the text at `key` names.
58
+ def self.named(input, key, names, default)
59
+ text = input.choice(key, names.map(&:to_s), default.to_s)
60
+ names.find { |name| name.to_s == text } || default
61
+ end
62
+
63
+ # A machine built this way, at power-on.
64
+ def build
65
+ C64.new(vic_model:, cia_model:, sid_model:, region:, ram_expansion:, reu:, kernal:, datasette:, board:)
66
+ end
67
+
68
+ # The chips, led by the model's name when they make one of
69
+ # Badline::Model's.
70
+ def to_s
71
+ model = Model.of(self)
72
+ parts = [vic_model, cia_model, sid_model, region.name]
73
+ parts.unshift(model.name) if model
74
+ parts << ram_expansion if ram_expansion
75
+ parts << "a #{reu}K REU" if reu
76
+ parts << "the #{kernal} KERNAL" unless kernal == :c64
77
+ parts << "no datasette" unless datasette
78
+ parts << "the #{board} board" unless board == :c64
79
+ parts.join(", ")
80
+ end
81
+ end
82
+ end
83
+ end
@@ -4,6 +4,10 @@ require "zlib"
4
4
 
5
5
  module Badline
6
6
  module Snapshot
7
+ # A file that isn't a snapshot badline reads, is cut short, or is of a
8
+ # machine built another way.
9
+ class FormatError < StandardError; end
10
+
7
11
  # One module of a snapshot: its name, its version and its payload,
8
12
  # without the 22-byte module header.
9
13
  Section = Data.define(:name, :major, :minor, :data) do
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Snapshot
5
+ module FieldDoc
6
+ # The doc's markdown: one table per module, of each key, its type and
7
+ # its default, with keys that differ only in a unit's number, such as
8
+ # voice1 to voice3, on one row.
9
+ class Markdown
10
+ NAMES = { "c64" => "C64", "vic20" => "VIC-20", "c128" => "C128" }.freeze
11
+ TAG_TYPES = { Keyed::INT => "int", Keyed::BOOL => "bool", Keyed::BYTES => "bytes", Keyed::INTS => "ints",
12
+ Keyed::TEXT => "text" }.freeze
13
+
14
+ # A row: the key, the type, and the defaults each family whose
15
+ # machines read or write it reads it with.
16
+ Row = Struct.new(:key, :type, :defaults)
17
+
18
+ INTRO = <<~MARKDOWN
19
+ # Snapshot format
20
+
21
+ This file is generated by `rake snapshot:fields` from the code that
22
+ loads a snapshot. Don't edit it by hand. doc/snapshots.md covers
23
+ what a snapshot holds and which versions load.
24
+
25
+ A snapshot is a VICE `.vsf` container. The machine is in modules
26
+ named `BL-` plus a unit, each a deflated list of records: a key, a
27
+ type and a value. The types are `int` (a zigzag BER integer), `bool`,
28
+ `bytes`, `ints` (a list of integers) and `text`. A load skips a key
29
+ it doesn't know, and a key that isn't there leaves the value a
30
+ machine built afresh has: the default below. `word`, `byte` and
31
+ `int & 0x..` are ints cut to the latch's width. A text that lists
32
+ its values takes one of them. An optional int is absent when the
33
+ latch holds nothing. A true drive's modules are named from its
34
+ device number, `BL-D8` to `BL-D11`. Keys with `<N>` stand for each
35
+ numbered unit. A default of "written only" is a key the load
36
+ doesn't read, or reads only when the snapshot has it. Where the
37
+ machines differ, the default is given for each, and a key only
38
+ some of them have names them.
39
+ MARKDOWN
40
+
41
+ def initialize(loads)
42
+ @modules = {}
43
+ loads.each { |load| add(load) }
44
+ end
45
+
46
+ def to_s
47
+ sections = @modules.map do |name, rows|
48
+ families = rows.values.flat_map { |row| row.defaults.keys }.uniq
49
+ ["## #{name}", "", "Written by the #{families.map { |family| NAMES.fetch(family) }.join(', ')}.", "",
50
+ "| Key | Type | Default |", "| --- | --- | --- |",
51
+ *rows.values.map { |row| line(row, families) }].join("\n")
52
+ end
53
+ "#{INTRO}\n#{sections.join("\n\n")}\n"
54
+ end
55
+
56
+ private
57
+
58
+ def add(load)
59
+ load.fields.each do |name, fields|
60
+ numbered = numbered_keys(load.written[name].keys + fields.map(&:key))
61
+ fields.each { |field| note(name, numbered.fetch(field.key, field.key), field.type, load.family, field) }
62
+ read = fields.to_set(&:key)
63
+ load.written[name].each do |key, tag|
64
+ next if read.include?(key)
65
+
66
+ note(name, numbered.fetch(key, key), TAG_TYPES.fetch(tag, "?"), load.family, nil)
67
+ end
68
+ end
69
+ end
70
+
71
+ def note(name, key, type, family, field)
72
+ row = (@modules[name] ||= {})[key] ||= Row.new(key, type, {})
73
+ (row.defaults[family] ||= []) << (field ? brief(field.default, field.type) : "written only")
74
+ end
75
+
76
+ # Keys that differ only in a number, as the same key with <N>: each
77
+ # key whose number another key in the module shares the rest of.
78
+ def numbered_keys(keys)
79
+ groups = keys.uniq.group_by { |key| key.gsub(/(?<=[a-z])\d+(?=\.|\z)/, "<N>") }
80
+ groups.each_with_object({}) do |(general, members), numbered|
81
+ members.each { |key| numbered[key] = general } if members.length > 1
82
+ end
83
+ end
84
+
85
+ def line(row, families)
86
+ each = row.defaults.transform_values { |defaults| summary(defaults.uniq) }
87
+ default = if each.values.uniq.length == 1 && each.length == families.length then each.values.first
88
+ else each.map { |family, value| "#{NAMES.fetch(family)}: #{value}" }.join("; ")
89
+ end
90
+ "| `#{row.key}` | #{row.type} | #{default} |"
91
+ end
92
+
93
+ def summary(defaults) = defaults.length > 3 ? "varies" : defaults.join(" or ")
94
+
95
+ def brief(value, type)
96
+ case value
97
+ when nil then "absent"
98
+ when Array then list(value)
99
+ when String then type.start_with?("bytes") ? list(value.bytes) : value.inspect
100
+ else value.to_s
101
+ end
102
+ end
103
+
104
+ def list(values)
105
+ return values.inspect if values.length <= 8
106
+
107
+ values.uniq.length == 1 ? "#{values.length} × #{values.first}" : "#{values.length} values"
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "badline"
4
+ require "badline/c128"
5
+
6
+ module Badline
7
+ module Snapshot
8
+ # doc/snapshot-format.md, written by running the code: each family's
9
+ # machine is saved with its attachments, and its modules loaded into a
10
+ # machine built the same way at power-on through Keyed::Recorders,
11
+ # which note every key read with its type and the value the new machine
12
+ # had, its default. `rake snapshot:fields` writes it, and a spec checks
13
+ # that the file matches.
14
+ module FieldDoc
15
+ PATH = File.expand_path("../../../doc/snapshot-format.md", __dir__)
16
+
17
+ # Modules read through Recorders.
18
+ class RecordingModules < Keyed::Modules
19
+ private
20
+
21
+ def parse(section) = Keyed::Recorder.parse(section)
22
+
23
+ def missing(name) = Keyed::Recorder.missing(name)
24
+ end
25
+
26
+ # One machine saved and loaded: the family it belongs to, and for
27
+ # each module the keys its records hold, with their tags, and the fields the load read.
28
+ Load = Data.define(:family, :written, :fields)
29
+
30
+ # The machines the doc is made from: each family at power-on, and the
31
+ # C64 with each kind of expansion, cartridge and media.
32
+ def self.machines
33
+ {
34
+ "c64" => [C64.new, C64.new(ram_expansion: :plus256k), C64.new(reu: 512), with_cartridge, with_trap_dos,
35
+ with_tape, with_drive(:d64), with_drive(:d81)],
36
+ "vic20" => [Vic20.new, with_rom],
37
+ "c128" => [C128.new(mode: :c128), with_drive(:d71)]
38
+ }
39
+ end
40
+
41
+ def self.blank(length) = Array.new(length, 0)
42
+
43
+ def self.with_cartridge
44
+ chips = [0x8000, 0xa000].map do |address|
45
+ Storage::CRTFile::Chip.new(chip_type: 2, bank: 0, address:, data: blank(0x2000))
46
+ end
47
+ image = Storage::CRTFile::Image.new(hardware_type: 32, subtype: 0, exrom: 1, game: 0, name: "DOC", chips:)
48
+ C64.new.tap do |machine|
49
+ machine.attach_cartridge(C64::Cartridge.from_crt(Storage::CRTFile.new(bytes: Storage::CRTFile.encode(image))))
50
+ end
51
+ end
52
+
53
+ def self.with_trap_dos
54
+ C64.new.tap { |machine| machine.mount(Storage::D64Image.new("", read_only: true, bytes: blank(174_848))) }
55
+ end
56
+
57
+ def self.with_tape
58
+ bytes = "C64-TAPE-RAW".bytes + [1, 0, 0, 0, 4, 0, 0, 0, 0x30, 0x30, 0x30, 0x30]
59
+ C64.new.tap { |machine| machine.datasette.insert(Storage::TAP.new("", bytes:)) }
60
+ end
61
+
62
+ def self.with_drive(kind)
63
+ case kind
64
+ when :d81
65
+ C64.new.tap do |machine|
66
+ machine.plug_drive1581.insert(Drives::Model1581::Disk.new(Storage::D81Image.new("", bytes: blank(819_200))))
67
+ end
68
+ when :d71
69
+ C128.new(mode: :c128).tap do |machine|
70
+ image = Storage::D71Image.new("", bytes: blank(349_696))
71
+ machine.plug_true_drive.insert(Drives::Model1541::Disk.decode(image))
72
+ end
73
+ else
74
+ C64.new.tap do |machine|
75
+ image = Storage::D64Image.new("", bytes: blank(174_848))
76
+ machine.plug_true_drive.insert(Drives::Model1541::Disk.decode(image))
77
+ end
78
+ end
79
+ end
80
+
81
+ def self.with_rom
82
+ Vic20.new.tap { |machine| machine.bus.map_rom(0xa000, blank(0x2000)) }
83
+ end
84
+
85
+ # Saves `machine` and loads it into a new one through Recorders.
86
+ def self.load(family, machine)
87
+ modules = RecordingModules.new(Image.of(machine).sections)
88
+ Image.setup(modules.machine).build.load_modules(modules)
89
+ modules.machine.text("written_by", "")
90
+ written = {}
91
+ fields = {}
92
+ modules.readers.each do |reader|
93
+ written[reader.name] = reader.tags
94
+ fields[reader.name] = reader.fields
95
+ end
96
+ Load.new(family:, written:, fields:)
97
+ end
98
+
99
+ def self.loads = machines.flat_map { |family, list| list.map { |machine| load(family, machine) } }
100
+
101
+ # The doc, as markdown.
102
+ def self.markdown(loads = self.loads) = Markdown.new(loads).to_s
103
+
104
+ def self.write(path = PATH) = File.write(path, markdown)
105
+ end
106
+ end
107
+ end
108
+
109
+ require "badline/snapshot/field_doc/markdown"