badline 0.12.1 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (505) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -0
  3. data/CLAUDE.md +59 -31
  4. data/README.md +1 -1
  5. data/doc/library.md +9 -9
  6. data/doc/pinned-behaviour.md +105 -105
  7. data/doc/snapshots.md +1 -4
  8. data/lib/badline/audio/bare_player.rb +3 -3
  9. data/lib/badline/audio/cli.rb +6 -6
  10. data/lib/badline/audio/jukebox.rb +2 -2
  11. data/lib/badline/audio/machine_player.rb +2 -2
  12. data/lib/badline/{media → audio}/queue.rb +1 -1
  13. data/lib/badline/audio/queued_tune.rb +6 -6
  14. data/lib/badline/audio/renderer.rb +5 -5
  15. data/lib/badline/audio/stereo.rb +1 -1
  16. data/lib/badline/c128/{bus_state.rb → bus/saved_state.rb} +1 -1
  17. data/lib/badline/c128/bus.rb +18 -17
  18. data/lib/badline/c128/color_lines.rb +2 -2
  19. data/lib/badline/c128/cpu.rb +1 -1
  20. data/lib/badline/c128/drives.rb +10 -11
  21. data/lib/badline/c128/fast_serial.rb +5 -5
  22. data/lib/badline/c128/mmu_pages.rb +1 -1
  23. data/lib/badline/c128/modes.rb +2 -2
  24. data/lib/badline/c128/saved_state.rb +21 -47
  25. data/lib/badline/c128/z80.rb +2 -2
  26. data/lib/badline/c128.rb +14 -9
  27. data/lib/badline/{computer → c64}/attachments.rb +4 -6
  28. data/lib/badline/c64/banked_ram/banking.rb +32 -0
  29. data/lib/badline/c64/banked_ram/plus256k.rb +56 -0
  30. data/lib/badline/c64/banked_ram/plus60k.rb +45 -0
  31. data/lib/badline/c64/banked_ram/unexpanded.rb +30 -0
  32. data/lib/badline/c64/banked_ram.rb +23 -0
  33. data/lib/badline/c64/bus/extra_sids.rb +32 -0
  34. data/lib/badline/c64/bus/fittings.rb +40 -0
  35. data/lib/badline/c64/bus/pla.rb +149 -0
  36. data/lib/badline/c64/bus/roms.rb +41 -0
  37. data/lib/badline/c64/bus/saved_state.rb +68 -0
  38. data/lib/badline/c64/bus/sid_slots.rb +44 -0
  39. data/lib/badline/c64/bus.rb +218 -0
  40. data/lib/badline/c64/cartridge/action_replay.rb +128 -0
  41. data/lib/badline/c64/cartridge/atomic_power.rb +26 -0
  42. data/lib/badline/c64/cartridge/bank.rb +83 -0
  43. data/lib/badline/c64/cartridge/comal80.rb +52 -0
  44. data/lib/badline/c64/cartridge/dinamic.rb +36 -0
  45. data/lib/badline/c64/cartridge/easy_flash.rb +147 -0
  46. data/lib/badline/c64/cartridge/epyx_fastload.rb +81 -0
  47. data/lib/badline/c64/cartridge/final_cartridge3.rb +91 -0
  48. data/lib/badline/c64/cartridge/flash/saved_state.rb +40 -0
  49. data/lib/badline/c64/cartridge/flash.rb +279 -0
  50. data/lib/badline/c64/cartridge/freezer.rb +35 -0
  51. data/lib/badline/c64/cartridge/fun_play.rb +40 -0
  52. data/lib/badline/c64/cartridge/g_mod2.rb +76 -0
  53. data/lib/badline/c64/cartridge/game_system.rb +42 -0
  54. data/lib/badline/c64/cartridge/geo_ram.rb +81 -0
  55. data/lib/badline/c64/cartridge/kcs_power.rb +77 -0
  56. data/lib/badline/c64/cartridge/mach5.rb +34 -0
  57. data/lib/badline/c64/cartridge/magic_desk.rb +32 -0
  58. data/lib/badline/c64/cartridge/ocean.rb +37 -0
  59. data/lib/badline/c64/cartridge/pagefox.rb +70 -0
  60. data/lib/badline/c64/cartridge/retro_replay/saved_state.rb +47 -0
  61. data/lib/badline/c64/cartridge/retro_replay.rb +286 -0
  62. data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
  63. data/lib/badline/c64/cartridge/rgcd.rb +60 -0
  64. data/lib/badline/c64/cartridge/saved_state.rb +63 -0
  65. data/lib/badline/c64/cartridge/simons_basic.rb +37 -0
  66. data/lib/badline/c64/cartridge/standard.rb +17 -0
  67. data/lib/badline/c64/cartridge/super_games.rb +50 -0
  68. data/lib/badline/c64/cartridge/westermann.rb +32 -0
  69. data/lib/badline/c64/cartridge/zaxxon.rb +68 -0
  70. data/lib/badline/c64/cartridge.rb +258 -0
  71. data/lib/badline/c64/color_memory.rb +27 -0
  72. data/lib/badline/{computer → c64}/common.rb +2 -2
  73. data/lib/badline/{computer → c64}/kernal_traps.rb +18 -18
  74. data/lib/badline/c64/reu/dma/saved_state.rb +52 -0
  75. data/lib/badline/c64/reu/dma.rb +275 -0
  76. data/lib/badline/c64/reu/ram.rb +109 -0
  77. data/lib/badline/c64/reu/saved_state.rb +55 -0
  78. data/lib/badline/c64/reu/trigger.rb +34 -0
  79. data/lib/badline/c64/reu.rb +291 -0
  80. data/lib/badline/{computer → c64}/saved_state.rb +13 -18
  81. data/lib/badline/{computer → c64}/true_drives.rb +11 -11
  82. data/lib/badline/{computer.rb → c64.rb} +18 -13
  83. data/lib/badline/chips/cia/fast_forward.rb +62 -0
  84. data/lib/badline/chips/cia/interrupt_register.rb +145 -0
  85. data/lib/badline/chips/cia/saved_state.rb +49 -0
  86. data/lib/badline/chips/cia/serial/saved_state.rb +45 -0
  87. data/lib/badline/chips/cia/serial.rb +250 -0
  88. data/lib/badline/chips/cia/time_of_day.rb +232 -0
  89. data/lib/badline/chips/cia/timer.rb +208 -0
  90. data/lib/badline/chips/cia.rb +281 -0
  91. data/lib/badline/chips/cpu/addressing.rb +133 -0
  92. data/lib/badline/chips/cpu/boundary.rb +56 -0
  93. data/lib/badline/chips/cpu/core.rb +167 -0
  94. data/lib/badline/chips/cpu/instruction.rb +338 -0
  95. data/lib/badline/chips/cpu/instruction_set/arithmetic.rb +118 -0
  96. data/lib/badline/chips/cpu/instruction_set/bitwise.rb +130 -0
  97. data/lib/badline/chips/cpu/instruction_set/branch.rb +83 -0
  98. data/lib/badline/chips/cpu/instruction_set/flag.rb +67 -0
  99. data/lib/badline/chips/cpu/instruction_set/illegal.rb +274 -0
  100. data/lib/badline/chips/cpu/instruction_set/inc_dec.rb +73 -0
  101. data/lib/badline/chips/cpu/instruction_set/stack.rb +56 -0
  102. data/lib/badline/chips/cpu/instruction_set/transfer.rb +141 -0
  103. data/lib/badline/chips/cpu/instruction_set.rb +59 -0
  104. data/lib/badline/chips/cpu/interrupts.rb +108 -0
  105. data/lib/badline/chips/cpu/microcode.rb +179 -0
  106. data/lib/badline/chips/cpu/operations.rb +90 -0
  107. data/lib/badline/chips/cpu/port.rb +116 -0
  108. data/lib/badline/chips/cpu/saved_state.rb +117 -0
  109. data/lib/badline/chips/cpu/stack_operations.rb +84 -0
  110. data/lib/badline/chips/cpu/traps.rb +23 -0
  111. data/lib/badline/chips/cpu.rb +12 -0
  112. data/lib/badline/chips/sid/catch_up.rb +122 -0
  113. data/lib/badline/chips/sid/decimator.rb +66 -0
  114. data/lib/badline/chips/sid/envelope/saved_state.rb +70 -0
  115. data/lib/badline/chips/sid/envelope.rb +241 -0
  116. data/lib/badline/chips/sid/filter/saved_state.rb +42 -0
  117. data/lib/badline/chips/sid/filter.rb +241 -0
  118. data/lib/badline/chips/sid/saved_state.rb +52 -0
  119. data/lib/badline/chips/sid/voice.rb +79 -0
  120. data/lib/badline/chips/sid/waveform/combined.rb +128 -0
  121. data/lib/badline/chips/sid/waveform/fast_forward.rb +107 -0
  122. data/lib/badline/chips/sid/waveform/noise_writeback.rb +124 -0
  123. data/lib/badline/chips/sid/waveform/saved_state.rb +68 -0
  124. data/lib/badline/chips/sid/waveform.rb +307 -0
  125. data/lib/badline/chips/sid.rb +265 -0
  126. data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
  127. data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -1
  128. data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -1
  129. data/lib/badline/chips/vdc/saved_state.rb +36 -0
  130. data/lib/badline/{c128 → chips}/vdc/window.rb +1 -1
  131. data/lib/badline/{c128 → chips}/vdc.rb +7 -31
  132. data/lib/badline/chips/via/control_lines.rb +124 -0
  133. data/lib/badline/chips/via/fast_forward.rb +55 -0
  134. data/lib/badline/chips/via/interrupt_register.rb +69 -0
  135. data/lib/badline/chips/via/saved_state.rb +44 -0
  136. data/lib/badline/chips/via/shift_register.rb +182 -0
  137. data/lib/badline/chips/via/timer1.rb +133 -0
  138. data/lib/badline/chips/via/timer2.rb +135 -0
  139. data/lib/badline/chips/via.rb +268 -0
  140. data/lib/badline/chips/vic/bank.rb +135 -0
  141. data/lib/badline/chips/vic/border_mask.rb +88 -0
  142. data/lib/badline/chips/vic/collisions.rb +117 -0
  143. data/lib/badline/chips/vic/color_patches.rb +49 -0
  144. data/lib/badline/chips/vic/display_state.rb +187 -0
  145. data/lib/badline/chips/vic/graphics_mode.rb +166 -0
  146. data/lib/badline/chips/vic/graphics_shifter/saved_state.rb +40 -0
  147. data/lib/badline/chips/vic/graphics_shifter.rb +187 -0
  148. data/lib/badline/chips/vic/register_log.rb +83 -0
  149. data/lib/badline/chips/vic/registers.rb +197 -0
  150. data/lib/badline/chips/vic/saved_state.rb +82 -0
  151. data/lib/badline/chips/vic/sequencer/saved_state.rb +91 -0
  152. data/lib/badline/chips/vic/sequencer.rb +277 -0
  153. data/lib/badline/chips/vic/sequencer_output.rb +118 -0
  154. data/lib/badline/chips/vic/sprite/internal_bus.rb +70 -0
  155. data/lib/badline/chips/vic/sprite/saved_state.rb +66 -0
  156. data/lib/badline/chips/vic/sprite/shifter.rb +148 -0
  157. data/lib/badline/chips/vic/sprite/timing.rb +58 -0
  158. data/lib/badline/chips/vic/sprite.rb +339 -0
  159. data/lib/badline/chips/vic/sprites/saved_state.rb +59 -0
  160. data/lib/badline/chips/vic/sprites.rb +284 -0
  161. data/lib/badline/chips/vic.rb +783 -0
  162. data/lib/badline/chips/vic_i/painter/saved_state.rb +40 -0
  163. data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +6 -30
  164. data/lib/badline/{vic20/vic → chips/vic_i}/saved_state.rb +2 -2
  165. data/lib/badline/chips/vic_i/sound/output.rb +85 -0
  166. data/lib/badline/chips/vic_i/sound.rb +235 -0
  167. data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
  168. data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +5 -5
  169. data/lib/badline/chips/z80/arithmetic.rb +119 -0
  170. data/lib/badline/chips/z80/bit_page.rb +57 -0
  171. data/lib/badline/chips/z80/block_io.rb +60 -0
  172. data/lib/badline/chips/z80/block_transfers.rb +61 -0
  173. data/lib/badline/chips/z80/bus_cycles.rb +113 -0
  174. data/lib/badline/chips/z80/core.rb +115 -0
  175. data/lib/badline/chips/z80/exchanges.rb +52 -0
  176. data/lib/badline/chips/z80/extended_page.rb +91 -0
  177. data/lib/badline/chips/z80/flags.rb +39 -0
  178. data/lib/badline/chips/z80/interrupt_acceptance.rb +48 -0
  179. data/lib/badline/chips/z80/jumps.rb +84 -0
  180. data/lib/badline/chips/z80/loads.rb +100 -0
  181. data/lib/badline/chips/z80/main_page.rb +136 -0
  182. data/lib/badline/chips/z80/registers.rb +122 -0
  183. data/lib/badline/chips/z80/saved_state.rb +71 -0
  184. data/lib/badline/chips/z80/shifts.rb +66 -0
  185. data/lib/badline/chips/z80.rb +13 -0
  186. data/lib/badline/core.rb +26 -28
  187. data/lib/badline/drives/datasette/saved_state.rb +37 -0
  188. data/lib/badline/drives/datasette.rb +140 -0
  189. data/lib/badline/drives/engine/core.rb +149 -0
  190. data/lib/badline/drives/engine/fast_serial.rb +75 -0
  191. data/lib/badline/drives/engine/idle.rb +127 -0
  192. data/lib/badline/drives/engine/idle_cpu.rb +30 -0
  193. data/lib/badline/drives/engine/orbit.rb +81 -0
  194. data/lib/badline/drives/engine/serial_lines.rb +75 -0
  195. data/lib/badline/drives/engine/sleep.rb +114 -0
  196. data/lib/badline/drives/engine/vias.rb +86 -0
  197. data/lib/badline/drives/engine/watch.rb +152 -0
  198. data/lib/badline/drives/engine.rb +11 -0
  199. data/lib/badline/drives/model1541/bus.rb +88 -0
  200. data/lib/badline/drives/model1541/byte_ready.rb +50 -0
  201. data/lib/badline/drives/model1541/cpu.rb +13 -0
  202. data/lib/badline/drives/model1541/disk/saved_state.rb +88 -0
  203. data/lib/badline/drives/model1541/disk.rb +317 -0
  204. data/lib/badline/drives/model1541/disk_via.rb +38 -0
  205. data/lib/badline/drives/model1541/gcr.rb +59 -0
  206. data/lib/badline/drives/model1541/mechanism/saved_state.rb +72 -0
  207. data/lib/badline/drives/model1541/mechanism.rb +315 -0
  208. data/lib/badline/drives/model1541/rotation.rb +123 -0
  209. data/lib/badline/drives/model1541/saved_state.rb +44 -0
  210. data/lib/badline/drives/model1541/sector_reader.rb +78 -0
  211. data/lib/badline/drives/model1541/serial_port.rb +20 -0
  212. data/lib/badline/drives/model1541/track.rb +100 -0
  213. data/lib/badline/drives/model1541.rb +81 -0
  214. data/lib/badline/drives/model1571/bus.rb +113 -0
  215. data/lib/badline/drives/model1571/cpu.rb +13 -0
  216. data/lib/badline/drives/model1571/saved_state.rb +47 -0
  217. data/lib/badline/drives/model1571/serial_port.rb +39 -0
  218. data/lib/badline/drives/model1571/serial_via.rb +27 -0
  219. data/lib/badline/drives/model1571/wd1770.rb +122 -0
  220. data/lib/badline/drives/model1571.rb +142 -0
  221. data/lib/badline/drives/model1581/bus.rb +139 -0
  222. data/lib/badline/drives/model1581/cpu.rb +13 -0
  223. data/lib/badline/drives/model1581/disk/saved_state.rb +89 -0
  224. data/lib/badline/drives/model1581/disk.rb +137 -0
  225. data/lib/badline/drives/model1581/mechanism.rb +119 -0
  226. data/lib/badline/drives/model1581/saved_state.rb +42 -0
  227. data/lib/badline/drives/model1581/serial_port.rb +54 -0
  228. data/lib/badline/drives/model1581/slot.rb +79 -0
  229. data/lib/badline/drives/model1581/track.rb +102 -0
  230. data/lib/badline/drives/model1581/track_bytes.rb +77 -0
  231. data/lib/badline/drives/model1581/wd1772/registers.rb +91 -0
  232. data/lib/badline/drives/model1581/wd1772/saved_state.rb +68 -0
  233. data/lib/badline/drives/model1581/wd1772/sector_writes.rb +75 -0
  234. data/lib/badline/drives/model1581/wd1772/sectors.rb +152 -0
  235. data/lib/badline/drives/model1581/wd1772/stepping.rb +111 -0
  236. data/lib/badline/drives/model1581/wd1772/tracks.rb +127 -0
  237. data/lib/badline/drives/model1581/wd1772/turn.rb +75 -0
  238. data/lib/badline/drives/model1581/wd1772.rb +218 -0
  239. data/lib/badline/drives/model1581.rb +206 -0
  240. data/lib/badline/drives/serial_bus.rb +161 -0
  241. data/lib/badline/frontend/boot.rb +3 -3
  242. data/lib/badline/frontend/machine_window.rb +3 -1
  243. data/lib/badline/frontend/player/filter_view.rb +1 -1
  244. data/lib/badline/frontend/player/player_controller.rb +2 -2
  245. data/lib/badline/frontend/player/player_screen.rb +1 -0
  246. data/lib/badline/frontend/player/theme.rb +7 -7
  247. data/lib/badline/frontend/timeline.rb +3 -3
  248. data/lib/badline/input/control_ports.rb +78 -0
  249. data/lib/badline/input/joystick.rb +27 -0
  250. data/lib/badline/input/keyboard.rb +114 -0
  251. data/lib/badline/input.rb +3 -0
  252. data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
  253. data/lib/badline/kernal_trap/dos/channel.rb +183 -0
  254. data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -1
  255. data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -1
  256. data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
  257. data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -1
  258. data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -1
  259. data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
  260. data/lib/badline/kernal_trap/{drive.rb → dos.rb} +11 -10
  261. data/lib/badline/kernal_trap/load.rb +5 -5
  262. data/lib/badline/kernal_trap/save.rb +4 -4
  263. data/lib/badline/kernal_trap/serial.rb +7 -7
  264. data/lib/badline/kernal_trap.rb +1 -2
  265. data/lib/badline/machine/clocking.rb +1 -1
  266. data/lib/badline/machine.rb +5 -5
  267. data/lib/badline/media/true_drive.rb +1 -1
  268. data/lib/badline/media/tune.rb +2 -2
  269. data/lib/badline/media.rb +3 -3
  270. data/lib/badline/model.rb +1 -1
  271. data/lib/badline/roms/README +6 -6
  272. data/lib/badline/sdl.rb +1 -0
  273. data/lib/badline/{storage/sid_file.rb → sid_tune/file.rb} +3 -3
  274. data/lib/badline/{storage → sid_tune}/hvsc.rb +7 -7
  275. data/lib/badline/{storage → sid_tune}/song_lengths.rb +2 -2
  276. data/lib/badline/{storage → sid_tune}/stil/credit.rb +1 -1
  277. data/lib/badline/{storage → sid_tune}/stil.rb +3 -3
  278. data/lib/badline/sid_tune.rb +6 -0
  279. data/lib/badline/snapshot/c128_setup.rb +43 -0
  280. data/lib/badline/snapshot/c64_setup.rb +79 -0
  281. data/lib/badline/snapshot/image.rb +5 -25
  282. data/lib/badline/snapshot/machine_state.rb +1 -1
  283. data/lib/badline/snapshot/setup.rb +22 -66
  284. data/lib/badline/snapshot/state.rb +8 -18
  285. data/lib/badline/snapshot/storage_setup.rb +68 -0
  286. data/lib/badline/snapshot/vic20_setup.rb +37 -0
  287. data/lib/badline/snapshot/vice/c64_mem.rb +1 -1
  288. data/lib/badline/snapshot/vice/restore.rb +1 -1
  289. data/lib/badline/snapshot/vice/reu1764.rb +1 -1
  290. data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
  291. data/lib/badline/snapshot/vice.rb +7 -5
  292. data/lib/badline/snapshot.rb +3 -4
  293. data/lib/badline/storage/d64_image.rb +0 -2
  294. data/lib/badline/storage/d71_image.rb +0 -2
  295. data/lib/badline/storage/d81_image.rb +0 -2
  296. data/lib/badline/storage/disk_image.rb +3 -6
  297. data/lib/badline/storage/g64_image.rb +2 -2
  298. data/lib/badline/storage/host_directory.rb +0 -5
  299. data/lib/badline/storage/t64.rb +2 -8
  300. data/lib/badline/storage/unavailable.rb +1 -1
  301. data/lib/badline/storage.rb +0 -37
  302. data/lib/badline/support/c128_checkpoint.rb +39 -0
  303. data/lib/badline/support/checkpoint.rb +108 -0
  304. data/lib/badline/support/vic20_checkpoint.rb +38 -0
  305. data/lib/badline/support.rb +5 -0
  306. data/lib/badline/version.rb +1 -1
  307. data/lib/badline/vic20/attachments.rb +5 -5
  308. data/lib/badline/vic20/bus/saved_state.rb +35 -0
  309. data/lib/badline/vic20/bus.rb +3 -25
  310. data/lib/badline/vic20/cpu.rb +1 -1
  311. data/lib/badline/vic20/port_wiring.rb +4 -4
  312. data/lib/badline/vic20/saved_state.rb +16 -30
  313. data/lib/badline/vic20/user_via_ports.rb +2 -2
  314. data/lib/badline/vic20.rb +19 -14
  315. metadata +245 -221
  316. data/lib/badline/address_bus/extra_sids.rb +0 -30
  317. data/lib/badline/address_bus/fittings.rb +0 -38
  318. data/lib/badline/address_bus/pla.rb +0 -147
  319. data/lib/badline/address_bus/roms.rb +0 -39
  320. data/lib/badline/address_bus/saved_state.rb +0 -66
  321. data/lib/badline/address_bus/sid_slots.rb +0 -42
  322. data/lib/badline/address_bus.rb +0 -216
  323. data/lib/badline/cartridge/action_replay.rb +0 -126
  324. data/lib/badline/cartridge/atomic_power.rb +0 -24
  325. data/lib/badline/cartridge/bank.rb +0 -81
  326. data/lib/badline/cartridge/comal80.rb +0 -50
  327. data/lib/badline/cartridge/dinamic.rb +0 -34
  328. data/lib/badline/cartridge/easy_flash.rb +0 -145
  329. data/lib/badline/cartridge/epyx_fastload.rb +0 -79
  330. data/lib/badline/cartridge/final_cartridge3.rb +0 -89
  331. data/lib/badline/cartridge/flash.rb +0 -306
  332. data/lib/badline/cartridge/freezer.rb +0 -33
  333. data/lib/badline/cartridge/fun_play.rb +0 -38
  334. data/lib/badline/cartridge/g_mod2.rb +0 -74
  335. data/lib/badline/cartridge/game_system.rb +0 -40
  336. data/lib/badline/cartridge/geo_ram.rb +0 -79
  337. data/lib/badline/cartridge/kcs_power.rb +0 -75
  338. data/lib/badline/cartridge/mach5.rb +0 -32
  339. data/lib/badline/cartridge/magic_desk.rb +0 -30
  340. data/lib/badline/cartridge/ocean.rb +0 -35
  341. data/lib/badline/cartridge/pagefox.rb +0 -68
  342. data/lib/badline/cartridge/retro_replay.rb +0 -320
  343. data/lib/badline/cartridge/rex_utility.rb +0 -29
  344. data/lib/badline/cartridge/rgcd.rb +0 -58
  345. data/lib/badline/cartridge/simons_basic.rb +0 -35
  346. data/lib/badline/cartridge/standard.rb +0 -15
  347. data/lib/badline/cartridge/super_games.rb +0 -48
  348. data/lib/badline/cartridge/westermann.rb +0 -30
  349. data/lib/badline/cartridge/zaxxon.rb +0 -66
  350. data/lib/badline/cartridge.rb +0 -303
  351. data/lib/badline/checkpoint.rb +0 -98
  352. data/lib/badline/cia/fast_forward.rb +0 -60
  353. data/lib/badline/cia/interrupt_register.rb +0 -143
  354. data/lib/badline/cia/serial.rb +0 -275
  355. data/lib/badline/cia/state.rb +0 -47
  356. data/lib/badline/cia/timer.rb +0 -206
  357. data/lib/badline/cia.rb +0 -279
  358. data/lib/badline/color_memory.rb +0 -25
  359. data/lib/badline/control_ports.rb +0 -76
  360. data/lib/badline/cpu/addressing.rb +0 -131
  361. data/lib/badline/cpu/boundary.rb +0 -54
  362. data/lib/badline/cpu/core.rb +0 -165
  363. data/lib/badline/cpu/microcode.rb +0 -177
  364. data/lib/badline/cpu/operations.rb +0 -88
  365. data/lib/badline/cpu/saved_state.rb +0 -115
  366. data/lib/badline/cpu/stack_operations.rb +0 -82
  367. data/lib/badline/cpu.rb +0 -10
  368. data/lib/badline/cpu_port.rb +0 -112
  369. data/lib/badline/datasette.rb +0 -161
  370. data/lib/badline/drive/core.rb +0 -147
  371. data/lib/badline/drive/fast_serial.rb +0 -73
  372. data/lib/badline/drive/idle.rb +0 -125
  373. data/lib/badline/drive/idle_cpu.rb +0 -28
  374. data/lib/badline/drive/orbit.rb +0 -79
  375. data/lib/badline/drive/serial_lines.rb +0 -73
  376. data/lib/badline/drive/sleep.rb +0 -112
  377. data/lib/badline/drive/vias.rb +0 -84
  378. data/lib/badline/drive/watch.rb +0 -150
  379. data/lib/badline/drive.rb +0 -11
  380. data/lib/badline/drive1541/bus.rb +0 -86
  381. data/lib/badline/drive1541/byte_ready.rb +0 -48
  382. data/lib/badline/drive1541/cpu.rb +0 -11
  383. data/lib/badline/drive1541/disk.rb +0 -315
  384. data/lib/badline/drive1541/disk_state.rb +0 -86
  385. data/lib/badline/drive1541/disk_via.rb +0 -36
  386. data/lib/badline/drive1541/gcr.rb +0 -57
  387. data/lib/badline/drive1541/mechanism.rb +0 -313
  388. data/lib/badline/drive1541/mechanism_state.rb +0 -68
  389. data/lib/badline/drive1541/rotation.rb +0 -121
  390. data/lib/badline/drive1541/sector_reader.rb +0 -76
  391. data/lib/badline/drive1541/serial_port.rb +0 -18
  392. data/lib/badline/drive1541/track.rb +0 -98
  393. data/lib/badline/drive1541.rb +0 -111
  394. data/lib/badline/drive1571/bus.rb +0 -111
  395. data/lib/badline/drive1571/cpu.rb +0 -11
  396. data/lib/badline/drive1571/serial_port.rb +0 -37
  397. data/lib/badline/drive1571/serial_via.rb +0 -25
  398. data/lib/badline/drive1571/wd1770.rb +0 -120
  399. data/lib/badline/drive1571.rb +0 -175
  400. data/lib/badline/drive1581/bus.rb +0 -137
  401. data/lib/badline/drive1581/cpu.rb +0 -11
  402. data/lib/badline/drive1581/disk.rb +0 -135
  403. data/lib/badline/drive1581/disk_state.rb +0 -87
  404. data/lib/badline/drive1581/mechanism.rb +0 -117
  405. data/lib/badline/drive1581/serial_port.rb +0 -52
  406. data/lib/badline/drive1581/slot.rb +0 -78
  407. data/lib/badline/drive1581/track.rb +0 -100
  408. data/lib/badline/drive1581/track_bytes.rb +0 -75
  409. data/lib/badline/drive1581/wd1772/registers.rb +0 -89
  410. data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
  411. data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
  412. data/lib/badline/drive1581/wd1772/state.rb +0 -66
  413. data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
  414. data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
  415. data/lib/badline/drive1581/wd1772/turn.rb +0 -73
  416. data/lib/badline/drive1581/wd1772.rb +0 -216
  417. data/lib/badline/drive1581.rb +0 -233
  418. data/lib/badline/iec_bus.rb +0 -159
  419. data/lib/badline/instruction.rb +0 -334
  420. data/lib/badline/instruction_set/arithmetic.rb +0 -114
  421. data/lib/badline/instruction_set/bitwise.rb +0 -126
  422. data/lib/badline/instruction_set/branch.rb +0 -79
  423. data/lib/badline/instruction_set/flag.rb +0 -63
  424. data/lib/badline/instruction_set/illegal.rb +0 -270
  425. data/lib/badline/instruction_set/inc_dec.rb +0 -69
  426. data/lib/badline/instruction_set/stack.rb +0 -52
  427. data/lib/badline/instruction_set/transfer.rb +0 -137
  428. data/lib/badline/instruction_set.rb +0 -55
  429. data/lib/badline/interrupts.rb +0 -104
  430. data/lib/badline/joystick.rb +0 -25
  431. data/lib/badline/kernal_trap/channel.rb +0 -181
  432. data/lib/badline/keyboard.rb +0 -112
  433. data/lib/badline/ram_expansion/banking.rb +0 -30
  434. data/lib/badline/ram_expansion/plus256k.rb +0 -54
  435. data/lib/badline/ram_expansion/plus60k.rb +0 -43
  436. data/lib/badline/ram_expansion/unexpanded.rb +0 -28
  437. data/lib/badline/ram_expansion.rb +0 -21
  438. data/lib/badline/reu/dma/saved_state.rb +0 -50
  439. data/lib/badline/reu/dma.rb +0 -273
  440. data/lib/badline/reu/ram.rb +0 -107
  441. data/lib/badline/reu/saved_state.rb +0 -80
  442. data/lib/badline/reu/trigger.rb +0 -32
  443. data/lib/badline/reu.rb +0 -289
  444. data/lib/badline/sid/catch_up.rb +0 -120
  445. data/lib/badline/sid/decimator.rb +0 -64
  446. data/lib/badline/sid/envelope/state.rb +0 -68
  447. data/lib/badline/sid/envelope.rb +0 -239
  448. data/lib/badline/sid/filter.rb +0 -263
  449. data/lib/badline/sid/voice.rb +0 -77
  450. data/lib/badline/sid/waveform/combined.rb +0 -126
  451. data/lib/badline/sid/waveform/fast_forward.rb +0 -105
  452. data/lib/badline/sid/waveform/noise_writeback.rb +0 -122
  453. data/lib/badline/sid/waveform/state.rb +0 -66
  454. data/lib/badline/sid/waveform.rb +0 -305
  455. data/lib/badline/sid.rb +0 -303
  456. data/lib/badline/time_of_day.rb +0 -228
  457. data/lib/badline/traps.rb +0 -19
  458. data/lib/badline/via/control_lines.rb +0 -122
  459. data/lib/badline/via/fast_forward.rb +0 -53
  460. data/lib/badline/via/interrupt_register.rb +0 -67
  461. data/lib/badline/via/shift_register.rb +0 -180
  462. data/lib/badline/via/state.rb +0 -42
  463. data/lib/badline/via/timer1.rb +0 -131
  464. data/lib/badline/via/timer2.rb +0 -133
  465. data/lib/badline/via.rb +0 -266
  466. data/lib/badline/vic/bank.rb +0 -133
  467. data/lib/badline/vic/border_mask.rb +0 -86
  468. data/lib/badline/vic/collisions.rb +0 -115
  469. data/lib/badline/vic/color_patches.rb +0 -47
  470. data/lib/badline/vic/display_state.rb +0 -185
  471. data/lib/badline/vic/graphics_mode.rb +0 -164
  472. data/lib/badline/vic/graphics_shifter.rb +0 -207
  473. data/lib/badline/vic/register_log.rb +0 -81
  474. data/lib/badline/vic/registers.rb +0 -195
  475. data/lib/badline/vic/sequencer.rb +0 -275
  476. data/lib/badline/vic/sequencer_output.rb +0 -116
  477. data/lib/badline/vic/sequencer_state.rb +0 -89
  478. data/lib/badline/vic/sprite/internal_bus.rb +0 -68
  479. data/lib/badline/vic/sprite/saved_state.rb +0 -64
  480. data/lib/badline/vic/sprite/shifter.rb +0 -146
  481. data/lib/badline/vic/sprite/timing.rb +0 -56
  482. data/lib/badline/vic/sprite.rb +0 -337
  483. data/lib/badline/vic/sprites.rb +0 -282
  484. data/lib/badline/vic/sprites_state.rb +0 -57
  485. data/lib/badline/vic.rb +0 -853
  486. data/lib/badline/vic20/sound/output.rb +0 -83
  487. data/lib/badline/vic20/sound.rb +0 -233
  488. data/lib/badline/z80/arithmetic.rb +0 -117
  489. data/lib/badline/z80/bit_page.rb +0 -55
  490. data/lib/badline/z80/block_io.rb +0 -58
  491. data/lib/badline/z80/block_transfers.rb +0 -59
  492. data/lib/badline/z80/bus_cycles.rb +0 -111
  493. data/lib/badline/z80/core.rb +0 -113
  494. data/lib/badline/z80/exchanges.rb +0 -50
  495. data/lib/badline/z80/extended_page.rb +0 -89
  496. data/lib/badline/z80/flags.rb +0 -37
  497. data/lib/badline/z80/interrupt_acceptance.rb +0 -46
  498. data/lib/badline/z80/jumps.rb +0 -82
  499. data/lib/badline/z80/loads.rb +0 -98
  500. data/lib/badline/z80/main_page.rb +0 -134
  501. data/lib/badline/z80/registers.rb +0 -120
  502. data/lib/badline/z80/saved_state.rb +0 -69
  503. data/lib/badline/z80/shifts.rb +0 -64
  504. data/lib/badline/z80.rb +0 -11
  505. /data/lib/badline/snapshot/{fields.rb → vice/fields.rb} +0 -0
