badline 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (516) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/CLAUDE.md +59 -31
  4. data/README.md +1 -1
  5. data/doc/library.md +9 -9
  6. data/doc/pinned-behaviour.md +105 -105
  7. data/doc/snapshots.md +1 -4
  8. data/lib/badline/audio/bare_player.rb +4 -4
  9. data/lib/badline/audio/cli.rb +6 -6
  10. data/lib/badline/audio/jukebox.rb +2 -2
  11. data/lib/badline/audio/machine_player.rb +2 -2
  12. data/lib/badline/{media → audio}/queue.rb +1 -1
  13. data/lib/badline/audio/queued_tune.rb +6 -6
  14. data/lib/badline/audio/renderer.rb +5 -5
  15. data/lib/badline/audio/stereo.rb +1 -1
  16. data/lib/badline/c128/{bus_state.rb → bus/saved_state.rb} +6 -6
  17. data/lib/badline/c128/bus.rb +30 -51
  18. data/lib/badline/c128/color_lines.rb +2 -2
  19. data/lib/badline/c128/cpu.rb +1 -1
  20. data/lib/badline/c128/drives.rb +10 -11
  21. data/lib/badline/c128/fast_serial.rb +5 -5
  22. data/lib/badline/c128/mmu_pages.rb +1 -1
  23. data/lib/badline/c128/modes.rb +2 -2
  24. data/lib/badline/c128/saved_state.rb +21 -47
  25. data/lib/badline/c128/z80.rb +2 -2
  26. data/lib/badline/c128.rb +18 -72
  27. data/lib/badline/{computer → c64}/attachments.rb +16 -47
  28. data/lib/badline/c64/banked_ram/banking.rb +32 -0
  29. data/lib/badline/c64/banked_ram/plus256k.rb +56 -0
  30. data/lib/badline/c64/banked_ram/plus60k.rb +45 -0
  31. data/lib/badline/c64/banked_ram/unexpanded.rb +30 -0
  32. data/lib/badline/c64/banked_ram.rb +23 -0
  33. data/lib/badline/c64/bus/extra_sids.rb +32 -0
  34. data/lib/badline/c64/bus/fittings.rb +40 -0
  35. data/lib/badline/c64/bus/pla.rb +149 -0
  36. data/lib/badline/c64/bus/roms.rb +41 -0
  37. data/lib/badline/c64/bus/saved_state.rb +68 -0
  38. data/lib/badline/c64/bus/sid_slots.rb +44 -0
  39. data/lib/badline/c64/bus.rb +218 -0
  40. data/lib/badline/c64/cartridge/action_replay.rb +128 -0
  41. data/lib/badline/c64/cartridge/atomic_power.rb +26 -0
  42. data/lib/badline/c64/cartridge/bank.rb +83 -0
  43. data/lib/badline/c64/cartridge/comal80.rb +52 -0
  44. data/lib/badline/c64/cartridge/dinamic.rb +36 -0
  45. data/lib/badline/c64/cartridge/easy_flash.rb +147 -0
  46. data/lib/badline/c64/cartridge/epyx_fastload.rb +81 -0
  47. data/lib/badline/c64/cartridge/final_cartridge3.rb +91 -0
  48. data/lib/badline/c64/cartridge/flash/saved_state.rb +40 -0
  49. data/lib/badline/c64/cartridge/flash.rb +279 -0
  50. data/lib/badline/c64/cartridge/freezer.rb +35 -0
  51. data/lib/badline/c64/cartridge/fun_play.rb +40 -0
  52. data/lib/badline/c64/cartridge/g_mod2.rb +76 -0
  53. data/lib/badline/c64/cartridge/game_system.rb +42 -0
  54. data/lib/badline/c64/cartridge/geo_ram.rb +81 -0
  55. data/lib/badline/c64/cartridge/kcs_power.rb +77 -0
  56. data/lib/badline/c64/cartridge/mach5.rb +34 -0
  57. data/lib/badline/c64/cartridge/magic_desk.rb +32 -0
  58. data/lib/badline/c64/cartridge/ocean.rb +37 -0
  59. data/lib/badline/c64/cartridge/pagefox.rb +70 -0
  60. data/lib/badline/c64/cartridge/retro_replay/saved_state.rb +47 -0
  61. data/lib/badline/c64/cartridge/retro_replay.rb +286 -0
  62. data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
  63. data/lib/badline/c64/cartridge/rgcd.rb +60 -0
  64. data/lib/badline/c64/cartridge/saved_state.rb +63 -0
  65. data/lib/badline/c64/cartridge/simons_basic.rb +37 -0
  66. data/lib/badline/c64/cartridge/standard.rb +17 -0
  67. data/lib/badline/c64/cartridge/super_games.rb +50 -0
  68. data/lib/badline/c64/cartridge/westermann.rb +32 -0
  69. data/lib/badline/c64/cartridge/zaxxon.rb +68 -0
  70. data/lib/badline/c64/cartridge.rb +258 -0
  71. data/lib/badline/c64/color_memory.rb +27 -0
  72. data/lib/badline/c64/common.rb +34 -0
  73. data/lib/badline/c64/kernal_traps.rb +89 -0
  74. data/lib/badline/c64/reu/dma/saved_state.rb +52 -0
  75. data/lib/badline/c64/reu/dma.rb +275 -0
  76. data/lib/badline/c64/reu/ram.rb +109 -0
  77. data/lib/badline/c64/reu/saved_state.rb +55 -0
  78. data/lib/badline/c64/reu/trigger.rb +34 -0
  79. data/lib/badline/c64/reu.rb +291 -0
  80. data/lib/badline/{computer → c64}/saved_state.rb +13 -18
  81. data/lib/badline/{computer → c64}/true_drives.rb +20 -31
  82. data/lib/badline/{computer.rb → c64.rb} +22 -80
  83. data/lib/badline/chips/cia/fast_forward.rb +62 -0
  84. data/lib/badline/chips/cia/interrupt_register.rb +145 -0
  85. data/lib/badline/chips/cia/saved_state.rb +49 -0
  86. data/lib/badline/chips/cia/serial/saved_state.rb +45 -0
  87. data/lib/badline/chips/cia/serial.rb +250 -0
  88. data/lib/badline/chips/cia/time_of_day.rb +232 -0
  89. data/lib/badline/chips/cia/timer.rb +208 -0
  90. data/lib/badline/chips/cia.rb +281 -0
  91. data/lib/badline/chips/cpu/addressing.rb +133 -0
  92. data/lib/badline/chips/cpu/boundary.rb +56 -0
  93. data/lib/badline/chips/cpu/core.rb +167 -0
  94. data/lib/badline/chips/cpu/instruction.rb +338 -0
  95. data/lib/badline/chips/cpu/instruction_set/arithmetic.rb +118 -0
  96. data/lib/badline/chips/cpu/instruction_set/bitwise.rb +130 -0
  97. data/lib/badline/chips/cpu/instruction_set/branch.rb +83 -0
  98. data/lib/badline/chips/cpu/instruction_set/flag.rb +67 -0
  99. data/lib/badline/chips/cpu/instruction_set/illegal.rb +274 -0
  100. data/lib/badline/chips/cpu/instruction_set/inc_dec.rb +73 -0
  101. data/lib/badline/chips/cpu/instruction_set/stack.rb +56 -0
  102. data/lib/badline/chips/cpu/instruction_set/transfer.rb +141 -0
  103. data/lib/badline/chips/cpu/instruction_set.rb +59 -0
  104. data/lib/badline/chips/cpu/interrupts.rb +108 -0
  105. data/lib/badline/chips/cpu/microcode.rb +179 -0
  106. data/lib/badline/chips/cpu/operations.rb +90 -0
  107. data/lib/badline/chips/cpu/port.rb +116 -0
  108. data/lib/badline/chips/cpu/saved_state.rb +117 -0
  109. data/lib/badline/chips/cpu/stack_operations.rb +84 -0
  110. data/lib/badline/chips/cpu/traps.rb +23 -0
  111. data/lib/badline/chips/cpu.rb +12 -0
  112. data/lib/badline/chips/sid/catch_up.rb +122 -0
  113. data/lib/badline/chips/sid/decimator.rb +66 -0
  114. data/lib/badline/chips/sid/envelope/saved_state.rb +70 -0
  115. data/lib/badline/chips/sid/envelope.rb +241 -0
  116. data/lib/badline/chips/sid/filter/saved_state.rb +42 -0
  117. data/lib/badline/chips/sid/filter.rb +241 -0
  118. data/lib/badline/chips/sid/saved_state.rb +52 -0
  119. data/lib/badline/chips/sid/voice.rb +79 -0
  120. data/lib/badline/chips/sid/waveform/combined.rb +128 -0
  121. data/lib/badline/chips/sid/waveform/fast_forward.rb +107 -0
  122. data/lib/badline/chips/sid/waveform/noise_writeback.rb +124 -0
  123. data/lib/badline/chips/sid/waveform/saved_state.rb +68 -0
  124. data/lib/badline/chips/sid/waveform.rb +307 -0
  125. data/lib/badline/chips/sid.rb +265 -0
  126. data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
  127. data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -1
  128. data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -1
  129. data/lib/badline/chips/vdc/saved_state.rb +36 -0
  130. data/lib/badline/{c128 → chips}/vdc/window.rb +1 -1
  131. data/lib/badline/{c128 → chips}/vdc.rb +7 -31
  132. data/lib/badline/chips/via/control_lines.rb +124 -0
  133. data/lib/badline/chips/via/fast_forward.rb +55 -0
  134. data/lib/badline/chips/via/interrupt_register.rb +69 -0
  135. data/lib/badline/chips/via/saved_state.rb +44 -0
  136. data/lib/badline/chips/via/shift_register.rb +182 -0
  137. data/lib/badline/chips/via/timer1.rb +133 -0
  138. data/lib/badline/chips/via/timer2.rb +135 -0
  139. data/lib/badline/chips/via.rb +268 -0
  140. data/lib/badline/chips/vic/bank.rb +135 -0
  141. data/lib/badline/chips/vic/border_mask.rb +88 -0
  142. data/lib/badline/chips/vic/collisions.rb +117 -0
  143. data/lib/badline/chips/vic/color_patches.rb +49 -0
  144. data/lib/badline/chips/vic/display_state.rb +187 -0
  145. data/lib/badline/chips/vic/graphics_mode.rb +166 -0
  146. data/lib/badline/chips/vic/graphics_shifter/saved_state.rb +40 -0
  147. data/lib/badline/chips/vic/graphics_shifter.rb +187 -0
  148. data/lib/badline/chips/vic/register_log.rb +83 -0
  149. data/lib/badline/chips/vic/registers.rb +197 -0
  150. data/lib/badline/chips/vic/saved_state.rb +82 -0
  151. data/lib/badline/chips/vic/sequencer/saved_state.rb +91 -0
  152. data/lib/badline/chips/vic/sequencer.rb +277 -0
  153. data/lib/badline/chips/vic/sequencer_output.rb +118 -0
  154. data/lib/badline/chips/vic/sprite/internal_bus.rb +70 -0
  155. data/lib/badline/chips/vic/sprite/saved_state.rb +66 -0
  156. data/lib/badline/chips/vic/sprite/shifter.rb +148 -0
  157. data/lib/badline/chips/vic/sprite/timing.rb +58 -0
  158. data/lib/badline/chips/vic/sprite.rb +339 -0
  159. data/lib/badline/chips/vic/sprites/saved_state.rb +59 -0
  160. data/lib/badline/chips/vic/sprites.rb +284 -0
  161. data/lib/badline/chips/vic.rb +783 -0
  162. data/lib/badline/chips/vic_i/painter/saved_state.rb +40 -0
  163. data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +6 -30
  164. data/lib/badline/{vic20/vic → chips/vic_i}/saved_state.rb +2 -2
  165. data/lib/badline/chips/vic_i/sound/output.rb +85 -0
  166. data/lib/badline/chips/vic_i/sound.rb +235 -0
  167. data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
  168. data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +5 -5
  169. data/lib/badline/chips/z80/arithmetic.rb +119 -0
  170. data/lib/badline/chips/z80/bit_page.rb +57 -0
  171. data/lib/badline/chips/z80/block_io.rb +60 -0
  172. data/lib/badline/chips/z80/block_transfers.rb +61 -0
  173. data/lib/badline/chips/z80/bus_cycles.rb +113 -0
  174. data/lib/badline/chips/z80/core.rb +115 -0
  175. data/lib/badline/chips/z80/exchanges.rb +52 -0
  176. data/lib/badline/chips/z80/extended_page.rb +91 -0
  177. data/lib/badline/chips/z80/flags.rb +39 -0
  178. data/lib/badline/chips/z80/interrupt_acceptance.rb +48 -0
  179. data/lib/badline/chips/z80/jumps.rb +84 -0
  180. data/lib/badline/chips/z80/loads.rb +100 -0
  181. data/lib/badline/chips/z80/main_page.rb +136 -0
  182. data/lib/badline/chips/z80/registers.rb +122 -0
  183. data/lib/badline/chips/z80/saved_state.rb +71 -0
  184. data/lib/badline/chips/z80/shifts.rb +66 -0
  185. data/lib/badline/chips/z80.rb +13 -0
  186. data/lib/badline/core.rb +27 -29
  187. data/lib/badline/drives/datasette/saved_state.rb +37 -0
  188. data/lib/badline/drives/datasette.rb +140 -0
  189. data/lib/badline/drives/engine/core.rb +149 -0
  190. data/lib/badline/drives/engine/fast_serial.rb +75 -0
  191. data/lib/badline/drives/engine/idle.rb +127 -0
  192. data/lib/badline/drives/engine/idle_cpu.rb +30 -0
  193. data/lib/badline/drives/engine/orbit.rb +81 -0
  194. data/lib/badline/drives/engine/serial_lines.rb +75 -0
  195. data/lib/badline/drives/engine/sleep.rb +114 -0
  196. data/lib/badline/drives/engine/vias.rb +86 -0
  197. data/lib/badline/drives/engine/watch.rb +152 -0
  198. data/lib/badline/drives/engine.rb +11 -0
  199. data/lib/badline/drives/model1541/bus.rb +88 -0
  200. data/lib/badline/drives/model1541/byte_ready.rb +50 -0
  201. data/lib/badline/drives/model1541/cpu.rb +13 -0
  202. data/lib/badline/drives/model1541/disk/saved_state.rb +88 -0
  203. data/lib/badline/drives/model1541/disk.rb +317 -0
  204. data/lib/badline/drives/model1541/disk_via.rb +38 -0
  205. data/lib/badline/drives/model1541/gcr.rb +59 -0
  206. data/lib/badline/drives/model1541/mechanism/saved_state.rb +72 -0
  207. data/lib/badline/drives/model1541/mechanism.rb +315 -0
  208. data/lib/badline/drives/model1541/rotation.rb +123 -0
  209. data/lib/badline/drives/model1541/saved_state.rb +44 -0
  210. data/lib/badline/drives/model1541/sector_reader.rb +78 -0
  211. data/lib/badline/drives/model1541/serial_port.rb +20 -0
  212. data/lib/badline/drives/model1541/track.rb +100 -0
  213. data/lib/badline/drives/model1541.rb +81 -0
  214. data/lib/badline/drives/model1571/bus.rb +113 -0
  215. data/lib/badline/drives/model1571/cpu.rb +13 -0
  216. data/lib/badline/drives/model1571/saved_state.rb +47 -0
  217. data/lib/badline/drives/model1571/serial_port.rb +39 -0
  218. data/lib/badline/drives/model1571/serial_via.rb +27 -0
  219. data/lib/badline/drives/model1571/wd1770.rb +122 -0
  220. data/lib/badline/drives/model1571.rb +142 -0
  221. data/lib/badline/drives/model1581/bus.rb +139 -0
  222. data/lib/badline/drives/model1581/cpu.rb +13 -0
  223. data/lib/badline/drives/model1581/disk/saved_state.rb +89 -0
  224. data/lib/badline/drives/model1581/disk.rb +137 -0
  225. data/lib/badline/drives/model1581/mechanism.rb +119 -0
  226. data/lib/badline/drives/model1581/saved_state.rb +42 -0
  227. data/lib/badline/drives/model1581/serial_port.rb +54 -0
  228. data/lib/badline/drives/model1581/slot.rb +79 -0
  229. data/lib/badline/drives/model1581/track.rb +102 -0
  230. data/lib/badline/drives/model1581/track_bytes.rb +77 -0
  231. data/lib/badline/drives/model1581/wd1772/registers.rb +91 -0
  232. data/lib/badline/drives/model1581/wd1772/saved_state.rb +68 -0
  233. data/lib/badline/drives/model1581/wd1772/sector_writes.rb +75 -0
  234. data/lib/badline/drives/model1581/wd1772/sectors.rb +152 -0
  235. data/lib/badline/drives/model1581/wd1772/stepping.rb +111 -0
  236. data/lib/badline/drives/model1581/wd1772/tracks.rb +127 -0
  237. data/lib/badline/drives/model1581/wd1772/turn.rb +75 -0
  238. data/lib/badline/drives/model1581/wd1772.rb +218 -0
  239. data/lib/badline/drives/model1581.rb +206 -0
  240. data/lib/badline/drives/serial_bus.rb +161 -0
  241. data/lib/badline/frontend/boot.rb +10 -61
  242. data/lib/badline/frontend/machine_window.rb +3 -1
  243. data/lib/badline/frontend/player/filter_view.rb +1 -1
  244. data/lib/badline/frontend/player/player_controller.rb +2 -2
  245. data/lib/badline/frontend/player/player_screen.rb +1 -0
  246. data/lib/badline/frontend/player/theme.rb +7 -7
  247. data/lib/badline/frontend/timeline.rb +3 -3
  248. data/lib/badline/input/control_ports.rb +78 -0
  249. data/lib/badline/input/joystick.rb +27 -0
  250. data/lib/badline/input/keyboard.rb +114 -0
  251. data/lib/badline/input.rb +3 -0
  252. data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
  253. data/lib/badline/kernal_trap/dos/channel.rb +183 -0
  254. data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -1
  255. data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -1
  256. data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
  257. data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -1
  258. data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -1
  259. data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
  260. data/lib/badline/kernal_trap/{drive.rb → dos.rb} +11 -10
  261. data/lib/badline/kernal_trap/{file.rb → file_routine.rb} +1 -1
  262. data/lib/badline/kernal_trap/load.rb +6 -6
  263. data/lib/badline/kernal_trap/save.rb +5 -5
  264. data/lib/badline/kernal_trap/serial.rb +7 -7
  265. data/lib/badline/kernal_trap.rb +2 -3
  266. data/lib/badline/machine/clocking.rb +50 -0
  267. data/lib/badline/machine.rb +63 -7
  268. data/lib/badline/media/boot_disk.rb +2 -2
  269. data/lib/badline/media/disk_list.rb +3 -3
  270. data/lib/badline/media/disk_set.rb +1 -1
  271. data/lib/badline/media/extensions.rb +33 -0
  272. data/lib/badline/media/program.rb +28 -0
  273. data/lib/badline/media/true_drive.rb +4 -3
  274. data/lib/badline/media/tune.rb +35 -0
  275. data/lib/badline/media/vic20_cartridge.rb +1 -7
  276. data/lib/badline/media/vic20_media.rb +38 -80
  277. data/lib/badline/media.rb +84 -81
  278. data/lib/badline/model.rb +1 -1
  279. data/lib/badline/options/event.rb +3 -1
  280. data/lib/badline/roms/README +6 -6
  281. data/lib/badline/sdl.rb +1 -0
  282. data/lib/badline/{storage/sid_file.rb → sid_tune/file.rb} +3 -3
  283. data/lib/badline/{storage → sid_tune}/hvsc.rb +7 -7
  284. data/lib/badline/{storage → sid_tune}/song_lengths.rb +2 -2
  285. data/lib/badline/{storage → sid_tune}/stil/credit.rb +1 -1
  286. data/lib/badline/{storage → sid_tune}/stil.rb +3 -3
  287. data/lib/badline/sid_tune.rb +6 -0
  288. data/lib/badline/snapshot/c128_setup.rb +43 -0
  289. data/lib/badline/snapshot/c64_setup.rb +79 -0
  290. data/lib/badline/snapshot/image.rb +5 -25
  291. data/lib/badline/snapshot/machine_state.rb +10 -2
  292. data/lib/badline/snapshot/setup.rb +22 -66
  293. data/lib/badline/snapshot/state.rb +8 -17
  294. data/lib/badline/snapshot/storage_setup.rb +68 -0
  295. data/lib/badline/snapshot/vic20_setup.rb +37 -0
  296. data/lib/badline/snapshot/vice/c64_mem.rb +1 -1
  297. data/lib/badline/snapshot/vice/restore.rb +1 -1
  298. data/lib/badline/snapshot/vice/reu1764.rb +1 -1
  299. data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
  300. data/lib/badline/snapshot/vice.rb +7 -5
  301. data/lib/badline/snapshot.rb +13 -12
  302. data/lib/badline/storage/d64_image.rb +15 -9
  303. data/lib/badline/storage/d71_image.rb +0 -2
  304. data/lib/badline/storage/d81_image.rb +0 -2
  305. data/lib/badline/storage/disk_image/writing.rb +2 -2
  306. data/lib/badline/storage/disk_image.rb +3 -6
  307. data/lib/badline/storage/g64_image.rb +2 -2
  308. data/lib/badline/storage/host_directory.rb +0 -5
  309. data/lib/badline/storage/t64.rb +2 -8
  310. data/lib/badline/storage/unavailable.rb +1 -1
  311. data/lib/badline/storage.rb +0 -37
  312. data/lib/badline/support/c128_checkpoint.rb +39 -0
  313. data/lib/badline/support/checkpoint.rb +108 -0
  314. data/lib/badline/support/vic20_checkpoint.rb +38 -0
  315. data/lib/badline/support.rb +5 -0
  316. data/lib/badline/version.rb +1 -1
  317. data/lib/badline/vic20/attachments.rb +11 -81
  318. data/lib/badline/vic20/bus/saved_state.rb +35 -0
  319. data/lib/badline/vic20/bus.rb +3 -25
  320. data/lib/badline/vic20/cpu.rb +1 -1
  321. data/lib/badline/vic20/port_wiring.rb +4 -4
  322. data/lib/badline/vic20/saved_state.rb +16 -60
  323. data/lib/badline/vic20/user_via_ports.rb +2 -2
  324. data/lib/badline/vic20.rb +20 -51
  325. metadata +250 -221
  326. data/lib/badline/address_bus/extra_sids.rb +0 -30
  327. data/lib/badline/address_bus/fittings.rb +0 -38
  328. data/lib/badline/address_bus/pla.rb +0 -147
  329. data/lib/badline/address_bus/roms.rb +0 -39
  330. data/lib/badline/address_bus/saved_state.rb +0 -72
  331. data/lib/badline/address_bus/sid_slots.rb +0 -42
  332. data/lib/badline/address_bus.rb +0 -235
  333. data/lib/badline/cartridge/action_replay.rb +0 -126
  334. data/lib/badline/cartridge/atomic_power.rb +0 -24
  335. data/lib/badline/cartridge/bank.rb +0 -81
  336. data/lib/badline/cartridge/comal80.rb +0 -50
  337. data/lib/badline/cartridge/dinamic.rb +0 -34
  338. data/lib/badline/cartridge/easy_flash.rb +0 -145
  339. data/lib/badline/cartridge/epyx_fastload.rb +0 -79
  340. data/lib/badline/cartridge/final_cartridge3.rb +0 -89
  341. data/lib/badline/cartridge/flash.rb +0 -306
  342. data/lib/badline/cartridge/freezer.rb +0 -33
  343. data/lib/badline/cartridge/fun_play.rb +0 -38
  344. data/lib/badline/cartridge/g_mod2.rb +0 -74
  345. data/lib/badline/cartridge/game_system.rb +0 -40
  346. data/lib/badline/cartridge/geo_ram.rb +0 -79
  347. data/lib/badline/cartridge/kcs_power.rb +0 -75
  348. data/lib/badline/cartridge/mach5.rb +0 -32
  349. data/lib/badline/cartridge/magic_desk.rb +0 -30
  350. data/lib/badline/cartridge/ocean.rb +0 -35
  351. data/lib/badline/cartridge/pagefox.rb +0 -68
  352. data/lib/badline/cartridge/retro_replay.rb +0 -320
  353. data/lib/badline/cartridge/rex_utility.rb +0 -29
  354. data/lib/badline/cartridge/rgcd.rb +0 -58
  355. data/lib/badline/cartridge/simons_basic.rb +0 -35
  356. data/lib/badline/cartridge/standard.rb +0 -15
  357. data/lib/badline/cartridge/super_games.rb +0 -48
  358. data/lib/badline/cartridge/westermann.rb +0 -30
  359. data/lib/badline/cartridge/zaxxon.rb +0 -66
  360. data/lib/badline/cartridge.rb +0 -303
  361. data/lib/badline/checkpoint.rb +0 -98
  362. data/lib/badline/cia/fast_forward.rb +0 -60
  363. data/lib/badline/cia/interrupt_register.rb +0 -143
  364. data/lib/badline/cia/serial.rb +0 -275
  365. data/lib/badline/cia/state.rb +0 -47
  366. data/lib/badline/cia/timer.rb +0 -206
  367. data/lib/badline/cia.rb +0 -279
  368. data/lib/badline/color_memory.rb +0 -25
  369. data/lib/badline/computer/kernal_traps.rb +0 -29
  370. data/lib/badline/control_ports.rb +0 -76
  371. data/lib/badline/cpu/addressing.rb +0 -131
  372. data/lib/badline/cpu/boundary.rb +0 -54
  373. data/lib/badline/cpu/core.rb +0 -165
  374. data/lib/badline/cpu/microcode.rb +0 -177
  375. data/lib/badline/cpu/operations.rb +0 -88
  376. data/lib/badline/cpu/saved_state.rb +0 -115
  377. data/lib/badline/cpu/stack_operations.rb +0 -82
  378. data/lib/badline/cpu.rb +0 -10
  379. data/lib/badline/cycleable.rb +0 -38
  380. data/lib/badline/datasette.rb +0 -161
  381. data/lib/badline/drive/core.rb +0 -147
  382. data/lib/badline/drive/fast_serial.rb +0 -73
  383. data/lib/badline/drive/idle.rb +0 -125
  384. data/lib/badline/drive/idle_cpu.rb +0 -28
  385. data/lib/badline/drive/orbit.rb +0 -79
  386. data/lib/badline/drive/serial_lines.rb +0 -73
  387. data/lib/badline/drive/sleep.rb +0 -112
  388. data/lib/badline/drive/vias.rb +0 -84
  389. data/lib/badline/drive/watch.rb +0 -150
  390. data/lib/badline/drive.rb +0 -11
  391. data/lib/badline/drive1541/bus.rb +0 -86
  392. data/lib/badline/drive1541/byte_ready.rb +0 -48
  393. data/lib/badline/drive1541/cpu.rb +0 -11
  394. data/lib/badline/drive1541/disk.rb +0 -318
  395. data/lib/badline/drive1541/disk_state.rb +0 -94
  396. data/lib/badline/drive1541/disk_via.rb +0 -36
  397. data/lib/badline/drive1541/gcr.rb +0 -57
  398. data/lib/badline/drive1541/mechanism.rb +0 -313
  399. data/lib/badline/drive1541/mechanism_state.rb +0 -68
  400. data/lib/badline/drive1541/rotation.rb +0 -121
  401. data/lib/badline/drive1541/sector_reader.rb +0 -76
  402. data/lib/badline/drive1541/serial_port.rb +0 -18
  403. data/lib/badline/drive1541/track.rb +0 -98
  404. data/lib/badline/drive1541.rb +0 -111
  405. data/lib/badline/drive1571/bus.rb +0 -111
  406. data/lib/badline/drive1571/cpu.rb +0 -11
  407. data/lib/badline/drive1571/serial_port.rb +0 -37
  408. data/lib/badline/drive1571/serial_via.rb +0 -25
  409. data/lib/badline/drive1571/wd1770.rb +0 -120
  410. data/lib/badline/drive1571.rb +0 -175
  411. data/lib/badline/drive1581/bus.rb +0 -137
  412. data/lib/badline/drive1581/cpu.rb +0 -11
  413. data/lib/badline/drive1581/disk.rb +0 -135
  414. data/lib/badline/drive1581/disk_state.rb +0 -87
  415. data/lib/badline/drive1581/mechanism.rb +0 -117
  416. data/lib/badline/drive1581/serial_port.rb +0 -52
  417. data/lib/badline/drive1581/slot.rb +0 -78
  418. data/lib/badline/drive1581/track.rb +0 -100
  419. data/lib/badline/drive1581/track_bytes.rb +0 -75
  420. data/lib/badline/drive1581/wd1772/registers.rb +0 -89
  421. data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
  422. data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
  423. data/lib/badline/drive1581/wd1772/state.rb +0 -66
  424. data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
  425. data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
  426. data/lib/badline/drive1581/wd1772/turn.rb +0 -73
  427. data/lib/badline/drive1581/wd1772.rb +0 -216
  428. data/lib/badline/drive1581.rb +0 -233
  429. data/lib/badline/iec_bus.rb +0 -159
  430. data/lib/badline/instruction.rb +0 -334
  431. data/lib/badline/instruction_set/arithmetic.rb +0 -114
  432. data/lib/badline/instruction_set/bitwise.rb +0 -126
  433. data/lib/badline/instruction_set/branch.rb +0 -79
  434. data/lib/badline/instruction_set/flag.rb +0 -63
  435. data/lib/badline/instruction_set/illegal.rb +0 -270
  436. data/lib/badline/instruction_set/inc_dec.rb +0 -69
  437. data/lib/badline/instruction_set/stack.rb +0 -52
  438. data/lib/badline/instruction_set/transfer.rb +0 -137
  439. data/lib/badline/instruction_set.rb +0 -55
  440. data/lib/badline/interrupts.rb +0 -104
  441. data/lib/badline/joystick.rb +0 -25
  442. data/lib/badline/kernal_trap/channel.rb +0 -181
  443. data/lib/badline/keyboard.rb +0 -112
  444. data/lib/badline/ram_expansion/banking.rb +0 -30
  445. data/lib/badline/ram_expansion/plus256k.rb +0 -54
  446. data/lib/badline/ram_expansion/plus60k.rb +0 -43
  447. data/lib/badline/ram_expansion/unexpanded.rb +0 -28
  448. data/lib/badline/ram_expansion.rb +0 -21
  449. data/lib/badline/reu/dma/saved_state.rb +0 -50
  450. data/lib/badline/reu/dma.rb +0 -273
  451. data/lib/badline/reu/ram.rb +0 -107
  452. data/lib/badline/reu/saved_state.rb +0 -80
  453. data/lib/badline/reu/trigger.rb +0 -32
  454. data/lib/badline/reu.rb +0 -289
  455. data/lib/badline/sid/catch_up.rb +0 -120
  456. data/lib/badline/sid/decimator.rb +0 -64
  457. data/lib/badline/sid/envelope/state.rb +0 -68
  458. data/lib/badline/sid/envelope.rb +0 -239
  459. data/lib/badline/sid/filter.rb +0 -263
  460. data/lib/badline/sid/voice.rb +0 -77
  461. data/lib/badline/sid/waveform/combined.rb +0 -126
  462. data/lib/badline/sid/waveform/fast_forward.rb +0 -105
  463. data/lib/badline/sid/waveform/noise_writeback.rb +0 -122
  464. data/lib/badline/sid/waveform/state.rb +0 -66
  465. data/lib/badline/sid/waveform.rb +0 -305
  466. data/lib/badline/sid.rb +0 -303
  467. data/lib/badline/time_of_day.rb +0 -228
  468. data/lib/badline/traps.rb +0 -19
  469. data/lib/badline/via/control_lines.rb +0 -122
  470. data/lib/badline/via/fast_forward.rb +0 -53
  471. data/lib/badline/via/interrupt_register.rb +0 -67
  472. data/lib/badline/via/shift_register.rb +0 -180
  473. data/lib/badline/via/state.rb +0 -42
  474. data/lib/badline/via/timer1.rb +0 -131
  475. data/lib/badline/via/timer2.rb +0 -133
  476. data/lib/badline/via.rb +0 -266
  477. data/lib/badline/vic/bank.rb +0 -133
  478. data/lib/badline/vic/border_mask.rb +0 -86
  479. data/lib/badline/vic/collisions.rb +0 -115
  480. data/lib/badline/vic/color_patches.rb +0 -47
  481. data/lib/badline/vic/display_state.rb +0 -185
  482. data/lib/badline/vic/graphics_mode.rb +0 -164
  483. data/lib/badline/vic/graphics_shifter.rb +0 -207
  484. data/lib/badline/vic/register_log.rb +0 -81
  485. data/lib/badline/vic/registers.rb +0 -195
  486. data/lib/badline/vic/sequencer.rb +0 -275
  487. data/lib/badline/vic/sequencer_output.rb +0 -116
  488. data/lib/badline/vic/sequencer_state.rb +0 -89
  489. data/lib/badline/vic/sprite/internal_bus.rb +0 -68
  490. data/lib/badline/vic/sprite/saved_state.rb +0 -64
  491. data/lib/badline/vic/sprite/shifter.rb +0 -146
  492. data/lib/badline/vic/sprite/timing.rb +0 -56
  493. data/lib/badline/vic/sprite.rb +0 -337
  494. data/lib/badline/vic/sprites.rb +0 -282
  495. data/lib/badline/vic/sprites_state.rb +0 -57
  496. data/lib/badline/vic.rb +0 -852
  497. data/lib/badline/vic20/sound/output.rb +0 -83
  498. data/lib/badline/vic20/sound.rb +0 -233
  499. data/lib/badline/z80/arithmetic.rb +0 -117
  500. data/lib/badline/z80/bit_page.rb +0 -55
  501. data/lib/badline/z80/block_io.rb +0 -58
  502. data/lib/badline/z80/block_transfers.rb +0 -59
  503. data/lib/badline/z80/bus_cycles.rb +0 -111
  504. data/lib/badline/z80/core.rb +0 -113
  505. data/lib/badline/z80/exchanges.rb +0 -50
  506. data/lib/badline/z80/extended_page.rb +0 -89
  507. data/lib/badline/z80/flags.rb +0 -37
  508. data/lib/badline/z80/interrupt_acceptance.rb +0 -46
  509. data/lib/badline/z80/jumps.rb +0 -82
  510. data/lib/badline/z80/loads.rb +0 -98
  511. data/lib/badline/z80/main_page.rb +0 -134
  512. data/lib/badline/z80/registers.rb +0 -120
  513. data/lib/badline/z80/saved_state.rb +0 -69
  514. data/lib/badline/z80/shifts.rb +0 -64
  515. data/lib/badline/z80.rb +0 -11
  516. /data/lib/badline/snapshot/{fields.rb → vice/fields.rb} +0 -0
