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,271 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ class REU
6
+ # One transfer between the C64 and the REU's RAM, clocked a cycle at a
7
+ # time while the REC holds the bus. The REC only reads the C64's bus
8
+ # while BA is high, so a read followed by BA low waits for BA to rise.
9
+ # After a write it goes on through the first BA-low cycle and stops at
10
+ # the second. See doc/pinned-behaviour.md, REU DMA.
11
+ class DMA
12
+ # Transfer types, as the command register's bottom two bits give
13
+ # them.
14
+ STASH = 0
15
+ FETCH = 1
16
+ SWAP = 2
17
+ VERIFY = 3
18
+
19
+ # What the REC did on the cycle before.
20
+ IDLE = 0
21
+ READ = 1
22
+ WRITE = 2
23
+
24
+ # Where the transfer stopped, what it left for the length register,
25
+ # and the status bits it ended with.
26
+ attr_reader :c64, :expansion, :length, :events
27
+
28
+ def initialize(ram, span, bus)
29
+ @ram = ram
30
+ @span = span
31
+ @bus = bus
32
+ @c64 = @expansion = @length = @events = 0
33
+ @holding = false
34
+ end
35
+
36
+ # Whether the REC held the bus on the last cycle clocked, which it
37
+ # does while it waits for BA too, since the CPU stays halted.
38
+ def holds_bus? = @holding
39
+
40
+ # A length of 0 moves 64K. control is the address control register,
41
+ # which can hold either address where it is.
42
+ def start(type, c64, expansion, length, control)
43
+ @type = type
44
+ @c64 = c64
45
+ @expansion = expansion
46
+ @length = length.zero? ? 0x10000 : length
47
+ @c64_step = control.anybits?(FIX_C64) ? 0 : 1
48
+ @expansion_step = control.anybits?(FIX_EXPANSION) ? 0 : 1
49
+ @events = 0
50
+ @holding = true
51
+ @last = IDLE
52
+ @waiting = false
53
+ @ba_low_after_writes = 0
54
+ @stopped_after_write = false
55
+ @swap_write_due = false
56
+ @swap_read_again = false
57
+ @swap_byte = 0
58
+ @held_read = 0
59
+ @moved_all = false
60
+ @extra_cycle = false
61
+ end
62
+
63
+ # Writes the byte a fetch from these addresses starts with, without
64
+ # counting it. Other transfers start with a read.
65
+ def write_ahead(type, c64, expansion)
66
+ return unless type == FETCH
67
+
68
+ @c64 = c64
69
+ byte = @ram.peek(expansion)
70
+ @ram.latch = byte
71
+ write_c64(byte)
72
+ end
73
+
74
+ # One cycle of the transfer. The cycle the REC lets go of the bus on
75
+ # is the CPU's. late says BA fell on this cycle but a REC that moved a
76
+ # byte on the last one doesn't see it yet (VIC#reu_ba_late?), and
77
+ # handed_on that BA runs on from a bad line's DMA into a sprite's
78
+ # here (VIC#reu_ba_handed_on?).
79
+ def cycle!(ba_low, late, handed_on)
80
+ note_ba(ba_low, late)
81
+ @swap_read_again ||= handed_on && @swap_write_due
82
+ settle_held_read(ba_low) if @held_read.positive?
83
+ return if @waiting && ba_low
84
+
85
+ @waiting = false
86
+ @moved_all ? wind_down : move(ba_low)
87
+ end
88
+
89
+ private
90
+
91
+ # The second BA-low cycle in a row after writes stops the REC, and so
92
+ # does any BA-low cycle after a read. It then waits for BA to rise.
93
+ def note_ba(ba_low, late)
94
+ seen = ba_low && !late
95
+ if @last == READ
96
+ note_ba_after_read(seen)
97
+ elsif @last == WRITE
98
+ note_ba_after_write(seen)
99
+ end
100
+ @last = IDLE
101
+ end
102
+
103
+ # A swap's read that BA stops before its write is made again.
104
+ def note_ba_after_read(ba_low)
105
+ @waiting = ba_low
106
+ @ba_low_after_writes = 0
107
+ @swap_read_again = ba_low && @swap_write_due && @held_read.zero?
108
+ end
109
+
110
+ # A fetch's last write doesn't go through the first BA-low cycle.
111
+ # Pinned by REU/reutiming2/d and d2.
112
+ def note_ba_after_write(ba_low)
113
+ @ba_low_after_writes = ba_low ? @ba_low_after_writes + 1 : 0
114
+ @stopped_after_write = @ba_low_after_writes == 2 || (ba_low && @type == FETCH && @length == 1)
115
+ return unless @stopped_after_write
116
+
117
+ @waiting = true
118
+ @ba_low_after_writes = 0
119
+ end
120
+
121
+ # A fetch or a swap whose last write ran into BA, or a verify that
122
+ # found a difference before its last byte, takes one more cycle before
123
+ # the REC lets go of the bus.
124
+ def wind_down
125
+ if @extra_cycle || (@stopped_after_write && (@type == FETCH || @type == SWAP))
126
+ @extra_cycle = @stopped_after_write = false
127
+ @last = READ
128
+ return
129
+ end
130
+
131
+ @holding = false
132
+ settle
133
+ end
134
+
135
+ def move(ba_low)
136
+ case @type
137
+ when STASH then stash
138
+ when FETCH then fetch
139
+ when SWAP then swap(ba_low)
140
+ else verify
141
+ end
142
+ end
143
+
144
+ # The REU's data bus latch keeps the last byte the REC stored.
145
+ def stash
146
+ byte = read_c64
147
+ @ram.poke(@expansion, byte)
148
+ @ram.latch = byte
149
+ step
150
+ @last = READ
151
+ end
152
+
153
+ def fetch
154
+ byte = @ram.peek(@expansion)
155
+ @ram.latch = byte
156
+ write_c64(byte)
157
+ step
158
+ @last = WRITE
159
+ end
160
+
161
+ # Two cycles a byte: the C64's byte is read and stored while the
162
+ # REU's is fetched, and the REU's is written to the C64 on the next.
163
+ def swap(ba_low)
164
+ return read_swap_again if @swap_read_again
165
+
166
+ if @swap_write_due
167
+ @swap_write_due = false
168
+ write_c64(@swap_byte)
169
+ step
170
+ @last = WRITE
171
+ return
172
+ end
173
+
174
+ @swap_byte = @ram.peek(@expansion)
175
+ @swap_write_due = true
176
+ @last = READ
177
+ return swap_read_on_ba if ba_low
178
+
179
+ @ram.poke(@expansion, read_c64)
180
+ end
181
+
182
+ # A swap's read on the first BA-low cycle after a write, while AEC is
183
+ # still high. On the last byte the read is made there, the write
184
+ # follows on the next cycle whatever BA does, and the REC lets go.
185
+ # Otherwise the read stays open and takes what is on the bus two
186
+ # cycles later, or on the cycle BA rises if that comes first. Pinned
187
+ # by REU/reutiming2/e5-m2, f3-m2 and f4-m2.
188
+ def swap_read_on_ba
189
+ return @held_read = 2 unless @length == 1
190
+
191
+ @ram.poke(@expansion, read_c64)
192
+ @last = IDLE
193
+ @ba_low_after_writes = 0
194
+ end
195
+
196
+ # A swap's read that BA cut off from its write is made again when BA
197
+ # rises, and the write follows it. Pinned by REU/reutiming2/e4-m2,
198
+ # e6-m2 and g3-m2.
199
+ def read_swap_again
200
+ @swap_read_again = false
201
+ @ram.poke(@expansion, read_c64)
202
+ @last = READ
203
+ end
204
+
205
+ def settle_held_read(ba_low)
206
+ @held_read -= 1
207
+ return if @held_read.positive? && ba_low
208
+
209
+ @held_read = 0
210
+ @ram.poke(@expansion, read_c64)
211
+ end
212
+
213
+ # A difference ends the transfer, with one cycle more if bytes were
214
+ # left to compare.
215
+ def verify
216
+ same = @ram.peek(@expansion) == read_c64
217
+ step
218
+ @last = READ
219
+ return if same
220
+
221
+ @events |= FAULT
222
+ @extra_cycle = @length.positive?
223
+ @moved_all = true
224
+ end
225
+
226
+ # The REC reaches C64 memory as the CPU sees it, but at $00 and $01
227
+ # it reaches the RAM under the CPU's port.
228
+ def read_c64
229
+ @c64 < 0x02 ? @bus.ram.peek(@c64) : @bus.peek(@c64)
230
+ end
231
+
232
+ def write_c64(byte)
233
+ @c64 < 0x02 ? @bus.ram.poke(@c64, byte) : @bus.poke(@c64, byte)
234
+ end
235
+
236
+ # The REC counts the expansion address in its 19 low bits, from the
237
+ # top of its span back to 0, and leaves the bank bits above them as
238
+ # they were.
239
+ def step
240
+ @c64 = (@c64 + @c64_step) & 0xffff
241
+ low = (@expansion & 0x7ffff) + @expansion_step
242
+ @expansion = (@expansion & 0xf80000) | (low == @span ? 0 : low)
243
+ @length -= 1
244
+ @moved_all = true if @length.zero?
245
+ end
246
+
247
+ # The length register is left at 1 after a whole block. A fetch has
248
+ # already fetched the byte after its last into the latch.
249
+ def settle
250
+ return settle_verify if @type == VERIFY
251
+
252
+ @length += 1
253
+ @events |= END_OF_BLOCK
254
+ @ram.latch = @ram.peek(@expansion) if @type == FETCH
255
+ end
256
+
257
+ # A verify that compared every byte ends the block. One that found a
258
+ # difference on the byte before the last compares the last too, and
259
+ # ends the block if that one is the same.
260
+ def settle_verify
261
+ if @length.zero?
262
+ @length = 1
263
+ @events |= END_OF_BLOCK
264
+ elsif @length == 1 && @ram.peek(@expansion) == read_c64
265
+ @events |= END_OF_BLOCK
266
+ end
267
+ end
268
+ end
269
+ end
270
+ end
271
+ end
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ class REU
6
+ class DMA
7
+ # The kinds of transfer, by name.
8
+ TYPE_NAMES = %w[stash fetch swap verify].freeze
9
+
10
+ # A transfer's fields in a keyed snapshot module, under `prefix`.
11
+ # Before the first transfer, the fields it sets on starting are
12
+ # absent.
13
+ module KeyedState
14
+ def save_fields(out, prefix)
15
+ out.int("#{prefix}c64", @c64).int("#{prefix}expansion", @expansion).int("#{prefix}length", @length)
16
+ out.int("#{prefix}events", @events)
17
+ type = @type
18
+ out.text("#{prefix}type", TYPE_NAMES.fetch(type)) unless type.nil?
19
+ out.optional_int("#{prefix}c64_step", @c64_step).optional_int("#{prefix}expansion_step", @expansion_step)
20
+ out.optional_int("#{prefix}last", @last).optional_int("#{prefix}ba_low_after_writes", @ba_low_after_writes)
21
+ out.optional_int("#{prefix}swap_byte", @swap_byte).optional_int("#{prefix}held_read", @held_read)
22
+ save_flag_fields(out, prefix)
23
+ end
24
+
25
+ def load_fields(input, prefix)
26
+ @c64 = input.word("#{prefix}c64", @c64)
27
+ @expansion = input.int("#{prefix}expansion", @expansion)
28
+ @length = input.int("#{prefix}length", @length)
29
+ @events = input.int("#{prefix}events", @events)
30
+ type = input.choice("#{prefix}type", TYPE_NAMES + ["none"], "none")
31
+ @type = type == "none" ? nil : TYPE_NAMES.index(type)
32
+ @c64_step = input.optional_int("#{prefix}c64_step")
33
+ @expansion_step = input.optional_int("#{prefix}expansion_step")
34
+ @last = input.optional_int("#{prefix}last")
35
+ @ba_low_after_writes = input.optional_int("#{prefix}ba_low_after_writes")
36
+ @swap_byte = input.optional_int("#{prefix}swap_byte")
37
+ @held_read = input.optional_int("#{prefix}held_read")
38
+ load_flag_fields(input, prefix)
39
+ end
40
+
41
+ private
42
+
43
+ def save_flag_fields(out, prefix)
44
+ out.bool("#{prefix}holding", @holding).bool("#{prefix}waiting", @waiting)
45
+ out.bool("#{prefix}stopped_after_write", @stopped_after_write)
46
+ out.bool("#{prefix}swap_write_due", @swap_write_due).bool("#{prefix}swap_read_again", @swap_read_again)
47
+ out.bool("#{prefix}moved_all", @moved_all).bool("#{prefix}extra_cycle", @extra_cycle)
48
+ end
49
+
50
+ def load_flag_fields(input, prefix)
51
+ @holding = input.bool("#{prefix}holding", @holding)
52
+ @waiting = input.bool("#{prefix}waiting", @waiting)
53
+ @stopped_after_write = input.bool("#{prefix}stopped_after_write", @stopped_after_write)
54
+ @swap_write_due = input.bool("#{prefix}swap_write_due", @swap_write_due)
55
+ @swap_read_again = input.bool("#{prefix}swap_read_again", @swap_read_again)
56
+ @moved_all = input.bool("#{prefix}moved_all", @moved_all)
57
+ @extra_cycle = input.bool("#{prefix}extra_cycle", @extra_cycle)
58
+ end
59
+ end
60
+
61
+ include KeyedState
62
+ end
63
+
64
+ class RAM
65
+ # The data latch and each bank the REC has touched, as bank<N>; a
66
+ # bank left out holds its power-on contents.
67
+ module KeyedState
68
+ def save_fields(out)
69
+ out.int("latch", @latch)
70
+ @banks.each_with_index { |bank, number| out.bytes("bank#{number}", bank) unless bank.empty? }
71
+ end
72
+
73
+ def load_fields(input)
74
+ @latch = input.byte("latch", @latch)
75
+ @banks.each_index do |number|
76
+ @banks[number] = input.bytes("bank#{number}", "".b).bytes
77
+ end
78
+ end
79
+ end
80
+
81
+ include KeyedState
82
+ end
83
+
84
+ # The REU's fields in a keyed snapshot module (Snapshot::Keyed): the
85
+ # REC's registers and the values its counters start from, an armed or
86
+ # running transfer, the transfer under dma.*, and the RAM. The IRQ
87
+ # line comes from the status register on load.
88
+ module KeyedState
89
+ # The REU's size in K, which the machine's setup names.
90
+ def size_kb = @size_kb
91
+
92
+ def save_fields(out)
93
+ out.int("status", @status).int("command", @command).int("c64", @c64).int("c64_start", @c64_start)
94
+ out.int("expansion", @expansion).int("expansion_start", @expansion_start).int("bank", @bank)
95
+ out.int("bank_start", @bank_start).int("length", @length).int("length_start", @length_start)
96
+ out.int("interrupt_mask", @interrupt_mask).int("address_control", @address_control)
97
+ out.bool("armed", @armed).bool("requested", @requested).bool("running", @running)
98
+ out.bool("ba_was_low", @ba_was_low)
99
+ @dma.save_fields(out, "dma.")
100
+ @ram.save_fields(out)
101
+ out
102
+ end
103
+
104
+ def load_fields(input)
105
+ load_register_fields(input)
106
+ @armed = input.bool("armed", @armed)
107
+ @requested = input.bool("requested", @requested)
108
+ @running = input.bool("running", @running)
109
+ @ba_was_low = input.bool("ba_was_low", @ba_was_low)
110
+ @dma.load_fields(input, "dma.")
111
+ @ram.load_fields(input)
112
+ end
113
+
114
+ # Without calling back into the machine, which reads the line again.
115
+ def restored!
116
+ @irq = @status.anybits?(INTERRUPT_PENDING)
117
+ end
118
+
119
+ private
120
+
121
+ def load_register_fields(input)
122
+ @status = input.byte("status", @status)
123
+ @command = input.byte("command", @command)
124
+ @c64 = input.word("c64", @c64)
125
+ @c64_start = input.word("c64_start", @c64_start)
126
+ @expansion = input.word("expansion", @expansion)
127
+ @expansion_start = input.word("expansion_start", @expansion_start)
128
+ @bank = input.byte("bank", @bank)
129
+ @bank_start = input.byte("bank_start", @bank_start)
130
+ @length = input.word("length", @length)
131
+ @length_start = input.word("length_start", @length_start)
132
+ @interrupt_mask = input.byte("interrupt_mask", @interrupt_mask)
133
+ @address_control = input.byte("address_control", @address_control)
134
+ end
135
+ end
136
+
137
+ include KeyedState
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,94 @@
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
+ # Every byte, as one string, with a bank the REC hasn't touched at
42
+ # its power-on contents.
43
+ def contents
44
+ power_on = power_on_strings
45
+ Array.new(@banks.length) do |number|
46
+ bank = @banks[number]
47
+ bank.empty? ? power_on[(number >> 1) & 1] : bank.pack("C*")
48
+ end.join
49
+ end
50
+
51
+ # Takes every byte from a string as long as the RAM. A bank that
52
+ # holds its power-on contents stays untouched.
53
+ def restore(bytes)
54
+ power_on = power_on_strings
55
+ @banks.each_index do |number|
56
+ slice = bytes.byteslice(number * BANK_SIZE, BANK_SIZE).to_s
57
+ @banks[number] = slice == power_on[(number >> 1) & 1] ? [] : slice.bytes
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def power_on_strings
64
+ [0, 1].map do |half|
65
+ @power_on[half] = power_on_bank(half == 1) if @power_on[half].empty?
66
+ @power_on[half].pack("C*")
67
+ end
68
+ end
69
+
70
+ # A bank takes its power-on contents the first time it is touched,
71
+ # so an REU costs only the memory a program uses.
72
+ def bank(number)
73
+ bank = @banks[number]
74
+ return bank unless bank.empty?
75
+
76
+ half = (number >> 1) & 1
77
+ @power_on[half] = power_on_bank(half == 1) if @power_on[half].empty?
78
+ @banks[number] = @power_on[half].dup
79
+ end
80
+
81
+ # Pairs of $FF and $00 bytes, starting with a single $FF, and each
82
+ # odd page the inverse of the even one before it.
83
+ def power_on_bank(upper)
84
+ Array.new(BANK_SIZE) do |offset|
85
+ byte = (offset + 1).anybits?(2) ? 0x00 : 0xff
86
+ byte ^= 0xff if offset.anybits?(0x100)
87
+ inverted = INVERTED.any? { |range| range.cover?(offset) }
88
+ inverted == upper ? byte : byte ^ 0xff
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ 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