badline 0.12.1 → 0.13.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 (505) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -0
  3. data/CLAUDE.md +59 -31
  4. data/README.md +1 -1
  5. data/doc/library.md +9 -9
  6. data/doc/pinned-behaviour.md +105 -105
  7. data/doc/snapshots.md +1 -4
  8. data/lib/badline/audio/bare_player.rb +3 -3
  9. data/lib/badline/audio/cli.rb +6 -6
  10. data/lib/badline/audio/jukebox.rb +2 -2
  11. data/lib/badline/audio/machine_player.rb +2 -2
  12. data/lib/badline/{media → audio}/queue.rb +1 -1
  13. data/lib/badline/audio/queued_tune.rb +6 -6
  14. data/lib/badline/audio/renderer.rb +5 -5
  15. data/lib/badline/audio/stereo.rb +1 -1
  16. data/lib/badline/c128/{bus_state.rb → bus/saved_state.rb} +1 -1
  17. data/lib/badline/c128/bus.rb +18 -17
  18. data/lib/badline/c128/color_lines.rb +2 -2
  19. data/lib/badline/c128/cpu.rb +1 -1
  20. data/lib/badline/c128/drives.rb +10 -11
  21. data/lib/badline/c128/fast_serial.rb +5 -5
  22. data/lib/badline/c128/mmu_pages.rb +1 -1
  23. data/lib/badline/c128/modes.rb +2 -2
  24. data/lib/badline/c128/saved_state.rb +21 -47
  25. data/lib/badline/c128/z80.rb +2 -2
  26. data/lib/badline/c128.rb +14 -9
  27. data/lib/badline/{computer → c64}/attachments.rb +4 -6
  28. data/lib/badline/c64/banked_ram/banking.rb +32 -0
  29. data/lib/badline/c64/banked_ram/plus256k.rb +56 -0
  30. data/lib/badline/c64/banked_ram/plus60k.rb +45 -0
  31. data/lib/badline/c64/banked_ram/unexpanded.rb +30 -0
  32. data/lib/badline/c64/banked_ram.rb +23 -0
  33. data/lib/badline/c64/bus/extra_sids.rb +32 -0
  34. data/lib/badline/c64/bus/fittings.rb +40 -0
  35. data/lib/badline/c64/bus/pla.rb +149 -0
  36. data/lib/badline/c64/bus/roms.rb +41 -0
  37. data/lib/badline/c64/bus/saved_state.rb +68 -0
  38. data/lib/badline/c64/bus/sid_slots.rb +44 -0
  39. data/lib/badline/c64/bus.rb +218 -0
  40. data/lib/badline/c64/cartridge/action_replay.rb +128 -0
  41. data/lib/badline/c64/cartridge/atomic_power.rb +26 -0
  42. data/lib/badline/c64/cartridge/bank.rb +83 -0
  43. data/lib/badline/c64/cartridge/comal80.rb +52 -0
  44. data/lib/badline/c64/cartridge/dinamic.rb +36 -0
  45. data/lib/badline/c64/cartridge/easy_flash.rb +147 -0
  46. data/lib/badline/c64/cartridge/epyx_fastload.rb +81 -0
  47. data/lib/badline/c64/cartridge/final_cartridge3.rb +91 -0
  48. data/lib/badline/c64/cartridge/flash/saved_state.rb +40 -0
  49. data/lib/badline/c64/cartridge/flash.rb +279 -0
  50. data/lib/badline/c64/cartridge/freezer.rb +35 -0
  51. data/lib/badline/c64/cartridge/fun_play.rb +40 -0
  52. data/lib/badline/c64/cartridge/g_mod2.rb +76 -0
  53. data/lib/badline/c64/cartridge/game_system.rb +42 -0
  54. data/lib/badline/c64/cartridge/geo_ram.rb +81 -0
  55. data/lib/badline/c64/cartridge/kcs_power.rb +77 -0
  56. data/lib/badline/c64/cartridge/mach5.rb +34 -0
  57. data/lib/badline/c64/cartridge/magic_desk.rb +32 -0
  58. data/lib/badline/c64/cartridge/ocean.rb +37 -0
  59. data/lib/badline/c64/cartridge/pagefox.rb +70 -0
  60. data/lib/badline/c64/cartridge/retro_replay/saved_state.rb +47 -0
  61. data/lib/badline/c64/cartridge/retro_replay.rb +286 -0
  62. data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
  63. data/lib/badline/c64/cartridge/rgcd.rb +60 -0
  64. data/lib/badline/c64/cartridge/saved_state.rb +63 -0
  65. data/lib/badline/c64/cartridge/simons_basic.rb +37 -0
  66. data/lib/badline/c64/cartridge/standard.rb +17 -0
  67. data/lib/badline/c64/cartridge/super_games.rb +50 -0
  68. data/lib/badline/c64/cartridge/westermann.rb +32 -0
  69. data/lib/badline/c64/cartridge/zaxxon.rb +68 -0
  70. data/lib/badline/c64/cartridge.rb +258 -0
  71. data/lib/badline/c64/color_memory.rb +27 -0
  72. data/lib/badline/{computer → c64}/common.rb +2 -2
  73. data/lib/badline/{computer → c64}/kernal_traps.rb +18 -18
  74. data/lib/badline/c64/reu/dma/saved_state.rb +52 -0
  75. data/lib/badline/c64/reu/dma.rb +275 -0
  76. data/lib/badline/c64/reu/ram.rb +109 -0
  77. data/lib/badline/c64/reu/saved_state.rb +55 -0
  78. data/lib/badline/c64/reu/trigger.rb +34 -0
  79. data/lib/badline/c64/reu.rb +291 -0
  80. data/lib/badline/{computer → c64}/saved_state.rb +13 -18
  81. data/lib/badline/{computer → c64}/true_drives.rb +11 -11
  82. data/lib/badline/{computer.rb → c64.rb} +18 -13
  83. data/lib/badline/chips/cia/fast_forward.rb +62 -0
  84. data/lib/badline/chips/cia/interrupt_register.rb +145 -0
  85. data/lib/badline/chips/cia/saved_state.rb +49 -0
  86. data/lib/badline/chips/cia/serial/saved_state.rb +45 -0
  87. data/lib/badline/chips/cia/serial.rb +250 -0
  88. data/lib/badline/chips/cia/time_of_day.rb +232 -0
  89. data/lib/badline/chips/cia/timer.rb +208 -0
  90. data/lib/badline/chips/cia.rb +281 -0
  91. data/lib/badline/chips/cpu/addressing.rb +133 -0
  92. data/lib/badline/chips/cpu/boundary.rb +56 -0
  93. data/lib/badline/chips/cpu/core.rb +167 -0
  94. data/lib/badline/chips/cpu/instruction.rb +338 -0
  95. data/lib/badline/chips/cpu/instruction_set/arithmetic.rb +118 -0
  96. data/lib/badline/chips/cpu/instruction_set/bitwise.rb +130 -0
  97. data/lib/badline/chips/cpu/instruction_set/branch.rb +83 -0
  98. data/lib/badline/chips/cpu/instruction_set/flag.rb +67 -0
  99. data/lib/badline/chips/cpu/instruction_set/illegal.rb +274 -0
  100. data/lib/badline/chips/cpu/instruction_set/inc_dec.rb +73 -0
  101. data/lib/badline/chips/cpu/instruction_set/stack.rb +56 -0
  102. data/lib/badline/chips/cpu/instruction_set/transfer.rb +141 -0
  103. data/lib/badline/chips/cpu/instruction_set.rb +59 -0
  104. data/lib/badline/chips/cpu/interrupts.rb +108 -0
  105. data/lib/badline/chips/cpu/microcode.rb +179 -0
  106. data/lib/badline/chips/cpu/operations.rb +90 -0
  107. data/lib/badline/chips/cpu/port.rb +116 -0
  108. data/lib/badline/chips/cpu/saved_state.rb +117 -0
  109. data/lib/badline/chips/cpu/stack_operations.rb +84 -0
  110. data/lib/badline/chips/cpu/traps.rb +23 -0
  111. data/lib/badline/chips/cpu.rb +12 -0
  112. data/lib/badline/chips/sid/catch_up.rb +122 -0
  113. data/lib/badline/chips/sid/decimator.rb +66 -0
  114. data/lib/badline/chips/sid/envelope/saved_state.rb +70 -0
  115. data/lib/badline/chips/sid/envelope.rb +241 -0
  116. data/lib/badline/chips/sid/filter/saved_state.rb +42 -0
  117. data/lib/badline/chips/sid/filter.rb +241 -0
  118. data/lib/badline/chips/sid/saved_state.rb +52 -0
  119. data/lib/badline/chips/sid/voice.rb +79 -0
  120. data/lib/badline/chips/sid/waveform/combined.rb +128 -0
  121. data/lib/badline/chips/sid/waveform/fast_forward.rb +107 -0
  122. data/lib/badline/chips/sid/waveform/noise_writeback.rb +124 -0
  123. data/lib/badline/chips/sid/waveform/saved_state.rb +68 -0
  124. data/lib/badline/chips/sid/waveform.rb +307 -0
  125. data/lib/badline/chips/sid.rb +265 -0
  126. data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
  127. data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -1
  128. data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -1
  129. data/lib/badline/chips/vdc/saved_state.rb +36 -0
  130. data/lib/badline/{c128 → chips}/vdc/window.rb +1 -1
  131. data/lib/badline/{c128 → chips}/vdc.rb +7 -31
  132. data/lib/badline/chips/via/control_lines.rb +124 -0
  133. data/lib/badline/chips/via/fast_forward.rb +55 -0
  134. data/lib/badline/chips/via/interrupt_register.rb +69 -0
  135. data/lib/badline/chips/via/saved_state.rb +44 -0
  136. data/lib/badline/chips/via/shift_register.rb +182 -0
  137. data/lib/badline/chips/via/timer1.rb +133 -0
  138. data/lib/badline/chips/via/timer2.rb +135 -0
  139. data/lib/badline/chips/via.rb +268 -0
  140. data/lib/badline/chips/vic/bank.rb +135 -0
  141. data/lib/badline/chips/vic/border_mask.rb +88 -0
  142. data/lib/badline/chips/vic/collisions.rb +117 -0
  143. data/lib/badline/chips/vic/color_patches.rb +49 -0
  144. data/lib/badline/chips/vic/display_state.rb +187 -0
  145. data/lib/badline/chips/vic/graphics_mode.rb +166 -0
  146. data/lib/badline/chips/vic/graphics_shifter/saved_state.rb +40 -0
  147. data/lib/badline/chips/vic/graphics_shifter.rb +187 -0
  148. data/lib/badline/chips/vic/register_log.rb +83 -0
  149. data/lib/badline/chips/vic/registers.rb +197 -0
  150. data/lib/badline/chips/vic/saved_state.rb +82 -0
  151. data/lib/badline/chips/vic/sequencer/saved_state.rb +91 -0
  152. data/lib/badline/chips/vic/sequencer.rb +277 -0
  153. data/lib/badline/chips/vic/sequencer_output.rb +118 -0
  154. data/lib/badline/chips/vic/sprite/internal_bus.rb +70 -0
  155. data/lib/badline/chips/vic/sprite/saved_state.rb +66 -0
  156. data/lib/badline/chips/vic/sprite/shifter.rb +148 -0
  157. data/lib/badline/chips/vic/sprite/timing.rb +58 -0
  158. data/lib/badline/chips/vic/sprite.rb +339 -0
  159. data/lib/badline/chips/vic/sprites/saved_state.rb +59 -0
  160. data/lib/badline/chips/vic/sprites.rb +284 -0
  161. data/lib/badline/chips/vic.rb +783 -0
  162. data/lib/badline/chips/vic_i/painter/saved_state.rb +40 -0
  163. data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +6 -30
  164. data/lib/badline/{vic20/vic → chips/vic_i}/saved_state.rb +2 -2
  165. data/lib/badline/chips/vic_i/sound/output.rb +85 -0
  166. data/lib/badline/chips/vic_i/sound.rb +235 -0
  167. data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
  168. data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +5 -5
  169. data/lib/badline/chips/z80/arithmetic.rb +119 -0
  170. data/lib/badline/chips/z80/bit_page.rb +57 -0
  171. data/lib/badline/chips/z80/block_io.rb +60 -0
  172. data/lib/badline/chips/z80/block_transfers.rb +61 -0
  173. data/lib/badline/chips/z80/bus_cycles.rb +113 -0
  174. data/lib/badline/chips/z80/core.rb +115 -0
  175. data/lib/badline/chips/z80/exchanges.rb +52 -0
  176. data/lib/badline/chips/z80/extended_page.rb +91 -0
  177. data/lib/badline/chips/z80/flags.rb +39 -0
  178. data/lib/badline/chips/z80/interrupt_acceptance.rb +48 -0
  179. data/lib/badline/chips/z80/jumps.rb +84 -0
  180. data/lib/badline/chips/z80/loads.rb +100 -0
  181. data/lib/badline/chips/z80/main_page.rb +136 -0
  182. data/lib/badline/chips/z80/registers.rb +122 -0
  183. data/lib/badline/chips/z80/saved_state.rb +71 -0
  184. data/lib/badline/chips/z80/shifts.rb +66 -0
  185. data/lib/badline/chips/z80.rb +13 -0
  186. data/lib/badline/core.rb +26 -28
  187. data/lib/badline/drives/datasette/saved_state.rb +37 -0
  188. data/lib/badline/drives/datasette.rb +140 -0
  189. data/lib/badline/drives/engine/core.rb +149 -0
  190. data/lib/badline/drives/engine/fast_serial.rb +75 -0
  191. data/lib/badline/drives/engine/idle.rb +127 -0
  192. data/lib/badline/drives/engine/idle_cpu.rb +30 -0
  193. data/lib/badline/drives/engine/orbit.rb +81 -0
  194. data/lib/badline/drives/engine/serial_lines.rb +75 -0
  195. data/lib/badline/drives/engine/sleep.rb +114 -0
  196. data/lib/badline/drives/engine/vias.rb +86 -0
  197. data/lib/badline/drives/engine/watch.rb +152 -0
  198. data/lib/badline/drives/engine.rb +11 -0
  199. data/lib/badline/drives/model1541/bus.rb +88 -0
  200. data/lib/badline/drives/model1541/byte_ready.rb +50 -0
  201. data/lib/badline/drives/model1541/cpu.rb +13 -0
  202. data/lib/badline/drives/model1541/disk/saved_state.rb +88 -0
  203. data/lib/badline/drives/model1541/disk.rb +317 -0
  204. data/lib/badline/drives/model1541/disk_via.rb +38 -0
  205. data/lib/badline/drives/model1541/gcr.rb +59 -0
  206. data/lib/badline/drives/model1541/mechanism/saved_state.rb +72 -0
  207. data/lib/badline/drives/model1541/mechanism.rb +315 -0
  208. data/lib/badline/drives/model1541/rotation.rb +123 -0
  209. data/lib/badline/drives/model1541/saved_state.rb +44 -0
  210. data/lib/badline/drives/model1541/sector_reader.rb +78 -0
  211. data/lib/badline/drives/model1541/serial_port.rb +20 -0
  212. data/lib/badline/drives/model1541/track.rb +100 -0
  213. data/lib/badline/drives/model1541.rb +81 -0
  214. data/lib/badline/drives/model1571/bus.rb +113 -0
  215. data/lib/badline/drives/model1571/cpu.rb +13 -0
  216. data/lib/badline/drives/model1571/saved_state.rb +47 -0
  217. data/lib/badline/drives/model1571/serial_port.rb +39 -0
  218. data/lib/badline/drives/model1571/serial_via.rb +27 -0
  219. data/lib/badline/drives/model1571/wd1770.rb +122 -0
  220. data/lib/badline/drives/model1571.rb +142 -0
  221. data/lib/badline/drives/model1581/bus.rb +139 -0
  222. data/lib/badline/drives/model1581/cpu.rb +13 -0
  223. data/lib/badline/drives/model1581/disk/saved_state.rb +89 -0
  224. data/lib/badline/drives/model1581/disk.rb +137 -0
  225. data/lib/badline/drives/model1581/mechanism.rb +119 -0
  226. data/lib/badline/drives/model1581/saved_state.rb +42 -0
  227. data/lib/badline/drives/model1581/serial_port.rb +54 -0
  228. data/lib/badline/drives/model1581/slot.rb +79 -0
  229. data/lib/badline/drives/model1581/track.rb +102 -0
  230. data/lib/badline/drives/model1581/track_bytes.rb +77 -0
  231. data/lib/badline/drives/model1581/wd1772/registers.rb +91 -0
  232. data/lib/badline/drives/model1581/wd1772/saved_state.rb +68 -0
  233. data/lib/badline/drives/model1581/wd1772/sector_writes.rb +75 -0
  234. data/lib/badline/drives/model1581/wd1772/sectors.rb +152 -0
  235. data/lib/badline/drives/model1581/wd1772/stepping.rb +111 -0
  236. data/lib/badline/drives/model1581/wd1772/tracks.rb +127 -0
  237. data/lib/badline/drives/model1581/wd1772/turn.rb +75 -0
  238. data/lib/badline/drives/model1581/wd1772.rb +218 -0
  239. data/lib/badline/drives/model1581.rb +206 -0
  240. data/lib/badline/drives/serial_bus.rb +161 -0
  241. data/lib/badline/frontend/boot.rb +3 -3
  242. data/lib/badline/frontend/machine_window.rb +3 -1
  243. data/lib/badline/frontend/player/filter_view.rb +1 -1
  244. data/lib/badline/frontend/player/player_controller.rb +2 -2
  245. data/lib/badline/frontend/player/player_screen.rb +1 -0
  246. data/lib/badline/frontend/player/theme.rb +7 -7
  247. data/lib/badline/frontend/timeline.rb +3 -3
  248. data/lib/badline/input/control_ports.rb +78 -0
  249. data/lib/badline/input/joystick.rb +27 -0
  250. data/lib/badline/input/keyboard.rb +114 -0
  251. data/lib/badline/input.rb +3 -0
  252. data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
  253. data/lib/badline/kernal_trap/dos/channel.rb +183 -0
  254. data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -1
  255. data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -1
  256. data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
  257. data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -1
  258. data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -1
  259. data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
  260. data/lib/badline/kernal_trap/{drive.rb → dos.rb} +11 -10
  261. data/lib/badline/kernal_trap/load.rb +5 -5
  262. data/lib/badline/kernal_trap/save.rb +4 -4
  263. data/lib/badline/kernal_trap/serial.rb +7 -7
  264. data/lib/badline/kernal_trap.rb +1 -2
  265. data/lib/badline/machine/clocking.rb +1 -1
  266. data/lib/badline/machine.rb +5 -5
  267. data/lib/badline/media/true_drive.rb +1 -1
  268. data/lib/badline/media/tune.rb +2 -2
  269. data/lib/badline/media.rb +3 -3
  270. data/lib/badline/model.rb +1 -1
  271. data/lib/badline/roms/README +6 -6
  272. data/lib/badline/sdl.rb +1 -0
  273. data/lib/badline/{storage/sid_file.rb → sid_tune/file.rb} +3 -3
  274. data/lib/badline/{storage → sid_tune}/hvsc.rb +7 -7
  275. data/lib/badline/{storage → sid_tune}/song_lengths.rb +2 -2
  276. data/lib/badline/{storage → sid_tune}/stil/credit.rb +1 -1
  277. data/lib/badline/{storage → sid_tune}/stil.rb +3 -3
  278. data/lib/badline/sid_tune.rb +6 -0
  279. data/lib/badline/snapshot/c128_setup.rb +43 -0
  280. data/lib/badline/snapshot/c64_setup.rb +79 -0
  281. data/lib/badline/snapshot/image.rb +5 -25
  282. data/lib/badline/snapshot/machine_state.rb +1 -1
  283. data/lib/badline/snapshot/setup.rb +22 -66
  284. data/lib/badline/snapshot/state.rb +8 -18
  285. data/lib/badline/snapshot/storage_setup.rb +68 -0
  286. data/lib/badline/snapshot/vic20_setup.rb +37 -0
  287. data/lib/badline/snapshot/vice/c64_mem.rb +1 -1
  288. data/lib/badline/snapshot/vice/restore.rb +1 -1
  289. data/lib/badline/snapshot/vice/reu1764.rb +1 -1
  290. data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
  291. data/lib/badline/snapshot/vice.rb +7 -5
  292. data/lib/badline/snapshot.rb +3 -4
  293. data/lib/badline/storage/d64_image.rb +0 -2
  294. data/lib/badline/storage/d71_image.rb +0 -2
  295. data/lib/badline/storage/d81_image.rb +0 -2
  296. data/lib/badline/storage/disk_image.rb +3 -6
  297. data/lib/badline/storage/g64_image.rb +2 -2
  298. data/lib/badline/storage/host_directory.rb +0 -5
  299. data/lib/badline/storage/t64.rb +2 -8
  300. data/lib/badline/storage/unavailable.rb +1 -1
  301. data/lib/badline/storage.rb +0 -37
  302. data/lib/badline/support/c128_checkpoint.rb +39 -0
  303. data/lib/badline/support/checkpoint.rb +108 -0
  304. data/lib/badline/support/vic20_checkpoint.rb +38 -0
  305. data/lib/badline/support.rb +5 -0
  306. data/lib/badline/version.rb +1 -1
  307. data/lib/badline/vic20/attachments.rb +5 -5
  308. data/lib/badline/vic20/bus/saved_state.rb +35 -0
  309. data/lib/badline/vic20/bus.rb +3 -25
  310. data/lib/badline/vic20/cpu.rb +1 -1
  311. data/lib/badline/vic20/port_wiring.rb +4 -4
  312. data/lib/badline/vic20/saved_state.rb +16 -30
  313. data/lib/badline/vic20/user_via_ports.rb +2 -2
  314. data/lib/badline/vic20.rb +19 -14
  315. metadata +245 -221
  316. data/lib/badline/address_bus/extra_sids.rb +0 -30
  317. data/lib/badline/address_bus/fittings.rb +0 -38
  318. data/lib/badline/address_bus/pla.rb +0 -147
  319. data/lib/badline/address_bus/roms.rb +0 -39
  320. data/lib/badline/address_bus/saved_state.rb +0 -66
  321. data/lib/badline/address_bus/sid_slots.rb +0 -42
  322. data/lib/badline/address_bus.rb +0 -216
  323. data/lib/badline/cartridge/action_replay.rb +0 -126
  324. data/lib/badline/cartridge/atomic_power.rb +0 -24
  325. data/lib/badline/cartridge/bank.rb +0 -81
  326. data/lib/badline/cartridge/comal80.rb +0 -50
  327. data/lib/badline/cartridge/dinamic.rb +0 -34
  328. data/lib/badline/cartridge/easy_flash.rb +0 -145
  329. data/lib/badline/cartridge/epyx_fastload.rb +0 -79
  330. data/lib/badline/cartridge/final_cartridge3.rb +0 -89
  331. data/lib/badline/cartridge/flash.rb +0 -306
  332. data/lib/badline/cartridge/freezer.rb +0 -33
  333. data/lib/badline/cartridge/fun_play.rb +0 -38
  334. data/lib/badline/cartridge/g_mod2.rb +0 -74
  335. data/lib/badline/cartridge/game_system.rb +0 -40
  336. data/lib/badline/cartridge/geo_ram.rb +0 -79
  337. data/lib/badline/cartridge/kcs_power.rb +0 -75
  338. data/lib/badline/cartridge/mach5.rb +0 -32
  339. data/lib/badline/cartridge/magic_desk.rb +0 -30
  340. data/lib/badline/cartridge/ocean.rb +0 -35
  341. data/lib/badline/cartridge/pagefox.rb +0 -68
  342. data/lib/badline/cartridge/retro_replay.rb +0 -320
  343. data/lib/badline/cartridge/rex_utility.rb +0 -29
  344. data/lib/badline/cartridge/rgcd.rb +0 -58
  345. data/lib/badline/cartridge/simons_basic.rb +0 -35
  346. data/lib/badline/cartridge/standard.rb +0 -15
  347. data/lib/badline/cartridge/super_games.rb +0 -48
  348. data/lib/badline/cartridge/westermann.rb +0 -30
  349. data/lib/badline/cartridge/zaxxon.rb +0 -66
  350. data/lib/badline/cartridge.rb +0 -303
  351. data/lib/badline/checkpoint.rb +0 -98
  352. data/lib/badline/cia/fast_forward.rb +0 -60
  353. data/lib/badline/cia/interrupt_register.rb +0 -143
  354. data/lib/badline/cia/serial.rb +0 -275
  355. data/lib/badline/cia/state.rb +0 -47
  356. data/lib/badline/cia/timer.rb +0 -206
  357. data/lib/badline/cia.rb +0 -279
  358. data/lib/badline/color_memory.rb +0 -25
  359. data/lib/badline/control_ports.rb +0 -76
  360. data/lib/badline/cpu/addressing.rb +0 -131
  361. data/lib/badline/cpu/boundary.rb +0 -54
  362. data/lib/badline/cpu/core.rb +0 -165
  363. data/lib/badline/cpu/microcode.rb +0 -177
  364. data/lib/badline/cpu/operations.rb +0 -88
  365. data/lib/badline/cpu/saved_state.rb +0 -115
  366. data/lib/badline/cpu/stack_operations.rb +0 -82
  367. data/lib/badline/cpu.rb +0 -10
  368. data/lib/badline/cpu_port.rb +0 -112
  369. data/lib/badline/datasette.rb +0 -161
  370. data/lib/badline/drive/core.rb +0 -147
  371. data/lib/badline/drive/fast_serial.rb +0 -73
  372. data/lib/badline/drive/idle.rb +0 -125
  373. data/lib/badline/drive/idle_cpu.rb +0 -28
  374. data/lib/badline/drive/orbit.rb +0 -79
  375. data/lib/badline/drive/serial_lines.rb +0 -73
  376. data/lib/badline/drive/sleep.rb +0 -112
  377. data/lib/badline/drive/vias.rb +0 -84
  378. data/lib/badline/drive/watch.rb +0 -150
  379. data/lib/badline/drive.rb +0 -11
  380. data/lib/badline/drive1541/bus.rb +0 -86
  381. data/lib/badline/drive1541/byte_ready.rb +0 -48
  382. data/lib/badline/drive1541/cpu.rb +0 -11
  383. data/lib/badline/drive1541/disk.rb +0 -315
  384. data/lib/badline/drive1541/disk_state.rb +0 -86
  385. data/lib/badline/drive1541/disk_via.rb +0 -36
  386. data/lib/badline/drive1541/gcr.rb +0 -57
  387. data/lib/badline/drive1541/mechanism.rb +0 -313
  388. data/lib/badline/drive1541/mechanism_state.rb +0 -68
  389. data/lib/badline/drive1541/rotation.rb +0 -121
  390. data/lib/badline/drive1541/sector_reader.rb +0 -76
  391. data/lib/badline/drive1541/serial_port.rb +0 -18
  392. data/lib/badline/drive1541/track.rb +0 -98
  393. data/lib/badline/drive1541.rb +0 -111
  394. data/lib/badline/drive1571/bus.rb +0 -111
  395. data/lib/badline/drive1571/cpu.rb +0 -11
  396. data/lib/badline/drive1571/serial_port.rb +0 -37
  397. data/lib/badline/drive1571/serial_via.rb +0 -25
  398. data/lib/badline/drive1571/wd1770.rb +0 -120
  399. data/lib/badline/drive1571.rb +0 -175
  400. data/lib/badline/drive1581/bus.rb +0 -137
  401. data/lib/badline/drive1581/cpu.rb +0 -11
  402. data/lib/badline/drive1581/disk.rb +0 -135
  403. data/lib/badline/drive1581/disk_state.rb +0 -87
  404. data/lib/badline/drive1581/mechanism.rb +0 -117
  405. data/lib/badline/drive1581/serial_port.rb +0 -52
  406. data/lib/badline/drive1581/slot.rb +0 -78
  407. data/lib/badline/drive1581/track.rb +0 -100
  408. data/lib/badline/drive1581/track_bytes.rb +0 -75
  409. data/lib/badline/drive1581/wd1772/registers.rb +0 -89
  410. data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
  411. data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
  412. data/lib/badline/drive1581/wd1772/state.rb +0 -66
  413. data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
  414. data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
  415. data/lib/badline/drive1581/wd1772/turn.rb +0 -73
  416. data/lib/badline/drive1581/wd1772.rb +0 -216
  417. data/lib/badline/drive1581.rb +0 -233
  418. data/lib/badline/iec_bus.rb +0 -159
  419. data/lib/badline/instruction.rb +0 -334
  420. data/lib/badline/instruction_set/arithmetic.rb +0 -114
  421. data/lib/badline/instruction_set/bitwise.rb +0 -126
  422. data/lib/badline/instruction_set/branch.rb +0 -79
  423. data/lib/badline/instruction_set/flag.rb +0 -63
  424. data/lib/badline/instruction_set/illegal.rb +0 -270
  425. data/lib/badline/instruction_set/inc_dec.rb +0 -69
  426. data/lib/badline/instruction_set/stack.rb +0 -52
  427. data/lib/badline/instruction_set/transfer.rb +0 -137
  428. data/lib/badline/instruction_set.rb +0 -55
  429. data/lib/badline/interrupts.rb +0 -104
  430. data/lib/badline/joystick.rb +0 -25
  431. data/lib/badline/kernal_trap/channel.rb +0 -181
  432. data/lib/badline/keyboard.rb +0 -112
  433. data/lib/badline/ram_expansion/banking.rb +0 -30
  434. data/lib/badline/ram_expansion/plus256k.rb +0 -54
  435. data/lib/badline/ram_expansion/plus60k.rb +0 -43
  436. data/lib/badline/ram_expansion/unexpanded.rb +0 -28
  437. data/lib/badline/ram_expansion.rb +0 -21
  438. data/lib/badline/reu/dma/saved_state.rb +0 -50
  439. data/lib/badline/reu/dma.rb +0 -273
  440. data/lib/badline/reu/ram.rb +0 -107
  441. data/lib/badline/reu/saved_state.rb +0 -80
  442. data/lib/badline/reu/trigger.rb +0 -32
  443. data/lib/badline/reu.rb +0 -289
  444. data/lib/badline/sid/catch_up.rb +0 -120
  445. data/lib/badline/sid/decimator.rb +0 -64
  446. data/lib/badline/sid/envelope/state.rb +0 -68
  447. data/lib/badline/sid/envelope.rb +0 -239
  448. data/lib/badline/sid/filter.rb +0 -263
  449. data/lib/badline/sid/voice.rb +0 -77
  450. data/lib/badline/sid/waveform/combined.rb +0 -126
  451. data/lib/badline/sid/waveform/fast_forward.rb +0 -105
  452. data/lib/badline/sid/waveform/noise_writeback.rb +0 -122
  453. data/lib/badline/sid/waveform/state.rb +0 -66
  454. data/lib/badline/sid/waveform.rb +0 -305
  455. data/lib/badline/sid.rb +0 -303
  456. data/lib/badline/time_of_day.rb +0 -228
  457. data/lib/badline/traps.rb +0 -19
  458. data/lib/badline/via/control_lines.rb +0 -122
  459. data/lib/badline/via/fast_forward.rb +0 -53
  460. data/lib/badline/via/interrupt_register.rb +0 -67
  461. data/lib/badline/via/shift_register.rb +0 -180
  462. data/lib/badline/via/state.rb +0 -42
  463. data/lib/badline/via/timer1.rb +0 -131
  464. data/lib/badline/via/timer2.rb +0 -133
  465. data/lib/badline/via.rb +0 -266
  466. data/lib/badline/vic/bank.rb +0 -133
  467. data/lib/badline/vic/border_mask.rb +0 -86
  468. data/lib/badline/vic/collisions.rb +0 -115
  469. data/lib/badline/vic/color_patches.rb +0 -47
  470. data/lib/badline/vic/display_state.rb +0 -185
  471. data/lib/badline/vic/graphics_mode.rb +0 -164
  472. data/lib/badline/vic/graphics_shifter.rb +0 -207
  473. data/lib/badline/vic/register_log.rb +0 -81
  474. data/lib/badline/vic/registers.rb +0 -195
  475. data/lib/badline/vic/sequencer.rb +0 -275
  476. data/lib/badline/vic/sequencer_output.rb +0 -116
  477. data/lib/badline/vic/sequencer_state.rb +0 -89
  478. data/lib/badline/vic/sprite/internal_bus.rb +0 -68
  479. data/lib/badline/vic/sprite/saved_state.rb +0 -64
  480. data/lib/badline/vic/sprite/shifter.rb +0 -146
  481. data/lib/badline/vic/sprite/timing.rb +0 -56
  482. data/lib/badline/vic/sprite.rb +0 -337
  483. data/lib/badline/vic/sprites.rb +0 -282
  484. data/lib/badline/vic/sprites_state.rb +0 -57
  485. data/lib/badline/vic.rb +0 -853
  486. data/lib/badline/vic20/sound/output.rb +0 -83
  487. data/lib/badline/vic20/sound.rb +0 -233
  488. data/lib/badline/z80/arithmetic.rb +0 -117
  489. data/lib/badline/z80/bit_page.rb +0 -55
  490. data/lib/badline/z80/block_io.rb +0 -58
  491. data/lib/badline/z80/block_transfers.rb +0 -59
  492. data/lib/badline/z80/bus_cycles.rb +0 -111
  493. data/lib/badline/z80/core.rb +0 -113
  494. data/lib/badline/z80/exchanges.rb +0 -50
  495. data/lib/badline/z80/extended_page.rb +0 -89
  496. data/lib/badline/z80/flags.rb +0 -37
  497. data/lib/badline/z80/interrupt_acceptance.rb +0 -46
  498. data/lib/badline/z80/jumps.rb +0 -82
  499. data/lib/badline/z80/loads.rb +0 -98
  500. data/lib/badline/z80/main_page.rb +0 -134
  501. data/lib/badline/z80/registers.rb +0 -120
  502. data/lib/badline/z80/saved_state.rb +0 -69
  503. data/lib/badline/z80/shifts.rb +0 -64
  504. data/lib/badline/z80.rb +0 -11
  505. /data/lib/badline/snapshot/{fields.rb → vice/fields.rb} +0 -0
