badline 0.12.1 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (505) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -0
  3. data/CLAUDE.md +59 -31
  4. data/README.md +1 -1
  5. data/doc/library.md +9 -9
  6. data/doc/pinned-behaviour.md +105 -105
  7. data/doc/snapshots.md +1 -4
  8. data/lib/badline/audio/bare_player.rb +3 -3
  9. data/lib/badline/audio/cli.rb +6 -6
  10. data/lib/badline/audio/jukebox.rb +2 -2
  11. data/lib/badline/audio/machine_player.rb +2 -2
  12. data/lib/badline/{media → audio}/queue.rb +1 -1
  13. data/lib/badline/audio/queued_tune.rb +6 -6
  14. data/lib/badline/audio/renderer.rb +5 -5
  15. data/lib/badline/audio/stereo.rb +1 -1
  16. data/lib/badline/c128/{bus_state.rb → bus/saved_state.rb} +1 -1
  17. data/lib/badline/c128/bus.rb +18 -17
  18. data/lib/badline/c128/color_lines.rb +2 -2
  19. data/lib/badline/c128/cpu.rb +1 -1
  20. data/lib/badline/c128/drives.rb +10 -11
  21. data/lib/badline/c128/fast_serial.rb +5 -5
  22. data/lib/badline/c128/mmu_pages.rb +1 -1
  23. data/lib/badline/c128/modes.rb +2 -2
  24. data/lib/badline/c128/saved_state.rb +21 -47
  25. data/lib/badline/c128/z80.rb +2 -2
  26. data/lib/badline/c128.rb +14 -9
  27. data/lib/badline/{computer → c64}/attachments.rb +4 -6
  28. data/lib/badline/c64/banked_ram/banking.rb +32 -0
  29. data/lib/badline/c64/banked_ram/plus256k.rb +56 -0
  30. data/lib/badline/c64/banked_ram/plus60k.rb +45 -0
  31. data/lib/badline/c64/banked_ram/unexpanded.rb +30 -0
  32. data/lib/badline/c64/banked_ram.rb +23 -0
  33. data/lib/badline/c64/bus/extra_sids.rb +32 -0
  34. data/lib/badline/c64/bus/fittings.rb +40 -0
  35. data/lib/badline/c64/bus/pla.rb +149 -0
  36. data/lib/badline/c64/bus/roms.rb +41 -0
  37. data/lib/badline/c64/bus/saved_state.rb +68 -0
  38. data/lib/badline/c64/bus/sid_slots.rb +44 -0
  39. data/lib/badline/c64/bus.rb +218 -0
  40. data/lib/badline/c64/cartridge/action_replay.rb +128 -0
  41. data/lib/badline/c64/cartridge/atomic_power.rb +26 -0
  42. data/lib/badline/c64/cartridge/bank.rb +83 -0
  43. data/lib/badline/c64/cartridge/comal80.rb +52 -0
  44. data/lib/badline/c64/cartridge/dinamic.rb +36 -0
  45. data/lib/badline/c64/cartridge/easy_flash.rb +147 -0
  46. data/lib/badline/c64/cartridge/epyx_fastload.rb +81 -0
  47. data/lib/badline/c64/cartridge/final_cartridge3.rb +91 -0
  48. data/lib/badline/c64/cartridge/flash/saved_state.rb +40 -0
  49. data/lib/badline/c64/cartridge/flash.rb +279 -0
  50. data/lib/badline/c64/cartridge/freezer.rb +35 -0
  51. data/lib/badline/c64/cartridge/fun_play.rb +40 -0
  52. data/lib/badline/c64/cartridge/g_mod2.rb +76 -0
  53. data/lib/badline/c64/cartridge/game_system.rb +42 -0
  54. data/lib/badline/c64/cartridge/geo_ram.rb +81 -0
  55. data/lib/badline/c64/cartridge/kcs_power.rb +77 -0
  56. data/lib/badline/c64/cartridge/mach5.rb +34 -0
  57. data/lib/badline/c64/cartridge/magic_desk.rb +32 -0
  58. data/lib/badline/c64/cartridge/ocean.rb +37 -0
  59. data/lib/badline/c64/cartridge/pagefox.rb +70 -0
  60. data/lib/badline/c64/cartridge/retro_replay/saved_state.rb +47 -0
  61. data/lib/badline/c64/cartridge/retro_replay.rb +286 -0
  62. data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
  63. data/lib/badline/c64/cartridge/rgcd.rb +60 -0
  64. data/lib/badline/c64/cartridge/saved_state.rb +63 -0
  65. data/lib/badline/c64/cartridge/simons_basic.rb +37 -0
  66. data/lib/badline/c64/cartridge/standard.rb +17 -0
  67. data/lib/badline/c64/cartridge/super_games.rb +50 -0
  68. data/lib/badline/c64/cartridge/westermann.rb +32 -0
  69. data/lib/badline/c64/cartridge/zaxxon.rb +68 -0
  70. data/lib/badline/c64/cartridge.rb +258 -0
  71. data/lib/badline/c64/color_memory.rb +27 -0
  72. data/lib/badline/{computer → c64}/common.rb +2 -2
  73. data/lib/badline/{computer → c64}/kernal_traps.rb +18 -18
  74. data/lib/badline/c64/reu/dma/saved_state.rb +52 -0
  75. data/lib/badline/c64/reu/dma.rb +275 -0
  76. data/lib/badline/c64/reu/ram.rb +109 -0
  77. data/lib/badline/c64/reu/saved_state.rb +55 -0
  78. data/lib/badline/c64/reu/trigger.rb +34 -0
  79. data/lib/badline/c64/reu.rb +291 -0
  80. data/lib/badline/{computer → c64}/saved_state.rb +13 -18
  81. data/lib/badline/{computer → c64}/true_drives.rb +11 -11
  82. data/lib/badline/{computer.rb → c64.rb} +18 -13
  83. data/lib/badline/chips/cia/fast_forward.rb +62 -0
  84. data/lib/badline/chips/cia/interrupt_register.rb +145 -0
  85. data/lib/badline/chips/cia/saved_state.rb +49 -0
  86. data/lib/badline/chips/cia/serial/saved_state.rb +45 -0
  87. data/lib/badline/chips/cia/serial.rb +250 -0
  88. data/lib/badline/chips/cia/time_of_day.rb +232 -0
  89. data/lib/badline/chips/cia/timer.rb +208 -0
  90. data/lib/badline/chips/cia.rb +281 -0
  91. data/lib/badline/chips/cpu/addressing.rb +133 -0
  92. data/lib/badline/chips/cpu/boundary.rb +56 -0
  93. data/lib/badline/chips/cpu/core.rb +167 -0
  94. data/lib/badline/chips/cpu/instruction.rb +338 -0
  95. data/lib/badline/chips/cpu/instruction_set/arithmetic.rb +118 -0
  96. data/lib/badline/chips/cpu/instruction_set/bitwise.rb +130 -0
  97. data/lib/badline/chips/cpu/instruction_set/branch.rb +83 -0
  98. data/lib/badline/chips/cpu/instruction_set/flag.rb +67 -0
  99. data/lib/badline/chips/cpu/instruction_set/illegal.rb +274 -0
  100. data/lib/badline/chips/cpu/instruction_set/inc_dec.rb +73 -0
  101. data/lib/badline/chips/cpu/instruction_set/stack.rb +56 -0
  102. data/lib/badline/chips/cpu/instruction_set/transfer.rb +141 -0
  103. data/lib/badline/chips/cpu/instruction_set.rb +59 -0
  104. data/lib/badline/chips/cpu/interrupts.rb +108 -0
  105. data/lib/badline/chips/cpu/microcode.rb +179 -0
  106. data/lib/badline/chips/cpu/operations.rb +90 -0
  107. data/lib/badline/chips/cpu/port.rb +116 -0
  108. data/lib/badline/chips/cpu/saved_state.rb +117 -0
  109. data/lib/badline/chips/cpu/stack_operations.rb +84 -0
  110. data/lib/badline/chips/cpu/traps.rb +23 -0
  111. data/lib/badline/chips/cpu.rb +12 -0
  112. data/lib/badline/chips/sid/catch_up.rb +122 -0
  113. data/lib/badline/chips/sid/decimator.rb +66 -0
  114. data/lib/badline/chips/sid/envelope/saved_state.rb +70 -0
  115. data/lib/badline/chips/sid/envelope.rb +241 -0
  116. data/lib/badline/chips/sid/filter/saved_state.rb +42 -0
  117. data/lib/badline/chips/sid/filter.rb +241 -0
  118. data/lib/badline/chips/sid/saved_state.rb +52 -0
  119. data/lib/badline/chips/sid/voice.rb +79 -0
  120. data/lib/badline/chips/sid/waveform/combined.rb +128 -0
  121. data/lib/badline/chips/sid/waveform/fast_forward.rb +107 -0
  122. data/lib/badline/chips/sid/waveform/noise_writeback.rb +124 -0
  123. data/lib/badline/chips/sid/waveform/saved_state.rb +68 -0
  124. data/lib/badline/chips/sid/waveform.rb +307 -0
  125. data/lib/badline/chips/sid.rb +265 -0
  126. data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
  127. data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -1
  128. data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -1
  129. data/lib/badline/chips/vdc/saved_state.rb +36 -0
  130. data/lib/badline/{c128 → chips}/vdc/window.rb +1 -1
  131. data/lib/badline/{c128 → chips}/vdc.rb +7 -31
  132. data/lib/badline/chips/via/control_lines.rb +124 -0
  133. data/lib/badline/chips/via/fast_forward.rb +55 -0
  134. data/lib/badline/chips/via/interrupt_register.rb +69 -0
  135. data/lib/badline/chips/via/saved_state.rb +44 -0
  136. data/lib/badline/chips/via/shift_register.rb +182 -0
  137. data/lib/badline/chips/via/timer1.rb +133 -0
  138. data/lib/badline/chips/via/timer2.rb +135 -0
  139. data/lib/badline/chips/via.rb +268 -0
  140. data/lib/badline/chips/vic/bank.rb +135 -0
  141. data/lib/badline/chips/vic/border_mask.rb +88 -0
  142. data/lib/badline/chips/vic/collisions.rb +117 -0
  143. data/lib/badline/chips/vic/color_patches.rb +49 -0
  144. data/lib/badline/chips/vic/display_state.rb +187 -0
  145. data/lib/badline/chips/vic/graphics_mode.rb +166 -0
  146. data/lib/badline/chips/vic/graphics_shifter/saved_state.rb +40 -0
  147. data/lib/badline/chips/vic/graphics_shifter.rb +187 -0
  148. data/lib/badline/chips/vic/register_log.rb +83 -0
  149. data/lib/badline/chips/vic/registers.rb +197 -0
  150. data/lib/badline/chips/vic/saved_state.rb +82 -0
  151. data/lib/badline/chips/vic/sequencer/saved_state.rb +91 -0
  152. data/lib/badline/chips/vic/sequencer.rb +277 -0
  153. data/lib/badline/chips/vic/sequencer_output.rb +118 -0
  154. data/lib/badline/chips/vic/sprite/internal_bus.rb +70 -0
  155. data/lib/badline/chips/vic/sprite/saved_state.rb +66 -0
  156. data/lib/badline/chips/vic/sprite/shifter.rb +148 -0
  157. data/lib/badline/chips/vic/sprite/timing.rb +58 -0
  158. data/lib/badline/chips/vic/sprite.rb +339 -0
  159. data/lib/badline/chips/vic/sprites/saved_state.rb +59 -0
  160. data/lib/badline/chips/vic/sprites.rb +284 -0
  161. data/lib/badline/chips/vic.rb +783 -0
  162. data/lib/badline/chips/vic_i/painter/saved_state.rb +40 -0
  163. data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +6 -30
  164. data/lib/badline/{vic20/vic → chips/vic_i}/saved_state.rb +2 -2
  165. data/lib/badline/chips/vic_i/sound/output.rb +85 -0
  166. data/lib/badline/chips/vic_i/sound.rb +235 -0
  167. data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
  168. data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +5 -5
  169. data/lib/badline/chips/z80/arithmetic.rb +119 -0
  170. data/lib/badline/chips/z80/bit_page.rb +57 -0
  171. data/lib/badline/chips/z80/block_io.rb +60 -0
  172. data/lib/badline/chips/z80/block_transfers.rb +61 -0
  173. data/lib/badline/chips/z80/bus_cycles.rb +113 -0
  174. data/lib/badline/chips/z80/core.rb +115 -0
  175. data/lib/badline/chips/z80/exchanges.rb +52 -0
  176. data/lib/badline/chips/z80/extended_page.rb +91 -0
  177. data/lib/badline/chips/z80/flags.rb +39 -0
  178. data/lib/badline/chips/z80/interrupt_acceptance.rb +48 -0
  179. data/lib/badline/chips/z80/jumps.rb +84 -0
  180. data/lib/badline/chips/z80/loads.rb +100 -0
  181. data/lib/badline/chips/z80/main_page.rb +136 -0
  182. data/lib/badline/chips/z80/registers.rb +122 -0
  183. data/lib/badline/chips/z80/saved_state.rb +71 -0
  184. data/lib/badline/chips/z80/shifts.rb +66 -0
  185. data/lib/badline/chips/z80.rb +13 -0
  186. data/lib/badline/core.rb +26 -28
  187. data/lib/badline/drives/datasette/saved_state.rb +37 -0
  188. data/lib/badline/drives/datasette.rb +140 -0
  189. data/lib/badline/drives/engine/core.rb +149 -0
  190. data/lib/badline/drives/engine/fast_serial.rb +75 -0
  191. data/lib/badline/drives/engine/idle.rb +127 -0
  192. data/lib/badline/drives/engine/idle_cpu.rb +30 -0
  193. data/lib/badline/drives/engine/orbit.rb +81 -0
  194. data/lib/badline/drives/engine/serial_lines.rb +75 -0
  195. data/lib/badline/drives/engine/sleep.rb +114 -0
  196. data/lib/badline/drives/engine/vias.rb +86 -0
  197. data/lib/badline/drives/engine/watch.rb +152 -0
  198. data/lib/badline/drives/engine.rb +11 -0
  199. data/lib/badline/drives/model1541/bus.rb +88 -0
  200. data/lib/badline/drives/model1541/byte_ready.rb +50 -0
  201. data/lib/badline/drives/model1541/cpu.rb +13 -0
  202. data/lib/badline/drives/model1541/disk/saved_state.rb +88 -0
  203. data/lib/badline/drives/model1541/disk.rb +317 -0
  204. data/lib/badline/drives/model1541/disk_via.rb +38 -0
  205. data/lib/badline/drives/model1541/gcr.rb +59 -0
  206. data/lib/badline/drives/model1541/mechanism/saved_state.rb +72 -0
  207. data/lib/badline/drives/model1541/mechanism.rb +315 -0
  208. data/lib/badline/drives/model1541/rotation.rb +123 -0
  209. data/lib/badline/drives/model1541/saved_state.rb +44 -0
  210. data/lib/badline/drives/model1541/sector_reader.rb +78 -0
  211. data/lib/badline/drives/model1541/serial_port.rb +20 -0
  212. data/lib/badline/drives/model1541/track.rb +100 -0
  213. data/lib/badline/drives/model1541.rb +81 -0
  214. data/lib/badline/drives/model1571/bus.rb +113 -0
  215. data/lib/badline/drives/model1571/cpu.rb +13 -0
  216. data/lib/badline/drives/model1571/saved_state.rb +47 -0
  217. data/lib/badline/drives/model1571/serial_port.rb +39 -0
  218. data/lib/badline/drives/model1571/serial_via.rb +27 -0
  219. data/lib/badline/drives/model1571/wd1770.rb +122 -0
  220. data/lib/badline/drives/model1571.rb +142 -0
  221. data/lib/badline/drives/model1581/bus.rb +139 -0
  222. data/lib/badline/drives/model1581/cpu.rb +13 -0
  223. data/lib/badline/drives/model1581/disk/saved_state.rb +89 -0
  224. data/lib/badline/drives/model1581/disk.rb +137 -0
  225. data/lib/badline/drives/model1581/mechanism.rb +119 -0
  226. data/lib/badline/drives/model1581/saved_state.rb +42 -0
  227. data/lib/badline/drives/model1581/serial_port.rb +54 -0
  228. data/lib/badline/drives/model1581/slot.rb +79 -0
  229. data/lib/badline/drives/model1581/track.rb +102 -0
  230. data/lib/badline/drives/model1581/track_bytes.rb +77 -0
  231. data/lib/badline/drives/model1581/wd1772/registers.rb +91 -0
  232. data/lib/badline/drives/model1581/wd1772/saved_state.rb +68 -0
  233. data/lib/badline/drives/model1581/wd1772/sector_writes.rb +75 -0
  234. data/lib/badline/drives/model1581/wd1772/sectors.rb +152 -0
  235. data/lib/badline/drives/model1581/wd1772/stepping.rb +111 -0
  236. data/lib/badline/drives/model1581/wd1772/tracks.rb +127 -0
  237. data/lib/badline/drives/model1581/wd1772/turn.rb +75 -0
  238. data/lib/badline/drives/model1581/wd1772.rb +218 -0
  239. data/lib/badline/drives/model1581.rb +206 -0
  240. data/lib/badline/drives/serial_bus.rb +161 -0
  241. data/lib/badline/frontend/boot.rb +3 -3
  242. data/lib/badline/frontend/machine_window.rb +3 -1
  243. data/lib/badline/frontend/player/filter_view.rb +1 -1
  244. data/lib/badline/frontend/player/player_controller.rb +2 -2
  245. data/lib/badline/frontend/player/player_screen.rb +1 -0
  246. data/lib/badline/frontend/player/theme.rb +7 -7
  247. data/lib/badline/frontend/timeline.rb +3 -3
  248. data/lib/badline/input/control_ports.rb +78 -0
  249. data/lib/badline/input/joystick.rb +27 -0
  250. data/lib/badline/input/keyboard.rb +114 -0
  251. data/lib/badline/input.rb +3 -0
  252. data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
  253. data/lib/badline/kernal_trap/dos/channel.rb +183 -0
  254. data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -1
  255. data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -1
  256. data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
  257. data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -1
  258. data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -1
  259. data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
  260. data/lib/badline/kernal_trap/{drive.rb → dos.rb} +11 -10
  261. data/lib/badline/kernal_trap/load.rb +5 -5
  262. data/lib/badline/kernal_trap/save.rb +4 -4
  263. data/lib/badline/kernal_trap/serial.rb +7 -7
  264. data/lib/badline/kernal_trap.rb +1 -2
  265. data/lib/badline/machine/clocking.rb +1 -1
  266. data/lib/badline/machine.rb +5 -5
  267. data/lib/badline/media/true_drive.rb +1 -1
  268. data/lib/badline/media/tune.rb +2 -2
  269. data/lib/badline/media.rb +3 -3
  270. data/lib/badline/model.rb +1 -1
  271. data/lib/badline/roms/README +6 -6
  272. data/lib/badline/sdl.rb +1 -0
  273. data/lib/badline/{storage/sid_file.rb → sid_tune/file.rb} +3 -3
  274. data/lib/badline/{storage → sid_tune}/hvsc.rb +7 -7
  275. data/lib/badline/{storage → sid_tune}/song_lengths.rb +2 -2
  276. data/lib/badline/{storage → sid_tune}/stil/credit.rb +1 -1
  277. data/lib/badline/{storage → sid_tune}/stil.rb +3 -3
  278. data/lib/badline/sid_tune.rb +6 -0
  279. data/lib/badline/snapshot/c128_setup.rb +43 -0
  280. data/lib/badline/snapshot/c64_setup.rb +79 -0
  281. data/lib/badline/snapshot/image.rb +5 -25
  282. data/lib/badline/snapshot/machine_state.rb +1 -1
  283. data/lib/badline/snapshot/setup.rb +22 -66
  284. data/lib/badline/snapshot/state.rb +8 -18
  285. data/lib/badline/snapshot/storage_setup.rb +68 -0
  286. data/lib/badline/snapshot/vic20_setup.rb +37 -0
  287. data/lib/badline/snapshot/vice/c64_mem.rb +1 -1
  288. data/lib/badline/snapshot/vice/restore.rb +1 -1
  289. data/lib/badline/snapshot/vice/reu1764.rb +1 -1
  290. data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
  291. data/lib/badline/snapshot/vice.rb +7 -5
  292. data/lib/badline/snapshot.rb +3 -4
  293. data/lib/badline/storage/d64_image.rb +0 -2
  294. data/lib/badline/storage/d71_image.rb +0 -2
  295. data/lib/badline/storage/d81_image.rb +0 -2
  296. data/lib/badline/storage/disk_image.rb +3 -6
  297. data/lib/badline/storage/g64_image.rb +2 -2
  298. data/lib/badline/storage/host_directory.rb +0 -5
  299. data/lib/badline/storage/t64.rb +2 -8
  300. data/lib/badline/storage/unavailable.rb +1 -1
  301. data/lib/badline/storage.rb +0 -37
  302. data/lib/badline/support/c128_checkpoint.rb +39 -0
  303. data/lib/badline/support/checkpoint.rb +108 -0
  304. data/lib/badline/support/vic20_checkpoint.rb +38 -0
  305. data/lib/badline/support.rb +5 -0
  306. data/lib/badline/version.rb +1 -1
  307. data/lib/badline/vic20/attachments.rb +5 -5
  308. data/lib/badline/vic20/bus/saved_state.rb +35 -0
  309. data/lib/badline/vic20/bus.rb +3 -25
  310. data/lib/badline/vic20/cpu.rb +1 -1
  311. data/lib/badline/vic20/port_wiring.rb +4 -4
  312. data/lib/badline/vic20/saved_state.rb +16 -30
  313. data/lib/badline/vic20/user_via_ports.rb +2 -2
  314. data/lib/badline/vic20.rb +19 -14
  315. metadata +245 -221
  316. data/lib/badline/address_bus/extra_sids.rb +0 -30
  317. data/lib/badline/address_bus/fittings.rb +0 -38
  318. data/lib/badline/address_bus/pla.rb +0 -147
  319. data/lib/badline/address_bus/roms.rb +0 -39
  320. data/lib/badline/address_bus/saved_state.rb +0 -66
  321. data/lib/badline/address_bus/sid_slots.rb +0 -42
  322. data/lib/badline/address_bus.rb +0 -216
  323. data/lib/badline/cartridge/action_replay.rb +0 -126
  324. data/lib/badline/cartridge/atomic_power.rb +0 -24
  325. data/lib/badline/cartridge/bank.rb +0 -81
  326. data/lib/badline/cartridge/comal80.rb +0 -50
  327. data/lib/badline/cartridge/dinamic.rb +0 -34
  328. data/lib/badline/cartridge/easy_flash.rb +0 -145
  329. data/lib/badline/cartridge/epyx_fastload.rb +0 -79
  330. data/lib/badline/cartridge/final_cartridge3.rb +0 -89
  331. data/lib/badline/cartridge/flash.rb +0 -306
  332. data/lib/badline/cartridge/freezer.rb +0 -33
  333. data/lib/badline/cartridge/fun_play.rb +0 -38
  334. data/lib/badline/cartridge/g_mod2.rb +0 -74
  335. data/lib/badline/cartridge/game_system.rb +0 -40
  336. data/lib/badline/cartridge/geo_ram.rb +0 -79
  337. data/lib/badline/cartridge/kcs_power.rb +0 -75
  338. data/lib/badline/cartridge/mach5.rb +0 -32
  339. data/lib/badline/cartridge/magic_desk.rb +0 -30
  340. data/lib/badline/cartridge/ocean.rb +0 -35
  341. data/lib/badline/cartridge/pagefox.rb +0 -68
  342. data/lib/badline/cartridge/retro_replay.rb +0 -320
  343. data/lib/badline/cartridge/rex_utility.rb +0 -29
  344. data/lib/badline/cartridge/rgcd.rb +0 -58
  345. data/lib/badline/cartridge/simons_basic.rb +0 -35
  346. data/lib/badline/cartridge/standard.rb +0 -15
  347. data/lib/badline/cartridge/super_games.rb +0 -48
  348. data/lib/badline/cartridge/westermann.rb +0 -30
  349. data/lib/badline/cartridge/zaxxon.rb +0 -66
  350. data/lib/badline/cartridge.rb +0 -303
  351. data/lib/badline/checkpoint.rb +0 -98
  352. data/lib/badline/cia/fast_forward.rb +0 -60
  353. data/lib/badline/cia/interrupt_register.rb +0 -143
  354. data/lib/badline/cia/serial.rb +0 -275
  355. data/lib/badline/cia/state.rb +0 -47
  356. data/lib/badline/cia/timer.rb +0 -206
  357. data/lib/badline/cia.rb +0 -279
  358. data/lib/badline/color_memory.rb +0 -25
  359. data/lib/badline/control_ports.rb +0 -76
  360. data/lib/badline/cpu/addressing.rb +0 -131
  361. data/lib/badline/cpu/boundary.rb +0 -54
  362. data/lib/badline/cpu/core.rb +0 -165
  363. data/lib/badline/cpu/microcode.rb +0 -177
  364. data/lib/badline/cpu/operations.rb +0 -88
  365. data/lib/badline/cpu/saved_state.rb +0 -115
  366. data/lib/badline/cpu/stack_operations.rb +0 -82
  367. data/lib/badline/cpu.rb +0 -10
  368. data/lib/badline/cpu_port.rb +0 -112
  369. data/lib/badline/datasette.rb +0 -161
  370. data/lib/badline/drive/core.rb +0 -147
  371. data/lib/badline/drive/fast_serial.rb +0 -73
  372. data/lib/badline/drive/idle.rb +0 -125
  373. data/lib/badline/drive/idle_cpu.rb +0 -28
  374. data/lib/badline/drive/orbit.rb +0 -79
  375. data/lib/badline/drive/serial_lines.rb +0 -73
  376. data/lib/badline/drive/sleep.rb +0 -112
  377. data/lib/badline/drive/vias.rb +0 -84
  378. data/lib/badline/drive/watch.rb +0 -150
  379. data/lib/badline/drive.rb +0 -11
  380. data/lib/badline/drive1541/bus.rb +0 -86
  381. data/lib/badline/drive1541/byte_ready.rb +0 -48
  382. data/lib/badline/drive1541/cpu.rb +0 -11
  383. data/lib/badline/drive1541/disk.rb +0 -315
  384. data/lib/badline/drive1541/disk_state.rb +0 -86
  385. data/lib/badline/drive1541/disk_via.rb +0 -36
  386. data/lib/badline/drive1541/gcr.rb +0 -57
  387. data/lib/badline/drive1541/mechanism.rb +0 -313
  388. data/lib/badline/drive1541/mechanism_state.rb +0 -68
  389. data/lib/badline/drive1541/rotation.rb +0 -121
  390. data/lib/badline/drive1541/sector_reader.rb +0 -76
  391. data/lib/badline/drive1541/serial_port.rb +0 -18
  392. data/lib/badline/drive1541/track.rb +0 -98
  393. data/lib/badline/drive1541.rb +0 -111
  394. data/lib/badline/drive1571/bus.rb +0 -111
  395. data/lib/badline/drive1571/cpu.rb +0 -11
  396. data/lib/badline/drive1571/serial_port.rb +0 -37
  397. data/lib/badline/drive1571/serial_via.rb +0 -25
  398. data/lib/badline/drive1571/wd1770.rb +0 -120
  399. data/lib/badline/drive1571.rb +0 -175
  400. data/lib/badline/drive1581/bus.rb +0 -137
  401. data/lib/badline/drive1581/cpu.rb +0 -11
  402. data/lib/badline/drive1581/disk.rb +0 -135
  403. data/lib/badline/drive1581/disk_state.rb +0 -87
  404. data/lib/badline/drive1581/mechanism.rb +0 -117
  405. data/lib/badline/drive1581/serial_port.rb +0 -52
  406. data/lib/badline/drive1581/slot.rb +0 -78
  407. data/lib/badline/drive1581/track.rb +0 -100
  408. data/lib/badline/drive1581/track_bytes.rb +0 -75
  409. data/lib/badline/drive1581/wd1772/registers.rb +0 -89
  410. data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
  411. data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
  412. data/lib/badline/drive1581/wd1772/state.rb +0 -66
  413. data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
  414. data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
  415. data/lib/badline/drive1581/wd1772/turn.rb +0 -73
  416. data/lib/badline/drive1581/wd1772.rb +0 -216
  417. data/lib/badline/drive1581.rb +0 -233
  418. data/lib/badline/iec_bus.rb +0 -159
  419. data/lib/badline/instruction.rb +0 -334
  420. data/lib/badline/instruction_set/arithmetic.rb +0 -114
  421. data/lib/badline/instruction_set/bitwise.rb +0 -126
  422. data/lib/badline/instruction_set/branch.rb +0 -79
  423. data/lib/badline/instruction_set/flag.rb +0 -63
  424. data/lib/badline/instruction_set/illegal.rb +0 -270
  425. data/lib/badline/instruction_set/inc_dec.rb +0 -69
  426. data/lib/badline/instruction_set/stack.rb +0 -52
  427. data/lib/badline/instruction_set/transfer.rb +0 -137
  428. data/lib/badline/instruction_set.rb +0 -55
  429. data/lib/badline/interrupts.rb +0 -104
  430. data/lib/badline/joystick.rb +0 -25
  431. data/lib/badline/kernal_trap/channel.rb +0 -181
  432. data/lib/badline/keyboard.rb +0 -112
  433. data/lib/badline/ram_expansion/banking.rb +0 -30
  434. data/lib/badline/ram_expansion/plus256k.rb +0 -54
  435. data/lib/badline/ram_expansion/plus60k.rb +0 -43
  436. data/lib/badline/ram_expansion/unexpanded.rb +0 -28
  437. data/lib/badline/ram_expansion.rb +0 -21
  438. data/lib/badline/reu/dma/saved_state.rb +0 -50
  439. data/lib/badline/reu/dma.rb +0 -273
  440. data/lib/badline/reu/ram.rb +0 -107
  441. data/lib/badline/reu/saved_state.rb +0 -80
  442. data/lib/badline/reu/trigger.rb +0 -32
  443. data/lib/badline/reu.rb +0 -289
  444. data/lib/badline/sid/catch_up.rb +0 -120
  445. data/lib/badline/sid/decimator.rb +0 -64
  446. data/lib/badline/sid/envelope/state.rb +0 -68
  447. data/lib/badline/sid/envelope.rb +0 -239
  448. data/lib/badline/sid/filter.rb +0 -263
  449. data/lib/badline/sid/voice.rb +0 -77
  450. data/lib/badline/sid/waveform/combined.rb +0 -126
  451. data/lib/badline/sid/waveform/fast_forward.rb +0 -105
  452. data/lib/badline/sid/waveform/noise_writeback.rb +0 -122
  453. data/lib/badline/sid/waveform/state.rb +0 -66
  454. data/lib/badline/sid/waveform.rb +0 -305
  455. data/lib/badline/sid.rb +0 -303
  456. data/lib/badline/time_of_day.rb +0 -228
  457. data/lib/badline/traps.rb +0 -19
  458. data/lib/badline/via/control_lines.rb +0 -122
  459. data/lib/badline/via/fast_forward.rb +0 -53
  460. data/lib/badline/via/interrupt_register.rb +0 -67
  461. data/lib/badline/via/shift_register.rb +0 -180
  462. data/lib/badline/via/state.rb +0 -42
  463. data/lib/badline/via/timer1.rb +0 -131
  464. data/lib/badline/via/timer2.rb +0 -133
  465. data/lib/badline/via.rb +0 -266
  466. data/lib/badline/vic/bank.rb +0 -133
  467. data/lib/badline/vic/border_mask.rb +0 -86
  468. data/lib/badline/vic/collisions.rb +0 -115
  469. data/lib/badline/vic/color_patches.rb +0 -47
  470. data/lib/badline/vic/display_state.rb +0 -185
  471. data/lib/badline/vic/graphics_mode.rb +0 -164
  472. data/lib/badline/vic/graphics_shifter.rb +0 -207
  473. data/lib/badline/vic/register_log.rb +0 -81
  474. data/lib/badline/vic/registers.rb +0 -195
  475. data/lib/badline/vic/sequencer.rb +0 -275
  476. data/lib/badline/vic/sequencer_output.rb +0 -116
  477. data/lib/badline/vic/sequencer_state.rb +0 -89
  478. data/lib/badline/vic/sprite/internal_bus.rb +0 -68
  479. data/lib/badline/vic/sprite/saved_state.rb +0 -64
  480. data/lib/badline/vic/sprite/shifter.rb +0 -146
  481. data/lib/badline/vic/sprite/timing.rb +0 -56
  482. data/lib/badline/vic/sprite.rb +0 -337
  483. data/lib/badline/vic/sprites.rb +0 -282
  484. data/lib/badline/vic/sprites_state.rb +0 -57
  485. data/lib/badline/vic.rb +0 -853
  486. data/lib/badline/vic20/sound/output.rb +0 -83
  487. data/lib/badline/vic20/sound.rb +0 -233
  488. data/lib/badline/z80/arithmetic.rb +0 -117
  489. data/lib/badline/z80/bit_page.rb +0 -55
  490. data/lib/badline/z80/block_io.rb +0 -58
  491. data/lib/badline/z80/block_transfers.rb +0 -59
  492. data/lib/badline/z80/bus_cycles.rb +0 -111
  493. data/lib/badline/z80/core.rb +0 -113
  494. data/lib/badline/z80/exchanges.rb +0 -50
  495. data/lib/badline/z80/extended_page.rb +0 -89
  496. data/lib/badline/z80/flags.rb +0 -37
  497. data/lib/badline/z80/interrupt_acceptance.rb +0 -46
  498. data/lib/badline/z80/jumps.rb +0 -82
  499. data/lib/badline/z80/loads.rb +0 -98
  500. data/lib/badline/z80/main_page.rb +0 -134
  501. data/lib/badline/z80/registers.rb +0 -120
  502. data/lib/badline/z80/saved_state.rb +0 -69
  503. data/lib/badline/z80/shifts.rb +0 -64
  504. data/lib/badline/z80.rb +0 -11
  505. /data/lib/badline/snapshot/{fields.rb → vice/fields.rb} +0 -0
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Badline
4
- class Computer
4
+ class C64
5
5
  # The disk device 8 serves through the LOAD, SAVE and serial traps, and
