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,313 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "badline/drive1541/rotation"
4
- require "badline/drive1541/mechanism_state"
5
- require "badline/drive1541/byte_ready"
6
-
7
- module Badline
8
- class Drive1541
9
- # The disk mechanism behind VIA 2: the spindle motor, the head on its
10
- # stepper, the LED, the read and write electronics and the
11
- # write-protect sensor.
12
- #
13
- # Port B drives it and reads it back:
14
- #
15
- # PB0-1 stepper phase (out) PB4 write protect (in, 1 = writable)
16
- # PB2 motor on (out) PB5-6 bit rate, speed zone 0-3 (out)
17
- # PB3 LED on (out) PB7 SYNC (in, 0 while in a SYNC mark)
18
- #
19
- # Port A reads the read shift register's low eight bits, which CA1
20
- # latches on BYTE READY. In write mode it drives the write shift
21
- # register, and the read shift register takes the bits written.
22
- #
23
- # The disk turns at 300 rpm under the head, and a read clock at the
24
- # bit rate PB5-6 select clocks the bits off it (see Rotation).
25
- #
26
- # Ten 1 bits in a row are a SYNC mark while CB2 selects reading: PB7
27
- # reads it, and it holds the bit counter at zero, so the first 0 bit
28
- # after it starts a byte. Every eighth bit after that is BYTE READY,
29
- # which pulls VIA 2's CA1 low until the next bit and reaches the CPU's
30
- # SO pin (see byte_ready!).
31
- #
32
- # CB2 low selects write mode, where SYNC detection and the flux are
33
- # off and the clock runs on at the selected rate. At each BYTE READY
34
- # the write shift register loads what the VIA drives on port A, and
35
- # the next eight clocks put that byte's bits on the track, most
36
- # significant first, in place of what it held. While reading, the load
37
- # takes the byte just read, so a switch to writing mid-byte writes the
38
- # rest of it. A write lays its bits one to a cell from the cell under
39
- # the head, so on a track written at the selected rate each bit fills
40
- # the cell it passes over. A write to a half track without data gives
41
- # it a blank track first, a turn long at the selected rate, and a
42
- # write to a track written at another rate lays the whole track out
43
- # again as a turn at the selected rate first (Track#relaid).
44
- #
45
- # PB4 reads the write-protect sensor: high with no disk in, or with
46
- # the notch of a writable one open. With the disk write-protected the
47
- # write gate stays shut: the bits and BYTE READY go on, and nothing
48
- # reaches the disk. The DOS reads PB4 first and refuses to write, so
49
- # only a program that writes without asking finds that out.
50
- #
51
- # The motor stopping flushes what was written to the disk's image
52
- # (see Disk#flush), which is when the DOS is done with a job, and so
53
- # does taking the disk out.
54
- #
55
- # The stepper moves the head a half track each time the phase steps
56
- # by one, inwards for +1 and outwards for -1. Each half track has a
57
- # phase of its own, from power-on the low two bits of its number, so
58
- # the head sits on a whole track when phase 0 or 2 holds it. The
59
- # stepper's coils are powered only while PB2 runs the motor, as VICE
60
- # reads the 1541's schematic, so a phase set with the motor off moves
61
- # nothing until the motor comes on and it pulls the head. Tracks run
62
- # from half track 2 (track 1), where the head stops against the end of
63
- # its rail, to Disk::MAX_HALF_TRACK. A step out against the stop slips:
64
- # the head stays on track 1 and the phase that tried to pull it out
65
- # becomes track 1's, so the DOS's bump leaves the head on track 1 in
66
- # line with the phase it ends on, and its first step in reaches the
67
- # half track after it.
68
- #
69
- # The 1571's stepper is lined up so that phase 0 holds track 1, where
70
- # its track 0 sensor looks for the head (Mechanism.new's +slip+).
71
- class Mechanism
72
- include Rotation
73
- include MechanismState
74
- include ByteReady
75
-
76
- MOTOR = 0x04
77
- LED = 0x08
78
- WRITE_PROTECT = 0x10
79
- SYNC = 0x80
80
-
81
- MIN_HALF_TRACK = 2
82
- # Where the head sits at power-on: track 18, the directory.
83
- START_HALF_TRACK = 36
84
-
85
- SYNC_BITS = 10
86
-
87
- attr_reader :disk, :half_track, :zone
88
-
89
- # +slip+ is the stepper's phase offset at power-on: 0, where each half
90
- # track's phase is the low two bits of its number, or 2 for track 1
91
- # on phase 0.
92
- def initialize(slip: 0)
93
- @via = nil
94
- @so_pending = false
95
- @disk = nil
96
- @half_track = START_HALF_TRACK
97
- @slip = slip
98
- @motor = false
99
- @led = false
100
- @zone = 0
101
- @clock = Track.cell(0)
102
- @time = 0
103
- @clock_at = @clock / 2
104
- @clocks = 0
105
- @shift = 0
106
- @ones = 0
107
- @bits = 0
108
- @sync = false
109
- @byte_ready = false
110
- @byte_latched = false
111
- @writing = false
112
- @write_shift = 0
113
- @write_gate = false
114
- @protected = false
115
- @side_base = 0
116
- @cycle_ticks = CYCLE
117
- load_track
118
- end
119
-
120
- # The drive's clock rate: the disk turns on by fewer ticks each
121
- # cycle at 2 MHz.
122
- def clock_hz=(clock_hz)
123
- @cycle_ticks = CYCLE * Drive1541::CLOCK_HZ / clock_hz
124
- end
125
-
126
- # The head that reads, 0 or 1, on a drive with two (Disk::SIDE).
127
- def side = @side_base.zero? ? 0 : 1
128
-
129
- def side=(side)
130
- side_base = side * Disk::SIDE
131
- return if side_base == @side_base
132
-
133
- @side_base = side_base
134
- load_track
135
- end
136
-
137
- def motor_on? = @motor
138
-
139
- def led_on? = @led
140
-
141
- def sync? = @sync
142
-
143
- def writing? = @writing
144
-
145
- # What port B and CB2 can change with the motor off: the motor, the
146
- # LED, the zone and the clock's rate, the stepper, write mode and
147
- # where a write starts, and the track and cell under the head. The
148
- # rest moves only while the motor turns, or as a disk goes in (see
149
- # Drive::Idle).
150
- def idle_state
151
- [@motor, @led, @zone, @clock, @half_track, @slip, @side_base, @disk, @track, @index, @mask, @cell_end,
152
- @time, @writing, @write_index, @sync, @byte_latched]
153
- end
154
-
155
- # Puts a Disk in, or takes it out with nil, flushing the disk that
156
- # was in. The head goes on from the same point in the turn.
157
- def insert(disk)
158
- flush
159
- @disk = disk
160
- @protected = disk&.write_protected? || false
161
- @write_gate = !disk.nil? && !@protected
162
- load_track
163
- end
164
-
165
- # Stores what the head wrote in the disk's image.
166
- def flush
167
- @disk.flush if @disk&.written?
168
- rescue Storage::WriteError => e
169
- warn "1541: couldn't write the disk back: #{e.message}"
170
- end
171
-
172
- # VIA 2 drives CB2 to +high+: low selects write mode, which stops
173
- # SYNC detection at once.
174
- def cb2_written(high)
175
- @write_index = nil if high || !@writing
176
- @writing = !high
177
- @sync = !@writing && @ones >= SYNC_BITS
178
- end
179
-
180
- # VIA 2 drives port B's lines to +lines+.
181
- def port_b_written(lines)
182
- motor = @motor
183
- @motor = lines.anybits?(MOTOR)
184
- flush if motor && !@motor
185
- @led = lines.anybits?(LED)
186
- zone = (lines >> 5) & 0x03
187
- if zone != @zone
188
- @zone = zone
189
- @clock = Track.cell(zone)
190
- @track_written = false
191
- end
192
- step(lines & 0x03) if @motor
193
- end
194
-
195
- # Port A is the read shift register.
196
- def read_a(_lines) = @shift & 0xff
197
-
198
- # SYNC low in a SYNC mark, and write protect low for a protected
199
- # disk.
200
- def read_b(_lines)
201
- lines = @sync ? 0xff & ~SYNC : 0xff
202
- @protected ? lines & ~WRITE_PROTECT : lines
203
- end
204
-
205
- private
206
-
207
- def read_bit(one)
208
- if @byte_ready
209
- @byte_ready = false
210
- byte_ready_ended!
211
- end
212
- @shift = ((@shift << 1) & 0x3fe) | (one ? 1 : 0)
213
- if one
214
- @ones += 1
215
- @sync = true if @ones >= SYNC_BITS
216
- else
217
- @ones = 0
218
- @sync = false
219
- end
220
- count_bit
221
- end
222
-
223
- # The write shift register's top bit goes onto the track through the
224
- # write gate, and into the read shift register, as the head's own
225
- # signal.
226
- def write_bit(at)
227
- if @byte_ready
228
- @byte_ready = false
229
- byte_ready_ended!
230
- end
231
- one = @write_shift.anybits?(0x80)
232
- @write_shift = (@write_shift << 1) & 0xff
233
- store_bit(one, at) if @write_gate
234
- @shift = ((@shift << 1) & 0x3fe) | (one ? 1 : 0)
235
- @ones = one ? @ones + 1 : 0
236
- count_bit
237
- end
238
-
239
- # Each bit written goes in the cell after the last one's, from the
240
- # cell under the head when the write started.
241
- def store_bit(one, at)
242
- track_written(at) unless @track_written
243
- @write_index ||= (@index * 8) + 8 - @mask.bit_length
244
- index = @write_index >> 3
245
- mask = 0x80 >> (@write_index & 7)
246
- if one
247
- @bytes[index] |= mask
248
- else
249
- @bytes[index] &= ~mask
250
- end
251
- @write_index += 1
252
- @write_index = 0 if @write_index == @length * 8
253
- end
254
-
255
- # The first write to the track since the head came to it or the rate
256
- # changed: a half track without data gets a blank track, and a track
257
- # written at another rate is laid out again at this one.
258
- def track_written(at)
259
- surface = self.surface
260
- track = @disk.writable_track(surface, @zone)
261
- @disk.write(surface, track.relaid(@zone)) unless track.written_at?(@zone)
262
- load_track(at)
263
- @disk.written(surface)
264
- @track_written = true
265
- end
266
-
267
- # Every eighth bit outside a SYNC mark is BYTE READY, which loads the
268
- # write shift register: from what the VIA drives on port A in write
269
- # mode, and with the byte just read otherwise.
270
- def count_bit
271
- if @sync
272
- @bits = 0
273
- return
274
- end
275
- @bits += 1
276
- return unless @bits == 8
277
-
278
- @bits = 0
279
- @write_shift = @writing ? @via.port_a_output : @shift & 0xff
280
- @byte_ready = true
281
- byte_ready!
282
- end
283
-
284
- # The stepper's rotor turns with the head, a phase to each half
285
- # track, so the energized phase pulls the head to the neighbouring
286
- # half track it belongs to. A phase two away pulls both ways, and the
287
- # head stays. Against the stop at track 1 the head can't follow, and
288
- # the phases slip round to where the head is.
289
- def step(phase)
290
- move = (phase - @half_track - @slip) & 0x03
291
- if move == 1
292
- seek(@half_track + 1)
293
- elsif move == 3 && @half_track == MIN_HALF_TRACK
294
- @slip = (phase - MIN_HALF_TRACK) & 0x03
295
- elsif move == 3
296
- seek(@half_track - 1)
297
- end
298
- end
299
-
300
- # The half track under the head that reads, numbered on the disk
301
- # (see Disk::SIDE).
302
- def surface = @half_track + @side_base
303
-
304
- def seek(half_track)
305
- half_track = half_track.clamp(MIN_HALF_TRACK, Disk::MAX_HALF_TRACK)
306
- return if half_track == @half_track
307
-
308
- @half_track = half_track
309
- load_track
310
- end
311
- end
312
- end
313
- end
@@ -1,68 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Drive1541
5
- # Saving and restoring the Mechanism for a snapshot.
6
- module MechanismState
7
- # The disk (Disk#save_state) and everything the head, the motor, the
8
- # stepper and the read and write electronics hold, down to the cell
9
- # under the head and the read clock's phase.
10
- def save_state(out)
11
- out.boolean(!@disk.nil?)
12
- @disk&.save_state(out)
13
- [@half_track, @slip, @side_base, @zone, @clock, @time, @clock_at, @clocks, @shift, @ones, @bits, @write_shift,
14
- @index, @mask, @cell_end, @width, @next].each { |value| out.int(value) }
15
- [@motor, @led, @sync, @byte_ready, @byte_latched, @writing, @write_gate, @protected,
16
- @track_written].each { |flag| out.boolean(flag) }
17
- out.optional_int(@write_index)
18
- end
19
-
20
- # Puts the state back, reusing the disk in when it's the one the state
21
- # names (Disk::State.load). A disk taken out is flushed, as insert
22
- # does.
23
- def load_state(input)
24
- disk = input.boolean? ? Disk::State.load(input, @disk) : nil
25
- flush unless disk.equal?(@disk)
26
- @disk = disk
27
- load_head(input)
28
- load_flags(input)
29
- @write_index = input.optional_int
30
- head_on_track
31
- end
32
-
33
- private
34
-
35
- def load_head(input)
36
- @half_track = input.int
37
- @slip = input.int
38
- @side_base = input.int
39
- @zone = input.int
40
- @clock = input.int
41
- @time = input.int
42
- @clock_at = input.int
43
- @clocks = input.int
44
- @shift = input.int
45
- @ones = input.int
46
- @bits = input.int
47
- @write_shift = input.int
48
- @index = input.int
49
- @mask = input.int
50
- @cell_end = input.int
51
- @width = input.int
52
- @next = input.int
53
- end
54
-
55
- def load_flags(input)
56
- @motor = input.boolean?
57
- @led = input.boolean?
58
- @sync = input.boolean?
59
- @byte_ready = input.boolean?
60
- @byte_latched = input.boolean?
61
- @writing = input.boolean?
62
- @write_gate = input.boolean?
63
- @protected = input.boolean?
64
- @track_written = input.boolean?
65
- end
66
- end
67
- end
68
- end
@@ -1,121 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Drive1541
5
- # The disk turning under the Mechanism's head, and its read clock.
6
- #
7
- # The disk turns at 300 rpm, whatever the bit rate: once in 200 ms, or
8
- # 200,000 drive cycles. Each track's bits pass under the head at the
9
- # rate they were written at (see Track), and a 1 bit is a flux
10
- # transition at the start of its cell.
11
- #
12
- # The read circuit clocks bits out at the rate PB5-6 select, from a
13
- # counter the 16 MHz crystal steps every 16 - zone ticks. A flux
14
- # transition clears the counter. The counter clocks a bit into the
15
- # read shift register as it reaches 2 and every four steps after
16
- # that, and the bit is a 1 only for the first clock after the counter
17
- # passed 0. A bit is 4 * (16 - zone) ticks, so a byte takes 32, 30, 28
18
- # or 26 drive cycles in zones 0 to 3, and each transition brings the
19
- # clock back into step with the flux. A track read at the rate it was
20
- # written reads its bits. At another rate the clock and the cells
21
- # drift apart between transitions: a faster clock slips an extra 0
22
- # bit into some runs of 0 bits, a slower one drops one from some, and
23
- # the bytes come out garbled. Without flux the counter runs round on
24
- # its own and reads a 1 bit in every four.
25
- module Rotation
26
- CYCLE = 16 * Track::TICK
27
-
28
- # What the head reads with no disk in, or off the tracks a disk has:
29
- # no flux.
30
- BLANK = Track.new(Array.new(Disk::TRACK_LENGTHS[0], 0).freeze, 0)
31
-
32
- # One drive cycle: nothing with the motor off, and otherwise the
33
- # disk turns on by a cycle's ticks, 16 at 1 MHz and 8 at 2 MHz,
34
- # through whatever cells and clocks fall in them.
35
- def cycle!
36
- return unless @motor
37
-
38
- @time += @cycle_ticks
39
- pass_time if @time >= @next
40
- end
41
-
42
- private
43
-
44
- # The cell edges and clocks up to now, in the order they come. A
45
- # clock that falls on a cell edge comes after it.
46
- def pass_time
47
- while @cell_end <= @time || @clock_at <= @time
48
- if @cell_end <= @clock_at
49
- next_cell
50
- else
51
- clock
52
- end
53
- end
54
- @next = [@cell_end, @clock_at].min
55
- end
56
-
57
- # The head comes to the next cell, and a 1 bit's flux clears the
58
- # read clock while reading.
59
- def next_cell
60
- start = @cell_end
61
- @mask >>= 1
62
- start = next_byte(start) if @mask.zero?
63
- @cell_end = @index == @last && @mask == 1 ? Track::TURN : start + @width
64
- return if @writing || @bytes[@index].nobits?(@mask)
65
-
66
- @clock_at = start + (@clock / 2)
67
- @clocks = 0
68
- end
69
-
70
- # The head comes to the next byte, and at the end of the track back
71
- # round to the first, where the turn starts over.
72
- def next_byte(start)
73
- @mask = 0x80
74
- @index += 1
75
- if @index == @length
76
- @index = 0
77
- @time -= Track::TURN
78
- @clock_at -= Track::TURN
79
- start = 0
80
- end
81
- @width = @widths[@index] if @widths
82
- start
83
- end
84
-
85
- # The read clock ticks a bit into the shift register: a 1 the first
86
- # time after a flux transition or the counter's wrap.
87
- def clock
88
- at = @clock_at
89
- one = @clocks.zero?
90
- @clocks = (@clocks + 1) & 3
91
- @clock_at = at + @clock
92
- @writing ? write_bit(at) : read_bit(one)
93
- end
94
-
95
- # The track under the head and its layout, leaving the head's place
96
- # on it as it stands.
97
- def head_on_track
98
- @track = @disk&.track(surface) || BLANK
99
- @bytes = @track.bytes
100
- @widths = @track.widths
101
- @length = @track.length
102
- @last = @length - 1
103
- end
104
-
105
- # The track under the head, from the cell that's under it +time+
106
- # into the turn.
107
- def load_track(time = @time)
108
- @track = @disk&.track(surface) || BLANK
109
- @bytes = @track.bytes
110
- @widths = @track.widths
111
- @length = @track.length
112
- @last = @length - 1
113
- @index, @mask, @cell_end = @track.cell_at(time)
114
- @width = @widths ? @widths[@index] : @track.width
115
- @write_index = nil
116
- @track_written = false
117
- @next = [@cell_end, @clock_at].min
118
- end
119
- end
120
- end
121
- end
@@ -1,76 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Drive1541
5
- # Reads a track's blocks back out of its GCR, as the DOS finds them:
6
- # each SYNC mark is ten or more 1 bits, and the block after it starts
7
- # at the first 0 bit. Writes land wherever the head was, so a block
8
- # can start at any bit of the stored bytes, and the reader works on
9
- # the bits.
10
- #
11
- # A header block starts with $08, and the next block after a header is
12
- # that sector's data block, whatever it holds.
13
- module SectorReader
14
- HEADER_BITS = 10 * 8
15
- DATA_BITS = 325 * 8
16
- SYNC = /1{10,}/
17
-
18
- # A sector as read: its decoded header, [ID, checksum, sector, track,
19
- # the second ID byte, the first, ...], and its decoded data block,
20
- # [ID, 256 data bytes, checksum, ...], nil when there isn't one that
21
- # decodes.
22
- Sector = Struct.new(:header, :data)
23
-
24
- module_function
25
-
26
- # The sectors found on the track's bytes, by sector number. Headers
27
- # for another track are left out.
28
- def read(bytes, track)
29
- ring = ring(bytes)
30
- return {} unless ring
31
-
32
- sectors = {}
33
- each_block(ring) do |header, data|
34
- next unless header[3] == track
35
-
36
- sectors[header[2]] ||= Sector.new(header, data)
37
- end
38
- sectors
39
- end
40
-
41
- # The track's bits, starting at a 0 bit so no SYNC mark straddles the
42
- # start, twice over so a block can run on past the end. Nil for a
43
- # track without a 0 bit.
44
- def ring(bytes)
45
- bits = bytes.pack("C*").unpack1("B*")
46
- zero = bits.index("0")
47
- return unless zero
48
-
49
- bits = bits[zero..] + bits[0, zero]
50
- [bits * 2, bits.length]
51
- end
52
-
53
- # Yields each header whose SYNC mark starts in the first turn, with
54
- # the data block after it.
55
- def each_block(ring)
56
- bits, length = ring
57
- pos = 0
58
- while (sync = SYNC.match(bits, pos)) && sync.begin(0) < length
59
- pos = sync.end(0)
60
- header = decode(bits, pos, HEADER_BITS)
61
- next unless header && header[0] == Disk::HEADER_ID
62
-
63
- data_sync = SYNC.match(bits, pos + HEADER_BITS)
64
- yield header, data_sync && decode(bits, data_sync.end(0), DATA_BITS)
65
- end
66
- end
67
-
68
- def decode(bits, pos, count)
69
- slice = bits[pos, count]
70
- return unless slice.length == count
71
-
72
- GCR.decode([slice].pack("B*").bytes)
73
- end
74
- end
75
- end
76
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Drive1541
5
- # What VIA 1's ports read from outside the chip. Port B carries the
6
- # serial bus inputs and the device number jumpers (Drive::SerialLines);
7
- # port A goes to the unused parallel header and floats high.
8
- class SerialPort
9
- include Drive::SerialLines
10
-
11
- def initialize(device: 8, bus: IECBus.new)
12
- init_serial_lines(device, bus)
13
- end
14
-
15
- def read_a(_lines) = 0xff
16
- end
17
- end
18
- end
@@ -1,98 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Drive1541
5
- # One ring of flux on the disk, as the GCR bytes the head reads from it,
6
- # most significant bit first, and the speed zone it was written in
7
- # (0-3). The bytes wrap around: the last one's bits run into the
8
- # first's. A track is as long as its bytes, which is what a .g64 image
9
- # stores for each half track.
10
- #
11
- # The disk turns at 300 rpm, so every track passes under the head in
12
- # the same 200 ms, and its bits pass at the rate they were written at.
13
- # Each bit is a cell of time, starting at the track's index angle with
14
- # the first byte's top bit, and a 1 bit is a flux transition at the
15
- # start of its cell. The cells are spread evenly over the turn, so a
16
- # track as long as a turn holds at its zone's rate
17
- # (Disk::TRACK_LENGTHS) passes at that rate, within the part of a byte
18
- # the length rounds off, and a longer or shorter one faster or slower.
19
- # A .g64 speed map gives each byte the zone it was written in, and the
20
- # cells of each byte are as wide as their zone's, scaled together to
21
- # fill the turn.
22
- #
23
- # Times are in TICKs, 1/65536 of a tick of the drive's 16 MHz crystal,
24
- # so the cells add up to a turn within a tick.
25
- class Track
26
- TICK = 1 << 16
27
- TURN = 200_000 * 16 * TICK
28
-
29
- # A bit cell at the zone's rate, in TICKs.
30
- def self.cell(zone) = 4 * (16 - zone) * TICK
31
-
32
- attr_reader :bytes, :zone, :speeds, :width, :widths
33
-
34
- # +speeds+ holds each byte's zone, where the track's rate changes
35
- # along it.
36
- def initialize(bytes, zone, speeds = nil)
37
- @bytes = bytes
38
- @zone = zone
39
- @speeds = speeds
40
- @widths = speeds && scaled_widths(speeds)
41
- @width = speeds ? @widths[0] : TURN / (bytes.length * 8)
42
- end
43
-
44
- def length = @bytes.length
45
-
46
- # Whether the whole track was written at the +zone+'s rate.
47
- def written_at?(zone) = @widths.nil? && @zone == zone
48
-
49
- # The bit cell under the head +time+ TICKs into the turn, as
50
- # [byte, mask, the time the cell ends].
51
- def cell_at(time)
52
- start = 0
53
- index = 0
54
- if @widths
55
- while index < length - 1 && time >= start + (@widths[index] * 8)
56
- start += @widths[index] * 8
57
- index += 1
58
- end
59
- else
60
- index = [time / (@width * 8), length - 1].min
61
- start = index * @width * 8
62
- end
63
- width = @widths ? @widths[index] : @width
64
- bit = [(time - start) / width, 7].min
65
- cell_end = index == length - 1 && bit == 7 ? TURN : start + ((bit + 1) * width)
66
- [index, 0x80 >> bit, cell_end]
67
- end
68
-
69
- # The track laid out again as one turn at the +zone+'s rate, each
70
- # flux transition in the cell under it.
71
- def relaid(zone)
72
- bits = Disk::TRACK_LENGTHS[zone] * 8
73
- cell = TURN / bits
74
- relaid = Array.new(bits / 8, 0)
75
- time = 0
76
- @bytes.each_with_index do |byte, index|
77
- width = @widths ? @widths[index] : @width
78
- 8.times do |bit|
79
- if byte.anybits?(0x80 >> bit)
80
- cell_index = [time / cell, bits - 1].min
81
- relaid[cell_index >> 3] |= 0x80 >> (cell_index & 7)
82
- end
83
- time += width
84
- end
85
- end
86
- Track.new(relaid, zone)
87
- end
88
-
89
- private
90
-
91
- def scaled_widths(speeds)
92
- units = 0
93
- speeds.each { |zone| units += 16 - zone }
94
- speeds.map { |zone| TURN * (16 - zone) / (units * 8) }
95
- end
96
- end
97
- end
98
- end