badline 0.12.1 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (565) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -1
  3. data/CLAUDE.md +86 -38
  4. data/CONTRIBUTING.md +4 -3
  5. data/README.md +9 -6
  6. data/doc/library.md +9 -9
  7. data/doc/media.md +2 -1
  8. data/doc/pinned-behaviour.md +134 -105
  9. data/doc/snapshot-format.md +1047 -0
  10. data/doc/snapshots.md +73 -43
  11. data/lib/badline/audio/bare_player.rb +53 -20
  12. data/lib/badline/audio/cli.rb +6 -6
  13. data/lib/badline/audio/jukebox.rb +2 -2
  14. data/lib/badline/audio/machine_player.rb +16 -10
  15. data/lib/badline/{media → audio}/queue.rb +1 -1
  16. data/lib/badline/audio/queued_tune.rb +6 -6
  17. data/lib/badline/audio/renderer.rb +33 -22
  18. data/lib/badline/audio/stereo.rb +1 -1
  19. data/lib/badline/c128/banks.rb +6 -3
  20. data/lib/badline/c128/bus/keyed_state.rb +45 -0
  21. data/lib/badline/c128/bus.rb +35 -20
  22. data/lib/badline/c128/color_lines.rb +2 -2
  23. data/lib/badline/c128/cpu.rb +1 -1
  24. data/lib/badline/c128/drives.rb +14 -34
  25. data/lib/badline/c128/fast_serial.rb +5 -5
  26. data/lib/badline/c128/keyed_modules.rb +117 -0
  27. data/lib/badline/c128/keyed_state.rb +91 -0
  28. data/lib/badline/c128/keys.rb +9 -0
  29. data/lib/badline/c128/mmu.rb +9 -8
  30. data/lib/badline/c128/mmu_pages.rb +21 -1
  31. data/lib/badline/c128/modes.rb +21 -11
  32. data/lib/badline/c128/z80.rb +2 -2
  33. data/lib/badline/c128/z80_turns.rb +1 -1
  34. data/lib/badline/c128.rb +21 -16
  35. data/lib/badline/c64/attachments.rb +42 -0
  36. data/lib/badline/c64/banked_ram/banking.rb +32 -0
  37. data/lib/badline/c64/banked_ram/plus256k.rb +64 -0
  38. data/lib/badline/c64/banked_ram/plus60k.rb +47 -0
  39. data/lib/badline/c64/banked_ram/unexpanded.rb +30 -0
  40. data/lib/badline/c64/banked_ram.rb +23 -0
  41. data/lib/badline/c64/bus/debug_register.rb +32 -0
  42. data/lib/badline/c64/bus/extra_sids.rb +32 -0
  43. data/lib/badline/c64/bus/fittings.rb +40 -0
  44. data/lib/badline/c64/bus/keyed_state.rb +41 -0
  45. data/lib/badline/c64/bus/pla.rb +149 -0
  46. data/lib/badline/c64/bus/roms.rb +41 -0
  47. data/lib/badline/c64/bus/sid_slots.rb +44 -0
  48. data/lib/badline/c64/bus.rb +219 -0
  49. data/lib/badline/c64/cartridge/action_replay.rb +115 -0
  50. data/lib/badline/c64/cartridge/atomic_power.rb +26 -0
  51. data/lib/badline/c64/cartridge/bank.rb +83 -0
  52. data/lib/badline/c64/cartridge/comal80.rb +52 -0
  53. data/lib/badline/c64/cartridge/dinamic.rb +36 -0
  54. data/lib/badline/c64/cartridge/easy_flash.rb +132 -0
  55. data/lib/badline/c64/cartridge/epyx_fastload.rb +73 -0
  56. data/lib/badline/c64/cartridge/final_cartridge3.rb +79 -0
  57. data/lib/badline/c64/cartridge/flash.rb +279 -0
  58. data/lib/badline/c64/cartridge/freezer.rb +35 -0
  59. data/lib/badline/c64/cartridge/fun_play.rb +40 -0
  60. data/lib/badline/c64/cartridge/g_mod2.rb +64 -0
  61. data/lib/badline/c64/cartridge/game_system.rb +42 -0
  62. data/lib/badline/c64/cartridge/geo_ram.rb +65 -0
  63. data/lib/badline/c64/cartridge/kcs_power.rb +69 -0
  64. data/lib/badline/c64/cartridge/keyed_state.rb +393 -0
  65. data/lib/badline/c64/cartridge/mach5.rb +34 -0
  66. data/lib/badline/c64/cartridge/magic_desk.rb +32 -0
  67. data/lib/badline/c64/cartridge/ocean.rb +37 -0
  68. data/lib/badline/c64/cartridge/pagefox.rb +60 -0
  69. data/lib/badline/c64/cartridge/retro_replay.rb +278 -0
  70. data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
  71. data/lib/badline/c64/cartridge/rgcd.rb +50 -0
  72. data/lib/badline/c64/cartridge/simons_basic.rb +37 -0
  73. data/lib/badline/c64/cartridge/standard.rb +17 -0
  74. data/lib/badline/c64/cartridge/super_games.rb +40 -0
  75. data/lib/badline/c64/cartridge/westermann.rb +32 -0
  76. data/lib/badline/c64/cartridge/zaxxon.rb +52 -0
  77. data/lib/badline/c64/cartridge.rb +232 -0
  78. data/lib/badline/c64/color_memory.rb +27 -0
  79. data/lib/badline/{computer → c64}/common.rb +2 -2
  80. data/lib/badline/{computer → c64}/kernal_traps.rb +39 -36
  81. data/lib/badline/c64/keyed_modules.rb +111 -0
  82. data/lib/badline/c64/keyed_state.rb +68 -0
  83. data/lib/badline/c64/reu/dma.rb +271 -0
  84. data/lib/badline/c64/reu/keyed_state.rb +140 -0
  85. data/lib/badline/c64/reu/ram.rb +94 -0
  86. data/lib/badline/c64/reu/trigger.rb +34 -0
  87. data/lib/badline/c64/reu.rb +289 -0
  88. data/lib/badline/c64/true_drives.rb +120 -0
  89. data/lib/badline/{computer.rb → c64.rb} +24 -15
  90. data/lib/badline/chips/cia/fast_forward.rb +62 -0
  91. data/lib/badline/chips/cia/interrupt_register.rb +128 -0
  92. data/lib/badline/chips/cia/keyed_parts.rb +213 -0
  93. data/lib/badline/chips/cia/serial.rb +246 -0
  94. data/lib/badline/chips/cia/time_of_day.rb +210 -0
  95. data/lib/badline/chips/cia/timer.rb +188 -0
  96. data/lib/badline/chips/cia.rb +281 -0
  97. data/lib/badline/chips/cpu/addressing.rb +133 -0
  98. data/lib/badline/chips/cpu/boundary.rb +56 -0
  99. data/lib/badline/chips/cpu/core.rb +183 -0
  100. data/lib/badline/chips/cpu/instruction.rb +338 -0
  101. data/lib/badline/chips/cpu/instruction_set/arithmetic.rb +118 -0
  102. data/lib/badline/chips/cpu/instruction_set/bitwise.rb +130 -0
  103. data/lib/badline/chips/cpu/instruction_set/branch.rb +83 -0
  104. data/lib/badline/chips/cpu/instruction_set/flag.rb +67 -0
  105. data/lib/badline/chips/cpu/instruction_set/illegal.rb +274 -0
  106. data/lib/badline/chips/cpu/instruction_set/inc_dec.rb +73 -0
  107. data/lib/badline/chips/cpu/instruction_set/stack.rb +56 -0
  108. data/lib/badline/chips/cpu/instruction_set/transfer.rb +141 -0
  109. data/lib/badline/chips/cpu/instruction_set.rb +59 -0
  110. data/lib/badline/chips/cpu/interrupts.rb +108 -0
  111. data/lib/badline/chips/cpu/keyed_state.rb +177 -0
  112. data/lib/badline/chips/cpu/microcode.rb +195 -0
  113. data/lib/badline/chips/cpu/operations.rb +90 -0
  114. data/lib/badline/chips/cpu/port.rb +133 -0
  115. data/lib/badline/chips/cpu/stack_operations.rb +84 -0
  116. data/lib/badline/chips/cpu/traps.rb +23 -0
  117. data/lib/badline/chips/cpu.rb +17 -0
  118. data/lib/badline/chips/sid/catch_up.rb +122 -0
  119. data/lib/badline/chips/sid/decimator.rb +68 -0
  120. data/lib/badline/chips/sid/envelope.rb +236 -0
  121. data/lib/badline/chips/sid/filter.rb +227 -0
  122. data/lib/badline/chips/sid/keyed_parts.rb +286 -0
  123. data/lib/badline/chips/sid/voice.rb +69 -0
  124. data/lib/badline/chips/sid/waveform/combined.rb +128 -0
  125. data/lib/badline/chips/sid/waveform/fast_forward.rb +107 -0
  126. data/lib/badline/chips/sid/waveform/noise_writeback.rb +124 -0
  127. data/lib/badline/chips/sid/waveform.rb +305 -0
  128. data/lib/badline/chips/sid.rb +264 -0
  129. data/lib/badline/chips/ted/beam.rb +119 -0
  130. data/lib/badline/chips/ted/timers.rb +66 -0
  131. data/lib/badline/chips/ted.rb +143 -0
  132. data/lib/badline/chips/tia.rb +49 -0
  133. data/lib/badline/chips/vdc/keyed_parts.rb +105 -0
  134. data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
  135. data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -13
  136. data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -17
  137. data/lib/badline/{c128 → chips}/vdc/window.rb +1 -10
  138. data/lib/badline/{c128 → chips}/vdc.rb +6 -31
  139. data/lib/badline/chips/via/control_lines.rb +109 -0
  140. data/lib/badline/chips/via/fast_forward.rb +55 -0
  141. data/lib/badline/chips/via/interrupt_register.rb +60 -0
  142. data/lib/badline/chips/via/keyed_parts.rb +163 -0
  143. data/lib/badline/chips/via/shift_register.rb +168 -0
  144. data/lib/badline/chips/via/timer1.rb +120 -0
  145. data/lib/badline/chips/via/timer2.rb +117 -0
  146. data/lib/badline/chips/via.rb +267 -0
  147. data/lib/badline/chips/vic/bank.rb +135 -0
  148. data/lib/badline/chips/vic/border_mask.rb +78 -0
  149. data/lib/badline/chips/vic/collisions.rb +106 -0
  150. data/lib/badline/chips/vic/color_patches.rb +38 -0
  151. data/lib/badline/chips/vic/display_state.rb +168 -0
  152. data/lib/badline/chips/vic/graphics_mode.rb +166 -0
  153. data/lib/badline/chips/vic/graphics_shifter.rb +183 -0
  154. data/lib/badline/chips/vic/keyed_parts.rb +228 -0
  155. data/lib/badline/chips/vic/keyed_sprites.rb +225 -0
  156. data/lib/badline/chips/vic/keyed_state.rb +102 -0
  157. data/lib/badline/chips/vic/register_log.rb +65 -0
  158. data/lib/badline/chips/vic/registers.rb +188 -0
  159. data/lib/badline/chips/vic/sequencer.rb +275 -0
  160. data/lib/badline/chips/vic/sequencer_output.rb +118 -0
  161. data/lib/badline/chips/vic/sprite/internal_bus.rb +59 -0
  162. data/lib/badline/chips/vic/sprite/shifter.rb +148 -0
  163. data/lib/badline/chips/vic/sprite/timing.rb +58 -0
  164. data/lib/badline/chips/vic/sprite.rb +337 -0
  165. data/lib/badline/chips/vic/sprites.rb +281 -0
  166. data/lib/badline/chips/vic.rb +787 -0
  167. data/lib/badline/chips/vic_i/keyed_parts.rb +142 -0
  168. data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +2 -30
  169. data/lib/badline/chips/vic_i/sound/output.rb +85 -0
  170. data/lib/badline/chips/vic_i/sound.rb +227 -0
  171. data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
  172. data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +6 -6
  173. data/lib/badline/chips/z80/arithmetic.rb +119 -0
  174. data/lib/badline/chips/z80/bit_page.rb +57 -0
  175. data/lib/badline/chips/z80/block_io.rb +60 -0
  176. data/lib/badline/chips/z80/block_transfers.rb +61 -0
  177. data/lib/badline/chips/z80/bus_cycles.rb +113 -0
  178. data/lib/badline/chips/z80/core.rb +115 -0
  179. data/lib/badline/chips/z80/exchanges.rb +52 -0
  180. data/lib/badline/chips/z80/extended_page.rb +91 -0
  181. data/lib/badline/chips/z80/flags.rb +39 -0
  182. data/lib/badline/chips/z80/interrupt_acceptance.rb +48 -0
  183. data/lib/badline/chips/z80/jumps.rb +84 -0
  184. data/lib/badline/chips/z80/keyed_state.rb +73 -0
  185. data/lib/badline/chips/z80/loads.rb +100 -0
  186. data/lib/badline/chips/z80/main_page.rb +136 -0
  187. data/lib/badline/chips/z80/registers.rb +122 -0
  188. data/lib/badline/chips/z80/shifts.rb +66 -0
  189. data/lib/badline/chips/z80.rb +13 -0
  190. data/lib/badline/chips.rb +10 -0
  191. data/lib/badline/core.rb +13 -32
  192. data/lib/badline/drives/datasette/keyed_state.rb +38 -0
  193. data/lib/badline/drives/datasette.rb +173 -0
  194. data/lib/badline/drives/engine/core.rb +152 -0
  195. data/lib/badline/drives/engine/fast_serial.rb +75 -0
  196. data/lib/badline/drives/engine/idle.rb +127 -0
  197. data/lib/badline/drives/engine/idle_cpu.rb +30 -0
  198. data/lib/badline/drives/engine/orbit.rb +81 -0
  199. data/lib/badline/drives/engine/serial_lines.rb +72 -0
  200. data/lib/badline/drives/engine/sleep.rb +114 -0
  201. data/lib/badline/drives/engine/vias.rb +86 -0
  202. data/lib/badline/drives/engine/watch.rb +152 -0
  203. data/lib/badline/drives/engine.rb +11 -0
  204. data/lib/badline/drives/model1541/bus.rb +75 -0
  205. data/lib/badline/drives/model1541/byte_ready.rb +50 -0
  206. data/lib/badline/drives/model1541/cpu.rb +13 -0
  207. data/lib/badline/drives/model1541/disk.rb +318 -0
  208. data/lib/badline/drives/model1541/disk_via.rb +38 -0
  209. data/lib/badline/drives/model1541/gcr.rb +59 -0
  210. data/lib/badline/drives/model1541/keyed_state.rb +251 -0
  211. data/lib/badline/drives/model1541/mechanism.rb +313 -0
  212. data/lib/badline/drives/model1541/rotation.rb +123 -0
  213. data/lib/badline/drives/model1541/sector_reader.rb +78 -0
  214. data/lib/badline/drives/model1541/serial_port.rb +20 -0
  215. data/lib/badline/drives/model1541/track.rb +100 -0
  216. data/lib/badline/drives/model1541.rb +80 -0
  217. data/lib/badline/drives/model1571/bus.rb +100 -0
  218. data/lib/badline/drives/model1571/cpu.rb +13 -0
  219. data/lib/badline/drives/model1571/keyed_state.rb +108 -0
  220. data/lib/badline/drives/model1571/serial_port.rb +39 -0
  221. data/lib/badline/drives/model1571/serial_via.rb +27 -0
  222. data/lib/badline/drives/model1571/wd1770.rb +108 -0
  223. data/lib/badline/drives/model1571.rb +141 -0
  224. data/lib/badline/drives/model1581/bus.rb +126 -0
  225. data/lib/badline/drives/model1581/cpu.rb +13 -0
  226. data/lib/badline/drives/model1581/disk.rb +133 -0
  227. data/lib/badline/drives/model1581/keyed_state.rb +280 -0
  228. data/lib/badline/drives/model1581/mechanism.rb +98 -0
  229. data/lib/badline/drives/model1581/serial_port.rb +54 -0
  230. data/lib/badline/drives/model1581/slot.rb +61 -0
  231. data/lib/badline/drives/model1581/track.rb +102 -0
  232. data/lib/badline/drives/model1581/track_bytes.rb +77 -0
  233. data/lib/badline/drives/model1581/wd1772/registers.rb +91 -0
  234. data/lib/badline/drives/model1581/wd1772/sector_writes.rb +75 -0
  235. data/lib/badline/drives/model1581/wd1772/sectors.rb +152 -0
  236. data/lib/badline/drives/model1581/wd1772/stepping.rb +111 -0
  237. data/lib/badline/drives/model1581/wd1772/tracks.rb +127 -0
  238. data/lib/badline/drives/model1581/wd1772/turn.rb +75 -0
  239. data/lib/badline/drives/model1581/wd1772.rb +216 -0
  240. data/lib/badline/drives/model1581.rb +206 -0
  241. data/lib/badline/drives/serial_bus.rb +161 -0
  242. data/lib/badline/drives.rb +8 -0
  243. data/lib/badline/frontend/app.rb +3 -3
  244. data/lib/badline/frontend/boot.rb +4 -4
  245. data/lib/badline/frontend/controls.rb +19 -3
  246. data/lib/badline/frontend/drive_led.rb +44 -21
  247. data/lib/badline/frontend/machine_window.rb +3 -1
  248. data/lib/badline/frontend/menu/menu_dialogs.rb +2 -2
  249. data/lib/badline/frontend/player/filter_view.rb +1 -1
  250. data/lib/badline/frontend/player/player_controller.rb +2 -2
  251. data/lib/badline/frontend/player/player_screen.rb +1 -0
  252. data/lib/badline/frontend/player/theme.rb +7 -7
  253. data/lib/badline/frontend/snapshots.rb +12 -1
  254. data/lib/badline/frontend/timeline.rb +30 -12
  255. data/lib/badline/input/control_ports.rb +78 -0
  256. data/lib/badline/input/joystick.rb +27 -0
  257. data/lib/badline/input/keyboard.rb +114 -0
  258. data/lib/badline/input/matrix_typist.rb +98 -0
  259. data/lib/badline/input.rb +4 -0
  260. data/lib/badline/kernal_trap/chrout.rb +45 -0
  261. data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
  262. data/lib/badline/kernal_trap/dos/channel.rb +156 -0
  263. data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -26
  264. data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -10
  265. data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
  266. data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -9
  267. data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -19
  268. data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
  269. data/lib/badline/kernal_trap/{drive.rb → dos.rb} +9 -27
  270. data/lib/badline/kernal_trap/file_routine.rb +4 -4
  271. data/lib/badline/kernal_trap/keyed_state.rb +150 -0
  272. data/lib/badline/kernal_trap/layout.rb +75 -11
  273. data/lib/badline/kernal_trap/load.rb +19 -21
  274. data/lib/badline/kernal_trap/routine.rb +12 -0
  275. data/lib/badline/kernal_trap/save.rb +12 -22
  276. data/lib/badline/kernal_trap/serial.rb +8 -24
  277. data/lib/badline/kernal_trap.rb +3 -2
  278. data/lib/badline/machine/clocking.rb +1 -1
  279. data/lib/badline/machine/keyboard_buffer.rb +49 -0
  280. data/lib/badline/machine/settling.rb +29 -0
  281. data/lib/badline/machine.rb +10 -7
  282. data/lib/badline/media/boot_disk.rb +14 -2
  283. data/lib/badline/media/extensions.rb +10 -0
  284. data/lib/badline/media/true_drive.rb +1 -1
  285. data/lib/badline/media/tune.rb +2 -2
  286. data/lib/badline/media.rb +3 -3
  287. data/lib/badline/memory.rb +3 -6
  288. data/lib/badline/model.rb +1 -1
  289. data/lib/badline/options/family.rb +5 -2
  290. data/lib/badline/options/help.rb +42 -16
  291. data/lib/badline/options/table.rb +2 -0
  292. data/lib/badline/options/validation.rb +2 -0
  293. data/lib/badline/options.rb +6 -1
  294. data/lib/badline/plus4/acia.rb +45 -0
  295. data/lib/badline/plus4/bus.rb +312 -0
  296. data/lib/badline/plus4/cpu.rb +10 -0
  297. data/lib/badline/plus4/cpu_port.rb +93 -0
  298. data/lib/badline/plus4/keyboard_port.rb +51 -0
  299. data/lib/badline/plus4/model.rb +38 -0
  300. data/lib/badline/plus4/user_port.rb +31 -0
  301. data/lib/badline/plus4.rb +164 -0
  302. data/lib/badline/roms/README +44 -6
  303. data/lib/badline/roms/plus4/basic.rom +0 -0
  304. data/lib/badline/roms/plus4/function-high.rom +0 -0
  305. data/lib/badline/roms/plus4/function-low.rom +0 -0
  306. data/lib/badline/roms/plus4/kernal-ntsc.rom +0 -0
  307. data/lib/badline/roms/plus4/kernal-pal.rom +0 -0
  308. data/lib/badline/sdl.rb +1 -0
  309. data/lib/badline/{storage/sid_file.rb → sid_tune/file.rb} +3 -3
  310. data/lib/badline/{storage → sid_tune}/hvsc.rb +7 -7
  311. data/lib/badline/{storage → sid_tune}/song_lengths.rb +2 -2
  312. data/lib/badline/{storage → sid_tune}/stil/credit.rb +1 -1
  313. data/lib/badline/{storage → sid_tune}/stil.rb +3 -3
  314. data/lib/badline/sid_tune.rb +6 -0
  315. data/lib/badline/snapshot/c128_setup.rb +32 -0
  316. data/lib/badline/snapshot/c64_setup.rb +83 -0
  317. data/lib/badline/snapshot/container.rb +4 -0
  318. data/lib/badline/snapshot/field_doc/markdown.rb +112 -0
  319. data/lib/badline/snapshot/field_doc.rb +109 -0
  320. data/lib/badline/snapshot/image.rb +132 -46
  321. data/lib/badline/snapshot/keyed/cursor.rb +40 -0
  322. data/lib/badline/snapshot/keyed/modules.rb +66 -0
  323. data/lib/badline/snapshot/keyed/reader.rb +188 -0
  324. data/lib/badline/snapshot/keyed/recorder.rb +88 -0
  325. data/lib/badline/snapshot/keyed/report.rb +26 -0
  326. data/lib/badline/snapshot/keyed/writer.rb +55 -0
  327. data/lib/badline/snapshot/keyed.rb +64 -0
  328. data/lib/badline/snapshot/machine_state.rb +17 -64
  329. data/lib/badline/snapshot/storage_setup.rb +63 -0
  330. data/lib/badline/snapshot/vic20_setup.rb +28 -0
  331. data/lib/badline/snapshot/vice/c64_mem.rb +1 -1
  332. data/lib/badline/snapshot/vice/restore.rb +1 -1
  333. data/lib/badline/snapshot/vice/reu1764.rb +3 -3
  334. data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
  335. data/lib/badline/snapshot/vice.rb +13 -35
  336. data/lib/badline/snapshot.rb +44 -22
  337. data/lib/badline/storage/crt_file.rb +3 -1
  338. data/lib/badline/storage/d64_image.rb +0 -2
  339. data/lib/badline/storage/d71_image.rb +0 -2
  340. data/lib/badline/storage/d81_image.rb +0 -2
  341. data/lib/badline/storage/disk_image.rb +3 -6
  342. data/lib/badline/storage/g64_image.rb +10 -5
  343. data/lib/badline/storage/host_directory.rb +0 -5
  344. data/lib/badline/storage/t64.rb +2 -8
  345. data/lib/badline/storage/tap.rb +43 -15
  346. data/lib/badline/storage/unavailable.rb +1 -1
  347. data/lib/badline/storage.rb +0 -37
  348. data/lib/badline/support/c128_checkpoint.rb +39 -0
  349. data/lib/badline/support/checkpoint.rb +108 -0
  350. data/lib/badline/support/vic20_checkpoint.rb +38 -0
  351. data/lib/badline/support.rb +5 -0
  352. data/lib/badline/version.rb +1 -1
  353. data/lib/badline/vic20/attachments.rb +8 -5
  354. data/lib/badline/vic20/bus/keyed_state.rb +52 -0
  355. data/lib/badline/vic20/bus.rb +2 -25
  356. data/lib/badline/vic20/cpu.rb +1 -1
  357. data/lib/badline/vic20/keyed_modules.rb +73 -0
  358. data/lib/badline/vic20/keyed_state.rb +45 -0
  359. data/lib/badline/vic20/port_wiring.rb +4 -4
  360. data/lib/badline/vic20/user_via_ports.rb +2 -2
  361. data/lib/badline/vic20.rb +22 -17
  362. data/lib/badline.rb +1 -0
  363. metadata +271 -228
  364. data/lib/badline/address_bus/extra_sids.rb +0 -30
  365. data/lib/badline/address_bus/fittings.rb +0 -38
  366. data/lib/badline/address_bus/pla.rb +0 -147
  367. data/lib/badline/address_bus/roms.rb +0 -39
  368. data/lib/badline/address_bus/saved_state.rb +0 -66
  369. data/lib/badline/address_bus/sid_slots.rb +0 -42
  370. data/lib/badline/address_bus.rb +0 -216
  371. data/lib/badline/c128/bus_state.rb +0 -53
  372. data/lib/badline/c128/saved_state.rb +0 -143
  373. data/lib/badline/cartridge/action_replay.rb +0 -126
  374. data/lib/badline/cartridge/atomic_power.rb +0 -24
  375. data/lib/badline/cartridge/bank.rb +0 -81
  376. data/lib/badline/cartridge/comal80.rb +0 -50
  377. data/lib/badline/cartridge/dinamic.rb +0 -34
  378. data/lib/badline/cartridge/easy_flash.rb +0 -145
  379. data/lib/badline/cartridge/epyx_fastload.rb +0 -79
  380. data/lib/badline/cartridge/final_cartridge3.rb +0 -89
  381. data/lib/badline/cartridge/flash.rb +0 -306
  382. data/lib/badline/cartridge/freezer.rb +0 -33
  383. data/lib/badline/cartridge/fun_play.rb +0 -38
  384. data/lib/badline/cartridge/g_mod2.rb +0 -74
  385. data/lib/badline/cartridge/game_system.rb +0 -40
  386. data/lib/badline/cartridge/geo_ram.rb +0 -79
  387. data/lib/badline/cartridge/kcs_power.rb +0 -75
  388. data/lib/badline/cartridge/mach5.rb +0 -32
  389. data/lib/badline/cartridge/magic_desk.rb +0 -30
  390. data/lib/badline/cartridge/ocean.rb +0 -35
  391. data/lib/badline/cartridge/pagefox.rb +0 -68
  392. data/lib/badline/cartridge/retro_replay.rb +0 -320
  393. data/lib/badline/cartridge/rex_utility.rb +0 -29
  394. data/lib/badline/cartridge/rgcd.rb +0 -58
  395. data/lib/badline/cartridge/simons_basic.rb +0 -35
  396. data/lib/badline/cartridge/standard.rb +0 -15
  397. data/lib/badline/cartridge/super_games.rb +0 -48
  398. data/lib/badline/cartridge/westermann.rb +0 -30
  399. data/lib/badline/cartridge/zaxxon.rb +0 -66
  400. data/lib/badline/cartridge.rb +0 -303
  401. data/lib/badline/checkpoint.rb +0 -98
  402. data/lib/badline/chrout_trap.rb +0 -43
  403. data/lib/badline/cia/fast_forward.rb +0 -60
  404. data/lib/badline/cia/interrupt_register.rb +0 -143
  405. data/lib/badline/cia/serial.rb +0 -275
  406. data/lib/badline/cia/state.rb +0 -47
  407. data/lib/badline/cia/timer.rb +0 -206
  408. data/lib/badline/cia.rb +0 -279
  409. data/lib/badline/color_memory.rb +0 -25
  410. data/lib/badline/computer/attachments.rb +0 -88
  411. data/lib/badline/computer/saved_state.rb +0 -117
  412. data/lib/badline/computer/true_drives.rb +0 -69
  413. data/lib/badline/control_ports.rb +0 -76
  414. data/lib/badline/cpu/addressing.rb +0 -131
  415. data/lib/badline/cpu/boundary.rb +0 -54
  416. data/lib/badline/cpu/core.rb +0 -165
  417. data/lib/badline/cpu/microcode.rb +0 -177
  418. data/lib/badline/cpu/operations.rb +0 -88
  419. data/lib/badline/cpu/saved_state.rb +0 -115
  420. data/lib/badline/cpu/stack_operations.rb +0 -82
  421. data/lib/badline/cpu.rb +0 -10
  422. data/lib/badline/cpu_port.rb +0 -112
  423. data/lib/badline/datasette.rb +0 -161
  424. data/lib/badline/debug_register.rb +0 -28
  425. data/lib/badline/drive/core.rb +0 -147
  426. data/lib/badline/drive/fast_serial.rb +0 -73
  427. data/lib/badline/drive/idle.rb +0 -125
  428. data/lib/badline/drive/idle_cpu.rb +0 -28
  429. data/lib/badline/drive/orbit.rb +0 -79
  430. data/lib/badline/drive/serial_lines.rb +0 -73
  431. data/lib/badline/drive/sleep.rb +0 -112
  432. data/lib/badline/drive/vias.rb +0 -84
  433. data/lib/badline/drive/watch.rb +0 -150
  434. data/lib/badline/drive.rb +0 -11
  435. data/lib/badline/drive1541/bus.rb +0 -86
  436. data/lib/badline/drive1541/byte_ready.rb +0 -48
  437. data/lib/badline/drive1541/cpu.rb +0 -11
  438. data/lib/badline/drive1541/disk.rb +0 -315
  439. data/lib/badline/drive1541/disk_state.rb +0 -86
  440. data/lib/badline/drive1541/disk_via.rb +0 -36
  441. data/lib/badline/drive1541/gcr.rb +0 -57
  442. data/lib/badline/drive1541/mechanism.rb +0 -313
  443. data/lib/badline/drive1541/mechanism_state.rb +0 -68
  444. data/lib/badline/drive1541/rotation.rb +0 -121
  445. data/lib/badline/drive1541/sector_reader.rb +0 -76
  446. data/lib/badline/drive1541/serial_port.rb +0 -18
  447. data/lib/badline/drive1541/track.rb +0 -98
  448. data/lib/badline/drive1541.rb +0 -111
  449. data/lib/badline/drive1571/bus.rb +0 -111
  450. data/lib/badline/drive1571/cpu.rb +0 -11
  451. data/lib/badline/drive1571/serial_port.rb +0 -37
  452. data/lib/badline/drive1571/serial_via.rb +0 -25
  453. data/lib/badline/drive1571/wd1770.rb +0 -120
  454. data/lib/badline/drive1571.rb +0 -175
  455. data/lib/badline/drive1581/bus.rb +0 -137
  456. data/lib/badline/drive1581/cpu.rb +0 -11
  457. data/lib/badline/drive1581/disk.rb +0 -135
  458. data/lib/badline/drive1581/disk_state.rb +0 -87
  459. data/lib/badline/drive1581/mechanism.rb +0 -117
  460. data/lib/badline/drive1581/serial_port.rb +0 -52
  461. data/lib/badline/drive1581/slot.rb +0 -78
  462. data/lib/badline/drive1581/track.rb +0 -100
  463. data/lib/badline/drive1581/track_bytes.rb +0 -75
  464. data/lib/badline/drive1581/wd1772/registers.rb +0 -89
  465. data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
  466. data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
  467. data/lib/badline/drive1581/wd1772/state.rb +0 -66
  468. data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
  469. data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
  470. data/lib/badline/drive1581/wd1772/turn.rb +0 -73
  471. data/lib/badline/drive1581/wd1772.rb +0 -216
  472. data/lib/badline/drive1581.rb +0 -233
  473. data/lib/badline/iec_bus.rb +0 -159
  474. data/lib/badline/instruction.rb +0 -334
  475. data/lib/badline/instruction_set/arithmetic.rb +0 -114
  476. data/lib/badline/instruction_set/bitwise.rb +0 -126
  477. data/lib/badline/instruction_set/branch.rb +0 -79
  478. data/lib/badline/instruction_set/flag.rb +0 -63
  479. data/lib/badline/instruction_set/illegal.rb +0 -270
  480. data/lib/badline/instruction_set/inc_dec.rb +0 -69
  481. data/lib/badline/instruction_set/stack.rb +0 -52
  482. data/lib/badline/instruction_set/transfer.rb +0 -137
  483. data/lib/badline/instruction_set.rb +0 -55
  484. data/lib/badline/interrupts.rb +0 -104
  485. data/lib/badline/joystick.rb +0 -25
  486. data/lib/badline/kernal_trap/channel.rb +0 -181
  487. data/lib/badline/keyboard.rb +0 -112
  488. data/lib/badline/keyboard_buffer.rb +0 -33
  489. data/lib/badline/ram_expansion/banking.rb +0 -30
  490. data/lib/badline/ram_expansion/plus256k.rb +0 -54
  491. data/lib/badline/ram_expansion/plus60k.rb +0 -43
  492. data/lib/badline/ram_expansion/unexpanded.rb +0 -28
  493. data/lib/badline/ram_expansion.rb +0 -21
  494. data/lib/badline/reu/dma/saved_state.rb +0 -50
  495. data/lib/badline/reu/dma.rb +0 -273
  496. data/lib/badline/reu/ram.rb +0 -107
  497. data/lib/badline/reu/saved_state.rb +0 -80
  498. data/lib/badline/reu/trigger.rb +0 -32
  499. data/lib/badline/reu.rb +0 -289
  500. data/lib/badline/sid/catch_up.rb +0 -120
  501. data/lib/badline/sid/decimator.rb +0 -64
  502. data/lib/badline/sid/envelope/state.rb +0 -68
  503. data/lib/badline/sid/envelope.rb +0 -239
  504. data/lib/badline/sid/filter.rb +0 -263
  505. data/lib/badline/sid/voice.rb +0 -77
  506. data/lib/badline/sid/waveform/combined.rb +0 -126
  507. data/lib/badline/sid/waveform/fast_forward.rb +0 -105
  508. data/lib/badline/sid/waveform/noise_writeback.rb +0 -122
  509. data/lib/badline/sid/waveform/state.rb +0 -66
  510. data/lib/badline/sid/waveform.rb +0 -305
  511. data/lib/badline/sid.rb +0 -303
  512. data/lib/badline/snapshot/setup.rb +0 -75
  513. data/lib/badline/snapshot/state.rb +0 -189
  514. data/lib/badline/time_of_day.rb +0 -228
  515. data/lib/badline/traps.rb +0 -19
  516. data/lib/badline/via/control_lines.rb +0 -122
  517. data/lib/badline/via/fast_forward.rb +0 -53
  518. data/lib/badline/via/interrupt_register.rb +0 -67
  519. data/lib/badline/via/shift_register.rb +0 -180
  520. data/lib/badline/via/state.rb +0 -42
  521. data/lib/badline/via/timer1.rb +0 -131
  522. data/lib/badline/via/timer2.rb +0 -133
  523. data/lib/badline/via.rb +0 -266
  524. data/lib/badline/vic/bank.rb +0 -133
  525. data/lib/badline/vic/border_mask.rb +0 -86
  526. data/lib/badline/vic/collisions.rb +0 -115
  527. data/lib/badline/vic/color_patches.rb +0 -47
  528. data/lib/badline/vic/display_state.rb +0 -185
  529. data/lib/badline/vic/graphics_mode.rb +0 -164
  530. data/lib/badline/vic/graphics_shifter.rb +0 -207
  531. data/lib/badline/vic/register_log.rb +0 -81
  532. data/lib/badline/vic/registers.rb +0 -195
  533. data/lib/badline/vic/sequencer.rb +0 -275
  534. data/lib/badline/vic/sequencer_output.rb +0 -116
  535. data/lib/badline/vic/sequencer_state.rb +0 -89
  536. data/lib/badline/vic/sprite/internal_bus.rb +0 -68
  537. data/lib/badline/vic/sprite/saved_state.rb +0 -64
  538. data/lib/badline/vic/sprite/shifter.rb +0 -146
  539. data/lib/badline/vic/sprite/timing.rb +0 -56
  540. data/lib/badline/vic/sprite.rb +0 -337
  541. data/lib/badline/vic/sprites.rb +0 -282
  542. data/lib/badline/vic/sprites_state.rb +0 -57
  543. data/lib/badline/vic.rb +0 -853
  544. data/lib/badline/vic20/saved_state.rb +0 -124
  545. data/lib/badline/vic20/sound/output.rb +0 -83
  546. data/lib/badline/vic20/sound.rb +0 -233
  547. data/lib/badline/vic20/vic/saved_state.rb +0 -55
  548. data/lib/badline/z80/arithmetic.rb +0 -117
  549. data/lib/badline/z80/bit_page.rb +0 -55
  550. data/lib/badline/z80/block_io.rb +0 -58
  551. data/lib/badline/z80/block_transfers.rb +0 -59
  552. data/lib/badline/z80/bus_cycles.rb +0 -111
  553. data/lib/badline/z80/core.rb +0 -113
  554. data/lib/badline/z80/exchanges.rb +0 -50
  555. data/lib/badline/z80/extended_page.rb +0 -89
  556. data/lib/badline/z80/flags.rb +0 -37
  557. data/lib/badline/z80/interrupt_acceptance.rb +0 -46
  558. data/lib/badline/z80/jumps.rb +0 -82
  559. data/lib/badline/z80/loads.rb +0 -98
  560. data/lib/badline/z80/main_page.rb +0 -134
  561. data/lib/badline/z80/registers.rb +0 -120
  562. data/lib/badline/z80/saved_state.rb +0 -69
  563. data/lib/badline/z80/shifts.rb +0 -64
  564. data/lib/badline/z80.rb +0 -11
  565. /data/lib/badline/snapshot/{fields.rb → vice/fields.rb} +0 -0
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Drives
5
+ module Engine
6
+ # What VIA 1's port B reads from the serial bus. DATA IN (PB0), CLK IN
7
+ # (PB2) and ATN IN (PB7) come through inverters, so a released line
8
+ # reads 0 and a pulled one 1. The jumpers on PB5 and PB6 pull a line
9
+ # low when closed, and both closed make device 8.
10
+ #
11
+ # The drive sees the host's side of the bus a host cycle late. The
12
+ # host's CIA changes its pins at the end of the cycle that writes them,
13
+ # and the drive's VIA samples its own late in each of its cycles, so a
14
+ # drive cycle that runs alongside the write reads the lines from
15
+ # before it. The drive runs after the host in each host cycle (see
16
+ # C64#cycle!), so the port reads the host's lines as latch_host
17
+ # took them at the end of the last one. Fast loaders that time their
18
+ # transfer from an ATN edge, as VICE's drive tests do, depend on it.
19
+ #
20
+ # A model's serial port includes it, with its own port A.
21
+ module SerialLines
22
+ DATA_IN = 0x01
23
+ CLK_IN = 0x04
24
+ ATN_IN = 0x80
25
+ SERIAL_INPUTS = DATA_IN | CLK_IN | ATN_IN
26
+ JUMPERS = 0b0110_0000
27
+
28
+ attr_reader :bus
29
+
30
+ def bus=(bus)
31
+ @bus = bus
32
+ latch_host
33
+ end
34
+
35
+ # Takes the host's lines as the machine last pushed them into the bus,
36
+ # for the drive cycles of the next host cycle.
37
+ def latch_host
38
+ @host = @bus.host_lines
39
+ end
40
+
41
+ # The host's lines as the port latched them, under `prefix`.
42
+ def save_fields(out, prefix) = out.int("#{prefix}host", @host)
43
+
44
+ def load_fields(input, prefix)
45
+ @host = input.int("#{prefix}host", @host)
46
+ end
47
+
48
+ # Whether the host has moved ATN since the last latch_host.
49
+ def atn_moved? = (@bus.host_lines ^ @host).anybits?(SerialBus::HOST_ATN_OUT)
50
+
51
+ def atn_low? = @bus.atn_low?(@host)
52
+
53
+ def read_b(_lines)
54
+ low = @bus.low_lines(@host)
55
+ value = @port_b
56
+ value |= DATA_IN if low.anybits?(SerialBus::DATA)
57
+ value |= CLK_IN if low.anybits?(SerialBus::CLK)
58
+ value |= ATN_IN if low.anybits?(SerialBus::ATN)
59
+ value
60
+ end
61
+
62
+ private
63
+
64
+ def init_serial_lines(device, bus)
65
+ @port_b = (0xff & ~(SERIAL_INPUTS | JUMPERS)) | (((device - 8) & 0x03) << 5)
66
+ @host = 0
67
+ self.bus = bus
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -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,75 @@
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
+ def peek(addr)
42
+ return @data = @rom.peek(addr | 0x4000) if addr >= 0x8000
43
+
44
+ addr &= 0x1fff
45
+ watch_read(addr) if @watching
46
+ @data = if addr < 0x0800
47
+ @ram.peek(addr)
48
+ elsif addr < 0x1800
49
+ @data
50
+ elsif addr < 0x1c00
51
+ @via1.peek(addr)
52
+ else
53
+ @via2.peek(addr)
54
+ end
55
+ end
56
+
57
+ def poke(addr, value)
58
+ @data = value
59
+ return if addr >= 0x8000
60
+
61
+ addr &= 0x1fff
62
+ if addr < 0x0800
63
+ touch(addr) if @recording
64
+ @ram.poke(addr, value)
65
+ elsif addr >= 0x1c00
66
+ @via2.poke(addr, value)
67
+ elsif addr >= 0x1800
68
+ @via1.poke(addr, value)
69
+ end
70
+ watch_write(addr) if @watching
71
+ end
72
+ end
73
+ end
74
+ end
75
+ 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