6
- # CHROUT capture, on the KERNAL the machine runs. Computer, Vic20 and
6
+ # CHROUT capture, on the KERNAL the machine runs. C64, Vic20 and
7
7
  # C128 each include it and answer two private methods: #trap_layout,
8
8
  # the KernalTrap::Layout of that KERNAL, and #trap_bus, the bus the
9
9
  # traps read and write through.
@@ -13,9 +13,9 @@ module Badline
13
13
  # drive reset clears, and its status. The traps go on the KERNAL the
14
14
  # machine runs (#trap_layout).
15
15
  def mount(storage)
16
- return @drive.insert(storage) if @drive
16
+ return @dos.insert(storage) if @dos
17
17
 
18
- @drive = KernalTrap::Drive.new(storage)
18
+ @dos = KernalTrap::DOS.new(storage)
19
19
  install_kernal_traps(trap_layout)
20
20
  end
21
21
 
@@ -23,18 +23,18 @@ module Badline
23
23
  # serial traps, so the KERNAL's routines go out over the serial bus.
24
24
  # Mounting again starts a new drive, with its RAM cleared.
25
25
  def unmount
26
- return unless @drive
26
+ return unless @dos
27
27
 
28
28
  remove_kernal_traps
29
- @drive = nil
29
+ @dos = nil
30
30
  end