@@ -1,161 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- # The 1530 datasette. Plays a pulse stream into CIA 1's FLAG pin while the
5
- # motor runs with a key pressed, and reports the keys through the cassette
6
- # sense line on the $01 port. With RECORD down too, it records the
7
- # machine's write line onto the tape instead.
8
- class Datasette
9
- # What inserting a tape raises on a machine without a cassette port.
10
- class Missing < ArgumentError; end
11
-
12
- attr_reader :tape
13
- attr_writer :motor
14
-
15
- def initialize(tape = nil)
16
- @tape = tape
17
- @connected = true
18
- @playing = false
19
- @recording = false
20
- @write_high = true
21
- @since = 0
22
- @motor = false
23
- @countdown = 0
24
- @flag_handler = nil
25
- @sense_handler = nil
26
- end
27
-
28
- # Falling edges on the tape read line.
29
- def on_flag(&handler)
30
- @flag_handler = handler
31
- end
32
-
33
- # The cassette sense line, which the $01 port reads back.
34
- def on_sense_change(&handler)
35
- @sense_handler = handler
36
- end
37
-
38
- # Whether the machine has a datasette at its cassette port. The SX-64
39
- # has none: its keys stay up and it takes no tape.
40
- def connected? = @connected
41
-
42
- def disconnect!
43
- eject
44
- @connected = false
45
- end
46
-
47
- def insert(tape)
48
- raise Missing, "this machine has no datasette" unless @connected
49
-
50
- @tape = tape
51
- rewind
52
- end
53
-
54
- def eject
55
- stop!
56
- @tape = nil
57
- end
58
-
59
- def rewind
60
- @tape&.rewind
61
- @countdown = 0
62
- end
63
-
64
- def play! = press(true)
65
- def stop! = press(false)
66
-
67
- # Presses RECORD and PLAY together.
68
- def record!
69
- return if !@connected || @tape.nil?
70
-
71
- press(true)
72
- @recording = true
73
- @since = 0
74
- end
75
-
76
- def recording? = @recording
77
-
78
- # The machine's tape write line. While the deck records with its motor
79
- # running, each rising edge ends a pulse on the tape, as long as the
80
- # time since the edge before, and plays back as a falling edge on the
81
- # read line.
82
- def write_line=(high)
83
- rose = high && !@write_high
84
- @write_high = high
85
- return unless rose && @recording && running?
86
-
87
- @tape.record_pulse(@since)
88
- @since = 0
89
- end
90
-
91
- def playing? = @playing
92
-
93
- # Sense reads low while a key is down on the deck.
94
- def sense_low? = @playing
95
-
96
- def motor? = @motor
97
-
98
- def running? = @playing && @motor && !@tape.nil?
99
-
100
- # The keys, the motor, the countdown to the next pulse and the tape:
101
- # its path, its bytes and how far it has played.
102
- def save_state(out)
103
- out.marker("DATASETTE")
104
- out.boolean(@playing).boolean(@motor).int(@countdown).boolean(!@tape.nil?)
105
- return unless @tape
106
-
107
- out.string(@tape.path).blob(@tape.bytes).int(@tape.position)
108
- end
109
-
110
- # The tape goes back in from the bytes the state holds, without its
111
- # host file, unless the tape in is the same one. The sense and flag
112
- # handlers don't fire.
113
- def load_state(input)
114
- input.marker("DATASETTE")
115
- @playing = input.boolean?
116
- @motor = input.boolean?
117
- @countdown = input.int
118
- return @tape = nil unless input.boolean?
119
-
120
- path = input.string
121
- bytes = input.blob
122
- position = input.int
123
- @tape = Storage::TAP.new(path, bytes:) unless @tape&.path&.b == path && @tape.bytes == bytes
124
- @tape.position = position
125
- end
126
-
127
- def cycle!
128
- return unless running?
129
- return @since += 1 if @recording
130
-
131
- @countdown = @tape.next_pulse.to_i if @countdown.zero?
132
- return if @countdown.zero?
133
-
134
- @countdown -= 1
135
- @flag_handler&.call if @countdown.zero?
136
- end
137
-
138
- def inspect
139
- "#<#{self.class.name} tape=#{@tape ? @tape.class.name : 'none'} " \
140
- "playing=#{@playing} motor=#{@motor}>"
141
- end
142
-
143
- private
144
-
145
- def press(down)
146
- return if down == @playing || !@connected
147
-
148
- finish_recording unless down
149
- @playing = down
150
- @sense_handler&.call
151
- end
152
-
153
- # Releasing the keys ends a recording, and writes the tape out.
154
- def finish_recording
155
- return unless @recording
156
-
157
- @recording = false
158
- @tape.save
159
- end
160
- end
161
- end
@@ -1,147 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- module Drive
5
- # What every Commodore disk drive here shares: a 6502 running the DOS
6
- # ROM, with chips on its bus facing the serial bus and the disk
7
- # mechanism, on a clock of its own.
8
- #
9
- # The drive runs on its own crystal, so it clocks against the host's
10
- # clock through a fractional accumulator: each host cycle adds the
11
- # drive's clock rate worth of phase, and every whole host period in it
12
- # runs a drive cycle. Against the PAL C64's 985,248 Hz a drive at
13
- # 1 MHz runs one drive cycle per host cycle and a second one about
14
- # every 67. The host sets its clock on attaching the drive, and until
15
- # then a 1 MHz drive runs one cycle per host cycle.
16
- #
17
- # The Mechanism reads a Disk put in with insert.
18
- #
19
- # While the DOS idles, host_cycle! skips the drive's cycles and catches
20
- # up on them later, exactly (see Idle). The readers of the drive's parts
21
- # catch up first, so they find the drive as running every cycle would
22
- # have left it. Once the DOS's timer interrupts come round, the drive
23
- # sleeps through them too (see Orbit).
24
- #
25
- # A model includes Core and builds its parts, sets @clock_hz and
26
- # @idle_loop, and runs one drive cycle in step. It hears ATN on
27
- # connecting (hear_atn), drives the serial bus (serial_output), and
28
- # answers Idle's and Orbit's questions about its chips, as VIAs does
29
- # for the 1541 and the 1571.
30
- module Core
31
- include Sleep
32
- include Idle
33
- include Orbit
34
-
35
- attr_reader :device, :serial_bus
36
-
37
- def cpu
38
- settle!
39
- @cpu
40
- end
41
-
42
- def bus
43
- settle!
44
- @bus
45
- end
46
-
47
- def mechanism
48
- settle!
49
- @mechanism
50
- end
51
-
52
- def cycles
53
- settle!
54
- @cycles
55
- end
56
-
57
- def ram = bus.ram
58
-
59
- def host_clock_hz=(clock_hz)
60
- settle!
61
- @host_clock_hz = clock_hz
62
- end
63
-
64
- # Plugs the drive into a serial bus, leaving the one it was on. A drive
65
- # starts out on a bus of its own, with nothing else on it.
66
- def connect(serial_bus)
67
- settle!
68
- @serial_bus&.detach(self)
69
- @serial_bus = serial_bus
70
- @serial_port.bus = serial_bus
71
- serial_bus.attach(self)
72
- hear_atn
73
- end
74
-
75
- # Puts a Disk in the drive (Disk.from_d64 makes one from an image).
76
- # Nil takes the disk out.
77
- def insert(disk)
78
- settle!
79
- @mechanism.insert(disk)
80
- end
81
-
82
- def disk = mechanism.disk
83
-
84
- # Whether the LED is lit. Reading it leaves the drive asleep: the LED
85
- # is the same at the end of every pass the drive sleeps through.
86
- def led_on? = @mechanism.led_on?
87
-
88
- # Stores what the head wrote since the motor last stopped in the
89
- # disk's image, as the motor stopping does.
90
- def flush
91
- settle!
92
- @mechanism.flush
93
- end
94
-
95
- # Runs the drive cycles that fall in one host cycle: none, one or two.
96
- # The host has run this cycle already, and the drive sees what it did
97
- # from the next one on (see SerialPort). Asleep, the drive owes the
98
- # cycles instead, until ATN moves or its counters are due (see Idle).
99
- # It looks at ATN only after the machine pushed its lines into the bus
100
- # (see host_written!).
101
- def host_cycle!
102
- if @asleep
103
- return if (@slept += 1) != @wake_at && @host_still
104
-
105
- return doze
106
- end
107
-
108
- phase = @phase + @clock_hz
109
- while phase >= @host_clock_hz
110
- @asleep ? @owed += 1 : run_cycle
111
- phase -= @host_clock_hz
112
- end
113
- @phase = phase
114
- settle! if @serial_port.atn_moved?
115
- @serial_port.latch_host
116
- plan_wake if @asleep
117
- end
118
-
119
- # The machine pushed its lines into the bus, so ATN may have moved.
120
- def host_written!
121
- @host_still = false
122
- end
123
-
124
- # The host moved its fast serial pins, which a 1541 has none to hear.
125
- def fast_lines_moved = nil
126
-
127
- # Runs one drive cycle, catching up first on any the drive owes (see
128
- # step).
129
- def cycle!
130
- settle!
131
- step
132
- end
133
-
134
- def inspect
135
- "#<#{self.class.name} cycles=#{cycles} cpu=(#{cpu.inspect})>"
136
- end
137
-
138
- private
139
-
140
- # A drive cycle from host_cycle!, which may find the idle loop.
141
- def run_cycle
142
- step
143
- idle_loop_reached if @cpu.program_counter == @idle_loop && @idle_skip
144
- end
145
- end
146
- end
147
- end
@@ -1,73 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- module Drive
5
- # Fast serial on a drive with a CIA, the 1571's 6526 or the 1581's
6
- # 8520: through buffers a port line turns round, the CIA's CNT drives
7
- # SRQ and its SP drives DATA, or it hears them. The drive pushes its
8
- # pins into the bus as they move, and hears the host's as the host
9
- # pushes them, pin by pin, so each byte goes through both shift
10
- # registers bit by bit. The CIA takes no part in a pass of the idle
11
- # loop, and any access to it, or the host moving its fast serial pins,
12
- # wakes the drive.
13
- #
14
- # A model includes it beside Core, and calls turn_fast_serial when its
15
- # direction line moves and drive_fast_serial each cycle the buffers
16
- # face out. Its serial_output carries @fast_output above its port.
17
- module FastSerial
18
- # Whether the buffers face out, the drive's CIA driving DATA and SRQ.
19
- attr_reader :fast_serial_out
20
-
21
- # The host moved its fast serial pins: the CIA hears SRQ on CNT and
22
- # DATA on SP while the buffers face in.
23
- def fast_lines_moved
24
- settle!
25
- hear_fast_serial unless @fast_serial_out
26
- end
27
-
28
- private
29
-
30
- def init_fast_serial
31
- @fast_serial_out = false
32
- @fast_output = 0
33
- end
34
-
35
- # The buffers turned round: outwards the CIA's pins drive the lines,
36
- # and inwards they let go and hear them.
37
- def turn_fast_serial(out)
38
- @fast_serial_out = out
39
- return unless @serial_bus
40
-
41
- push_fast_output(out ? fast_pins : 0)
42
- hear_fast_serial unless out
43
- end
44
-
45
- def drive_fast_serial
46
- low = fast_pins
47
- push_fast_output(low) if low != @fast_output
48
- end
49
-
50
- # The lines the CIA's CNT and SP pull while its serial port drives
51
- # them.
52
- def fast_pins
53
- serial = @cia.serial
54
- return 0 unless serial.output?
55
-
56
- low = serial.cnt ? 0 : IECBus::DRIVE_FAST_SRQ
57
- serial.sp_out ? low : low | IECBus::DRIVE_FAST_DATA
58
- end
59
-
60
- def push_fast_output(low)
61
- @fast_output = low
62
- @serial_bus&.drives_fast_moved!
63
- end
64
-
65
- def hear_fast_serial
66
- low = @serial_bus.low_lines
67
- serial = @cia.serial
68
- serial.cnt_in = low.nobits?(IECBus::SRQ)
69
- serial.sp_in = low.nobits?(IECBus::DATA)
70
- end
71
- end
72
- end
73
- end
@@ -1,125 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- module Drive
5
- # Skipping the drive's cycles while the DOS idles, exactly.
6
- #
7
- # With nothing to do, the DOS goes round its idle loop from the
8
- # model's @idle_loop ($EBFF in the 1541, 446 cycles a pass), until VIA
9
- # 2's timer 1 interrupts it every 14,850 cycles for the job loop, or
10
- # ATN interrupts it through VIA 1's CA1. A pass writes RAM and VIA 2's
11
- # port B, but puts back what it found, so the drive comes round to the
12
- # loop's start as it left it. Only the timers' counters and the cycle
13
- # counts move.
14
- #
15
- # Each time the CPU comes to the loop's start, the drive records the
16
- # pass that follows. At the next it checks that the pass
17
- #
18
- # - left the CPU, both VIAs but for their counters, the bus's last
19
- # byte, the SO pin, the mechanism (Mechanism#idle_state) and what
20
- # the ports read from it, and every byte of RAM it read or wrote as
21
- # it found them (Bus#watch!)
22
- # - read nothing that changes from pass to pass: no counter, no shift
23
- # register, and not VIA 1's port B, which reads the serial bus
24
- # - wrote nothing that reaches outside the drive: not VIA 1, whose port
25
- # B drives the serial bus, and not the motor on
26
- # - ran while no counter could set a flag (VIA#quiet_cycles), with the
27
- # motor off, no interrupt pulled and no trap on the CPU.
28
- #
29
- # Such a pass runs the same way again from where it ended, for as
30
- # long as ATN holds still and no counter sets a flag, so the drive
31
- # sleeps: host_cycle! only counts the host cycles that go by (see
32
- # Sleep). It wakes
33
- # when ATN moves, when a counter is due to set a flag, or when something
34
- # outside reads or changes the drive (the readers in Core call
35
- # settle!). Waking counts off the whole passes it owes in bulk,
36
- # moving the counters on, and runs the rest cycle by cycle.
37
- #
38
- # The loop reads neither CLK nor DATA, so the drive sleeps through them
39
- # moving and takes the C64's lines as they stand once it wakes. Its
40
- # own lines hold still while it sleeps, so the C64 reads them without
41
- # waking it (serial_output).
42
- #
43
- # A pass starts at the loop's start, where the CPU always comes from
44
- # the loop's last instruction, a JMP, so what that leaves in the CPU's
45
- # working registers is the same each time round.
46
- #
47
- # The timer's interrupts come round too, and once they do, the drive
48
- # sleeps on through them (see Orbit).
49
- module Idle
50
- # Whether the drive may sleep through its idle loop. On by default,
51
- # but for a drive whose CPU logs each instruction.
52
- attr_reader :idle_skip
53
-
54
- def idle_skip=(on)
55
- settle!
56
- @idle_skip = on
57
- end
58
-
59
- private
60
-
61
- def init_idle(debug)
62
- @idle_skip = !debug
63
- @recording = false
64
- @pass_cycles = 0
65
- @pass_instructions = 0
66
- init_sleep
67
- init_orbits
68
- end
69
-
70
- # The CPU is at the loop's start. At an instruction boundary, the
71
- # drive sleeps if the pass it recorded can repeat, and otherwise
72
- # records the next.
73
- def idle_loop_reached
74
- return unless @cpu.boundary?
75
-
76
- if @recording
77
- stop_recording
78
- return fall_asleep if repeatable_pass? && room_for_pass?
79
- end
80
- start_recording
81
- end
82
-
83
- def start_recording
84
- return if busy_for_pass? || @cpu.trapped?
85
-
86
- @recording = true
87
- @record_state = idle_state
88
- @record_cycles = @cycles
89
- @record_instructions = @cpu.instructions
90
- @record_quiet = quiet_cycles
91
- @bus.watch!
92
- end
93
-
94
- def stop_recording
95
- @recording = false
96
- @bus.unwatch!
97
- end
98
-
99
- # Whether the pass just recorded can repeat.
100
- def repeatable_pass?
101
- !@bus.volatile && @cycles - @record_cycles <= @record_quiet && idle_state == @record_state &&
102
- ram_as_found?
103
- end
104
-
105
- # Whether the counters leave room for a whole pass.
106
- def room_for_pass? = quiet_cycles >= @cycles - @record_cycles
107
-
108
- # Sleeps through the pass just recorded, over and over.
109
- def fall_asleep
110
- @pass_cycles = @cycles - @record_cycles
111
- @pass_instructions = @cpu.instructions - @record_instructions
112
- @asleep = true
113
- @host_still = false
114
- @owed = 0
115
- @budget = quiet_cycles
116
- anchor
117
- end
118
-
119
- def ram_as_found?
120
- ram = @bus.ram
121
- @bus.touched.all? { |addr, value| ram.peek(addr) == value }
122
- end
123
- end
124
- end
125
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- module Drive
5
- # What Idle needs of a drive's 6502, which includes it beside
6
- # CPU::Core.
7
- module IdleCPU
8
- # Everything the CPU holds but its cycle and instruction counts: the
9
- # registers, the interrupt lines and pipeline, and what the last
10
- # instruction left in its working registers. Drive::Idle compares
11
- # it at two instruction boundaries.
12
- def idle_state
13
- [@program_counter, @stack_pointer, @a, @x, @y, @status.value,
14
- @irq, @nmi, @irq_sample, @irq_pending, @nmi_sample, @nmi_pending, @skip_poll,
15
- @boundary_irq, @boundary_nmi, @so_high, @interrupt, @brk, @pending_write, @stalled_at, @traps,
16
- @operation, @optional_dummy, @boundary_crossed, @branch_taken,
17
- @address, @pointer, @dummy_address, @value, @rmw_result]
18
- end
19
-
20
- # Counts +cycles+ cycles and +instructions+ instructions that ran
21
- # without changing anything idle_state holds.
22
- def fast_forward(cycles, instructions)
23
- @cycles += cycles
24
- @instructions += instructions
25
- end
26
- end
27
- end
28
- end
@@ -1,79 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- module Drive
5
- # Sleeping through the DOS's timer interrupts, exactly, once they come
6
- # round.
7
- #
8
- # VIA 2's timer 1 interrupts the idle loop for the job loop, which
9
- # finds no job, restarts the timer and returns into the pass it cut
10
- # into, 14,998 cycles and more apart. The interrupts land at a
11
- # different point in the pass each time, until, six of them on, the
12
- # whole drive is back where it was: an orbit of 90,044 cycles.
13
- #
14
- # Each place the drive falls asleep (see Idle) is an anchor, and the
15
- # drive keeps everything it holds at each one: RAM, the counters of
16
- # the timers that are armed or that it read or wrote since, and the
17
- # rest as Idle compares a pass. It keeps them only while it keeps to
18
- # itself, with Bus#guard! checking that it doesn't read the serial
19
- # bus, write VIA 1, turn the motor on or change the LED. ATN moving,
20
- # or a reader settling the drive, forgets them.
21
- #
22
- # Coming to an anchor it kept before closes an orbit, which runs the
23
- # same way again from here for as long as ATN holds still, so the
24
- # drive sleeps on without waking for its counters. Waking counts off
25
- # the whole orbits it owes in bulk, moving on only the counters it
26
- # never touched, and runs the rest as Idle does.
27
- module Orbit
28
- # How many anchors the drive keeps while it looks for an orbit.
29
- ANCHORS = 32
30
-
31
- private
32
-
33
- def init_orbits
34
- @anchors = {}
35
- @orbit_cycles = nil
36
- @orbit_instructions = 0
37
- @bus.guard!
38
- end
39
-
40
- # The drive falls asleep at an anchor. One it came to before closes
41
- # an orbit: everything from there to here runs the same way again.
42
- def anchor
43
- forget_orbits if @bus.tainted || @anchors.size >= ANCHORS
44
- key = anchor_state
45
- if (seen = @anchors[key])
46
- @orbit_cycles = @cycles - seen[0]
47
- @orbit_instructions = @cpu.instructions - seen[1]
48
- else
49
- @anchors[key] = [@cycles, @cpu.instructions]
50
- end
51
- end
52
-
53
- def forget_orbits
54
- @anchors.clear
55
- @orbit_cycles = nil
56
- @bus.guard!
57
- end
58
-
59
- # Runs whole orbits, which bring the drive back to the anchor it
60
- # sleeps at but for the counters it never touched. Returns the
61
- # cycles.
62
- def skip_orbits(orbits)
63
- cycles = orbits * @orbit_cycles
64
- touched = @bus.touched_timers
65
- @cpu.fast_forward(cycles, orbits * @orbit_instructions)
66
- skip_chip_orbits(cycles, touched)
67
- @cycles += cycles
68
- cycles
69
- end
70
-
71
- # Everything the drive holds at an anchor, but for the counters of
72
- # the unarmed timers it hasn't touched since it was last tainted.
73
- def anchor_state
74
- touched = @bus.touched_timers
75
- [*idle_state, *counter_state(touched), @bus.ram.snapshot]
76
- end
77
- end
78
- end
79
- end
@@ -1,73 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- module Drive
5
- # What VIA 1's port B reads from the serial bus. DATA IN (PB0), CLK IN
6
- # (PB2) and ATN IN (PB7) come through inverters, so a released line
7
- # reads 0 and a pulled one 1. The jumpers on PB5 and PB6 pull a line
8
- # low when closed, and both closed make device 8.
9
- #
10
- # The drive sees the host's side of the bus a host cycle late. The
11
- # host's CIA changes its pins at the end of the cycle that writes them,
12
- # and the drive's VIA samples its own late in each of its cycles, so a
13
- # drive cycle that runs alongside the write reads the lines from
14
- # before it. The drive runs after the host in each host cycle (see
15
- # Computer#cycle!), so the port reads the host's lines as latch_host
16
- # took them at the end of the last one. Fast loaders that time their
17
- # transfer from an ATN edge, as VICE's drive tests do, depend on it.
18
- #
19
- # A model's serial port includes it, with its own port A.
20
- module SerialLines
21
- DATA_IN = 0x01
22
- CLK_IN = 0x04
23
- ATN_IN = 0x80
24
- SERIAL_INPUTS = DATA_IN | CLK_IN | ATN_IN
25
- JUMPERS = 0b0110_0000
26
-
27
- attr_reader :bus
28
-
29
- def bus=(bus)
30
- @bus = bus
31
- latch_host
32
- end
33
-
34
- # Takes the host's lines as the machine last pushed them into the bus,
35
- # for the drive cycles of the next host cycle.
36
- def latch_host
37
- @host = @bus.host_lines
38
- end
39
-
40
- # The host's lines as last latched. The jumpers and the bus are the
41
- # drive's wiring.
42
- def save_state(out)
43
- out.int(@host)
44
- end
45
-
46
- def load_state(input)
47
- @host = input.int
48
- end
49
-
50
- # Whether the host has moved ATN since the last latch_host.
51
- def atn_moved? = (@bus.host_lines ^ @host).anybits?(IECBus::HOST_ATN_OUT)
52
-
53
- def atn_low? = @bus.atn_low?(@host)
54
-
55
- def read_b(_lines)
56
- low = @bus.low_lines(@host)
57
- value = @port_b
58
- value |= DATA_IN if low.anybits?(IECBus::DATA)
59
- value |= CLK_IN if low.anybits?(IECBus::CLK)
60
- value |= ATN_IN if low.anybits?(IECBus::ATN)
61
- value
62
- end
63
-
64
- private
65
-
66
- def init_serial_lines(device, bus)
67
- @port_b = (0xff & ~(SERIAL_INPUTS | JUMPERS)) | (((device - 8) & 0x03) << 5)
68
- @host = 0
69
- self.bus = bus
70
- end
71
- end
72
- end
73
- end