badline 0.12.1 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (565) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -1
  3. data/CLAUDE.md +86 -38
  4. data/CONTRIBUTING.md +4 -3
  5. data/README.md +9 -6
  6. data/doc/library.md +9 -9
  7. data/doc/media.md +2 -1
  8. data/doc/pinned-behaviour.md +134 -105
  9. data/doc/snapshot-format.md +1047 -0
  10. data/doc/snapshots.md +73 -43
  11. data/lib/badline/audio/bare_player.rb +53 -20
  12. data/lib/badline/audio/cli.rb +6 -6
  13. data/lib/badline/audio/jukebox.rb +2 -2
  14. data/lib/badline/audio/machine_player.rb +16 -10
  15. data/lib/badline/{media → audio}/queue.rb +1 -1
  16. data/lib/badline/audio/queued_tune.rb +6 -6
  17. data/lib/badline/audio/renderer.rb +33 -22
  18. data/lib/badline/audio/stereo.rb +1 -1
  19. data/lib/badline/c128/banks.rb +6 -3
  20. data/lib/badline/c128/bus/keyed_state.rb +45 -0
  21. data/lib/badline/c128/bus.rb +35 -20
  22. data/lib/badline/c128/color_lines.rb +2 -2
  23. data/lib/badline/c128/cpu.rb +1 -1
  24. data/lib/badline/c128/drives.rb +14 -34
  25. data/lib/badline/c128/fast_serial.rb +5 -5
  26. data/lib/badline/c128/keyed_modules.rb +117 -0
  27. data/lib/badline/c128/keyed_state.rb +91 -0
  28. data/lib/badline/c128/keys.rb +9 -0
  29. data/lib/badline/c128/mmu.rb +9 -8
  30. data/lib/badline/c128/mmu_pages.rb +21 -1
  31. data/lib/badline/c128/modes.rb +21 -11
  32. data/lib/badline/c128/z80.rb +2 -2
  33. data/lib/badline/c128/z80_turns.rb +1 -1
  34. data/lib/badline/c128.rb +21 -16
  35. data/lib/badline/c64/attachments.rb +42 -0
  36. data/lib/badline/c64/banked_ram/banking.rb +32 -0
  37. data/lib/badline/c64/banked_ram/plus256k.rb +64 -0
  38. data/lib/badline/c64/banked_ram/plus60k.rb +47 -0
  39. data/lib/badline/c64/banked_ram/unexpanded.rb +30 -0
  40. data/lib/badline/c64/banked_ram.rb +23 -0
  41. data/lib/badline/c64/bus/debug_register.rb +32 -0
  42. data/lib/badline/c64/bus/extra_sids.rb +32 -0
  43. data/lib/badline/c64/bus/fittings.rb +40 -0
  44. data/lib/badline/c64/bus/keyed_state.rb +41 -0
  45. data/lib/badline/c64/bus/pla.rb +149 -0
  46. data/lib/badline/c64/bus/roms.rb +41 -0
  47. data/lib/badline/c64/bus/sid_slots.rb +44 -0
  48. data/lib/badline/c64/bus.rb +219 -0
  49. data/lib/badline/c64/cartridge/action_replay.rb +115 -0
  50. data/lib/badline/c64/cartridge/atomic_power.rb +26 -0
  51. data/lib/badline/c64/cartridge/bank.rb +83 -0
  52. data/lib/badline/c64/cartridge/comal80.rb +52 -0
  53. data/lib/badline/c64/cartridge/dinamic.rb +36 -0
  54. data/lib/badline/c64/cartridge/easy_flash.rb +132 -0
  55. data/lib/badline/c64/cartridge/epyx_fastload.rb +73 -0
  56. data/lib/badline/c64/cartridge/final_cartridge3.rb +79 -0
  57. data/lib/badline/c64/cartridge/flash.rb +279 -0
  58. data/lib/badline/c64/cartridge/freezer.rb +35 -0
  59. data/lib/badline/c64/cartridge/fun_play.rb +40 -0
  60. data/lib/badline/c64/cartridge/g_mod2.rb +64 -0
  61. data/lib/badline/c64/cartridge/game_system.rb +42 -0
  62. data/lib/badline/c64/cartridge/geo_ram.rb +65 -0
  63. data/lib/badline/c64/cartridge/kcs_power.rb +69 -0
  64. data/lib/badline/c64/cartridge/keyed_state.rb +393 -0
  65. data/lib/badline/c64/cartridge/mach5.rb +34 -0
  66. data/lib/badline/c64/cartridge/magic_desk.rb +32 -0
  67. data/lib/badline/c64/cartridge/ocean.rb +37 -0
  68. data/lib/badline/c64/cartridge/pagefox.rb +60 -0
  69. data/lib/badline/c64/cartridge/retro_replay.rb +278 -0
  70. data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
  71. data/lib/badline/c64/cartridge/rgcd.rb +50 -0
  72. data/lib/badline/c64/cartridge/simons_basic.rb +37 -0
  73. data/lib/badline/c64/cartridge/standard.rb +17 -0
  74. data/lib/badline/c64/cartridge/super_games.rb +40 -0
  75. data/lib/badline/c64/cartridge/westermann.rb +32 -0
  76. data/lib/badline/c64/cartridge/zaxxon.rb +52 -0
  77. data/lib/badline/c64/cartridge.rb +232 -0
  78. data/lib/badline/c64/color_memory.rb +27 -0
  79. data/lib/badline/{computer → c64}/common.rb +2 -2
  80. data/lib/badline/{computer → c64}/kernal_traps.rb +39 -36
  81. data/lib/badline/c64/keyed_modules.rb +111 -0
  82. data/lib/badline/c64/keyed_state.rb +68 -0
  83. data/lib/badline/c64/reu/dma.rb +271 -0
  84. data/lib/badline/c64/reu/keyed_state.rb +140 -0
  85. data/lib/badline/c64/reu/ram.rb +94 -0
  86. data/lib/badline/c64/reu/trigger.rb +34 -0
  87. data/lib/badline/c64/reu.rb +289 -0
  88. data/lib/badline/c64/true_drives.rb +120 -0
  89. data/lib/badline/{computer.rb → c64.rb} +24 -15
  90. data/lib/badline/chips/cia/fast_forward.rb +62 -0
  91. data/lib/badline/chips/cia/interrupt_register.rb +128 -0
  92. data/lib/badline/chips/cia/keyed_parts.rb +213 -0
  93. data/lib/badline/chips/cia/serial.rb +246 -0
  94. data/lib/badline/chips/cia/time_of_day.rb +210 -0
  95. data/lib/badline/chips/cia/timer.rb +188 -0
  96. data/lib/badline/chips/cia.rb +281 -0
  97. data/lib/badline/chips/cpu/addressing.rb +133 -0
  98. data/lib/badline/chips/cpu/boundary.rb +56 -0
  99. data/lib/badline/chips/cpu/core.rb +183 -0
  100. data/lib/badline/chips/cpu/instruction.rb +338 -0
  101. data/lib/badline/chips/cpu/instruction_set/arithmetic.rb +118 -0
  102. data/lib/badline/chips/cpu/instruction_set/bitwise.rb +130 -0
  103. data/lib/badline/chips/cpu/instruction_set/branch.rb +83 -0
  104. data/lib/badline/chips/cpu/instruction_set/flag.rb +67 -0
  105. data/lib/badline/chips/cpu/instruction_set/illegal.rb +274 -0
  106. data/lib/badline/chips/cpu/instruction_set/inc_dec.rb +73 -0
  107. data/lib/badline/chips/cpu/instruction_set/stack.rb +56 -0
  108. data/lib/badline/chips/cpu/instruction_set/transfer.rb +141 -0
  109. data/lib/badline/chips/cpu/instruction_set.rb +59 -0
  110. data/lib/badline/chips/cpu/interrupts.rb +108 -0
  111. data/lib/badline/chips/cpu/keyed_state.rb +177 -0
  112. data/lib/badline/chips/cpu/microcode.rb +195 -0
  113. data/lib/badline/chips/cpu/operations.rb +90 -0
  114. data/lib/badline/chips/cpu/port.rb +133 -0
  115. data/lib/badline/chips/cpu/stack_operations.rb +84 -0
  116. data/lib/badline/chips/cpu/traps.rb +23 -0
  117. data/lib/badline/chips/cpu.rb +17 -0
  118. data/lib/badline/chips/sid/catch_up.rb +122 -0
  119. data/lib/badline/chips/sid/decimator.rb +68 -0
  120. data/lib/badline/chips/sid/envelope.rb +236 -0
  121. data/lib/badline/chips/sid/filter.rb +227 -0
  122. data/lib/badline/chips/sid/keyed_parts.rb +286 -0
  123. data/lib/badline/chips/sid/voice.rb +69 -0
  124. data/lib/badline/chips/sid/waveform/combined.rb +128 -0
  125. data/lib/badline/chips/sid/waveform/fast_forward.rb +107 -0
  126. data/lib/badline/chips/sid/waveform/noise_writeback.rb +124 -0
  127. data/lib/badline/chips/sid/waveform.rb +305 -0
  128. data/lib/badline/chips/sid.rb +264 -0
  129. data/lib/badline/chips/ted/beam.rb +119 -0
  130. data/lib/badline/chips/ted/timers.rb +66 -0
  131. data/lib/badline/chips/ted.rb +143 -0
  132. data/lib/badline/chips/tia.rb +49 -0
  133. data/lib/badline/chips/vdc/keyed_parts.rb +105 -0
  134. data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
  135. data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -13
  136. data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -17
  137. data/lib/badline/{c128 → chips}/vdc/window.rb +1 -10
  138. data/lib/badline/{c128 → chips}/vdc.rb +6 -31
  139. data/lib/badline/chips/via/control_lines.rb +109 -0
  140. data/lib/badline/chips/via/fast_forward.rb +55 -0
  141. data/lib/badline/chips/via/interrupt_register.rb +60 -0
  142. data/lib/badline/chips/via/keyed_parts.rb +163 -0
  143. data/lib/badline/chips/via/shift_register.rb +168 -0
  144. data/lib/badline/chips/via/timer1.rb +120 -0
  145. data/lib/badline/chips/via/timer2.rb +117 -0
  146. data/lib/badline/chips/via.rb +267 -0
  147. data/lib/badline/chips/vic/bank.rb +135 -0
  148. data/lib/badline/chips/vic/border_mask.rb +78 -0
  149. data/lib/badline/chips/vic/collisions.rb +106 -0
  150. data/lib/badline/chips/vic/color_patches.rb +38 -0
  151. data/lib/badline/chips/vic/display_state.rb +168 -0
  152. data/lib/badline/chips/vic/graphics_mode.rb +166 -0
  153. data/lib/badline/chips/vic/graphics_shifter.rb +183 -0
  154. data/lib/badline/chips/vic/keyed_parts.rb +228 -0
  155. data/lib/badline/chips/vic/keyed_sprites.rb +225 -0
  156. data/lib/badline/chips/vic/keyed_state.rb +102 -0
  157. data/lib/badline/chips/vic/register_log.rb +65 -0
  158. data/lib/badline/chips/vic/registers.rb +188 -0
  159. data/lib/badline/chips/vic/sequencer.rb +275 -0
  160. data/lib/badline/chips/vic/sequencer_output.rb +118 -0
  161. data/lib/badline/chips/vic/sprite/internal_bus.rb +59 -0
  162. data/lib/badline/chips/vic/sprite/shifter.rb +148 -0
  163. data/lib/badline/chips/vic/sprite/timing.rb +58 -0
  164. data/lib/badline/chips/vic/sprite.rb +337 -0
  165. data/lib/badline/chips/vic/sprites.rb +281 -0
  166. data/lib/badline/chips/vic.rb +787 -0
  167. data/lib/badline/chips/vic_i/keyed_parts.rb +142 -0
  168. data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +2 -30
  169. data/lib/badline/chips/vic_i/sound/output.rb +85 -0
  170. data/lib/badline/chips/vic_i/sound.rb +227 -0
  171. data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
  172. data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +6 -6
  173. data/lib/badline/chips/z80/arithmetic.rb +119 -0
  174. data/lib/badline/chips/z80/bit_page.rb +57 -0
  175. data/lib/badline/chips/z80/block_io.rb +60 -0
  176. data/lib/badline/chips/z80/block_transfers.rb +61 -0
  177. data/lib/badline/chips/z80/bus_cycles.rb +113 -0
  178. data/lib/badline/chips/z80/core.rb +115 -0
  179. data/lib/badline/chips/z80/exchanges.rb +52 -0
  180. data/lib/badline/chips/z80/extended_page.rb +91 -0
  181. data/lib/badline/chips/z80/flags.rb +39 -0
  182. data/lib/badline/chips/z80/interrupt_acceptance.rb +48 -0
  183. data/lib/badline/chips/z80/jumps.rb +84 -0
  184. data/lib/badline/chips/z80/keyed_state.rb +73 -0
  185. data/lib/badline/chips/z80/loads.rb +100 -0
  186. data/lib/badline/chips/z80/main_page.rb +136 -0
  187. data/lib/badline/chips/z80/registers.rb +122 -0
  188. data/lib/badline/chips/z80/shifts.rb +66 -0
  189. data/lib/badline/chips/z80.rb +13 -0
  190. data/lib/badline/chips.rb +10 -0
  191. data/lib/badline/core.rb +13 -32
  192. data/lib/badline/drives/datasette/keyed_state.rb +38 -0
  193. data/lib/badline/drives/datasette.rb +173 -0
  194. data/lib/badline/drives/engine/core.rb +152 -0
  195. data/lib/badline/drives/engine/fast_serial.rb +75 -0
  196. data/lib/badline/drives/engine/idle.rb +127 -0
  197. data/lib/badline/drives/engine/idle_cpu.rb +30 -0
  198. data/lib/badline/drives/engine/orbit.rb +81 -0
  199. data/lib/badline/drives/engine/serial_lines.rb +72 -0
  200. data/lib/badline/drives/engine/sleep.rb +114 -0
  201. data/lib/badline/drives/engine/vias.rb +86 -0
  202. data/lib/badline/drives/engine/watch.rb +152 -0
  203. data/lib/badline/drives/engine.rb +11 -0
  204. data/lib/badline/drives/model1541/bus.rb +75 -0
  205. data/lib/badline/drives/model1541/byte_ready.rb +50 -0
  206. data/lib/badline/drives/model1541/cpu.rb +13 -0
  207. data/lib/badline/drives/model1541/disk.rb +318 -0
  208. data/lib/badline/drives/model1541/disk_via.rb +38 -0
  209. data/lib/badline/drives/model1541/gcr.rb +59 -0
  210. data/lib/badline/drives/model1541/keyed_state.rb +251 -0
  211. data/lib/badline/drives/model1541/mechanism.rb +313 -0
  212. data/lib/badline/drives/model1541/rotation.rb +123 -0
  213. data/lib/badline/drives/model1541/sector_reader.rb +78 -0
  214. data/lib/badline/drives/model1541/serial_port.rb +20 -0
  215. data/lib/badline/drives/model1541/track.rb +100 -0
  216. data/lib/badline/drives/model1541.rb +80 -0
  217. data/lib/badline/drives/model1571/bus.rb +100 -0
  218. data/lib/badline/drives/model1571/cpu.rb +13 -0
  219. data/lib/badline/drives/model1571/keyed_state.rb +108 -0
  220. data/lib/badline/drives/model1571/serial_port.rb +39 -0
  221. data/lib/badline/drives/model1571/serial_via.rb +27 -0
  222. data/lib/badline/drives/model1571/wd1770.rb +108 -0
  223. data/lib/badline/drives/model1571.rb +141 -0
  224. data/lib/badline/drives/model1581/bus.rb +126 -0
  225. data/lib/badline/drives/model1581/cpu.rb +13 -0
  226. data/lib/badline/drives/model1581/disk.rb +133 -0
  227. data/lib/badline/drives/model1581/keyed_state.rb +280 -0
  228. data/lib/badline/drives/model1581/mechanism.rb +98 -0
  229. data/lib/badline/drives/model1581/serial_port.rb +54 -0
  230. data/lib/badline/drives/model1581/slot.rb +61 -0
  231. data/lib/badline/drives/model1581/track.rb +102 -0
  232. data/lib/badline/drives/model1581/track_bytes.rb +77 -0
  233. data/lib/badline/drives/model1581/wd1772/registers.rb +91 -0
  234. data/lib/badline/drives/model1581/wd1772/sector_writes.rb +75 -0
  235. data/lib/badline/drives/model1581/wd1772/sectors.rb +152 -0
  236. data/lib/badline/drives/model1581/wd1772/stepping.rb +111 -0
  237. data/lib/badline/drives/model1581/wd1772/tracks.rb +127 -0
  238. data/lib/badline/drives/model1581/wd1772/turn.rb +75 -0
  239. data/lib/badline/drives/model1581/wd1772.rb +216 -0
  240. data/lib/badline/drives/model1581.rb +206 -0
  241. data/lib/badline/drives/serial_bus.rb +161 -0
  242. data/lib/badline/drives.rb +8 -0
  243. data/lib/badline/frontend/app.rb +3 -3
  244. data/lib/badline/frontend/boot.rb +4 -4
  245. data/lib/badline/frontend/controls.rb +19 -3
  246. data/lib/badline/frontend/drive_led.rb +44 -21
  247. data/lib/badline/frontend/machine_window.rb +3 -1
  248. data/lib/badline/frontend/menu/menu_dialogs.rb +2 -2
  249. data/lib/badline/frontend/player/filter_view.rb +1 -1
  250. data/lib/badline/frontend/player/player_controller.rb +2 -2
  251. data/lib/badline/frontend/player/player_screen.rb +1 -0
  252. data/lib/badline/frontend/player/theme.rb +7 -7
  253. data/lib/badline/frontend/snapshots.rb +12 -1
  254. data/lib/badline/frontend/timeline.rb +30 -12
  255. data/lib/badline/input/control_ports.rb +78 -0
  256. data/lib/badline/input/joystick.rb +27 -0
  257. data/lib/badline/input/keyboard.rb +114 -0
  258. data/lib/badline/input/matrix_typist.rb +98 -0
  259. data/lib/badline/input.rb +4 -0
  260. data/lib/badline/kernal_trap/chrout.rb +45 -0
  261. data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
  262. data/lib/badline/kernal_trap/dos/channel.rb +156 -0
  263. data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -26
  264. data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -10
  265. data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
  266. data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -9
  267. data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -19
  268. data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
  269. data/lib/badline/kernal_trap/{drive.rb → dos.rb} +9 -27
  270. data/lib/badline/kernal_trap/file_routine.rb +4 -4
  271. data/lib/badline/kernal_trap/keyed_state.rb +150 -0
  272. data/lib/badline/kernal_trap/layout.rb +75 -11
  273. data/lib/badline/kernal_trap/load.rb +19 -21
  274. data/lib/badline/kernal_trap/routine.rb +12 -0
  275. data/lib/badline/kernal_trap/save.rb +12 -22
  276. data/lib/badline/kernal_trap/serial.rb +8 -24
  277. data/lib/badline/kernal_trap.rb +3 -2
  278. data/lib/badline/machine/clocking.rb +1 -1
  279. data/lib/badline/machine/keyboard_buffer.rb +49 -0
  280. data/lib/badline/machine/settling.rb +29 -0
  281. data/lib/badline/machine.rb +10 -7
  282. data/lib/badline/media/boot_disk.rb +14 -2
  283. data/lib/badline/media/extensions.rb +10 -0
  284. data/lib/badline/media/true_drive.rb +1 -1
  285. data/lib/badline/media/tune.rb +2 -2
  286. data/lib/badline/media.rb +3 -3
  287. data/lib/badline/memory.rb +3 -6
  288. data/lib/badline/model.rb +1 -1
  289. data/lib/badline/options/family.rb +5 -2
  290. data/lib/badline/options/help.rb +42 -16
  291. data/lib/badline/options/table.rb +2 -0
  292. data/lib/badline/options/validation.rb +2 -0
  293. data/lib/badline/options.rb +6 -1
  294. data/lib/badline/plus4/acia.rb +45 -0
  295. data/lib/badline/plus4/bus.rb +312 -0
  296. data/lib/badline/plus4/cpu.rb +10 -0
  297. data/lib/badline/plus4/cpu_port.rb +93 -0
  298. data/lib/badline/plus4/keyboard_port.rb +51 -0
  299. data/lib/badline/plus4/model.rb +38 -0
  300. data/lib/badline/plus4/user_port.rb +31 -0
  301. data/lib/badline/plus4.rb +164 -0
  302. data/lib/badline/roms/README +44 -6
  303. data/lib/badline/roms/plus4/basic.rom +0 -0
  304. data/lib/badline/roms/plus4/function-high.rom +0 -0
  305. data/lib/badline/roms/plus4/function-low.rom +0 -0
  306. data/lib/badline/roms/plus4/kernal-ntsc.rom +0 -0
  307. data/lib/badline/roms/plus4/kernal-pal.rom +0 -0
  308. data/lib/badline/sdl.rb +1 -0
  309. data/lib/badline/{storage/sid_file.rb → sid_tune/file.rb} +3 -3
  310. data/lib/badline/{storage → sid_tune}/hvsc.rb +7 -7
  311. data/lib/badline/{storage → sid_tune}/song_lengths.rb +2 -2
  312. data/lib/badline/{storage → sid_tune}/stil/credit.rb +1 -1
  313. data/lib/badline/{storage → sid_tune}/stil.rb +3 -3
  314. data/lib/badline/sid_tune.rb +6 -0
  315. data/lib/badline/snapshot/c128_setup.rb +32 -0
  316. data/lib/badline/snapshot/c64_setup.rb +83 -0
  317. data/lib/badline/snapshot/container.rb +4 -0
  318. data/lib/badline/snapshot/field_doc/markdown.rb +112 -0
  319. data/lib/badline/snapshot/field_doc.rb +109 -0
  320. data/lib/badline/snapshot/image.rb +132 -46
  321. data/lib/badline/snapshot/keyed/cursor.rb +40 -0
  322. data/lib/badline/snapshot/keyed/modules.rb +66 -0
  323. data/lib/badline/snapshot/keyed/reader.rb +188 -0
  324. data/lib/badline/snapshot/keyed/recorder.rb +88 -0
  325. data/lib/badline/snapshot/keyed/report.rb +26 -0
  326. data/lib/badline/snapshot/keyed/writer.rb +55 -0
  327. data/lib/badline/snapshot/keyed.rb +64 -0
  328. data/lib/badline/snapshot/machine_state.rb +17 -64
  329. data/lib/badline/snapshot/storage_setup.rb +63 -0
  330. data/lib/badline/snapshot/vic20_setup.rb +28 -0
  331. data/lib/badline/snapshot/vice/c64_mem.rb +1 -1
  332. data/lib/badline/snapshot/vice/restore.rb +1 -1
  333. data/lib/badline/snapshot/vice/reu1764.rb +3 -3
  334. data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
  335. data/lib/badline/snapshot/vice.rb +13 -35
  336. data/lib/badline/snapshot.rb +44 -22
  337. data/lib/badline/storage/crt_file.rb +3 -1
  338. data/lib/badline/storage/d64_image.rb +0 -2
  339. data/lib/badline/storage/d71_image.rb +0 -2
  340. data/lib/badline/storage/d81_image.rb +0 -2
  341. data/lib/badline/storage/disk_image.rb +3 -6
  342. data/lib/badline/storage/g64_image.rb +10 -5
  343. data/lib/badline/storage/host_directory.rb +0 -5
  344. data/lib/badline/storage/t64.rb +2 -8
  345. data/lib/badline/storage/tap.rb +43 -15
  346. data/lib/badline/storage/unavailable.rb +1 -1
  347. data/lib/badline/storage.rb +0 -37
  348. data/lib/badline/support/c128_checkpoint.rb +39 -0
  349. data/lib/badline/support/checkpoint.rb +108 -0
  350. data/lib/badline/support/vic20_checkpoint.rb +38 -0
  351. data/lib/badline/support.rb +5 -0
  352. data/lib/badline/version.rb +1 -1
  353. data/lib/badline/vic20/attachments.rb +8 -5
  354. data/lib/badline/vic20/bus/keyed_state.rb +52 -0
  355. data/lib/badline/vic20/bus.rb +2 -25
  356. data/lib/badline/vic20/cpu.rb +1 -1
  357. data/lib/badline/vic20/keyed_modules.rb +73 -0
  358. data/lib/badline/vic20/keyed_state.rb +45 -0
  359. data/lib/badline/vic20/port_wiring.rb +4 -4
  360. data/lib/badline/vic20/user_via_ports.rb +2 -2
  361. data/lib/badline/vic20.rb +22 -17
  362. data/lib/badline.rb +1 -0
  363. metadata +271 -228
  364. data/lib/badline/address_bus/extra_sids.rb +0 -30
  365. data/lib/badline/address_bus/fittings.rb +0 -38
  366. data/lib/badline/address_bus/pla.rb +0 -147
  367. data/lib/badline/address_bus/roms.rb +0 -39
  368. data/lib/badline/address_bus/saved_state.rb +0 -66
  369. data/lib/badline/address_bus/sid_slots.rb +0 -42
  370. data/lib/badline/address_bus.rb +0 -216
  371. data/lib/badline/c128/bus_state.rb +0 -53
  372. data/lib/badline/c128/saved_state.rb +0 -143
  373. data/lib/badline/cartridge/action_replay.rb +0 -126
  374. data/lib/badline/cartridge/atomic_power.rb +0 -24
  375. data/lib/badline/cartridge/bank.rb +0 -81
  376. data/lib/badline/cartridge/comal80.rb +0 -50
  377. data/lib/badline/cartridge/dinamic.rb +0 -34
  378. data/lib/badline/cartridge/easy_flash.rb +0 -145
  379. data/lib/badline/cartridge/epyx_fastload.rb +0 -79
  380. data/lib/badline/cartridge/final_cartridge3.rb +0 -89
  381. data/lib/badline/cartridge/flash.rb +0 -306
  382. data/lib/badline/cartridge/freezer.rb +0 -33
  383. data/lib/badline/cartridge/fun_play.rb +0 -38
  384. data/lib/badline/cartridge/g_mod2.rb +0 -74
  385. data/lib/badline/cartridge/game_system.rb +0 -40
  386. data/lib/badline/cartridge/geo_ram.rb +0 -79
  387. data/lib/badline/cartridge/kcs_power.rb +0 -75
  388. data/lib/badline/cartridge/mach5.rb +0 -32
  389. data/lib/badline/cartridge/magic_desk.rb +0 -30
  390. data/lib/badline/cartridge/ocean.rb +0 -35
  391. data/lib/badline/cartridge/pagefox.rb +0 -68
  392. data/lib/badline/cartridge/retro_replay.rb +0 -320
  393. data/lib/badline/cartridge/rex_utility.rb +0 -29
  394. data/lib/badline/cartridge/rgcd.rb +0 -58
  395. data/lib/badline/cartridge/simons_basic.rb +0 -35
  396. data/lib/badline/cartridge/standard.rb +0 -15
  397. data/lib/badline/cartridge/super_games.rb +0 -48
  398. data/lib/badline/cartridge/westermann.rb +0 -30
  399. data/lib/badline/cartridge/zaxxon.rb +0 -66
  400. data/lib/badline/cartridge.rb +0 -303
  401. data/lib/badline/checkpoint.rb +0 -98
  402. data/lib/badline/chrout_trap.rb +0 -43
  403. data/lib/badline/cia/fast_forward.rb +0 -60
  404. data/lib/badline/cia/interrupt_register.rb +0 -143
  405. data/lib/badline/cia/serial.rb +0 -275
  406. data/lib/badline/cia/state.rb +0 -47
  407. data/lib/badline/cia/timer.rb +0 -206
  408. data/lib/badline/cia.rb +0 -279
  409. data/lib/badline/color_memory.rb +0 -25
  410. data/lib/badline/computer/attachments.rb +0 -88
  411. data/lib/badline/computer/saved_state.rb +0 -117
  412. data/lib/badline/computer/true_drives.rb +0 -69
  413. data/lib/badline/control_ports.rb +0 -76
  414. data/lib/badline/cpu/addressing.rb +0 -131
  415. data/lib/badline/cpu/boundary.rb +0 -54
  416. data/lib/badline/cpu/core.rb +0 -165
  417. data/lib/badline/cpu/microcode.rb +0 -177
  418. data/lib/badline/cpu/operations.rb +0 -88
  419. data/lib/badline/cpu/saved_state.rb +0 -115
  420. data/lib/badline/cpu/stack_operations.rb +0 -82
  421. data/lib/badline/cpu.rb +0 -10
  422. data/lib/badline/cpu_port.rb +0 -112
  423. data/lib/badline/datasette.rb +0 -161
  424. data/lib/badline/debug_register.rb +0 -28
  425. data/lib/badline/drive/core.rb +0 -147
  426. data/lib/badline/drive/fast_serial.rb +0 -73
  427. data/lib/badline/drive/idle.rb +0 -125
  428. data/lib/badline/drive/idle_cpu.rb +0 -28
  429. data/lib/badline/drive/orbit.rb +0 -79
  430. data/lib/badline/drive/serial_lines.rb +0 -73
  431. data/lib/badline/drive/sleep.rb +0 -112
  432. data/lib/badline/drive/vias.rb +0 -84
  433. data/lib/badline/drive/watch.rb +0 -150
  434. data/lib/badline/drive.rb +0 -11
  435. data/lib/badline/drive1541/bus.rb +0 -86
  436. data/lib/badline/drive1541/byte_ready.rb +0 -48
  437. data/lib/badline/drive1541/cpu.rb +0 -11
  438. data/lib/badline/drive1541/disk.rb +0 -315
  439. data/lib/badline/drive1541/disk_state.rb +0 -86
  440. data/lib/badline/drive1541/disk_via.rb +0 -36
  441. data/lib/badline/drive1541/gcr.rb +0 -57
  442. data/lib/badline/drive1541/mechanism.rb +0 -313
  443. data/lib/badline/drive1541/mechanism_state.rb +0 -68
  444. data/lib/badline/drive1541/rotation.rb +0 -121
  445. data/lib/badline/drive1541/sector_reader.rb +0 -76
  446. data/lib/badline/drive1541/serial_port.rb +0 -18
  447. data/lib/badline/drive1541/track.rb +0 -98
  448. data/lib/badline/drive1541.rb +0 -111
  449. data/lib/badline/drive1571/bus.rb +0 -111
  450. data/lib/badline/drive1571/cpu.rb +0 -11
  451. data/lib/badline/drive1571/serial_port.rb +0 -37
  452. data/lib/badline/drive1571/serial_via.rb +0 -25
  453. data/lib/badline/drive1571/wd1770.rb +0 -120
  454. data/lib/badline/drive1571.rb +0 -175
  455. data/lib/badline/drive1581/bus.rb +0 -137
  456. data/lib/badline/drive1581/cpu.rb +0 -11
  457. data/lib/badline/drive1581/disk.rb +0 -135
  458. data/lib/badline/drive1581/disk_state.rb +0 -87
  459. data/lib/badline/drive1581/mechanism.rb +0 -117
  460. data/lib/badline/drive1581/serial_port.rb +0 -52
  461. data/lib/badline/drive1581/slot.rb +0 -78
  462. data/lib/badline/drive1581/track.rb +0 -100
  463. data/lib/badline/drive1581/track_bytes.rb +0 -75
  464. data/lib/badline/drive1581/wd1772/registers.rb +0 -89
  465. data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
  466. data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
  467. data/lib/badline/drive1581/wd1772/state.rb +0 -66
  468. data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
  469. data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
  470. data/lib/badline/drive1581/wd1772/turn.rb +0 -73
  471. data/lib/badline/drive1581/wd1772.rb +0 -216
  472. data/lib/badline/drive1581.rb +0 -233
  473. data/lib/badline/iec_bus.rb +0 -159
  474. data/lib/badline/instruction.rb +0 -334
  475. data/lib/badline/instruction_set/arithmetic.rb +0 -114
  476. data/lib/badline/instruction_set/bitwise.rb +0 -126
  477. data/lib/badline/instruction_set/branch.rb +0 -79
  478. data/lib/badline/instruction_set/flag.rb +0 -63
  479. data/lib/badline/instruction_set/illegal.rb +0 -270
  480. data/lib/badline/instruction_set/inc_dec.rb +0 -69
  481. data/lib/badline/instruction_set/stack.rb +0 -52
  482. data/lib/badline/instruction_set/transfer.rb +0 -137
  483. data/lib/badline/instruction_set.rb +0 -55
  484. data/lib/badline/interrupts.rb +0 -104
  485. data/lib/badline/joystick.rb +0 -25
  486. data/lib/badline/kernal_trap/channel.rb +0 -181
  487. data/lib/badline/keyboard.rb +0 -112
  488. data/lib/badline/keyboard_buffer.rb +0 -33
  489. data/lib/badline/ram_expansion/banking.rb +0 -30
  490. data/lib/badline/ram_expansion/plus256k.rb +0 -54
  491. data/lib/badline/ram_expansion/plus60k.rb +0 -43
  492. data/lib/badline/ram_expansion/unexpanded.rb +0 -28
  493. data/lib/badline/ram_expansion.rb +0 -21
  494. data/lib/badline/reu/dma/saved_state.rb +0 -50
  495. data/lib/badline/reu/dma.rb +0 -273
  496. data/lib/badline/reu/ram.rb +0 -107
  497. data/lib/badline/reu/saved_state.rb +0 -80
  498. data/lib/badline/reu/trigger.rb +0 -32
  499. data/lib/badline/reu.rb +0 -289
  500. data/lib/badline/sid/catch_up.rb +0 -120
  501. data/lib/badline/sid/decimator.rb +0 -64
  502. data/lib/badline/sid/envelope/state.rb +0 -68
  503. data/lib/badline/sid/envelope.rb +0 -239
  504. data/lib/badline/sid/filter.rb +0 -263
  505. data/lib/badline/sid/voice.rb +0 -77
  506. data/lib/badline/sid/waveform/combined.rb +0 -126
  507. data/lib/badline/sid/waveform/fast_forward.rb +0 -105
  508. data/lib/badline/sid/waveform/noise_writeback.rb +0 -122
  509. data/lib/badline/sid/waveform/state.rb +0 -66
  510. data/lib/badline/sid/waveform.rb +0 -305
  511. data/lib/badline/sid.rb +0 -303
  512. data/lib/badline/snapshot/setup.rb +0 -75
  513. data/lib/badline/snapshot/state.rb +0 -189
  514. data/lib/badline/time_of_day.rb +0 -228
  515. data/lib/badline/traps.rb +0 -19
  516. data/lib/badline/via/control_lines.rb +0 -122
  517. data/lib/badline/via/fast_forward.rb +0 -53
  518. data/lib/badline/via/interrupt_register.rb +0 -67
  519. data/lib/badline/via/shift_register.rb +0 -180
  520. data/lib/badline/via/state.rb +0 -42
  521. data/lib/badline/via/timer1.rb +0 -131
  522. data/lib/badline/via/timer2.rb +0 -133
  523. data/lib/badline/via.rb +0 -266
  524. data/lib/badline/vic/bank.rb +0 -133
  525. data/lib/badline/vic/border_mask.rb +0 -86
  526. data/lib/badline/vic/collisions.rb +0 -115
  527. data/lib/badline/vic/color_patches.rb +0 -47
  528. data/lib/badline/vic/display_state.rb +0 -185
  529. data/lib/badline/vic/graphics_mode.rb +0 -164
  530. data/lib/badline/vic/graphics_shifter.rb +0 -207
  531. data/lib/badline/vic/register_log.rb +0 -81
  532. data/lib/badline/vic/registers.rb +0 -195
  533. data/lib/badline/vic/sequencer.rb +0 -275
  534. data/lib/badline/vic/sequencer_output.rb +0 -116
  535. data/lib/badline/vic/sequencer_state.rb +0 -89
  536. data/lib/badline/vic/sprite/internal_bus.rb +0 -68
  537. data/lib/badline/vic/sprite/saved_state.rb +0 -64
  538. data/lib/badline/vic/sprite/shifter.rb +0 -146
  539. data/lib/badline/vic/sprite/timing.rb +0 -56
  540. data/lib/badline/vic/sprite.rb +0 -337
  541. data/lib/badline/vic/sprites.rb +0 -282
  542. data/lib/badline/vic/sprites_state.rb +0 -57
  543. data/lib/badline/vic.rb +0 -853
  544. data/lib/badline/vic20/saved_state.rb +0 -124
  545. data/lib/badline/vic20/sound/output.rb +0 -83
  546. data/lib/badline/vic20/sound.rb +0 -233
  547. data/lib/badline/vic20/vic/saved_state.rb +0 -55
  548. data/lib/badline/z80/arithmetic.rb +0 -117
  549. data/lib/badline/z80/bit_page.rb +0 -55
  550. data/lib/badline/z80/block_io.rb +0 -58
  551. data/lib/badline/z80/block_transfers.rb +0 -59
  552. data/lib/badline/z80/bus_cycles.rb +0 -111
  553. data/lib/badline/z80/core.rb +0 -113
  554. data/lib/badline/z80/exchanges.rb +0 -50
  555. data/lib/badline/z80/extended_page.rb +0 -89
  556. data/lib/badline/z80/flags.rb +0 -37
  557. data/lib/badline/z80/interrupt_acceptance.rb +0 -46
  558. data/lib/badline/z80/jumps.rb +0 -82
  559. data/lib/badline/z80/loads.rb +0 -98
  560. data/lib/badline/z80/main_page.rb +0 -134
  561. data/lib/badline/z80/registers.rb +0 -120
  562. data/lib/badline/z80/saved_state.rb +0 -69
  563. data/lib/badline/z80/shifts.rb +0 -64
  564. data/lib/badline/z80.rb +0 -11
  565. /data/lib/badline/snapshot/{fields.rb → vice/fields.rb} +0 -0
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Drive1581
5
- # What the 8520's ports read from outside the chip (1581 Service
6
- # Manual, schematic sheet 3; the DOS's I/O definitions):
7
- #
8
- # PA0 side select (out) PB0 DATA IN (in)
9
- # PA1 /RDY from the mechanism PB1 DATA OUT (out)
10
- # PA2 /MOTOR (out) PB2 CLK IN (in)
11
- # PA3 device number switch 1 PB3 CLK OUT (out)
12
- # PA4 device number switch 2 PB4 ATN ACK (out)
13
- # PA5 power LED (out) PB5 fast serial direction (out)
14
- # PA6 activity LED (out) PB6 /WPRT from the mechanism
15
- # PA7 /DISK CHNG from the mech. PB7 ATN IN (in)
16
- #
17
- # DATA IN, CLK IN and ATN IN come through inverters, so a pulled line
18
- # reads 1, as on the 1541 (Drive::SerialLines). A closed switch pulls
19
- # its line low, and both closed make device 8. The ports' outputs
20
- # read back as driven: the peripheral pulls only the inputs.
21
- class SerialPort
22
- include Drive::SerialLines
23
-
24
- READY = 0x02
25
- SWITCHES = 0x18
26
- DISK_CHANGE = 0x80
27
- PROTECT = 0x40
28
-
29
- def initialize(mechanism, device: 8, bus: IECBus.new)
30
- @mechanism = mechanism
31
- @switches = (0xff & ~SWITCHES) | (((device - 8) & 0x03) << 3)
32
- init_serial_lines(device, bus)
33
- end
34
-
35
- def read_a(_port_a, _port_b)
36
- value = @switches
37
- value &= ~READY if @mechanism.ready?
38
- value &= ~DISK_CHANGE if @mechanism.disk_changed?
39
- value
40
- end
41
-
42
- def read_b(_port_a, _port_b)
43
- low = @bus.low_lines(@host)
44
- value = 0xff & ~(SERIAL_INPUTS | PROTECT)
45
- value |= DATA_IN if low.anybits?(IECBus::DATA)
46
- value |= CLK_IN if low.anybits?(IECBus::CLK)
47
- value |= ATN_IN if low.anybits?(IECBus::ATN)
48
- @mechanism.write_protected? ? value : value | PROTECT
49
- end
50
- end
51
- end
52
- end
@@ -1,78 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Drive1581
5
- # A machine's place for a Drive1581 on its serial bus, in a field of
6
- # its own beside its other true drives, so none of them makes another's
7
- # per-cycle call a union. The C64, the VIC-20 and the C128 include it,
8
- # and run the drive from their cycle as they run a 1541.
9
- #
10
- # A 1581 reads only .d81 images and the others none, so a .d81 put in
11
- # device 8 swaps the true drive there for a 1581, and any other disk
12
- # swaps a 1581 back for the machine's own true drive
13
- # (Media::TrueDrive).
14
- module Slot
15
- attr_reader :drive1581
16
-
17
- # Plugs in a Drive1581, which then runs alongside the machine on its
18
- # own clock and talks to it over the serial bus, as a 1541 does.
19
- def attach_drive1581(drive)
20
- @iec_bus.detach(@drive1581) if @drive1581
21
- drive.host_clock_hz = timing.clock_hz
22
- @drive1581 = drive
23
- drive.connect(@iec_bus)
24
- @serial_trap&.device = serial_trap_device
25
- drive1581_attached
26
- end
27
-
28
- # Unplugs the Drive1581.
29
- def detach_drive1581
30
- return unless @drive1581
31
-
32
- @iec_bus.detach(@drive1581)
33
- @drive1581 = nil
34
- @serial_trap&.device = serial_trap_device
35
- end
36
-
37
- # Plugs in a 1581 as device 8, in place of the true drive there, and
38
- # returns it.
39
- def plug_drive1581
40
- unplug_device8
41
- Drive1581.new.tap { |drive| attach_drive1581(drive) }
42
- end
43
-
44
- private
45
-
46
- # Unplugs the 1541 if it is device 8, for a 1581 to take its place.
47
- def unplug_device8
48
- detach_drive1541 if @drive1541&.device == KernalTrap::Routine::DEVICE
49
- end
50
-
51
- # What the machine does as a 1581 goes on its bus. The VIC-20 waits
52
- # for its DOS to boot before typing.
53
- def drive1581_attached = nil
54
-
55
- # Whether the 1581 is device 8.
56
- def drive1581_on_device8? = @drive1581&.device == KernalTrap::Routine::DEVICE
57
-
58
- # The 1581 on the serial bus, with its device number.
59
- def save_drive1581(out)
60
- out.boolean(!@drive1581.nil?)
61
- return unless @drive1581
62
-
63
- out.int(@drive1581.device)
64
- @drive1581.save_state(out)
65
- end
66
-
67
- # Layouts before 8 have no 1581.
68
- def load_drive1581(input)
69
- return detach_drive1581 if input.schema < 8 || !input.boolean?
70
-
71
- device = input.int
72
- detach_drive1581 if @drive1581 && @drive1581.device != device
73
- attach_drive1581(Drive1581.new(device:)) unless @drive1581
74
- @drive1581.load_state(input)
75
- end
76
- end
77
- end
78
- end
@@ -1,100 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Drive1581
5
- # One side of a cylinder as the WD1772 finds it: its sectors, each an
6
- # ID field and a data field at a place round the turn, counted in
7
- # bytes from the index pulse. The disk turns at 300 rpm and the bits
8
- # pass at 250 kbit/s, so a turn is LENGTH bytes of 32 µs. The bytes
9
- # between the fields, the gaps and the sync marks, are not kept: a
10
- # read track lays them out again (raw).
11
- #
12
- # A standard track is the one the 1581 DOS formats (its format routine,
13
- # and the 1581 Service Manual's per-sector organization): 32 bytes of
14
- # $4E after the index, then ten 512-byte sectors numbered from 1, each
15
- #
16
- # 12 x $00, 3 x $A1, $FE, track, side, sector, size code, CRC,
17
- # 22 x $4E, 12 x $00, 3 x $A1, $FB, 512 data bytes, CRC,
18
- # 35 x $4E
19
- #
20
- # and $4E to the index. A write track lays down whatever the CPU sends,
21
- # and parse finds its fields again.
22
- class Track
23
- LENGTH = 6250
24
- GAP = 0x4e
25
- SYNC = 0xa1
26
- ID_MARK = 0xfe
27
- DATA_MARK = 0xfb
28
- DELETED_MARK = 0xf8
29
-
30
- SECTORS = 10
31
- SECTOR_SIZE = 512
32
- SIZE_CODE = 2
33
-
34
- # Where the first sector's ID mark lies, and how far apart the
35
- # sectors are.
36
- FIRST_ID = 32 + 15
37
- SECTOR_SPACING = 574 + 35
38
-
39
- # From an ID mark to its data mark.
40
- DATA_OFFSET = 44
41
-
42
- # How far after an ID field's CRC a data mark still belongs to it
43
- # (WD177x data sheet).
44
- DATA_MARK_WINDOW = 43
45
-
46
- # An ID or data field: its mark's place, its bytes, whether its CRC
47
- # reads back, and for a data field whether its mark is the deleted
48
- # one.
49
- Field = Struct.new(:mark, :bytes, :good, :deleted)
50
-
51
- # A sector: its ID field and its data field, or nil where none
52
- # follows the ID.
53
- Sector = Struct.new(:id, :data)
54
-
55
- # The CRC-CCITT the WD1772 writes after each field, over the field
56
- # from its first $A1: x^16 + x^12 + x^5 + 1 from $FFFF.
57
- def self.crc(bytes, crc = 0xffff)
58
- bytes.each do |byte|
59
- crc ^= byte << 8
60
- 8.times { crc = crc.anybits?(0x8000) ? ((crc << 1) ^ 0x1021) & 0xffff : (crc << 1) & 0xffff }
61
- end
62
- crc
63
- end
64
-
65
- # A field's CRC as the two bytes written after it: the mark and
66
- # +bytes+, behind three $A1s.
67
- def self.field_crc(mark, bytes)
68
- crc = crc([SYNC, SYNC, SYNC, mark] + bytes)
69
- [crc >> 8, crc & 0xff]
70
- end
71
-
72
- # A standard track for +cylinder+ and +side+, each sector's data the
73
- # block yields for its number, 1 to 10.
74
- def self.standard(cylinder, side)
75
- sectors = Array.new(SECTORS) do |index|
76
- mark = FIRST_ID + (index * SECTOR_SPACING)
77
- id = Field.new(mark, [cylinder, side, index + 1, SIZE_CODE], true, false)
78
- Sector.new(id, Field.new(mark + DATA_OFFSET, yield(index + 1), true, false))
79
- end
80
- new(sectors)
81
- end
82
-
83
- attr_reader :sectors
84
-
85
- def initialize(sectors)
86
- @sectors = sectors
87
- end
88
-
89
- # The first sector whose ID mark lies at or after +position+, round
90
- # from the index if none does, or nil on a track without IDs.
91
- def next_id(position)
92
- @sectors.find { |sector| sector.id.mark >= position } || @sectors.first
93
- end
94
-
95
- # The sector with the ID field +id+, track, side, sector and size
96
- # code, or nil.
97
- def sector(id) = @sectors.find { |sector| sector.id.bytes == id }
98
- end
99
- end
100
- end
@@ -1,75 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Drive1581
5
- class Track
6
- # A Track as the bytes going round under the head, for the WD1772's
7
- # read track: its fields with their gaps and sync marks.
8
- module Bytes
9
- # The track's LENGTH bytes from the index: $4E gaps, and before each
10
- # field 12 x $00 and three $A1 sync marks, its mark, its bytes and
11
- # its CRC, spoiled where the field's CRC doesn't read back.
12
- def raw
13
- bytes = Array.new(LENGTH, GAP)
14
- @sectors.each do |sector|
15
- lay(bytes, sector.id, ID_MARK)
16
- data = sector.data
17
- lay(bytes, data, data.deleted ? DELETED_MARK : DATA_MARK) if data
18
- end
19
- bytes
20
- end
21
-
22
- private
23
-
24
- def lay(bytes, field, mark)
25
- start = field.mark - 15
26
- crc = Track.field_crc(mark, field.bytes)
27
- crc[1] ^= 0xff unless field.good
28
- [*Array.new(12, 0), SYNC, SYNC, SYNC, mark, *field.bytes, *crc].each_with_index do |byte, i|
29
- bytes[start + i] = byte if start + i < LENGTH
30
- end
31
- end
32
- end
33
-
34
- # Finding the fields in the bytes a write track laid down.
35
- module Parse
36
- # Every sector in +bytes+, a turn as a write track laid it down,
37
- # where +syncs+ marks the $A1s written as sync marks: an ID mark
38
- # behind three of them, its four bytes and CRC, and the data field
39
- # that follows it within DATA_MARK_WINDOW bytes, its length from
40
- # the ID's size code.
41
- def parse(bytes, syncs)
42
- sectors = []
43
- position = 0
44
- while (mark = find_mark(bytes, syncs, position...bytes.length, ID_MARK..ID_MARK))
45
- id = read_field(bytes, mark, 4)
46
- position = mark + 7
47
- data_mark = find_mark(bytes, syncs, position...(position + DATA_MARK_WINDOW), DELETED_MARK..DATA_MARK)
48
- sectors << Sector.new(id, data_mark && read_field(bytes, data_mark, 128 << (id.bytes[3] & 3)))
49
- end
50
- new(sectors)
51
- end
52
-
53
- private
54
-
55
- # The first place in +range+ that holds one of +marks+ behind three
56
- # sync marks.
57
- def find_mark(bytes, syncs, range, marks)
58
- ([range.first, 3].max...[range.end, bytes.length].min).find do |at|
59
- marks.cover?(bytes[at]) && syncs[at - 1] && syncs[at - 2] && syncs[at - 3]
60
- end
61
- end
62
-
63
- def read_field(bytes, mark, length)
64
- field = bytes[mark + 1, length] || []
65
- field += Array.new(length - field.length, 0)
66
- crc = bytes[mark + 1 + length, 2] || []
67
- Field.new(mark, field, crc == Track.field_crc(bytes[mark], field), bytes[mark] < 0xfa)
68
- end
69
- end
70
-
71
- include Bytes
72
- extend Parse
73
- end
74
- end
75
- end
@@ -1,89 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Drive1581
5
- class WD1772
6
- # The four registers as the CPU reaches them, and a command written
7
- # to the command register.
8
- module Registers
9
- # Register +offset+, 0 to 3.
10
- def peek(offset)
11
- case offset
12
- when 0 then status
13
- when 1 then @track
14
- when 2 then @sector
15
- else read_data
16
- end
17
- end
18
-
19
- def poke(offset, value)
20
- case offset
21
- when 0 then write_command(value)
22
- when 1 then @track = value unless busy?
23
- when 2 then @sector = value unless busy?
24
- else write_data(value)
25
- end
26
- end
27
-
28
- # The status register, which clears INTRQ: after a type I command
29
- # bits 1, 2, 5 and 6 follow the index sensor, the track 0 sensor, the
30
- # spin-up and the write-protect line as they are now.
31
- def status
32
- @intrq = false
33
- value = @status | (@motor_on ? MOTOR_ON : 0) | (busy? ? BUSY : 0)
34
- return value | (@drq ? DATA_REQUEST : 0) unless @type1
35
-
36
- value |= PROTECTED if @mechanism.write_protected?
37
- value |= TRACK0 if @mechanism.track0?
38
- value | (@mechanism.index?(@now) ? INDEX : 0)
39
- end
40
-
41
- private
42
-
43
- def read_data
44
- @drq = false
45
- @data
46
- end
47
-
48
- def write_data(value)
49
- @drq = false
50
- @data = value
51
- end
52
-
53
- # A command while busy goes nowhere, but for a force interrupt.
54
- def write_command(value)
55
- @intrq = false
56
- return force_interrupt(value) if value & 0xf0 == 0xd0
57
- return if busy?
58
-
59
- @command = value
60
- @phase = STARTING
61
- @due = @now + START
62
- end
63
-
64
- def start_command
65
- if @command < 0x80 then start_type1
66
- elsif @command < 0xc0 then start_type2
67
- elsif @command & 0xf0 == 0xc0 then start_read_address
68
- else start_type3
69
- end
70
- end
71
-
72
- # Stops a command where it is, leaving its status but for BUSY, or
73
- # with none running switches the status to type I. I3 interrupts at
74
- # once and I2 at the next index pulse.
75
- def force_interrupt(value)
76
- @type1 = true unless busy?
77
- @drq = false
78
- idle
79
- @intrq = true if value.anybits?(0x08)
80
- return unless value.anybits?(0x04)
81
-
82
- @phase = INDEX_INTERRUPT
83
- @count = 1
84
- count_index
85
- end
86
- end
87
- end
88
- end
89
- end
@@ -1,73 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Drive1581
5
- class WD1772
6
- # Write sector, once Sectors has found the ID: it asks for the first
7
- # byte 2 bytes after the ID's CRC and gives up at 22 with LOST_DATA,
8
- # then writes the data field where a format puts it, behind 12 x $00
9
- # and three $A1s, its mark deleted with a, a byte of 0 for each one
10
- # the CPU missed, and the CRC and a $FF after the last.
11
- module SectorWrites
12
- WRITE_REQUEST = 2
13
- WRITE_DEADLINE = 22
14
-
15
- private
16
-
17
- def write_sector(sector)
18
- @write_id = sector.id.mark
19
- @size = 128 << (sector.id.bytes[3] & 0x03)
20
- @gate_open = false
21
- @phase = WRITE_GATE
22
- @due = byte_end(@write_id + 6 + WRITE_REQUEST)
23
- end
24
-
25
- # Two bytes after the ID's CRC, DRQ asks for the first byte, and
26
- # twenty bytes on it has to be there.
27
- def write_gate
28
- unless @gate_open
29
- @gate_open = true
30
- @drq = true
31
- return @due += (WRITE_DEADLINE - WRITE_REQUEST) * BYTE
32
- end
33
- return lost if @drq
34
-
35
- @bytes = []
36
- @phase = WRITE_DATA
37
- @due = byte_end(@write_id + Track::DATA_OFFSET)
38
- end
39
-
40
- # The next byte goes under the head from the data register, a 0
41
- # where DRQ went unanswered, and DRQ asks for the one after it.
42
- # After the last come the CRC and a $FF.
43
- def byte_written
44
- return sector_written if @bytes.length == @size
45
-
46
- @status |= LOST_DATA if @drq && !@bytes.empty?
47
- @bytes << (@drq && !@bytes.empty? ? 0 : @data)
48
- @drq = @bytes.length < @size
49
- @due += @bytes.length == @size ? 3 * BYTE : BYTE
50
- end
51
-
52
- def sector_written
53
- sector = found
54
- if sector
55
- sector.data = Track::Field.new(@write_id + Track::DATA_OFFSET, @bytes, true,
56
- @command.anybits?(DELETED_MARK))
57
- @mechanism.write(@mechanism.track)
58
- end
59
- return finish if @command.nobits?(MULTIPLE)
60
-
61
- @sector = (@sector + 1) & 0xff
62
- begin_search
63
- end
64
-
65
- def lost
66
- @status |= LOST_DATA
67
- @drq = false
68
- finish
69
- end
70
- end
71
- end
72
- end
73
- end
@@ -1,150 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Drive1581
5
- class WD1772
6
- # The type II commands and read address, which find an ID field on
7
- # the track under the head:
8
- #
9
- # 100mhE00 read sector the data field after the ID that carries
10
- # the track and sector registers
11
- # 101mhEPa write sector a data field after that ID, deleted with a
12
- # 11000hE00 read address the next ID field's six bytes, the track
13
- # going into the sector register
14
- #
15
- # The search reads each ID field as it passes. One that matches but
16
- # whose CRC doesn't read back sets CRC_ERROR and the search goes on;
17
- # after five index pulses it gives up with NOT_FOUND. Each byte of a
18
- # field passes in BYTE cycles and sets DRQ as it lands in the data
19
- # register, and LOST_DATA where the last one was still unread. With m
20
- # the command goes on to the next sector until one isn't found. E
21
- # lets the head settle first. SectorWrites writes the data field.
22
- module Sectors
23
- private
24
-
25
- def start_type2
26
- start_search(@command < 0xa0 ? READ : WRITE)
27
- end
28
-
29
- def start_read_address
30
- start_search(ADDRESS)
31
- end
32
-
33
- def start_search(mode)
34
- @type1 = false
35
- @status = 0
36
- @drq = false
37
- @mode = mode
38
- resume_type2 unless spinning_up?(SEARCH)
39
- end
40
-
41
- def resume_type2
42
- if @mode == WRITE && @mechanism.write_protected?
43
- @status |= PROTECTED
44
- return finish
45
- end
46
- return begin_search if @command.nobits?(SETTLE_DELAY)
47
-
48
- @phase = SETTLE_SEARCH
49
- @due = @now + SETTLE
50
- end
51
-
52
- # Searches for five index pulses from now.
53
- def begin_search
54
- index = next_index
55
- @deadline = index == NEVER ? NEVER : index + (4 * Mechanism::REVOLUTION)
56
- search
57
- end
58
-
59
- # Waits for the next ID field to pass under the head.
60
- def search
61
- @phase = SEARCH
62
- track = @mechanism.track
63
- sector = track&.next_id((@mechanism.angle(@now) / BYTE) + 1)
64
- @found = sector ? track.sectors.index(sector) : -1
65
- @id_at = sector ? byte_end(sector.id.mark) : NEVER
66
- @due = [@id_at, @deadline].min
67
- end
68
-
69
- def found = @mechanism.track&.sectors&.[](@found)
70
-
71
- def id_passed
72
- return not_found unless @now == @id_at
73
-
74
- sector = found
75
- return search if sector.nil?
76
-
77
- id = sector.id
78
- return id_read(id) if @mode == ADDRESS
79
- return search unless matches?(id.bytes)
80
- return crc_mismatch unless id.good
81
-
82
- @status &= ~CRC_ERROR
83
- @mode == VERIFY_TRACK ? finish : sector_found(sector)
84
- end
85
-
86
- def matches?(id)
87
- id[0] == @track && (@mode == VERIFY_TRACK || id[2] == @sector)
88
- end
89
-
90
- def crc_mismatch
91
- @status |= CRC_ERROR
92
- search
93
- end
94
-
95
- def not_found
96
- @status |= NOT_FOUND
97
- finish
98
- end
99
-
100
- def sector_found(sector)
101
- return write_sector(sector) if @mode == WRITE
102
-
103
- data = sector.data
104
- return search if data.nil? || data.mark > sector.id.mark + 7 + Track::DATA_MARK_WINDOW
105
-
106
- @status |= DELETED if data.deleted
107
- transfer(data.bytes, data.mark, READ_DATA)
108
- @crc_good = data.good
109
- end
110
-
111
- # Read address: the ID's bytes and its CRC.
112
- def id_read(id)
113
- @status |= CRC_ERROR unless id.good
114
- transfer(id.bytes + Track.field_crc(Track::ID_MARK, id.bytes), id.mark, READ_ADDRESS)
115
- end
116
-
117
- def transfer(bytes, mark, phase)
118
- @bytes = bytes
119
- @index = 0
120
- @phase = phase
121
- @due = byte_end(mark + 1)
122
- end
123
-
124
- # A byte of the field lands in the data register. After the last,
125
- # the CRC passes.
126
- def byte_read
127
- return field_read if @index == @bytes.length
128
-
129
- @status |= LOST_DATA if @drq
130
- @data = @bytes[@index]
131
- @drq = true
132
- @index += 1
133
- @due += @index == @bytes.length && @phase == READ_DATA ? 2 * BYTE : BYTE
134
- end
135
-
136
- def field_read
137
- if @phase == READ_ADDRESS
138
- @sector = @bytes[0]
139
- elsif !@crc_good
140
- @status |= CRC_ERROR
141
- elsif @command.anybits?(MULTIPLE)
142
- @sector = (@sector + 1) & 0xff
143
- return begin_search
144
- end
145
- finish
146
- end
147
- end
148
- end
149
- end
150
- end
@@ -1,66 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Drive1581
5
- class WD1772
6
- # Saving and restoring the WD1772 for a snapshot: its registers and
7
- # lines, and the command running, down to the byte it is at.
8
- module State
9
- def save_state(out)
10
- [@now, @due, @phase, @command, @track, @sector, @data, @status, @steps, @count, @after_spin_up, @mode,
11
- @deadline, @id_at, @found, @index, @crc, @write_id, @size].each { |value| out.int(value) }
12
- [@type1, @drq, @intrq, @motor_on, @inward, @crc_good, @gate_open, @late,
13
- @settling].each { |flag| out.boolean(flag) }
14
- out.ints(@bytes).ints(@syncs.map { |sync| sync ? 1 : 0 })
15
- end
16
-
17
- def load_state(input)
18
- load_registers(input)
19
- load_command(input)
20
- load_flags(input)
21
- @bytes = input.ints
22
- @syncs = input.ints.map { |sync| sync == 1 }
23
- end
24
-
25
- private
26
-
27
- def load_registers(input)
28
- @now = input.int
29
- @due = input.int
30
- @phase = input.int
31
- @command = input.int
32
- @track = input.int
33
- @sector = input.int
34
- @data = input.int
35
- @status = input.int
36
- end
37
-
38
- def load_command(input)
39
- @steps = input.int
40
- @count = input.int
41
- @after_spin_up = input.int
42
- @mode = input.int
43
- @deadline = input.int
44
- @id_at = input.int
45
- @found = input.int
46
- @index = input.int
47
- @crc = input.int
48
- @write_id = input.int
49
- @size = input.int
50
- end
51
-
52
- def load_flags(input)
53
- @type1 = input.boolean?
54
- @drq = input.boolean?
55
- @intrq = input.boolean?
56
- @motor_on = input.boolean?
57
- @inward = input.boolean?
58
- @crc_good = input.boolean?
59
- @gate_open = input.boolean?
60
- @late = input.boolean?
61
- @settling = input.boolean?
62
- end
63
- end
64
- end
65
- end
66
- end