31
31
 
32
32
  # Whether device 8 serves a disk or directory through the traps.
33
- def mounted? = !@drive.nil?
33
+ def mounted? = !@dos.nil?
34
34
 
35
35
  # The path of the disk or directory device 8 serves through the
36
36
  # traps, or an empty one.
37
- def mounted_path = @drive.nil? ? "" : @drive.path
37
+ def mounted_path = @dos.nil? ? "" : @dos.path
38
38
 
39
39
  # Records what the KERNAL prints through CHROUT (ChroutTrap).
40
40
  def capture_output
@@ -47,11 +47,11 @@ module Badline
47
47
 
48
48
  def install_kernal_traps(layout)
49
49
  @trap_layout = layout
50
- load_trap = KernalTrap::Load.new(cpu:, bus: trap_bus, layout:, drive: @drive)
50
+ load_trap = KernalTrap::Load.new(cpu:, bus: trap_bus, layout:, dos: @dos)
51
51
  cpu.install_trap(layout.load) { load_trap.call }
52
- @serial_trap = KernalTrap::Serial.new(cpu:, bus: trap_bus, layout:, drive: @drive,
52
+ @serial_trap = KernalTrap::Serial.new(cpu:, bus: trap_bus, layout:, dos: @dos,
53
53
  device: serial_trap_device).install
54
- save_trap = @save_trap = KernalTrap::Save.new(cpu:, bus: trap_bus, layout:, drive: @drive)
54
+ save_trap = @save_trap = KernalTrap::Save.new(cpu:, bus: trap_bus, layout:, dos: @dos)
55
55
  cpu.install_trap(layout.save) { save_trap.call }
56
56
  end
57
57
 
@@ -65,22 +65,22 @@ module Badline
65
65
 
66
66
  # The disk device 8 serves through the traps, with the traps' own
67
67
  # state: open channels, the drive's status and RAM, a SAVE under way.
68
- def save_trap_drive(out)
69
- out.boolean(!@drive.nil?)
70
- return unless @drive
68
+ def save_trap_dos(out)
69
+ out.boolean(!@dos.nil?)
70
+ return unless @dos
71
71
 
72
- @drive.save_state(out)
72
+ @dos.save_state(out)
73
73
  @serial_trap.save_state(out)
74
74
  @save_trap.save_state(out)
75
75
  end
76
76
 
77
- def load_trap_drive(input)
77
+ def load_trap_dos(input)
78
78
  return unmount unless input.boolean?
79
79
 
80
- storage = Storage.reopen(input)
80
+ storage = Snapshot::StorageSetup.read(input)
81
81
  unmount
82
82
  mount(storage)
83
- @drive.load_state(input)
83
+ @dos.load_state(input)
84
84
  @serial_trap.load_state(input)
85
85
  @save_trap.load_state(input)
86
86
  end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ class REU
6
+ class DMA
7
+ # A transfer's state for a snapshot (REU::SavedState).
8
+ module SavedState
9
+ # Everything a transfer holds between cycles. Before the first
10
+ # transfer, the fields it sets on starting are empty.
11
+ def save_state(out)
12
+ out.int(@c64).int(@expansion).int(@length).int(@events)
13
+ [@type, @c64_step, @expansion_step, @last, @ba_low_after_writes, @swap_byte, @held_read].each do |value|
14
+ out.optional_int(value)
15
+ end
16
+ [@holding, @waiting, @stopped_after_write, @swap_write_due, @swap_read_again, @moved_all,
17
+ @extra_cycle].each do |flag|
18
+ out.boolean(flag)
19
+ end
20
+ end
21
+
22
+ def load_state(input)
23
+ @c64 = input.int
24
+ @expansion = input.int
25
+ @length = input.int
26
+ @events = input.int
27
+ load_steps(input)
28
+ @holding = input.boolean?
29
+ @waiting = input.boolean?
30
+ @stopped_after_write = input.boolean?
31
+ @swap_write_due = input.boolean?
32
+ @swap_read_again = input.boolean?
33
+ @moved_all = input.boolean?
34
+ @extra_cycle = input.boolean?
35
+ end
36
+
37
+ private
38
+
39
+ def load_steps(input)
40
+ @type = input.optional_int
41
+ @c64_step = input.optional_int
42
+ @expansion_step = input.optional_int
43
+ @last = input.optional_int
44
+ @ba_low_after_writes = input.optional_int
45
+ @swap_byte = input.optional_int
46
+ @held_read = input.optional_int
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,275 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "badline/c64/reu/dma/saved_state"
4
+
5
+ module Badline
6
+ class C64
7
+ class REU
8
+ # One transfer between the C64 and the REU's RAM, clocked a cycle at a
9
+ # time while the REC holds the bus. The REC only reads the C64's bus
10
+ # while BA is high, so a read followed by BA low waits for BA to rise.
11
+ # After a write it goes on through the first BA-low cycle and stops at
12
+ # the second. See doc/pinned-behaviour.md, REU DMA.
13
+ class DMA
14
+ include SavedState
15
+
16
+ # Transfer types, as the command register's bottom two bits give
17
+ # them.
18
+ STASH = 0
19
+ FETCH = 1
20
+ SWAP = 2
21
+ VERIFY = 3
22
+
23
+ # What the REC did on the cycle before.
24
+ IDLE = 0
25
+ READ = 1
26
+ WRITE = 2
27
+
28
+ # Where the transfer stopped, what it left for the length register,
29
+ # and the status bits it ended with.
30
+ attr_reader :c64, :expansion, :length, :events
31
+
32
+ def initialize(ram, span, bus)
33
+ @ram = ram
34
+ @span = span
35
+ @bus = bus
36
+ @c64 = @expansion = @length = @events = 0
37
+ @holding = false
38
+ end
39
+
40
+ # Whether the REC held the bus on the last cycle clocked, which it
41
+ # does while it waits for BA too, since the CPU stays halted.
42
+ def holds_bus? = @holding
43
+
44
+ # A length of 0 moves 64K. control is the address control register,
45
+ # which can hold either address where it is.
46
+ def start(type, c64, expansion, length, control)
47
+ @type = type
48
+ @c64 = c64
49
+ @expansion = expansion
50
+ @length = length.zero? ? 0x10000 : length
51
+ @c64_step = control.anybits?(FIX_C64) ? 0 : 1
52
+ @expansion_step = control.anybits?(FIX_EXPANSION) ? 0 : 1
53
+ @events = 0
54
+ @holding = true
55
+ @last = IDLE
56
+ @waiting = false
57
+ @ba_low_after_writes = 0
58
+ @stopped_after_write = false
59
+ @swap_write_due = false
60
+ @swap_read_again = false
61
+ @swap_byte = 0
62
+ @held_read = 0
63
+ @moved_all = false
64
+ @extra_cycle = false
65
+ end
66
+
67
+ # Writes the byte a fetch from these addresses starts with, without
68
+ # counting it. Other transfers start with a read.
69
+ def write_ahead(type, c64, expansion)
70
+ return unless type == FETCH
71
+
72
+ @c64 = c64
73
+ byte = @ram.peek(expansion)
74
+ @ram.latch = byte
75
+ write_c64(byte)
76
+ end
77
+
78
+ # One cycle of the transfer. The cycle the REC lets go of the bus on
79
+ # is the CPU's. late says BA fell on this cycle but a REC that moved a
80
+ # byte on the last one doesn't see it yet (VIC#reu_ba_late?), and
81
+ # handed_on that BA runs on from a bad line's DMA into a sprite's
82
+ # here (VIC#reu_ba_handed_on?).
83
+ def cycle!(ba_low, late, handed_on)
84
+ note_ba(ba_low, late)
85
+ @swap_read_again ||= handed_on && @swap_write_due
86
+ settle_held_read(ba_low) if @held_read.positive?
87
+ return if @waiting && ba_low
88
+
89
+ @waiting = false
90
+ @moved_all ? wind_down : move(ba_low)
91
+ end
92
+
93
+ private
94
+
95
+ # The second BA-low cycle in a row after writes stops the REC, and so
96
+ # does any BA-low cycle after a read. It then waits for BA to rise.
97
+ def note_ba(ba_low, late)
98
+ seen = ba_low && !late
99
+ if @last == READ
100
+ note_ba_after_read(seen)
101
+ elsif @last == WRITE
102
+ note_ba_after_write(seen)
103
+ end
104
+ @last = IDLE
105
+ end
106
+
107
+ # A swap's read that BA stops before its write is made again.
108
+ def note_ba_after_read(ba_low)
109
+ @waiting = ba_low
110
+ @ba_low_after_writes = 0
111
+ @swap_read_again = ba_low && @swap_write_due && @held_read.zero?
112
+ end
113
+
114
+ # A fetch's last write doesn't go through the first BA-low cycle.
115
+ # Pinned by REU/reutiming2/d and d2.
116
+ def note_ba_after_write(ba_low)
117
+ @ba_low_after_writes = ba_low ? @ba_low_after_writes + 1 : 0
118
+ @stopped_after_write = @ba_low_after_writes == 2 || (ba_low && @type == FETCH && @length == 1)
119
+ return unless @stopped_after_write
120
+
121
+ @waiting = true
122
+ @ba_low_after_writes = 0
123
+ end
124
+
125
+ # A fetch or a swap whose last write ran into BA, or a verify that
126
+ # found a difference before its last byte, takes one more cycle before
127
+ # the REC lets go of the bus.
128
+ def wind_down
129
+ if @extra_cycle || (@stopped_after_write && (@type == FETCH || @type == SWAP))
130
+ @extra_cycle = @stopped_after_write = false
131
+ @last = READ
132
+ return
133
+ end
134
+
135
+ @holding = false
136
+ settle
137
+ end
138
+
139
+ def move(ba_low)
140
+ case @type
141
+ when STASH then stash
142
+ when FETCH then fetch
143
+ when SWAP then swap(ba_low)
144
+ else verify
145
+ end
146
+ end
147
+
148
+ # The REU's data bus latch keeps the last byte the REC stored.
149
+ def stash
150
+ byte = read_c64
151
+ @ram.poke(@expansion, byte)
152
+ @ram.latch = byte
153
+ step
154
+ @last = READ
155
+ end
156
+
157
+ def fetch
158
+ byte = @ram.peek(@expansion)
159
+ @ram.latch = byte
160
+ write_c64(byte)
161
+ step
162
+ @last = WRITE
163
+ end
164
+
165
+ # Two cycles a byte: the C64's byte is read and stored while the
166
+ # REU's is fetched, and the REU's is written to the C64 on the next.
167
+ def swap(ba_low)
168
+ return read_swap_again if @swap_read_again
169
+
170
+ if @swap_write_due
171
+ @swap_write_due = false
172
+ write_c64(@swap_byte)
173
+ step
174
+ @last = WRITE
175
+ return
176
+ end
177
+
178
+ @swap_byte = @ram.peek(@expansion)
179
+ @swap_write_due = true
180
+ @last = READ
181
+ return swap_read_on_ba if ba_low
182
+
183
+ @ram.poke(@expansion, read_c64)
184
+ end
185
+
186
+ # A swap's read on the first BA-low cycle after a write, while AEC is
187
+ # still high. On the last byte the read is made there, the write
188
+ # follows on the next cycle whatever BA does, and the REC lets go.
189
+ # Otherwise the read stays open and takes what is on the bus two
190
+ # cycles later, or on the cycle BA rises if that comes first. Pinned
191
+ # by REU/reutiming2/e5-m2, f3-m2 and f4-m2.
192
+ def swap_read_on_ba
193
+ return @held_read = 2 unless @length == 1
194
+
195
+ @ram.poke(@expansion, read_c64)
196
+ @last = IDLE
197
+ @ba_low_after_writes = 0
198
+ end
199
+
200
+ # A swap's read that BA cut off from its write is made again when BA
201
+ # rises, and the write follows it. Pinned by REU/reutiming2/e4-m2,
202
+ # e6-m2 and g3-m2.
203
+ def read_swap_again
204
+ @swap_read_again = false
205
+ @ram.poke(@expansion, read_c64)
206
+ @last = READ
207
+ end
208
+
209
+ def settle_held_read(ba_low)
210
+ @held_read -= 1
211
+ return if @held_read.positive? && ba_low
212
+
213
+ @held_read = 0
214
+ @ram.poke(@expansion, read_c64)
215
+ end
216
+
217
+ # A difference ends the transfer, with one cycle more if bytes were
218
+ # left to compare.
219
+ def verify
220
+ same = @ram.peek(@expansion) == read_c64
221
+ step
222
+ @last = READ
223
+ return if same
224
+
225
+ @events |= FAULT
226
+ @extra_cycle = @length.positive?
227
+ @moved_all = true
228
+ end
229
+
230
+ # The REC reaches C64 memory as the CPU sees it, but at $00 and $01
231
+ # it reaches the RAM under the CPU's port.
232
+ def read_c64
233
+ @c64 < 0x02 ? @bus.ram.peek(@c64) : @bus.peek(@c64)
234
+ end
235
+
236
+ def write_c64(byte)
237
+ @c64 < 0x02 ? @bus.ram.poke(@c64, byte) : @bus.poke(@c64, byte)
238
+ end
239
+
240
+ # The REC counts the expansion address in its 19 low bits, from the
241
+ # top of its span back to 0, and leaves the bank bits above them as
242
+ # they were.
243
+ def step
244
+ @c64 = (@c64 + @c64_step) & 0xffff
245
+ low = (@expansion & 0x7ffff) + @expansion_step
246
+ @expansion = (@expansion & 0xf80000) | (low == @span ? 0 : low)
247
+ @length -= 1
248
+ @moved_all = true if @length.zero?
249
+ end
250
+
251
+ # The length register is left at 1 after a whole block. A fetch has
252
+ # already fetched the byte after its last into the latch.
253
+ def settle
254
+ return settle_verify if @type == VERIFY
255
+
256
+ @length += 1
257
+ @events |= END_OF_BLOCK
258
+ @ram.latch = @ram.peek(@expansion) if @type == FETCH
259
+ end
260
+
261
+ # A verify that compared every byte ends the block. One that found a
262
+ # difference on the byte before the last compares the last too, and
263
+ # ends the block if that one is the same.
264
+ def settle_verify
265
+ if @length.zero?
266
+ @length = 1
267
+ @events |= END_OF_BLOCK
268
+ elsif @length == 1 && @ram.peek(@expansion) == read_c64
269
+ @events |= END_OF_BLOCK
270
+ end
271
+ end
272
+ end
273
+ end
274
+ end
275
+ end
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ class REU
6
+ # The REU's DRAM, as the REC addresses it. The REC counts 19 address
7
+ # bits, 17 on the 1700, and the 1764 fills only the first 256K of
8
+ # them: past that a read finds the latch on the REU's data bus, which
9
+ # holds the last byte the REC moved. A unit past 512K takes its upper
10
+ # address lines from the bank register.
11
+ class RAM
12
+ BANK_SIZE = 0x10000
13
+
14
+ # Where a bank of a 1764 that has just been switched on reads
15
+ # inverted, over the first 128K of each 256K. Over the second 128K
16
+ # it is the rest of the bank that reads inverted. Measured from
17
+ # REU/raminitpattern/dumpfile-256k-x1541.bin, a real 1764's dump.
18
+ INVERTED = [0x2a00...0x5400, 0x8000...0xac00, 0xd600...0x10000].freeze
19
+
20
+ attr_reader :size
21
+ attr_accessor :latch
22
+
23
+ def initialize(size, span)
24
+ @size = size
25
+ @mask = (size > 0x80000 ? size : span) - 1
26
+ @banks = Array.new(size / BANK_SIZE) { [] }
27
+ @power_on = [[], []]
28
+ @latch = 0xff
29
+ end
30
+
31
+ def peek(addr)
32
+ addr &= @mask
33
+ addr < @size ? bank(addr >> 16)[addr & 0xffff] : @latch
34
+ end
35
+
36
+ def poke(addr, value)
37
+ addr &= @mask
38
+ bank(addr >> 16)[addr & 0xffff] = value if addr < @size
39
+ end
40
+
41
+ # The latch, and each 64K bank the REC has touched. A bank it hasn't
42
+ # keeps its power-on contents until it does.
43
+ def save_state(out)
44
+ out.int(@latch)
45
+ @banks.each do |bank|
46
+ out.boolean(!bank.empty?)
47
+ out.blob(bank) unless bank.empty?
48
+ end
49
+ end
50
+
51
+ def load_state(input)
52
+ @latch = input.int
53
+ @banks.each_index { |number| @banks[number] = input.boolean? ? input.blob : [] }
54
+ end
55
+
56
+ # Every byte, as one string, with a bank the REC hasn't touched at
57
+ # its power-on contents.
58
+ def contents
59
+ power_on = power_on_strings
60
+ Array.new(@banks.length) do |number|
61
+ bank = @banks[number]
62
+ bank.empty? ? power_on[(number >> 1) & 1] : bank.pack("C*")
63
+ end.join
64
+ end
65
+
66
+ # Takes every byte from a string as long as the RAM. A bank that
67
+ # holds its power-on contents stays untouched.
68
+ def restore(bytes)
69
+ power_on = power_on_strings
70
+ @banks.each_index do |number|
71
+ slice = bytes.byteslice(number * BANK_SIZE, BANK_SIZE).to_s
72
+ @banks[number] = slice == power_on[(number >> 1) & 1] ? [] : slice.bytes
73
+ end
74
+ end
75
+
76
+ private
77
+
78
+ def power_on_strings
79
+ [0, 1].map do |half|
80
+ @power_on[half] = power_on_bank(half == 1) if @power_on[half].empty?
81
+ @power_on[half].pack("C*")
82
+ end
83
+ end
84
+
85
+ # A bank takes its power-on contents the first time it is touched,
86
+ # so an REU costs only the memory a program uses.
87
+ def bank(number)
88
+ bank = @banks[number]
89
+ return bank unless bank.empty?
90
+
91
+ half = (number >> 1) & 1
92
+ @power_on[half] = power_on_bank(half == 1) if @power_on[half].empty?
93
+ @banks[number] = @power_on[half].dup
94
+ end
95
+
96
+ # Pairs of $FF and $00 bytes, starting with a single $FF, and each
97
+ # odd page the inverse of the even one before it.
98
+ def power_on_bank(upper)
99
+ Array.new(BANK_SIZE) do |offset|
100
+ byte = (offset + 1).anybits?(2) ? 0x00 : 0xff
101
+ byte ^= 0xff if offset.anybits?(0x100)
102
+ inverted = INVERTED.any? { |range| range.cover?(offset) }
103
+ inverted == upper ? byte : byte ^ 0xff
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ class REU
6
+ # The REU's state for a snapshot: the REC's registers and the values
7
+ # its counters start from, an armed or running transfer, the IRQ line,
8
+ # the transfer's own state and the RAM. The size is the machine's
9
+ # setup (Snapshot::C64Setup), so a restore finds an REU of the same size.
10
+ module SavedState
11
+ def size_kb = @size_kb
12
+
13
+ def save_state(out)
14
+ out.marker("REU")
15
+ [@status, @command, @c64, @c64_start, @expansion, @expansion_start, @bank, @bank_start, @length,
16
+ @length_start, @interrupt_mask, @address_control].each { |value| out.int(value) }
17
+ out.boolean(@armed).boolean(@requested).boolean(@running).boolean(@irq).boolean(@ba_was_low)
18
+ @dma.save_state(out)
19
+ @ram.save_state(out)
20
+ end
21
+
22
+ # The IRQ line comes back as it was without calling back into the
23
+ # machine, which reads it again afterwards.
24
+ def load_state(input)
25
+ input.marker("REU")
26
+ load_registers(input)
27
+ @armed = input.boolean?
28
+ @requested = input.boolean?
29
+ @running = input.boolean?
30
+ @irq = input.boolean?
31
+ @ba_was_low = input.boolean?
32
+ @dma.load_state(input)
33
+ @ram.load_state(input)
34
+ end
35
+
36
+ private
37
+
38
+ def load_registers(input)
39
+ @status = input.int
40
+ @command = input.int
41
+ @c64 = input.int
42
+ @c64_start = input.int
43
+ @expansion = input.int
44
+ @expansion_start = input.int
45
+ @bank = input.int
46
+ @bank_start = input.int
47
+ @length = input.int
48
+ @length_start = input.int
49
+ @interrupt_mask = input.int
50
+ @address_control = input.int
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ class REU
6
+ # Stands in for the page at $FF00 in the write table, passing each
7
+ # write on to what is mapped there and telling the REC when $FF00 is
8
+ # written, which starts an armed transfer.
9
+ class Trigger
10
+ ADDRESS = 0xff00
11
+
12
+ def initialize(reu)
13
+ @reu = reu
14
+ @target = nil
15
+ end
16
+
17
+ # Puts the trigger in front of target and returns it.
18
+ def wrap(target)
19
+ @target = target
20
+ self
21
+ end
22
+
23
+ def peek(addr)
24
+ @target.peek(addr)
25
+ end
26
+
27
+ def poke(addr, value)
28
+ @target.poke(addr, value)
29
+ @reu.ff00_written if addr == ADDRESS
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end