@@ -1,315 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "badline/drive1541/sector_reader"
4
- require "badline/drive1541/disk_state"
5
-
6
- module Badline
7
- class Drive1541
8
- # A disk as the head sees it: a Track for each half track that holds
9
- # data, numbered from 2 (track 1) to MAX_HALF_TRACK (track 42), and
10
- # nothing between them. A .d64 image fills the whole tracks; a .g64
11
- # can fill any of them, with tracks of any length.
12
- #
13
- # The disk has a second side, for the 1571's second head, its half
14
- # tracks numbered from SIDE on. A .d71 fills both sides, its tracks
15
- # 36-70 being tracks 1-35 of the second, and a .g71 holds 84 half
16
- # tracks a side. A 1541 reads the first side only.
17
- #
18
- # The head writes into the tracks' bytes, and a write to a half track
19
- # without data gives it a blank Track first. A disk made from an image
20
- # remembers it: flush reads the sectors back off the tracks written
21
- # since the last flush and stores them in the image, which writes its
22
- # host file. The disk is write-protected when the image won't take
23
- # writes.
24
- class Disk
25
- include State
26
-
27
- MAX_HALF_TRACK = 84
28
-
29
- # Where the second side's half tracks start: its track 1 is SIDE + 2.
30
- SIDE = MAX_HALF_TRACK + 1
31
-
32
- # The tracks a side of a .d71 holds.
33
- D71_SIDE_TRACKS = 35
34
-
35
- # The half track entries a side of a .g71 holds.
36
- G71_SIDE_ENTRIES = 84
37
-
38
- # GCR bytes around a track in each speed zone (Storage::D64Image.zone):
39
- # 200 ms of rotation at 300 rpm, in bytes of 32, 30, 28 and 26 µs.
40
- TRACK_LENGTHS = [6250, 6666, 7142, 7692].freeze
41
-
42
- # How far round the DOS's N: starts each track from the one before,
43
- # in each zone, in 1/10000 of a turn: it steps in and starts writing
44
- # the next track that long after it started the last.
45
- SKEWS = [2916, 897, 8915, 6869].freeze
46
- SKEW_TURN = 10_000
47
-
48
- SYNC_LENGTH = 5
49
- HEADER_GAP = 9
50
- GAP = 0x55
51
- HEADER_ID = 0x08
52
- DATA_ID = 0x07
53
-
54
- # A sector: SYNC, the 10-byte GCR header, the header gap, SYNC and
55
- # the 325-byte GCR data block. The gap after it takes up the rest.
56
- SECTOR_LENGTH = SYNC_LENGTH + 10 + HEADER_GAP + SYNC_LENGTH + 325
57
-
58
- # A disk from the image at +path+: a .g64 or .g71 as its tracks are,
59
- # a .d71 formatted on both sides, and anything else as a .d64,
60
- # formatted. `read_only` opens the image write-protected.
61
- def self.open(path, read_only: false)
62
- image = image_for(path, read_only)
63
- (State.g64?(path) ? from_g64(image) : from_d64(image)).opened(path, read_only)
64
- end
65
-
66
- # The image at +path+, by its name: a .g64 or .g71, a .d71, and
67
- # anything else a .d64.
68
- def self.image_for(path, read_only)
69
- return Storage::G64Image.new(path, read_only:) if State.g64?(path)
70
- return Storage::D71Image.new(path, read_only:) if File.extname(path).casecmp?(".d71")
71
-
72
- Storage::D64Image.new(path, read_only:)
73
- end
74
-
75
- # A disk from a G64 or G71 image, each half track as the image stores
76
- # it, with its speed map. Flushing it writes the tracks back as they
77
- # are.
78
- def self.from_g64(image)
79
- disk = new(image)
80
- image.half_tracks.times do |entry|
81
- track = image.track(entry)
82
- disk.write(half_track_of(entry), Track.new(*track, image.speeds(entry))) if track
83
- end
84
- disk
85
- end
86
-
87
- # The half track a G64 or G71 table entry holds: entry 0 is track 1,
88
- # and a .g71's entries from G71_SIDE_ENTRIES on are the second
89
- # side's.
90
- def self.half_track_of(entry)
91
- side = entry / G71_SIDE_ENTRIES
92
- (side * SIDE) + (entry % G71_SIDE_ENTRIES) + Mechanism::MIN_HALF_TRACK
93
- end
94
-
95
- # The table entry of a half track, or nil for one a G64 or G71 has
96
- # no entry for.
97
- def self.entry_of(half_track)
98
- side = half_track / SIDE
99
- entry = (half_track % SIDE) - Mechanism::MIN_HALF_TRACK
100
- (side * G71_SIDE_ENTRIES) + entry if entry.between?(0, G71_SIDE_ENTRIES - 1)
101
- end
102
-
103
- # The half track an image's track number is on: a .d71's tracks past
104
- # D71_SIDE_TRACKS are on the second side.
105
- def self.d64_half_track(image, track)
106
- return track * 2 unless image.sides == 2 && track > D71_SIDE_TRACKS
107
-
108
- SIDE + ((track - D71_SIDE_TRACKS) * 2)
109
- end
110
-
111
- # The image's track number a half track holds, or nil for a half
112
- # track or one past the image's last.
113
- def self.d64_track(image, half_track)
114
- side = half_track / SIDE
115
- return unless (half_track % SIDE).even?
116
-
117
- track = (half_track % SIDE) / 2
118
- track += D71_SIDE_TRACKS if side == 1
119
- track if track.positive? && track <= image.track_count && side < image.sides
120
- end
121
-
122
- # A disk formatted from a D64 image, each sector laid out as the DOS
123
- # formats it, with the disk ID from the header block. A block the
124
- # image's error table marks 20, 21, 22, 23, 27 or 29 is written the
125
- # way that DOS error would read. The table's other codes, 24, 25, 26
126
- # and 28, describe write or decoding faults the layout can't carry,
127
- # so their blocks are written good and read without an error.
128
- #
129
- # Each track starts sector 0 at the angle the DOS's N: leaves it: track
130
- # 1 at the index angle, and each track after it SKEWS[zone] of a turn
131
- # round from the last. A .d71's second side starts over at the index
132
- # angle.
133
- def self.from_d64(image)
134
- track, sector = image.header_block
135
- header = image.read_block(track, sector)
136
- id = [header[0xa2], header[0xa3]]
137
- disk = new(image)
138
- angle = 0
139
- (1..image.track_count).each do |track|
140
- half_track = d64_half_track(image, track)
141
- zone = Storage::D64Image.zone((half_track % SIDE) / 2)
142
- angle = half_track == SIDE + 2 ? 0 : (angle + SKEWS[zone]) % SKEW_TURN if track > 1
143
- bytes = format_track(image, track, id, zone)
144
- disk.write(half_track, Track.new(bytes.rotate(-(bytes.length * angle / SKEW_TURN)), zone))
145
- end
146
- disk
147
- end
148
-
149
- def self.format_track(image, track, id, zone = Storage::D64Image.zone(track))
150
- sectors = image.sectors_in(track)
151
- length = TRACK_LENGTHS[zone]
152
- gap = (length - (sectors * SECTOR_LENGTH)) / sectors
153
- bytes = []
154
- sectors.times do |sector|
155
- format_sector(bytes, image, track, sector, id)
156
- gap.times { bytes << GAP }
157
- end
158
- bytes << GAP while bytes.length < length
159
- bytes
160
- end
161
-
162
- # Error 21 leaves the block without SYNC marks, and 29 writes its
163
- # header with the wrong first ID byte.
164
- def self.format_sector(bytes, image, track, sector, id)
165
- error = image.block_error(track, sector)
166
- sync = error == 21 ? GAP : 0xff
167
- id = [id[0] ^ 0xff, id[1]] if error == 29
168
- SYNC_LENGTH.times { bytes << sync }
169
- bytes.concat(GCR.encode(header(track, sector, id, error)))
170
- HEADER_GAP.times { bytes << GAP }
171
- SYNC_LENGTH.times { bytes << sync }
172
- bytes.concat(GCR.encode(data_block(image.read_block(track, sector), error)))
173
- end
174
-
175
- # ID, checksum, sector, track, the second ID byte, the first and two
176
- # $0F fillers. Error 20 hides the block's ID and 27 spoils its
177
- # checksum.
178
- def self.header(track, sector, id, error)
179
- checksum = sector ^ track ^ id[1] ^ id[0]
180
- checksum ^= 0xff if error == 27
181
- [error == 20 ? 0x00 : HEADER_ID, checksum, sector, track, id[1], id[0], 0x0f, 0x0f]
182
- end
183
-
184
- # ID, 256 data bytes, their checksum and two $00 fillers. Error 22
185
- # hides the block's ID and 23 spoils its checksum.
186
- def self.data_block(data, error)
187
- checksum = 0
188
- data.each { |byte| checksum ^= byte }
189
- checksum ^= 0xff if error == 23
190
- block = [error == 22 ? 0x00 : DATA_ID]
191
- block.concat(data)
192
- block << checksum << 0x00 << 0x00
193
- end
194
-
195
- attr_reader :image
196
-
197
- def initialize(image = nil)
198
- @image = image
199
- @tracks = Array.new(SIDE * 2)
200
- @written = {}
201
- @path = nil
202
- @read_only = false
203
- end
204
-
205
- # The Track at the half track, or nil where there's no data.
206
- def track(half_track) = @tracks[half_track]
207
-
208
- def write(half_track, track)
209
- @tracks[half_track] = track
210
- end
211
-
212
- # Whether the write-protect notch is covered: the disk's image won't
213
- # take writes, or a disk without an image was opened read-only. A
214
- # disk without an image keeps what it takes only in its tracks.
215
- def write_protected? = @image.nil? ? @read_only : !@image.writable?
216
-
217
- # A half track the head writes to, blank to begin with: no flux, and
218
- # as many bytes as a turn holds at the bit rate of the +zone+ it's
219
- # written in.
220
- def writable_track(half_track, zone)
221
- @tracks[half_track] ||= Track.new(Array.new(TRACK_LENGTHS[zone], 0), zone)
222
- end
223
-
224
- # The head wrote to the half track.
225
- def written(half_track)
226
- @written[half_track] = true
227
- end
228
-
229
- # Whether any track was written since the last flush.
230
- def written? = !@written.empty?
231
-
232
- # Stores each track written since the last flush in the image, all
233
- # in one write to its host file. A G64 image takes the tracks as they
234
- # are. A D64 image takes the sectors read back off them, and keeps
235
- # whole tracks only, so a half track, or a track past its last, stays
236
- # on the disk alone. A sector that no longer reads back keeps its old
237
- # data, and the flush warns once, naming the tracks that lost one.
238
- def flush
239
- return flush_tracks if @image.respond_to?(:store_tracks)
240
-
241
- tracks = @written.keys.filter_map do |half|
242
- track = @image && Disk.d64_track(@image, half)
243
- [half, track] if track
244
- end
245
- @written.clear
246
- return if tracks.empty?
247
-
248
- sectors = tracks.to_h { |half, track| [track, SectorReader.read(@tracks[half].bytes, track)] }
249
- id = disk_id(sectors)
250
- warn_lost(sectors)
251
- @image.store_blocks(sectors.flat_map do |track, found|
252
- Array.new(@image.sectors_in(track)) { |sector| stored_block(track, sector, found[sector], id) }
253
- end)
254
- end
255
-
256
- private
257
-
258
- def flush_tracks
259
- tracks = @written.keys.sort.filter_map do |half|
260
- entry = Disk.entry_of(half)
261
- [entry, [@tracks[half].bytes, @tracks[half].zone]] if entry
262
- end.to_h
263
- @written.clear
264
- @image.store_tracks(tracks) unless tracks.empty?
265
- end
266
-
267
- def warn_lost(sectors)
268
- lost = sectors.keys.select do |track|
269
- Array.new(@image.sectors_in(track)) { |sector| lost?(track, sector, sectors[track][sector]) }.any?
270
- end
271
- return if lost.empty?
272
-
273
- warn "1541: tracks written that no longer read back whole: #{lost.join(', ')}. The .d64 keeps the old " \
274
- "data of the sectors lost, and a .g64 image keeps tracks as the drive writes them."
275
- end
276
-
277
- # A sector the head no longer finds, which the image doesn't already
278
- # hold as unreadable.
279
- def lost?(track, sector, found)
280
- found.nil? && ![20, 21].include?(@image.block_error(track, sector))
281
- end
282
-
283
- # The disk ID the headers must carry, from the header block's $A2 and
284
- # $A3 as Disk.from_d64 takes it: as just read back, or as the image
285
- # holds it.
286
- def disk_id(sectors)
287
- track, sector = @image.header_block
288
- header = sectors.dig(track, sector)&.data
289
- data = header ? header[1, 256] : @image.read_block(track, sector)
290
- [data[0xa2], data[0xa3]]
291
- end
292
-
293
- # [track, sector, data, error] for DiskImage#store_blocks: the data as
294
- # read, nil where it can't be, and the DOS error a read of it would
295
- # raise, the way Disk.from_d64 writes each one. A sector whose header
296
- # isn't found keeps its data, and reads as error 20, or 21 where the
297
- # image already has it so.
298
- def stored_block(track, sector, found, id)
299
- return [track, sector, nil, @image.block_error(track, sector) == 21 ? 21 : 20] unless found
300
-
301
- header = found.header
302
- data = found.data
303
- [track, sector, data && data[1, 256], block_error(header, data, id)]
304
- end
305
-
306
- def block_error(header, data, id)
307
- if header[1] != header[2] ^ header[3] ^ header[4] ^ header[5] then 27
308
- elsif header[5] != id[0] || header[4] != id[1] then 29
309
- elsif data.nil? || data[0] != DATA_ID then 22
310
- elsif data[257] != data[1, 256].reduce(:^) then 23
311
- end
312
- end
313
- end
314
- end
315
- end
@@ -1,86 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "badline/media/extensions"
4
-
5
- module Badline
6
- class Drive1541
7
- class Disk
8
- # Saving and restoring a Disk for a snapshot: the image by its path,
9
- # and every half track as the head sees it, with those written since
10
- # the last flush. The image itself is read again from its host file,
11
- # where there still is one.
12
- module State
13
- # The image's path, expanded, and whether it was opened read-only,
14
- # for a disk from Disk.open. Nil for a disk made another way.
15
- attr_reader :path, :read_only
16
-
17
- # Whether the image is a .g64 or .g71, by its name.
18
- def self.g64?(path) = Media::Extensions.kind(path) == :gcr
19
-
20
- # A disk for the image at the path (Disk.image_for), its tracks left
21
- # for the state.
22
- def self.reopen(path, read_only) = Disk.new(Disk.image_for(path, read_only)).opened(path, read_only)
23
-
24
- # The disk a state from save_state describes: +current+ when it was
25
- # opened from the same image the same way, and otherwise a disk for
26
- # the image at the path the state names. Where no file is at that
27
- # path, the disk has no image and is write-protected, and a
28
- # detached reader always gets one without an image. Either way its
29
- # tracks come from the state.
30
- def self.load(input, current)
31
- path = input.optional_string
32
- read_only = input.boolean?
33
- disk = current if current && !path.nil? && current.path == path && current.read_only == read_only
34
- disk ||= fresh(path, read_only, input.detached?)
35
- disk.load_tracks(input)
36
- disk
37
- end
38
-
39
- def self.fresh(path, read_only, detached)
40
- return Disk.new if path.nil? || detached
41
- return Disk.new.opened(path, true) unless File.file?(path)
42
-
43
- reopen(path, read_only)
44
- end
45
-
46
- # Notes the image's path and how it was opened.
47
- def opened(path, read_only)
48
- @path = File.expand_path(path)
49
- @read_only = read_only
50
- self
51
- end
52
-
53
- def save_state(out)
54
- out.optional_string(@path).boolean(@read_only)
55
- @tracks.each do |track|
56
- out.boolean(!track.nil?)
57
- save_track(track, out) if track
58
- end
59
- out.ints(@written.keys)
60
- end
61
-
62
- def load_tracks(input)
63
- @tracks.each_index do |half_track|
64
- @tracks[half_track] = input.boolean? ? load_track(input) : nil
65
- end
66
- @written.clear
67
- input.ints.each { |half_track| @written[half_track] = true }
68
- end
69
-
70
- private
71
-
72
- def save_track(track, out)
73
- out.int(track.zone).boolean(!track.speeds.nil?)
74
- out.ints(track.speeds) if track.speeds
75
- out.blob(track.bytes)
76
- end
77
-
78
- def load_track(input)
79
- zone = input.int
80
- speeds = input.boolean? ? input.ints : nil
81
- Track.new(input.blob, zone, speeds)
82
- end
83
- end
84
- end
85
- end
86
- end
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Drive1541
5
- # VIA 2, the one facing the disk mechanism. Its port B drives the
6
- # Mechanism, and CB2 selects its read or write mode. The mechanism
7
- # hears both after every write and reset, since ORB, DDRB, the ACR and
8
- # the PCR can all change them.
9
- class DiskVIA < VIA
10
- attr_reader :mechanism
11
-
12
- def initialize(start:, mechanism:)
13
- @mechanism = mechanism
14
- mechanism.via = self
15
- super(start:, peripheral: mechanism)
16
- end
17
-
18
- def reset!
19
- super
20
- tell_mechanism
21
- end
22
-
23
- def poke(addr, value)
24
- super
25
- tell_mechanism
26
- end
27
-
28
- private
29
-
30
- def tell_mechanism
31
- @mechanism.port_b_written(port_b_output)
32
- @mechanism.cb2_written(cb2_output)
33
- end
34
- end
35
- end
36
- end
@@ -1,57 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Drive1541
5
- # Group code recording, the 1541's on-disk code. Each nibble becomes
6
- # five bits, chosen so that no code has more than two 0 bits in a row
7
- # and no run of codes has ten 1 bits in a row, which only a SYNC mark
8
- # has. Four bytes become five.
9
- module GCR
10
- CODES = [0x0a, 0x0b, 0x12, 0x13, 0x0e, 0x0f, 0x16, 0x17,
11
- 0x09, 0x19, 0x1a, 0x1b, 0x0d, 0x1d, 0x1e, 0x15].freeze
12
-
13
- # Five-bit code => nibble, nil for the codes that aren't GCR.
14
- NIBBLES = Array.new(32) { |code| CODES.index(code) }.freeze
15
-
16
- module_function
17
-
18
- # Encodes a whole number of four-byte groups.
19
- def encode(bytes)
20
- out = []
21
- i = 0
22
- while i < bytes.length
23
- bits = 0
24
- 4.times do |n|
25
- byte = bytes[i + n]
26
- bits = (bits << 10) | (CODES[byte >> 4] << 5) | CODES[byte & 0x0f]
27
- end
28
- 4.downto(0) { |n| out << ((bits >> (n * 8)) & 0xff) }
29
- i += 4
30
- end
31
- out
32
- end
33
-
34
- # Decodes a whole number of five-byte groups, nil when any code
35
- # isn't GCR.
36
- def decode(bytes)
37
- out = []
38
- i = 0
39
- while i < bytes.length
40
- bits = 0
41
- 5.times { |n| bits = (bits << 8) | bytes[i + n] }
42
- n = 7
43
- while n.positive?
44
- high = NIBBLES[(bits >> (n * 5)) & 0x1f]
45
- low = NIBBLES[(bits >> ((n - 1) * 5)) & 0x1f]
46
- return nil if high.nil? || low.nil?
47
-
48
- out << ((high << 4) | low)
49
- n -= 2
50
- end
51
- i += 5
52
- end
53
- out
54
- end
55
- end
56
- end
57
- end