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
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Drives
5
+ module Engine
6
+ # The drive asleep, as Idle and Orbit let it: host_cycle! counts the
7
+ # host cycles that go by, and waking turns them into drive cycles
8
+ # through the phase accumulator and runs them. Whole orbits and whole
9
+ # passes go in bulk, and the rest cycle by cycle, which may find the
10
+ # idle loop and put the drive back to sleep.
11
+ #
12
+ # The drive looks at ATN only when the machine may have moved it, as
13
+ # it pushes its lines into the bus (Drives::SerialBus#host_lines=).
14
+ module Sleep
15
+ # Whether the drive is skipping its idle loop right now.
16
+ def asleep? = @asleep
17
+
18
+ # Brings the drive up to the present, cycle for cycle, and drops the
19
+ # pass it was recording and the orbits it found, since whoever called
20
+ # may change it. Every reader of the drive's parts calls this.
21
+ def settle!
22
+ if @asleep
23
+ wake!
24
+ @serial_port.latch_host
25
+ @asleep = false
26
+ @orbit_cycles = nil
27
+ end
28
+ stop_recording if @recording
29
+ forget_orbits
30
+ end
31
+
32
+ private
33
+
34
+ def init_sleep
35
+ @asleep = false
36
+ @host_still = false
37
+ @owed = 0
38
+ @budget = 0
39
+ @slept = 0
40
+ @wake_at = 0
41
+ end
42
+
43
+ # A host cycle asleep that may wake the drive. The next ones need no
44
+ # look at ATN until the machine pushes its lines again.
45
+ def doze
46
+ @host_still = true
47
+ if @serial_port.atn_moved?
48
+ settle!
49
+ elsif @slept == @wake_at
50
+ wake!
51
+ @serial_port.latch_host
52
+ plan_wake if @asleep
53
+ end
54
+ end
55
+
56
+ # Asleep, host_cycle! counts host cycles, and leaves it to wake! to
57
+ # turn them into drive cycles through the phase accumulator. This sets
58
+ # the host cycle that brings the drive cycles owed up to the budget.
59
+ # On an orbit the drive sleeps until something outside wakes it:
60
+ # @slept counts from 1, so it never comes to 0.
61
+ def plan_wake
62
+ @slept = 0
63
+ return @wake_at = 0 if @orbit_cycles
64
+
65
+ needed = ((@budget - @owed) * @host_clock_hz) - @phase
66
+ @wake_at = needed.positive? ? (needed + @clock_hz - 1) / @clock_hz : 1
67
+ end
68
+
69
+ # Runs the cycles owed.
70
+ def wake!
71
+ phase = @phase + (@slept * @clock_hz)
72
+ @phase = phase % @host_clock_hz
73
+ owed = @owed + (phase / @host_clock_hz)
74
+ @owed = 0
75
+ @slept = 0
76
+ catch_up(owed)
77
+ end
78
+
79
+ # Runs +owed+ drive cycles: whole orbits and whole passes in bulk,
80
+ # passes only up to the budget, and the rest cycle by cycle, which
81
+ # may put the drive back to sleep.
82
+ def catch_up(owed)
83
+ while owed.positive?
84
+ if @asleep
85
+ if @orbit_cycles && owed >= @orbit_cycles
86
+ owed -= skip_orbits(owed / @orbit_cycles)
87
+ next
88
+ end
89
+ @orbit_cycles = nil
90
+ passes = [owed, @budget].min / @pass_cycles
91
+ if passes.positive?
92
+ owed -= skip_passes(passes)
93
+ next
94
+ end
95
+ @asleep = false
96
+ end
97
+ run_cycle
98
+ owed -= 1
99
+ end
100
+ end
101
+
102
+ # Runs whole passes, moving the counters on. Returns the cycles.
103
+ def skip_passes(passes)
104
+ cycles = passes * @pass_cycles
105
+ @cpu.fast_forward(cycles, passes * @pass_instructions)
106
+ fast_forward_chips(cycles)
107
+ @cycles += cycles
108
+ @budget -= cycles
109
+ cycles
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Drives
5
+ module Engine
6
+ # The two VIAs the 1541 and the 1571 share: VIA 1 facing the serial
7
+ # bus, its CA1 on ATN, and VIA 2 running the GCR Mechanism. A model
8
+ # includes it beside Core, and it answers Core's, Idle's and Orbit's
9
+ # questions about the chips: what they hold, how long their counters
10
+ # leave them quiet, and how to run them a stretch at once. A model with
11
+ # more chips on its bus runs them in fast_forward_more.
12
+ module VIAs
13
+ def via1
14
+ settle!
15
+ @via1
16
+ end
17
+
18
+ def via2
19
+ settle!
20
+ @via2
21
+ end
22
+
23
+ # Puts in a Disk from the .d64, .g64, .d71 or .g71 image at +path+
24
+ # (Drives::Model1541::Disk.open), write-protected with `read_only`.
25
+ def insert_image(path, read_only: false)
26
+ insert(Model1541::Disk.open(path, read_only:))
27
+ end
28
+
29
+ # VIA 1's port B as it drives the serial bus. It holds still while the
30
+ # drive sleeps, so reading it leaves the drive asleep.
31
+ def serial_output = @via1.port_b_output
32
+
33
+ # The serial bus's RESET line reaches the CPU and both VIAs. RAM keeps
34
+ # its contents.
35
+ def reset!
36
+ settle!
37
+ @via1.reset!
38
+ @via2.reset!
39
+ @cpu.reset!
40
+ end
41
+
42
+ private
43
+
44
+ # ATN reaches VIA 1's CA1 as the serial port latched it.
45
+ def hear_atn
46
+ @via1.ca1 = @serial_port.atn_low?
47
+ end
48
+
49
+ # Whether the drive is doing anything a pass of the idle loop can't
50
+ # repeat: the motor on, or a VIA pulling IRQ.
51
+ def busy_for_pass? = @mechanism.motor_on? || @via1.irq? || @via2.irq?
52
+
53
+ def quiet_cycles
54
+ [@via1.quiet_cycles, @via2.quiet_cycles].min
55
+ end
56
+
57
+ def idle_state
58
+ mechanism = @mechanism
59
+ [*@cpu.idle_state, *@via1.idle_state, *@via2.idle_state, @bus.data, mechanism.so_pending,
60
+ *mechanism.idle_state, mechanism.read_a(0xff), mechanism.read_b(0xff)]
61
+ end
62
+
63
+ # The counters an orbit has to bring back (VIA#counter_state).
64
+ def counter_state(touched)
65
+ [*@via1.counter_state(touched & 0x03), *@via2.counter_state(touched >> 2)]
66
+ end
67
+
68
+ def fast_forward_chips(cycles)
69
+ @via1.fast_forward(cycles)
70
+ @via2.fast_forward(cycles)
71
+ fast_forward_more(cycles)
72
+ end
73
+
74
+ def skip_chip_orbits(cycles, touched)
75
+ @via1.skip_orbits(cycles, touched & 0x03)
76
+ @via2.skip_orbits(cycles, touched >> 2)
77
+ fast_forward_more(cycles)
78
+ end
79
+
80
+ # Runs the model's chips beyond the VIAs +cycles+ quiet cycles at once
81
+ # (see quiet_cycles). The 1541 has none.
82
+ def fast_forward_more(_cycles) = nil
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,152 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Drives
5
+ module Engine
6
+ # A drive bus's eye on what the CPU reaches, for Idle and Orbit. While
7
+ # Idle records a pass of the DOS's idle loop, the bus watches it (see
8
+ # watch!). While Idle looks for an orbit, the bus guards the drive
9
+ # (see guard!). The bus calls watch_read and watch_write with the
10
+ # address folded into $0000-$1FFF, RAM and the two VIAs at $1800 and
11
+ # $1C00, while @watching.
12
+ module Watch
13
+ # VIA registers, as bits by offset, whose access makes a watched
14
+ # stretch volatile: reads of either VIA's counters and shift register
15
+ # and of VIA 1's port B, and writes to VIA 2's timers, shift register
16
+ # and ACR. Any write to VIA 1 does too (watch_write).
17
+ VOLATILE_VIA1_READS = 0x0731
18
+ VOLATILE_VIA2_READS = 0x0730
19
+ VOLATILE_VIA2_WRITES = 0x0ff0
20
+
21
+ # The timer each VIA register reaches, by offset, as bits: 1 for
22
+ # timer 1 and 2 for timer 2.
23
+ TIMER_REGISTERS = [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0].freeze
24
+
25
+ # Whether a watched stretch did something that makes it unrepeatable.
26
+ attr_reader :volatile
27
+
28
+ # The RAM a watched stretch read or wrote, as each address's value
29
+ # from before the first access.
30
+ attr_reader :touched
31
+
32
+ # Whether the drive did something since guard! that reached outside
33
+ # it, or took something in from outside.
34
+ attr_reader :tainted
35
+
36
+ # The timers the drive read or wrote since guard!, as bits: VIA 1's
37
+ # timer 1 and timer 2 in bits 0 and 1, and VIA 2's in bits 2 and 3.
38
+ attr_reader :touched_timers
39
+
40
+ # Starts watching: see volatile and touched. The bus stops watching
41
+ # once the stretch turns volatile.
42
+ def watch!
43
+ @recording = true
44
+ @volatile = false
45
+ @touched = {}
46
+ watching!
47
+ end
48
+
49
+ def unwatch!
50
+ @recording = false
51
+ watching!
52
+ end
53
+
54
+ # Starts guarding: see tainted and touched_timers. Reading VIA 1's
55
+ # port B, which reads the serial bus, taints the drive, and so do
56
+ # any write to VIA 1, whose port B drives the serial bus, a write to
57
+ # VIA 2's shift register or ACR, and VIA 2 turning the motor on or
58
+ # changing the LED. The bus stops guarding once the drive is tainted.
59
+ def guard!
60
+ @guarding = true
61
+ @tainted = false
62
+ @touched_timers = 0
63
+ @led = @via2.port_b_output & Model1541::Mechanism::LED
64
+ watching!
65
+ end
66
+
67
+ private
68
+
69
+ def init_watch
70
+ @recording = @guarding = @watching = false
71
+ @volatile = @tainted = false
72
+ @touched = {}
73
+ @touched_timers = 0
74
+ @led = 0
75
+ end
76
+
77
+ def watching!
78
+ @watching = @recording || @guarding
79
+ end
80
+
81
+ # An access to a chip beyond the VIAs, as the 1571's CIA and floppy
82
+ # controller are: it makes the stretch volatile and taints the
83
+ # drive.
84
+ def watch_chip
85
+ volatile! if @recording
86
+ taint! if @guarding
87
+ end
88
+
89
+ def touch(addr)
90
+ @touched[addr] = @ram.peek(addr) unless @touched.key?(addr)
91
+ end
92
+
93
+ def watch_read(addr)
94
+ if addr < 0x0800
95
+ touch(addr) if @recording
96
+ elsif addr >= 0x1800
97
+ via1 = addr < 0x1c00
98
+ watch(via1 ? VOLATILE_VIA1_READS : VOLATILE_VIA2_READS, addr) if @recording
99
+ guard_read(via1, addr & 0x0f) if @guarding
100
+ end
101
+ end
102
+
103
+ def watch_write(addr)
104
+ if addr >= 0x1c00
105
+ watch_via2_write(addr) if @recording
106
+ guard_via2_write(addr & 0x0f) if @guarding
107
+ elsif addr >= 0x1800
108
+ volatile! if @recording
109
+ taint! if @guarding
110
+ end
111
+ end
112
+
113
+ # Any write to VIA 1 makes the stretch volatile (watch_write), and so
114
+ # does a write to VIA 2 that leaves the motor on.
115
+ def watch_via2_write(addr)
116
+ watch(VOLATILE_VIA2_WRITES, addr)
117
+ volatile! if @recording && @via2.port_b_output.anybits?(Model1541::Mechanism::MOTOR)
118
+ end
119
+
120
+ def watch(volatile, addr)
121
+ volatile! if volatile.anybits?(1 << (addr & 0x0f))
122
+ end
123
+
124
+ def volatile!
125
+ @volatile = true
126
+ @recording = false
127
+ watching!
128
+ end
129
+
130
+ def guard_read(via1, offset)
131
+ return taint! if via1 && offset.zero?
132
+
133
+ @touched_timers |= via1 ? TIMER_REGISTERS[offset] : TIMER_REGISTERS[offset] << 2
134
+ end
135
+
136
+ def guard_via2_write(offset)
137
+ return taint! if offset.between?(0x0a, 0x0b)
138
+
139
+ @touched_timers |= TIMER_REGISTERS[offset] << 2
140
+ lines = @via2.port_b_output
141
+ taint! if lines.anybits?(Model1541::Mechanism::MOTOR) || (lines & Model1541::Mechanism::LED) != @led
142
+ end
143
+
144
+ def taint!
145
+ @tainted = true
146
+ @guarding = false
147
+ watching!
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "badline/drives/engine/sleep"
4
+ require "badline/drives/engine/idle"
5
+ require "badline/drives/engine/orbit"
6
+ require "badline/drives/engine/core"
7
+ require "badline/drives/engine/vias"
8
+ require "badline/drives/engine/fast_serial"
9
+ require "badline/drives/engine/idle_cpu"
10
+ require "badline/drives/engine/watch"
11
+ require "badline/drives/engine/serial_lines"
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Drives
5
+ class Model1541
6
+ # The drive CPU's bus. The decoder looks at A15, A12, A11 and A10 only:
7
+ #
8
+ # $0000-$07FF - 2 KB of RAM
9
+ # $0800-$17FF - nothing: open bus
10
+ # $1800-$1BFF - VIA 1, its sixteen registers mirrored
11
+ # $1C00-$1FFF - VIA 2, its sixteen registers mirrored
12
+ # $2000-$7FFF - $0000-$1FFF again, since A13 and A14 aren't decoded
13
+ # $8000-$BFFF - the ROM again, since A14 isn't decoded
14
+ # $C000-$FFFF - the DOS ROM
15
+ #
16
+ # Writes to the ROM and to open bus go nowhere. A read from open bus
17
+ # finds the last byte on the data bus, which for LDA abs or LDA (zp),Y
18
+ # is the address's high byte, and for an indexed read that crosses a
19
+ # page is what its dummy read found. VICE-testprogs drive/openbus pins
20
+ # both on a real 1541.
21
+ #
22
+ # While Idle records a pass of the DOS's idle loop, the bus watches it,
23
+ # and while Idle looks for an orbit, it guards the drive (see
24
+ # Drives::Engine::Watch).
25
+ class Bus
26
+ include Addressable
27
+ include Engine::Watch
28
+
29
+ attr_reader :ram, :rom, :via1, :via2, :data
30
+
31
+ def initialize(rom:, via1:, via2:)
32
+ addressable_at(0, length: 2**16)
33
+ @ram = Memory.new([], length: 0x0800, start: 0)
34
+ @rom = rom
35
+ @via1 = via1
36
+ @via2 = via2
37
+ @data = 0
38
+ init_watch
39
+ end
40
+
41
+ # The last byte on the data bus and the RAM. What a watched stretch
42
+ # touched is Idle's, and a restored bus isn't watching.
43
+ def save_state(out)
44
+ out.int(@data)
45
+ @ram.save_state(out)
46
+ end
47
+
48
+ def load_state(input)
49
+ @data = input.int
50
+ @ram.load_state(input)
51
+ @watching = false
52
+ end
53
+
54
+ def peek(addr)
55
+ return @data = @rom.peek(addr | 0x4000) if addr >= 0x8000
56
+
57
+ addr &= 0x1fff
58
+ watch_read(addr) if @watching
59
+ @data = if addr < 0x0800
60
+ @ram.peek(addr)
61
+ elsif addr < 0x1800
62
+ @data
63
+ elsif addr < 0x1c00
64
+ @via1.peek(addr)
65
+ else
66
+ @via2.peek(addr)
67
+ end
68
+ end
69
+
70
+ def poke(addr, value)
71
+ @data = value
72
+ return if addr >= 0x8000
73
+
74
+ addr &= 0x1fff
75
+ if addr < 0x0800
76
+ touch(addr) if @recording
77
+ @ram.poke(addr, value)
78
+ elsif addr >= 0x1c00
79
+ @via2.poke(addr, value)
80
+ elsif addr >= 0x1800
81
+ @via1.poke(addr, value)
82
+ end
83
+ watch_write(addr) if @watching
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Drives
5
+ class Model1541
6
+ # The Mechanism's BYTE READY line: to VIA 2's CA1, to the CPU's SO pin
7
+ # through SOE, and on the 1571 to a latch VIA 1's PA7 reads.
8
+ module ByteReady
9
+ # VIA 2, which DiskVIA plugs in.
10
+ attr_writer :via
11
+
12
+ # Whether BYTE READY reached SO for the CPU to sample on the drive's
13
+ # next cycle.
14
+ attr_accessor :so_pending
15
+
16
+ # Whether SO is pending, which the drive's cycle samples and clears.
17
+ def take_so
18
+ so = @so_pending
19
+ @so_pending = false
20
+ so
21
+ end
22
+
23
+ # The read electronics signal a whole GCR byte. BYTE READY pulls VIA
24
+ # 2's CA1 low, a falling edge that sets its flag and, with latching
25
+ # on, latches port A. It reaches the CPU's SO pin while VIA 2's CA2
26
+ # (SOE) is high, which lets the DOS spin on BVC for each byte. The CPU
27
+ # samples SO on the next cycle.
28
+ def byte_ready!
29
+ @byte_latched = true
30
+ @via.ca1 = false
31
+ @so_pending = true if @via.ca2_output
32
+ end
33
+
34
+ # BYTE READY lets go of CA1 with the next bit.
35
+ def byte_ready_ended!
36
+ @via.ca1 = true
37
+ end
38
+
39
+ # Whether BYTE READY has come since the CPU last read VIA 2, as the
40
+ # 1571 latches it for VIA 1's PA7.
41
+ def byte_latched? = @byte_latched
42
+
43
+ # A read of VIA 2 clears the 1571's BYTE READY latch.
44
+ def release_byte_latch
45
+ @byte_latched = false
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Drives
5
+ class Model1541
6
+ # The drive's 6502, on the drive's Bus.
7
+ class CPU
8
+ include Badline::Chips::CPU::Core
9
+ include Engine::IdleCPU
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "badline/media/extensions"
4
+
5
+ module Badline
6
+ module Drives
7
+ class Model1541
8
+ class Disk
9
+ # Saving and restoring a Disk for a snapshot: the image by its path,
10
+ # and every half track as the head sees it, with those written since
11
+ # the last flush. The image itself is read again from its host file,
12
+ # where there still is one.
13
+ module SavedState
14
+ # The image's path, expanded, and whether it was opened read-only,
15
+ # for a disk from Disk.open. Nil for a disk made another way.
16
+ attr_reader :path, :read_only
17
+
18
+ # Whether the image is a .g64 or .g71, by its name.
19
+ def self.g64?(path) = Media::Extensions.kind(path) == :gcr
20
+
21
+ # A disk for the image at the path (Disk.image_for), its tracks left
22
+ # for the state.
23
+ def self.reopen(path, read_only) = Disk.new(Disk.image_for(path, read_only)).opened(path, read_only)
24
+
25
+ # The disk a state from save_state describes: +current+ when it was
26
+ # opened from the same image the same way, and otherwise a disk for
27
+ # the image at the path the state names. Where no file is at that
28
+ # path, the disk has no image and is write-protected, and a
29
+ # detached reader always gets one without an image. Either way its
30
+ # tracks come from the state.
31
+ def self.load(input, current)
32
+ path = input.optional_string
33
+ read_only = input.boolean?
34
+ disk = current if current && !path.nil? && current.path == path && current.read_only == read_only
35
+ disk ||= fresh(path, read_only, input.detached?)
36
+ disk.load_tracks(input)
37
+ disk
38
+ end
39
+
40
+ def self.fresh(path, read_only, detached)
41
+ return Disk.new if path.nil? || detached
42
+ return Disk.new.opened(path, true) unless File.file?(path)
43
+
44
+ reopen(path, read_only)
45
+ end
46
+
47
+ # Notes the image's path and how it was opened.
48
+ def opened(path, read_only)
49
+ @path = File.expand_path(path)
50
+ @read_only = read_only
51
+ self
52
+ end
53
+
54
+ def save_state(out)
55
+ out.optional_string(@path).boolean(@read_only)
56
+ @tracks.each do |track|
57
+ out.boolean(!track.nil?)
58
+ save_track(track, out) if track
59
+ end
60
+ out.ints(@written.keys)
61
+ end
62
+
63
+ def load_tracks(input)
64
+ @tracks.each_index do |half_track|
65
+ @tracks[half_track] = input.boolean? ? load_track(input) : nil
66
+ end
67
+ @written.clear
68
+ input.ints.each { |half_track| @written[half_track] = true }
69
+ end
70
+
71
+ private
72
+
73
+ def save_track(track, out)
74
+ out.int(track.zone).boolean(!track.speeds.nil?)
75
+ out.ints(track.speeds) if track.speeds
76
+ out.blob(track.bytes)
77
+ end
78
+
79
+ def load_track(input)
80
+ zone = input.int
81
+ speeds = input.boolean? ? input.ints : nil
82
+ Track.new(input.blob, zone, speeds)
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end