@@ -0,0 +1,182 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Chips
5
+ class VIA
6
+ # The 6522's shift register, with the CB1 clock and CB2 data lines it
7
+ # takes over in every mode but the first.
8
+ #
9
+ # ACR bits 4-2 pick the mode. Modes 1 to 3 shift in, left, with the new
10
+ # bit taken from CB2 into bit 0 on each rising CB1 edge. Modes 4 to 7
11
+ # shift out: each falling CB1 edge puts bit 7 on CB2 and rotates it back
12
+ # round into bit 0, so after eight bits the byte is back where it
13
+ # started. Modes 1, 4 and 5 clock off timer 2, modes 2 and 6 off φ2, and
14
+ # modes 3 and 7 off whatever drives CB1 from outside.
15
+ #
16
+ # Under its own clock the register drives CB1, idling high. Reading or
17
+ # writing the data register starts a byte, but only while the register
18
+ # is idle and enabled: an access in mode 0, or one before the eighth bit
19
+ # is in, leaves the count alone. CB1 falls on the first clock tick of
20
+ # the byte and rises on the second, and so on, so a byte is eight pulses
21
+ # over sixteen ticks. The interrupt flag is set on the tick that raises
22
+ # CB1 over the eighth bit, and CB1 then stays high until the next
23
+ # access.
24
+ #
25
+ # In modes 2 and 6 a tick is a φ2 cycle, from the second cycle after
26
+ # the access on, which makes a byte sixteen cycles. In modes 1, 4 and 5
27
+ # it comes two cycles after each timer 2 low byte underflow, on the
28
+ # cycle after the low byte reloads, which makes a byte sixteen
29
+ # underflows. Mode 4 never stops and never interrupts: its counter is
30
+ # disabled, and the byte goes round and round.
31
+ #
32
+ # Under an external clock the register shifts on every CB1 edge, access
33
+ # or not. The access only arms the counter: the flag is set on the eighth
34
+ # rising edge after it, and the counter then waits for the next access.
35
+ class ShiftRegister
36
+ DISABLED = 0
37
+ IN_T2 = 1
38
+ IN_PHI2 = 2
39
+ IN_EXTERNAL = 3
40
+ OUT_FREE_RUNNING = 4
41
+ OUT_T2 = 5
42
+ OUT_PHI2 = 6
43
+ OUT_EXTERNAL = 7
44
+
45
+ attr_reader :mode, :data
46
+ attr_accessor :cb2_input
47
+
48
+ def initialize
49
+ @mode = DISABLED
50
+ @data = 0x00
51
+ # Bits still to count before the flag, zero when the counter is idle.
52
+ @bits = 0
53
+ # The clock's last two cycles, newest in bit 0: timer 2 low byte
54
+ # underflows in modes 1, 4 and 5, and whether the byte has started
55
+ # in modes 2 and 6.
56
+ @delay = 0
57
+ @clock = true
58
+ @cb2 = true
59
+ # Nothing drives CB2 from outside, so it floats high.
60
+ @cb2_input = true
61
+ end
62
+
63
+ def mode=(value)
64
+ @mode = value & 0x07
65
+ end
66
+
67
+ def data=(value)
68
+ @data = value & 0xff
69
+ end
70
+
71
+ # A read or write of the data register, which starts a byte if the
72
+ # register is idle and enabled.
73
+ def access!
74
+ return if @mode == DISABLED || @bits.nonzero?
75
+
76
+ @bits = 8
77
+ @delay = 0 if @mode == IN_PHI2 || @mode == OUT_PHI2
78
+ end
79
+
80
+ # Whether the register is counting bits off its own clock, which
81
+ # changes it from cycle to cycle.
82
+ def clocking? = @bits.nonzero? && internal_clock?
83
+
84
+ def save_state(out)
85
+ out.int(@mode).int(@data).int(@bits).int(@delay).boolean(@clock).boolean(@cb2).boolean(@cb2_input)
86
+ end
87
+
88
+ def load_state(input)
89
+ @mode = input.int
90
+ @data = input.int
91
+ @bits = input.int
92
+ @delay = input.int
93
+ @clock = input.boolean?
94
+ @cb2 = input.boolean?
95
+ @cb2_input = input.boolean?
96
+ end
97
+
98
+ # Everything the register holds, for comparing it at two points.
99
+ def state = [@mode, @data, @bits, @delay, @clock, @cb2, @cb2_input]
100
+
101
+ # The CB1 level the register drives, or nil when CB1 is an input.
102
+ def cb1_output
103
+ internal_clock? ? @clock : nil
104
+ end
105
+
106
+ # The CB2 level the register drives, or nil when it doesn't.
107
+ def cb2_output
108
+ @mode >= OUT_FREE_RUNNING ? @cb2 : nil
109
+ end
110
+
111
+ # Clocked once per φ2 cycle, with whether timer 2's low byte underflowed
112
+ # on it. Returns true on the cycle that sets the interrupt flag.
113
+ def cycle!(t2_low_underflow)
114
+ case @mode
115
+ when IN_PHI2, OUT_PHI2 then @bits.nonzero? && phi2_tick
116
+ when IN_T2, OUT_T2, OUT_FREE_RUNNING then t2_tick(t2_low_underflow)
117
+ else false
118
+ end
119
+ end
120
+
121
+ # A level change on CB1 from outside. Only the external clock modes
122
+ # listen: shifting in samples CB2 as CB1 rises, and shifting out puts
123
+ # the next bit on CB2 as it falls. Returns true when the edge sets the
124
+ # interrupt flag.
125
+ def cb1_edge!(rising)
126
+ return false unless @mode == IN_EXTERNAL || @mode == OUT_EXTERNAL
127
+
128
+ shift_in if rising && @mode == IN_EXTERNAL
129
+ shift_out if !rising && @mode == OUT_EXTERNAL
130
+ rising && eighth_bit?
131
+ end
132
+
133
+ private
134
+
135
+ def internal_clock?
136
+ @mode != DISABLED && @mode != IN_EXTERNAL && @mode != OUT_EXTERNAL
137
+ end
138
+
139
+ # A φ2 cycle of a byte: every one but the first ticks.
140
+ def phi2_tick
141
+ started = @delay.nonzero?
142
+ @delay = 1
143
+ started && tick
144
+ end
145
+
146
+ # Ticks on the underflow from two cycles back, while a byte is under
147
+ # way.
148
+ def t2_tick(underflow)
149
+ due = @delay.anybits?(2)
150
+ @delay = ((@delay << 1) & 2) | (underflow ? 1 : 0)
151
+ due && @bits.nonzero? && tick
152
+ end
153
+
154
+ # One half period of the register's own clock: a falling edge puts a
155
+ # bit out, and a rising one takes a bit in and counts it.
156
+ def tick
157
+ @clock = !@clock
158
+ shift_out if !@clock && @mode >= OUT_FREE_RUNNING
159
+ shift_in if @clock && @mode < IN_EXTERNAL
160
+ @clock && @mode != OUT_FREE_RUNNING && eighth_bit?
161
+ end
162
+
163
+ # Counts a bit, and says whether it was the eighth since the access.
164
+ def eighth_bit?
165
+ return false if @bits.zero?
166
+
167
+ @bits -= 1
168
+ @bits.zero?
169
+ end
170
+
171
+ def shift_in
172
+ @data = ((@data << 1) | (@cb2_input ? 1 : 0)) & 0xff
173
+ end
174
+
175
+ def shift_out
176
+ @cb2 = @data.anybits?(0x80)
177
+ @data = ((@data << 1) | (@cb2 ? 1 : 0)) & 0xff
178
+ end
179
+ end
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Chips
5
+ class VIA
6
+ # Timer 1: a 16-bit counter that decrements on every φ2 cycle, with a
7
+ # latch it reloads from on every timeout and the PB7 output.
8
+ #
9
+ # Writing the high counter byte loads the counter on the cycle after,
10
+ # so a timer loaded with N reads N, N-1, ... 0 and then $FFFF, which is
11
+ # the cycle its interrupt flag sets: N + 1.5 cycles after the write in
12
+ # the datasheet's terms. The counter then reloads from the latch on the
13
+ # next cycle, which makes the period N + 2 cycles. It does so in one-shot
14
+ # mode too, unlike timer 2.
15
+ #
16
+ # Only a write of the high counter byte arms the timer. An armed timeout
17
+ # sets the flag and inverts PB7, and in one-shot mode disarms it, so the
18
+ # first timeout after the load alone does. Free-running keeps it armed,
19
+ # but switching to free-running doesn't arm it: an unarmed timer counts
20
+ # and reloads without touching the flag or PB7. The load pulls PB7 low,
21
+ # and ACR bit 7 turning on drives it high, so a timer loaded before its
22
+ # PB7 output is enabled reads high until the timeout pulls it low.
23
+ class Timer1
24
+ attr_accessor :counter, :latch
25
+
26
+ # The level the timer drives on PB7 when ACR bit 7 hands it the pin.
27
+ attr_reader :pb7
28
+
29
+ # ACR bit 7 turning on hands PB7 to the timer high.
30
+ def pb7_enabled!
31
+ @pb7 = true
32
+ end
33
+
34
+ def initialize
35
+ @counter = @latch = 0xffff
36
+ @reload = @hold = false
37
+ @armed = false
38
+ @pb7 = true
39
+ end
40
+
41
+ def write_latch_low(value)
42
+ @latch = (@latch & 0xff00) | value
43
+ end
44
+
45
+ def write_latch_high(value)
46
+ @latch = (value << 8) | (@latch & 0xff)
47
+ end
48
+
49
+ # The high counter byte write: load from the latch, hold the count
50
+ # for a cycle, arm the interrupt and pull PB7 low.
51
+ def start!
52
+ @counter = @latch
53
+ @hold = true
54
+ @reload = false
55
+ @armed = true
56
+ @pb7 = false
57
+ end
58
+
59
+ # One φ2 cycle. Returns true on the cycle that sets the interrupt flag.
60
+ def cycle!(free_run)
61
+ if @hold || @reload
62
+ @counter = @latch if @reload
63
+ @hold = @reload = false
64
+ return false
65
+ end
66
+ @counter = (@counter - 1) & 0xffff
67
+ @counter == 0xffff && timeout(free_run)
68
+ end
69
+
70
+ # How many cycles the timer can run without setting its flag: until
71
+ # an armed timer's timeout, and forever for an unarmed one, whose
72
+ # timeouts only reload the counter. None while an armed timer loads
73
+ # or reloads.
74
+ def quiet_cycles
75
+ return FastForward::QUIET unless @armed
76
+ return 0 if @hold || @reload
77
+
78
+ @counter
79
+ end
80
+
81
+ # Runs +cycles+ cycles at once, as many as quiet_cycles allows. An
82
+ # unarmed timer goes round its period of latch + 2 cycles: the
83
+ # timeout at $FFFF, the reload, and latch down to 0.
84
+ def fast_forward(cycles)
85
+ if @hold || @reload
86
+ cycle!(false)
87
+ cycles -= 1
88
+ end
89
+ return @counter -= cycles if cycles <= @counter
90
+
91
+ phase = (cycles - @counter - 1) % (@latch + 2)
92
+ @reload = phase.zero?
93
+ @counter = @reload ? 0xffff : @latch - phase + 1
94
+ end
95
+
96
+ def save_state(out)
97
+ out.int(@counter).int(@latch).boolean(@hold).boolean(@reload).boolean(@armed).boolean(@pb7)
98
+ end
99
+
100
+ def load_state(input)
101
+ @counter = input.int
102
+ @latch = input.int
103
+ @hold = input.boolean?
104
+ @reload = input.boolean?
105
+ @armed = input.boolean?
106
+ @pb7 = input.boolean?
107
+ end
108
+
109
+ # What the counter and PB7 don't hold, for comparing the timer at two
110
+ # points.
111
+ def state = [@latch, @armed]
112
+
113
+ # Whether a timeout sets the flag.
114
+ def armed? = @armed
115
+
116
+ # The count, for comparing the timer at two points where it matters.
117
+ def count_state = [@counter, @hold, @reload]
118
+
119
+ private
120
+
121
+ # The counter reloads either way. Armed, PB7 inverts and the flag
122
+ # sets, and one-shot mode disarms. Returns whether the flag sets.
123
+ def timeout(free_run)
124
+ interrupt = @armed
125
+ @reload = true
126
+ @pb7 = !@pb7 if @armed
127
+ @armed &&= free_run
128
+ interrupt
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Chips
5
+ class VIA
6
+ # Timer 2: a one-shot 16-bit counter that decrements on every φ2 cycle,
7
+ # or on every falling edge of PB6 when ACR bit 5 sets it counting pulses.
8
+ # Only its low byte has a latch.
9
+ #
10
+ # Timed, it follows timer 1's one-shot timing: loaded with N it reads N
11
+ # on the cycle after the write, and sets its flag on the cycle it rolls
12
+ # from 0 to $FFFF. Where timer 1 would reload, it rolls on down without
13
+ # further interrupts until the next load. Counting pulses, the flag sets
14
+ # on the pulse that takes it past zero, the N + 1st: the datasheet's
15
+ # "reaches zero" is the same underflow it means in timed mode.
16
+ #
17
+ # While the shift register clocks off it, the low byte also counts as
18
+ # an 8-bit timer of its own: on each low byte underflow it reloads from
19
+ # the latch on the next cycle, which makes the shift clock's half period
20
+ # N + 2 cycles. The borrow still reaches the high byte.
21
+ #
22
+ # ACR bit 5 reaches the count input a cycle after the write, so the
23
+ # counter takes one more step in the mode it leaves.
24
+ class Timer2
25
+ attr_accessor :counter, :latch_low
26
+
27
+ # ACR bit 5, which picks PB6 pulses over φ2.
28
+ attr_writer :count_pulses
29
+
30
+ # Whether the low byte underflowed on the last cycle.
31
+ attr_reader :low_underflowed
32
+
33
+ def initialize
34
+ @counter = 0xffff
35
+ @latch_low = 0xff
36
+ @hold = false
37
+ @low_reload = false
38
+ @armed = false
39
+ @low_underflowed = false
40
+ @count_pulses = @counting_pulses = false
41
+ end
42
+
43
+ # The high counter byte write: load the counter with it and the low
44
+ # latch, arm the interrupt and hold the count for a cycle.
45
+ def load(high)
46
+ @counter = (high << 8) | @latch_low
47
+ @hold = true
48
+ @low_reload = false
49
+ @armed = true
50
+ end
51
+
52
+ # One φ2 cycle, with whether the shift register clocks off the low
53
+ # byte. Returns true on the cycle that sets the flag.
54
+ def cycle!(sr_service)
55
+ pulses = @counting_pulses
56
+ @counting_pulses = @count_pulses
57
+ return idle! if pulses || @hold
58
+
59
+ @low_underflowed = @counter.nobits?(0xff)
60
+ @hold = @low_reload = sr_service && @low_underflowed
61
+ decrement
62
+ end
63
+
64
+ # A falling edge on PB6. Returns true when it sets the flag.
65
+ def pulse! = @counting_pulses && decrement
66
+
67
+ # How many cycles the timer can run without setting its flag, taken
68
+ # without the shift register clocking off it: until an armed timer
69
+ # underflows, and forever for one counting pulses or unarmed, which
70
+ # only rolls on. None while a load or a switch of mode is under way.
71
+ def quiet_cycles
72
+ return 0 if @hold || @counting_pulses != @count_pulses
73
+ return FastForward::QUIET if @counting_pulses || !@armed
74
+
75
+ @counter
76
+ end
77
+
78
+ # Runs +cycles+ cycles at once, as many as quiet_cycles allows. The
79
+ # low byte's underflow is set when the last cycle took it from $00.
80
+ def fast_forward(cycles)
81
+ @low_underflowed = false
82
+ return if @counting_pulses
83
+
84
+ @counter = (@counter - cycles) & 0xffff
85
+ @low_underflowed = @counter.allbits?(0xff)
86
+ end
87
+
88
+ def save_state(out)
89
+ out.int(@counter).int(@latch_low)
90
+ [@hold, @low_reload, @armed, @low_underflowed, @count_pulses, @counting_pulses].each do |flag|
91
+ out.boolean(flag)
92
+ end
93
+ end
94
+
95
+ def load_state(input)
96
+ @counter = input.int
97
+ @latch_low = input.int
98
+ @hold = input.boolean?
99
+ @low_reload = input.boolean?
100
+ @armed = input.boolean?
101
+ @low_underflowed = input.boolean?
102
+ @count_pulses = input.boolean?
103
+ @counting_pulses = input.boolean?
104
+ end
105
+
106
+ # What the counter and the low byte's underflow don't hold, for
107
+ # comparing the timer at two points.
108
+ def state = [@latch_low, @armed, @hold, @low_reload, @count_pulses, @counting_pulses]
109
+
110
+ # Whether the next underflow sets the flag.
111
+ def armed? = @armed
112
+
113
+ # The count, for comparing the timer at two points where it matters.
114
+ def count_state = [@counter, @low_underflowed]
115
+
116
+ private
117
+
118
+ # A cycle while counting pulses, or held after a load or a low byte
119
+ # underflow: the counter stands still, but the hold still ends, so
120
+ # none carries over into timed mode.
121
+ def idle!
122
+ @counter = (@counter & 0xff00) | @latch_low if @low_reload
123
+ @hold = @low_reload = @low_underflowed = false
124
+ end
125
+
126
+ def decrement
127
+ @counter = (@counter - 1) & 0xffff
128
+ interrupt = @armed && @counter == 0xffff
129
+ @armed = false if interrupt
130
+ interrupt
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end