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