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
@@ -1,143 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class CIA
5
- # The interrupt control register: the source flags, their mask and the
6
- # IR bit that drives the interrupt line, with the 6526's acknowledge
7
- # timing.
8
- class InterruptRegister
9
- attr_reader :status, :mask, :quiet
10
-
11
- # The 6526A is the faster of the two: see the rules below.
12
- def initialize(model = :mos6526)
13
- @fast = model == :mos6526a
14
- @mask = InterruptFlags.new([:timer_a, :timer_b, :alarm, :serial, :flag, 0, 0, 0])
15
- @status = InterruptFlags.new([:timer_a, :timer_b, :alarm, :serial, :flag, 0, 0, :interrupt])
16
- @pending = 0
17
- @read = @read_last_cycle = @read_two_cycles_ago = nil
18
- @timer_b_bug = false
19
- @quiet = true
20
- end
21
-
22
- # The CIA skips this while quiet: no read is recent enough to matter
23
- # and no assert is due.
24
- def cycle!
25
- @read_two_cycles_ago = @read_last_cycle
26
- @read_last_cycle = @read
27
- @read = nil
28
- if @pending.positive?
29
- @pending -= 1
30
- status.interrupt = true if @pending.zero?
31
- end
32
- @quiet = @pending.zero? && @read_last_cycle.nil? && @read_two_cycles_ago.nil?
33
- end
34
-
35
- def interrupted? = status.value >= 0x80
36
-
37
- def save_state(out)
38
- out.int(@mask.value).int(@status.value).int(@pending)
39
- [@read, @read_last_cycle, @read_two_cycles_ago].each { |read| out.optional_int(read) }
40
- out.boolean(@timer_b_bug).boolean(@quiet)
41
- end
42
-
43
- def load_state(input)
44
- @mask.value = input.int
45
- @status.value = input.int
46
- @pending = input.int
47
- @read = input.optional_int
48
- @read_last_cycle = input.optional_int
49
- @read_two_cycles_ago = input.optional_int
50
- @timer_b_bug = input.boolean?
51
- @quiet = input.boolean?
52
- end
53
-
54
- # Raises IR on this cycle.
55
- def assert_now
56
- status.interrupt = true
57
- @pending = 0
58
- end
59
-
60
- # Schedules IR to rise after delay cycles, keeping an earlier one.
61
- def assert!(delay = 1)
62
- @pending = @pending.positive? ? [@pending, delay].min : delay
63
- @quiet = false
64
- end
65
-
66
- # Latch a source, pulling the interrupt line if it is armed. The 6526
67
- # raises IR a cycle after the flag. The 6526A raises it on the flag's
68
- # own cycle, unless the ICR was read on the cycle before.
69
- def flag(source)
70
- bit = source_bit(source)
71
- @status.value |= bit
72
- return unless mask.value.anybits?(bit)
73
-
74
- @fast && @read_last_cycle.nil? ? assert_now : assert!
75
- end
76
-
77
- # The 6526 timer B bug: an underflow on the cycle after a read still
78
- # raises the flag, but the next read drops it unseen. The 6526A has
79
- # no such bug.
80
- def timer_b_underflow!
81
- @timer_b_bug = !@fast && !@read_last_cycle.nil?
82
- flag(:timer_b)
83
- end
84
-
85
- # A read releases the interrupt line at once, and cancels an assert
86
- # due on the next cycle, but its acknowledge lands a cycle late. On
87
- # the 6526 that holds only IR: the next cycle still reads IR set if it
88
- # was set, or about to be. The 6526A reads an IR about to rise as set
89
- # at once, and holds every bit it read: the next cycle reads them all
90
- # again, along with anything flagged since.
91
- def read
92
- status.timer_b = false if @timer_b_bug
93
- @timer_b_bug = false
94
- value = status.value
95
- value |= 0x80 if @fast && @pending == 1
96
- @read = @pending == 1 ? value | 0x80 : value
97
- @quiet = false
98
- value |= held(@read_last_cycle) if @read_last_cycle
99
- status.value = 0x0
100
- @pending = 0
101
- value
102
- end
103
-
104
- # Bit 7 picks between setting and clearing the mask bits given.
105
- def write(value)
106
- if value.nobits?(0x80)
107
- @mask.value &= ~(value & 0x1f)
108
- else
109
- @mask.value |= (value & 0x1f)
110
- end
111
- if mask.value.anybits?(status.value & 0x1f)
112
- assert!(arm_delay) unless interrupted?
113
- elsif @pending == 1 && @read_two_cycles_ago
114
- # On the 6526, masking the pending source cancels the assert due
115
- # on the next cycle only while a read two cycles back is
116
- # acknowledging.
117
- @pending = 0
118
- end
119
- end
120
-
121
- private
122
-
123
- # Arming a pending source raises IR two cycles later on the 6526,
124
- # and one cycle later on the 6526A.
125
- def arm_delay = @fast ? 1 : 2
126
-
127
- # What a read on the cycle before still holds: IR on the 6526, and
128
- # every bit it read on the 6526A.
129
- def held(last) = @fast ? last : last & 0x80
130
-
131
- def source_bit(source)
132
- case source
133
- when :timer_a then 0x01
134
- when :timer_b then 0x02
135
- when :alarm then 0x04
136
- when :serial then 0x08
137
- when :flag then 0x10
138
- else raise ArgumentError, "unknown interrupt source #{source}"
139
- end
140
- end
141
- end
142
- end
143
- end
@@ -1,275 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class CIA
5
- # The serial shift register and the CNT line that clocks it.
6
- #
7
- # With CRA bit 6 clear the port is an input: SP is sampled on every
8
- # rising CNT edge, and the byte reaches the data register after eight of
9
- # them. With the bit set the CIA drives CNT itself, toggling it on every
10
- # timer A underflow, so a byte takes sixteen underflows to go out. CNT falls
11
- # as each bit is put on SP, and rises again to clock it in.
12
- #
13
- # The register counts itself empty as soon as the eighth bit is on SP,
14
- # fifteen underflows in: the serial flag follows a few cycles later
15
- # rather than waiting for the sixteenth underflow, and a byte written
16
- # from that point on goes out on the next one.
17
- class Serial
18
- BITS = 8
19
-
20
- # A byte written to the data register reaches the shift register one
21
- # cycle later. The empty countdown starts on the underflow that puts
22
- # the eighth bit on SP and is decremented on that same cycle, so the
23
- # flag lands four cycles after it.
24
- LOAD_DELAY = 1
25
- EMPTY_DELAY = 5
26
- BUSY_DELAY = 5
27
-
28
- # The logic watching the shift register runs a few cycles behind it,
29
- # so the level saying a bit is still on its way out is scheduled
30
- # through a delay line: a bit set at position 7 - n takes effect n
31
- # cycles later. Putting a bit on SP raises the level after one cycle
32
- # and drops it again after two before raising it for good after
33
- # three; the eighth bit skips straight to the last of those. CNT
34
- # rising over a bit lowers the level four cycles later.
35
- IN_FLIGHT = 0x50
36
- LAST_IN_FLIGHT = 0x10
37
- BOUNCE = 0x20
38
- SETTLED = 0x08
39
-
40
- attr_reader :data, :sp_out, :cnt, :cnt_in, :idle
41
- attr_accessor :sp_in
42
-
43
- def initialize(control)
44
- @control = control
45
- @data = 0x0
46
- @shift = 0x0
47
- @steps = 0
48
- @empty_in = nil
49
- @busy_in = nil
50
- @busy = false
51
- @abandoned = false
52
- @pending = nil
53
- @underflow_high = false
54
- @in_flight = false
55
- @flight_up = 0x0
56
- @flight_down = 0x0
57
- @idle = true
58
- # Nothing drives the user port, so both lines float high.
59
- @cnt = true
60
- @cnt_in = true
61
- @sp_in = true
62
- @sp_out = true
63
- end
64
-
65
- # The bits shifted so far, and the byte waiting to go out after the
66
- # one shifting.
67
- attr_reader :steps, :pending
68
-
69
- def shift_register = @shift
70
-
71
- # Sets the data register and the shift register, as a VICE snapshot
72
- # gives them.
73
- def restore_shift(data, shift)
74
- @data = data
75
- @shift = shift
76
- end
77
-
78
- def output?
79
- @control.serial_mode?
80
- end
81
-
82
- # Whether nothing is counting down or in the delay lines, so only
83
- # timer A's underflows reach the register.
84
- def drained? = idle?
85
-
86
- # Takes timer A's underflow line as cycle! would have left it, with
87
- # +underflowed+ its level on the last cycle, for a CIA run without
88
- # the register in use (CIA#fast_forward).
89
- def follow_underflow(underflowed)
90
- @underflow_high = underflowed
91
- @idle = !underflowed
92
- end
93
-
94
- def cnt_in=(level)
95
- @cnt_in = level
96
- @cnt = level unless output?
97
- end
98
-
99
- def save_state(out)
100
- out.int(@data).int(@shift).int(@steps).optional_int(@empty_in).optional_int(@busy_in)
101
- out.boolean(@busy).boolean(@abandoned).optional_int(@pending).boolean(@underflow_high).boolean(@in_flight)
102
- out.int(@flight_up).int(@flight_down).boolean(@idle)
103
- [@cnt, @cnt_in, @sp_in, @sp_out].each { |level| out.boolean(level) }
104
- end
105
-
106
- def load_state(input)
107
- @data = input.int
108
- @shift = input.int
109
- @steps = input.int
110
- @empty_in = input.optional_int
111
- @busy_in = input.optional_int
112
- @busy = input.boolean?
113
- @abandoned = input.boolean?
114
- @pending = input.optional_int
115
- load_lines(input)
116
- end
117
-
118
- def write(value)
119
- @data = value
120
- @pending = LOAD_DELAY
121
- @idle = false
122
- end
123
-
124
- # Clocked every cycle with timer A's underflow line. Yields once the
125
- # shift register reports itself empty, which it does without waiting
126
- # for the underflow that raises CNT over the eighth bit.
127
- def cycle!(underflowed)
128
- return if @idle && !underflowed
129
-
130
- shift(underflowed)
131
- @pending -= 1 if @pending&.positive?
132
- drain_flight
133
- count_busy
134
- @idle = !underflowed && idle?
135
- return if @empty_in.nil?
136
-
137
- @empty_in -= 1
138
- return unless @empty_in.zero?
139
-
140
- @empty_in = nil
141
- @busy = false
142
- yield
143
- end
144
-
145
- # Clocked by rising CNT edges while receiving. Yields once a whole
146
- # byte has arrived.
147
- def rising_edge!
148
- return if output?
149
-
150
- @shift = ((@shift << 1) | (@sp_in ? 1 : 0)) & 0xff
151
- @steps += 1
152
- return unless @steps == BITS
153
-
154
- @steps = 0
155
- @data = @shift
156
- yield if block_given?
157
- end
158
-
159
- # A mode change drops the byte in flight and hands CNT back to
160
- # whichever side drives it now, and yields: that byte counts as gone.
161
- # Handing the port over as an input tears a transmission down, so a
162
- # busy register reports it; the same change latches how far the bit
163
- # in flight had got, and taking the port back reports that.
164
- def reset!
165
- abandoned = output? ? @abandoned : @busy
166
- @abandoned = output? ? false : @in_flight
167
- @in_flight = false
168
- @steps = 0
169
- @empty_in = nil
170
- @busy_in = nil
171
- @busy = false
172
- @pending = nil
173
- @cnt = output? || @cnt_in
174
- yield if abandoned
175
- end
176
-
177
- private
178
-
179
- def load_lines(input)
180
- @underflow_high = input.boolean?
181
- @in_flight = input.boolean?
182
- @flight_up = input.int
183
- @flight_down = input.int
184
- @idle = input.boolean?
185
- @cnt = input.boolean?
186
- @cnt_in = input.boolean?
187
- @sp_in = input.boolean?
188
- @sp_out = input.boolean?
189
- end
190
-
191
- # Without an underflow, a register with nothing counting down and
192
- # nothing in the delay lines has nothing to do on a cycle.
193
- def idle?
194
- !@pending&.positive? && (@flight_up | @flight_down).zero? &&
195
- @busy_in.nil? && @empty_in.nil?
196
- end
197
-
198
- # The shift register picks up a waiting byte whenever the underflow
199
- # line is asserted, but every half-step after that needs a fresh edge
200
- # on it. A zero latch holds the line down for good rather than
201
- # pulsing it, so such a byte stops after its first bit and never
202
- # reaches the data register.
203
- def shift(underflowed)
204
- edge = underflowed && !@underflow_high
205
- @underflow_high = underflowed
206
- clock(edge) if underflowed && output?
207
- end
208
-
209
- def clock(edge)
210
- start if @steps <= 1
211
- if @steps.zero?
212
- @flight_down |= SETTLED
213
- elsif edge || @steps == BITS * 2
214
- half_step
215
- end
216
- end
217
-
218
- def half_step
219
- @steps -= 1
220
- @cnt = @steps.even?
221
- if @cnt
222
- @flight_down |= SETTLED
223
- else
224
- shift_out
225
- end
226
- end
227
-
228
- # The register reads as busy from a few cycles after the first bit
229
- # reaches SP until it reports itself empty over the eighth.
230
- def mark_busy
231
- case @steps
232
- when (BITS * 2) - 1 then @busy_in = BUSY_DELAY
233
- when 1
234
- @empty_in = EMPTY_DELAY
235
- @busy_in = nil
236
- end
237
- end
238
-
239
- def count_busy
240
- return if @busy_in.nil?
241
-
242
- @busy_in -= 1
243
- return unless @busy_in.zero?
244
-
245
- @busy_in = nil
246
- @busy = true
247
- end
248
-
249
- def drain_flight
250
- @in_flight = false if @flight_down.anybits?(0x80)
251
- @flight_down = (@flight_down << 1) & 0xff
252
- @in_flight = true if @flight_up.anybits?(0x80)
253
- @flight_up = (@flight_up << 1) & 0xff
254
- end
255
-
256
- # A byte only moves out of the data register once the one before it
257
- # has put its last bit on SP.
258
- def start
259
- return unless @pending&.zero?
260
-
261
- @pending = nil
262
- @shift = @data
263
- @steps = BITS * 2
264
- end
265
-
266
- def shift_out
267
- @sp_out = @shift.anybits?(0x80)
268
- @shift = (@shift << 1) & 0xff
269
- mark_busy
270
- @flight_up |= @steps == 1 ? LAST_IN_FLIGHT : IN_FLIGHT
271
- @flight_down |= BOUNCE
272
- end
273
- end
274
- end
275
- end
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class CIA
5
- # A snapshot of the chip: everything it holds but its wiring, the ports,
6
- # the PB4 and CNT levels, the timers, the interrupt register, the serial
7
- # port and the TOD clock.
8
- module State
9
- def save_state(out)
10
- out.marker("CIA")
11
- out.int(@data_port_a).int(@data_port_b).int(@data_dir_a).int(@data_dir_b)
12
- out.boolean(@port_b4_high).boolean(@port_b4_driven_high).boolean(@cnt_high).boolean(@cnt_rise)
13
- out.int(@control_a.value).int(@control_b.value)
14
- @ta.save_state(out)
15
- @tb.save_state(out)
16
- @icr.save_state(out)
17
- @serial.save_state(out)
18
- @tod.save_state(out)
19
- end
20
-
21
- def load_state(input)
22
- input.marker("CIA")
23
- @data_port_a = input.int
24
- @data_port_b = input.int
25
- @data_dir_a = input.int
26
- @data_dir_b = input.int
27
- @port_b4_high = input.boolean?
28
- @port_b4_driven_high = input.boolean?
29
- @cnt_high = input.boolean?
30
- @cnt_rise = input.boolean?
31
- @control_a.value = input.int
32
- @control_b.value = input.int
33
- load_parts(input)
34
- end
35
-
36
- private
37
-
38
- def load_parts(input)
39
- @ta.load_state(input)
40
- @tb.load_state(input)
41
- @icr.load_state(input)
42
- @serial.load_state(input)
43
- @tod.load_state(input)
44
- end
45
- end
46
- end
47
- end
@@ -1,206 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class CIA
5
- class Timer
6
- attr_accessor :counter, :latch
7
- attr_reader :control, :underflowed
8
-
9
- def initialize(control)
10
- @control = control
11
- @counter = @latch = 0xffff
12
- @pipe = 0
13
- @load_delay = 0
14
- @reload = false
15
- @underflowed = false
16
- @oneshot_linger = 0
17
- @toggle = true
18
- settle
19
- end
20
-
21
- # The level this timer drives on its port B pin: a square wave that
22
- # flips on each underflow, or a single high tick when one happens.
23
- def output?
24
- control.out_mode? ? @toggle : @underflowed
25
- end
26
-
27
- # Whether the timer is stopped with nothing in its pipeline, so a
28
- # cycle changes nothing.
29
- def idle? = @empty && !started?
30
-
31
- # Whether the timer counts ø2 in continuous mode with nothing pending
32
- # but the reload after an underflow, so fast_forward can run it. A
33
- # latch below 2 is left out.
34
- def free_running?
35
- started? && !@control.run_mode? && @control.value.nobits?(0x20) && @latch >= 2 && @pipe == 0b11 &&
36
- (@load_delay | @oneshot_linger).zero? && (@settled || @reload)
37
- end
38
-
39
- # Runs a free-running timer +cycles+ cycles at once, as cycle! would:
40
- # an underflow every latch + 1 cycles, each one followed by the
41
- # reload. Returns the underflows.
42
- def fast_forward(cycles)
43
- return 0 if cycles.zero?
44
- return after_underflow(cycles, 0) unless @settled
45
-
46
- if cycles < @counter
47
- @counter -= cycles
48
- return 0
49
- end
50
- after_underflow(cycles - @counter, 1)
51
- end
52
-
53
- def cycle!(feed)
54
- feed &&= @control.value & 0x01 != 0
55
- if @settled
56
- return @counter -= 1 if feed && @counter > 1
57
- elsif @empty
58
- enter if feed
59
- return
60
- end
61
- run_tick(feed)
62
- end
63
-
64
- def run_tick(feed)
65
- @underflowed = false
66
- @oneshot_linger -= 1 if @oneshot_linger.positive?
67
- tick(feed)
68
- settle
69
- end
70
-
71
- # The counter, the latch and the pipeline between them. The control
72
- # register is the CIA's to save.
73
- def save_state(out)
74
- out.int(@counter).int(@latch).int(@pipe).int(@load_delay).boolean(@reload).boolean(@underflowed)
75
- out.int(@oneshot_linger).boolean(@toggle).boolean(@settled).boolean(@empty)
76
- end
77
-
78
- def load_state(input)
79
- @counter = input.int
80
- @latch = input.int
81
- @pipe = input.int
82
- @load_delay = input.int
83
- @reload = input.boolean?
84
- @underflowed = input.boolean?
85
- @oneshot_linger = input.int
86
- @toggle = input.boolean?
87
- @settled = input.boolean?
88
- @empty = input.boolean?
89
- end
90
-
91
- def write_control(value)
92
- @toggle = true if value.anybits?(0x01) && !started?
93
- @oneshot_linger = 2 if control.run_mode? && value.nobits?(0x08)
94
- control.value = value & ~0x10
95
- @load_delay = 3 if value.anybits?(0x10)
96
- settle
97
- end
98
-
99
- def write_latch_low(value)
100
- @latch = (@latch & 0xff00) | value
101
- end
102
-
103
- def write_latch_high(value)
104
- @latch = (value << 8) | (@latch & 0xff)
105
- @counter = @latch unless started?
106
- end
107
-
108
- # Whether the timer's PB output toggle is high, and its count pipeline
109
- # as two bits, the newer stage high.
110
- attr_reader :toggle, :pipe
111
-
112
- # Sets the control register without its load strobe, the toggle and
113
- # the count pipeline, as a VICE snapshot gives them.
114
- def restore_pipeline(control, toggle, pipe)
115
- @control.value = control & ~0x10
116
- @toggle = toggle
117
- @pipe = pipe
118
- settle
119
- end
120
-
121
- private
122
-
123
- def started?
124
- @control.value & 0x01 != 0
125
- end
126
-
127
- # Where fast_forward lands +cycles+ after an underflow, with
128
- # +underflows+ underflows counted so far.
129
- def after_underflow(cycles, underflows)
130
- periods, rest = cycles.divmod(@latch + 1)
131
- underflows += periods
132
- @toggle = !@toggle if underflows.odd?
133
- @underflowed = rest.zero?
134
- @reload = rest.zero?
135
- @counter = @latch - (rest.zero? ? 0 : rest - 1)
136
- settle
137
- underflows
138
- end
139
-
140
- def enter
141
- @pipe = 0b10
142
- @empty = false
143
- end
144
-
145
- # With no load, reload or one-shot linger pending, a full pipe only
146
- # counts and an empty one only waits to be fed.
147
- def settle
148
- quiet = (@load_delay | @oneshot_linger).zero? && !@reload
149
- @settled = quiet && @pipe == 0b11
150
- @empty = quiet && @pipe.zero?
151
- end
152
-
153
- def tick(feed)
154
- counting = @pipe.anybits?(0b01)
155
- @pipe = (@pipe >> 1) | (feed ? 0b10 : 0)
156
- loading = @reload || @load_delay == 1
157
- @reload = false
158
-
159
- if loading
160
- reload
161
- elsif premature_underflow?
162
- underflow
163
- elsif counting
164
- count
165
- end
166
-
167
- forced_load
168
- end
169
-
170
- def forced_load
171
- return unless @load_delay.positive?
172
-
173
- @load_delay -= 1
174
- @counter = @latch if @load_delay == 1
175
- end
176
-
177
- # the final pipeline stage, before any pending load lands
178
- def premature_underflow?
179
- @counter.zero? && @pipe.anybits?(0b01) && started?
180
- end
181
-
182
- # A load consumes its tick, so the counter never decrements on it
183
- def reload
184
- @counter = @latch
185
- # A zero latch underflows again on the reload tick while running
186
- underflow if @counter.zero? && started? && @pipe.anybits?(0b01)
187
- end
188
-
189
- def count
190
- @counter -= 1 if @counter.positive?
191
- underflow if @counter.zero? && @pipe.anybits?(0b01)
192
- end
193
-
194
- def underflow
195
- @underflowed = true
196
- @reload = true
197
- @counter = @latch
198
- @toggle = !@toggle
199
- return unless control.run_mode? || @oneshot_linger.positive?
200
-
201
- control.start = false
202
- @pipe = 0
203
- end
204
- end
205
- end
206
- end