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,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Chips
5
+ class VIC
6
+ class Sequencer
7
+ # Writes a column's 8-pixel group into the line buffers, through the
8
+ # main border flip-flop and XSCROLL.
9
+ module Output
10
+ private
11
+
12
+ # Write the 8-pixel group for a column into the line buffers. The main
13
+ # border flip-flop only changes state in the groups containing the
14
+ # window edge compares, so all other groups take a branch-free bulk
15
+ # path: fully border or fully window. A group's first pixel, where the
16
+ # 40-column compares fall, still sees CSEL as the column before had it.
17
+ def output(col, shift)
18
+ x_pos = (col + 16) * 8
19
+ csel = @registers.csel?
20
+ first = @window_compares[@first_csel ? 1 : 0]
21
+ @first_csel = csel
22
+ compares = @window_compares[csel ? 1 : 0]
23
+ win_lo, right_compare = compares
24
+
25
+ if !first.equal?(compares) || boundary_group?(x_pos, win_lo, right_compare)
26
+ output_boundary(x_pos, first, compares, shift)
27
+ elsif @main_border
28
+ output_border(x_pos)
29
+ else
30
+ output_window(x_pos, shift)
31
+ end
32
+ end
33
+
34
+ # True if the group contains a window edge, where the main border
35
+ # flip-flop can change state.
36
+ def boundary_group?(x_pos, win_lo, right_compare)
37
+ lo_delta = win_lo - x_pos
38
+ hi_delta = right_compare - x_pos
39
+ (lo_delta >= 0 && lo_delta < 8) || (hi_delta >= 0 && hi_delta < 8)
40
+ end
41
+
42
+ def output_border(x_pos)
43
+ @colors.fill(@registers.border, x_pos, 8) if @render
44
+ @border_groups[x_pos >> 3] = BorderMask::FULL
45
+ @fg.fill(false, x_pos, 8)
46
+ end
47
+
48
+ def output_window(x_pos, shift)
49
+ in_gfx = x_pos >= @gfx_x_start && x_pos < @gfx_x_end
50
+ @border_groups[x_pos >> 3] = BorderMask::NONE
51
+
52
+ if shift.zero?
53
+ @colors[x_pos, 8] = @cur_colors if @render
54
+ if in_gfx
55
+ @fg[x_pos, 8] = @cur_fg
56
+ else
57
+ @fg.fill(false, x_pos, 8)
58
+ end
59
+ else
60
+ output_window_shifted(x_pos, in_gfx, shift)
61
+ end
62
+ end
63
+
64
+ def output_window_shifted(x_pos, in_gfx, shift)
65
+ keep = 8 - shift
66
+
67
+ if @render
68
+ copy(@cur_colors, 0, @colors, x_pos + shift, keep)
69
+ copy(@prev_colors, keep, @colors, x_pos, shift)
70
+ end
71
+ output_shifted_fg(x_pos, in_gfx, shift, keep)
72
+ end
73
+
74
+ def output_shifted_fg(x_pos, in_gfx, shift, keep)
75
+ return @fg.fill(false, x_pos, 8) unless in_gfx
76
+
77
+ copy(@cur_fg, 0, @fg, x_pos + shift, keep)
78
+ copy(@prev_fg, keep, @fg, x_pos, shift)
79
+ end
80
+
81
+ def copy(src, from, dest, to, count)
82
+ i = 0
83
+ while i < count
84
+ dest[to + i] = src[from + i]
85
+ i += 1
86
+ end
87
+ end
88
+
89
+ # Slow path for the groups where the border flip-flop can change state.
90
+ def output_boundary(x_pos, first, compares, shift)
91
+ border = @registers.border
92
+ win_lo, right_compare = first
93
+ @border_groups[x_pos >> 3] = BorderMask::MIXED
94
+
95
+ i = 0
96
+ while i < 8
97
+ src = i - shift
98
+ if src >= 0
99
+ pixel = @cur_colors[src]
100
+ mask = @cur_fg[src]
101
+ else
102
+ pixel = @prev_colors[8 + src]
103
+ mask = @prev_fg[8 + src]
104
+ end
105
+ x = x_pos + i
106
+ shown = pixel_shown?(x, win_lo, right_compare)
107
+ @colors[x] = shown ? pixel : border
108
+ @border[x] = !shown
109
+ @fg[x] = x >= @gfx_x_start && x < @gfx_x_end ? mask : false
110
+ win_lo, right_compare = compares if i.zero?
111
+ i += 1
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Chips
5
+ class VIC
6
+ class Sprite
7
+ # = InternalBus
8
+ #
9
+ # What a sprite's s-accesses read while its DMA is off. The first and
10
+ # third fall in phi2, where the VIC's internal bus floats to $ff unless
11
+ # the CPU reads or writes a VIC register in that cycle, and the middle
12
+ # one is the idle fetch at $3fff (sbsprf24's readme).
13
+ class InternalBus
14
+ # The columns of a raster line, and where the region puts the
15
+ # sprites in it.
16
+ attr_reader :columns, :timing
17
+
18
+ def initialize(bank, timing)
19
+ @bank = bank
20
+ @timing = timing
21
+ @columns = timing.columns
22
+ @sprite_cycle = timing.sprite_cycle
23
+ @lines = 0
24
+ @ghost = 0xff
25
+ @value = Array.new(columns, 0xff)
26
+ @line = Array.new(columns, -1)
27
+ end
28
+
29
+ def save_state(out)
30
+ out.int(@lines).int(@ghost).ints(@value).ints(@line)
31
+ end
32
+
33
+ def load_state(input)
34
+ @lines = input.int
35
+ @ghost = input.int
36
+ input.ints_into(@value)
37
+ input.ints_into(@line)
38
+ end
39
+
40
+ # Sprites 3-7 fetch in Bauer cycles 1-10, so the idle byte is taken
41
+ # as the line starts.
42
+ def start_line(sprites_enabled)
43
+ @lines += 1
44
+ @ghost = @bank.peek(0x3fff) if sprites_enabled
45
+ end
46
+
47
+ # The VIC has advanced to `column`, so the access runs in Bauer cycle
48
+ # `column + 1`, and column 0 is the first cycle of the line about to
49
+ # start.
50
+ def access(column, value)
51
+ @value[column] = value
52
+ @line[column] = column.zero? ? @lines + 1 : @lines
53
+ end
54
+
55
+ # The row sprite `index` (3-7) fetched this line, in the phi2 halves
56
+ # of the two cycles from its p-access: Bauer cycles 2n-5 and 2n-4 on
57
+ # the 6569.
58
+ def row(index)
59
+ column = (@sprite_cycle + (2 * index) - 1) % @columns
60
+ (phi2(column) << 16) | (@ghost << 8) | phi2(column + 1)
61
+ end
62
+
63
+ private
64
+
65
+ def phi2(column) = @line[column] == @lines ? @value[column] : 0xff
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Chips
5
+ class VIC
6
+ class Sprite
7
+ # The sprite's save_state and load_state.
8
+ module SavedState
9
+ # The shift register, MC, MCBASE, the expansion flip-flop and whether
10
+ # the sprite shows, for a VICE snapshot.
11
+ attr_reader :sr, :mc, :mcbase, :exp_ff, :display_on
12
+
13
+ # Sets MC, MCBASE, the expansion flip-flop, whether the sprite's DMA
14
+ # runs and whether it shows, as a VICE snapshot gives them.
15
+ def restore_counters(counter, base, expanded, dma, shows)
16
+ @mc = counter
17
+ @mcbase = base
18
+ @exp_ff = expanded
19
+ @dma = dma
20
+ @display_on = shows
21
+ end
22
+
23
+ def save_state(out)
24
+ out.boolean(@dma).boolean(@display_on).int(@mcbase).int(@mc).boolean(@exp_ff).optional_int(@crunched_mc)
25
+ out.int(@bits).boolean(@row_ready).optional_int(@prev_bits).boolean(@first_byte_lost).boolean(@blind)
26
+ out.int(@show_from).optional_int(@stop_x)
27
+ out.ints(@codes).int(@leftmost).int(@span).ints(@reload_codes).int(@reload_leftmost).int(@reload_span)
28
+ out.int(@sr).int(@latch).boolean(@mc_flop).boolean(@xe_flop)
29
+ end
30
+
31
+ def load_state(input)
32
+ load_counters(input)
33
+ @show_from = input.int
34
+ @stop_x = input.optional_int
35
+ input.ints_into(@codes)
36
+ @leftmost = input.int
37
+ @span = input.int
38
+ input.ints_into(@reload_codes)
39
+ @reload_leftmost = input.int
40
+ @reload_span = input.int
41
+ @sr = input.int
42
+ @latch = input.int
43
+ @mc_flop = input.boolean?
44
+ @xe_flop = input.boolean?
45
+ end
46
+
47
+ private
48
+
49
+ def load_counters(input)
50
+ @dma = input.boolean?
51
+ @display_on = input.boolean?
52
+ @mcbase = input.int
53
+ @mc = input.int
54
+ @exp_ff = input.boolean?
55
+ @crunched_mc = input.optional_int
56
+ @bits = input.int
57
+ @row_ready = input.boolean?
58
+ @prev_bits = input.optional_int
59
+ @first_byte_lost = input.boolean?
60
+ @blind = input.boolean?
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,148 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Chips
5
+ class VIC
6
+ class Sprite
7
+ # The X comparator and the 24-bit shift register behind it: where a
8
+ # line fires the sprite, and the pixels each firing shifts out.
9
+ module Shifter
10
+ private
11
+
12
+ # The first pixel of every comparator match along the line. Writes to
13
+ # $d000/$d010 move the compare value mid-line, so a sprite can miss
14
+ # its match entirely and pick up a later one, a second one, or none.
15
+ def comparator_hits(log)
16
+ return compare_x(@registers) unless log
17
+
18
+ hits = []
19
+ log.rewind
20
+ log.advance(0)
21
+ from = 0
22
+ while from < @width
23
+ upto = [log.next_x, @width].min
24
+ compare_x(log).each do |start|
25
+ match = (start - 1) % @width
26
+ hits << start if match >= from && match < upto
27
+ end
28
+ break if upto >= @width
29
+
30
+ from = upto
31
+ log.advance(from)
32
+ end
33
+ hits
34
+ end
35
+
36
+ # The pixels the sprite starts at, one past each comparator match.
37
+ # The 6569's X counter only runs to 503, so the eight coordinates
38
+ # above it never match and the sprite stays dark — the gap the
39
+ # spritegap tests find at $1f8.
40
+ def compare_x(view)
41
+ msb = view[0x10].anybits?(@bit) ? 0x100 : 0
42
+ @timing.x_pixels[msb | view[index * 2]]
43
+ end
44
+
45
+ # Pixels from the X match to the next reload.
46
+ def reload_cut(start) = (start < @reload_x ? @reload_x : @reload_x + @width) - start
47
+
48
+ # A run that reaches the next reload is cut there, holding its last
49
+ # pixel through K+6. Returns the span that is left.
50
+ def cut_at_reload(cut, span, codes)
51
+ return span if cut > span || cut >= MAX_SPAN
52
+
53
+ RELOAD_HOLD.times { |i| codes[cut + i] = codes[cut - 1] }
54
+ cut + RELOAD_HOLD
55
+ end
56
+
57
+ # Shift one firing out into `codes`, up to the sprite's end, `cut`
58
+ # pixels from the reload.
59
+ def run(log, start, codes, bits, cut)
60
+ @sr = bits
61
+ log&.rewind
62
+ pos = start
63
+ count = 0
64
+ boundary = log ? 0 : Float::INFINITY
65
+ mc = multicolor?
66
+ expanded = x_expanded?
67
+ while count < MAX_SPAN
68
+ if pos >= boundary
69
+ log.advance(pos)
70
+ expanded = log[0x1d].anybits?(@bit)
71
+ mc = logged_multicolor(log, mc, expanded, count)
72
+ boundary = log.next_x
73
+ end
74
+ count.zero? ? prime(mc) : step(mc, expanded, count == cut - 1)
75
+ break if @latch.zero? && @sr.zero?
76
+
77
+ codes[count] = @latch
78
+ count += 1
79
+ pos += 1
80
+ end
81
+ count
82
+ end
83
+
84
+ # The X match loads the shift register and arms both flip-flops, so
85
+ # the sprite's first pixel comes straight off the fetched row.
86
+ def prime(multicolor)
87
+ @mc_flop = @new_chip && !multicolor
88
+ @xe_flop = false
89
+ @latch = (@sr >> 22) & (multicolor ? 3 : 2)
90
+ end
91
+
92
+ # The multicolor bit as the log has it at the pixel. A change after
93
+ # the first pixel reaches the 8565's flip-flop.
94
+ def logged_multicolor(log, was, expanded, count)
95
+ multicolor = log[0x1c].anybits?(@bit)
96
+ switch_multicolor(multicolor, expanded) if @new_chip && multicolor != was && count.positive?
97
+ multicolor
98
+ end
99
+
100
+ # On the 8565 a multicolor change works on the flip-flop instead of
101
+ # the next pixels. It stays as it is unless the change lands between
102
+ # the two halves of an expanded pixel, where it flips, or is set by a
103
+ # switch to hi-res.
104
+ def switch_multicolor(multicolor, expanded)
105
+ return unless expanded && !@xe_flop
106
+
107
+ @mc_flop = multicolor ? !@mc_flop : true
108
+ end
109
+
110
+ # One pixel of the sequencer. An unexpanded sprite shifts every pixel;
111
+ # an expanded one shifts every other, and the multicolor latch reloads
112
+ # every other shift, so its pairs stretch with the expansion. Both
113
+ # flip-flops sit idle while their register bit is clear, which is why
114
+ # the first pixel after a mid-sprite change repeats the last one.
115
+ def step(multicolor, expanded, last)
116
+ shift = true
117
+ if expanded
118
+ shift = @xe_flop
119
+ @xe_flop = !@xe_flop
120
+ else
121
+ @xe_flop = false
122
+ end
123
+ @mc_flop = false unless multicolor || @new_chip
124
+ return unless shift
125
+
126
+ @sr = (@sr << 1) & 0xffffff
127
+ load_latch(multicolor, last)
128
+ end
129
+
130
+ # A multicolor pair loaded on the last pixel before the reload keeps
131
+ # only its high bit, as a hi-res pixel does (spritefetchbug).
132
+ # On the 8565 a hi-res pixel with the multicolor flip-flop clear
133
+ # sets it and loads nothing, so the latch repeats its last pixel.
134
+ def load_latch(multicolor, last)
135
+ if multicolor
136
+ @latch = (@sr >> 22) & (last ? 2 : 3) if @mc_flop
137
+ @mc_flop = !@mc_flop
138
+ elsif @new_chip && !@mc_flop
139
+ @mc_flop = true
140
+ else
141
+ @latch = (@sr >> 22) & 2
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Chips
5
+ class VIC
6
+ class Sprite
7
+ # = Timing
8
+ #
9
+ # Where a region puts the sprites in the line: the cycles of their
10
+ # fetches and of the display compare, the pixels those land on, and
11
+ # the raster pixels the X counter reads each coordinate at. Where the
12
+ # fetches or the compare run a cycle later than on the 6569, what
13
+ # hangs off them moves 8 pixels with them.
14
+ class Timing
15
+ # The X counter's value where it steps back on a raster of more than
16
+ # 512 pixels, to run over the eight values below it again.
17
+ HOLD_AT = 0x188
18
+
19
+ attr_reader :columns, :sprite_cycle, :display_off_x, :x_pixels
20
+
21
+ def initialize(region)
22
+ @columns = region.cycles_per_line
23
+ @sprite_cycle = region.sprite_cycle
24
+ @shift = region.sprite_cycle - Region::PAL.sprite_cycle
25
+ @display_off_x = DISPLAY_OFF_X + (8 * (region.sprite_display_cycle - Region::PAL.sprite_display_cycle))
26
+ @x_pixels = Timing.x_pixels(@columns * 8, region.x_hold)
27
+ end
28
+
29
+ # The column BA falls in for a sprite's own fetch: 55 for sprite 0 on
30
+ # the 6569, and two later for each sprite after it.
31
+ def ba_column(index) = 55 + @shift + (2 * index)
32
+
33
+ # The raster pixel of a sprite's reload, counted from the start of
34
+ # the line it is fetched on, so past the end of it for sprites 3-7
35
+ # on the 6569.
36
+ def reload_x(index) = RELOAD_X + (8 * @shift) + (RELOAD_STEP * index)
37
+
38
+ # The X counter at a raster pixel: X_OFFSET behind it, wrapping at
39
+ # the end of the line, less the pixels it held for from HOLD_AT on,
40
+ # where it ran over $180-$187 a second time.
41
+ def self.xpos(pixel, width, hold)
42
+ count = (pixel - X_OFFSET) % width
43
+ count < HOLD_AT ? count : count - hold
44
+ end
45
+
46
+ # The raster pixels at which the X counter reads each coordinate, 512
47
+ # lists. A sprite starts at one where its X matches. On the 6569 the
48
+ # coordinates past 503 have none.
49
+ def self.x_pixels(width, hold)
50
+ pixels = Array.new(512) { [] }
51
+ width.times { |pixel| pixels[xpos(pixel, width, hold)] << pixel }
52
+ pixels.each(&:freeze).freeze
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end