badline 0.12.0 → 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 (516) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -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 +4 -4
  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} +6 -6
  17. data/lib/badline/c128/bus.rb +30 -51
  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 +18 -72
  27. data/lib/badline/{computer → c64}/attachments.rb +16 -47
  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/c64/common.rb +34 -0
  73. data/lib/badline/c64/kernal_traps.rb +89 -0
  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 +20 -31
  82. data/lib/badline/{computer.rb → c64.rb} +22 -80
  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 +27 -29
  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 +10 -61
  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/{file.rb → file_routine.rb} +1 -1
  262. data/lib/badline/kernal_trap/load.rb +6 -6
  263. data/lib/badline/kernal_trap/save.rb +5 -5
  264. data/lib/badline/kernal_trap/serial.rb +7 -7
  265. data/lib/badline/kernal_trap.rb +2 -3
  266. data/lib/badline/machine/clocking.rb +50 -0
  267. data/lib/badline/machine.rb +63 -7
  268. data/lib/badline/media/boot_disk.rb +2 -2
  269. data/lib/badline/media/disk_list.rb +3 -3
  270. data/lib/badline/media/disk_set.rb +1 -1
  271. data/lib/badline/media/extensions.rb +33 -0
  272. data/lib/badline/media/program.rb +28 -0
  273. data/lib/badline/media/true_drive.rb +4 -3
  274. data/lib/badline/media/tune.rb +35 -0
  275. data/lib/badline/media/vic20_cartridge.rb +1 -7
  276. data/lib/badline/media/vic20_media.rb +38 -80
  277. data/lib/badline/media.rb +84 -81
  278. data/lib/badline/model.rb +1 -1
  279. data/lib/badline/options/event.rb +3 -1
  280. data/lib/badline/roms/README +6 -6
  281. data/lib/badline/sdl.rb +1 -0
  282. data/lib/badline/{storage/sid_file.rb → sid_tune/file.rb} +3 -3
  283. data/lib/badline/{storage → sid_tune}/hvsc.rb +7 -7
  284. data/lib/badline/{storage → sid_tune}/song_lengths.rb +2 -2
  285. data/lib/badline/{storage → sid_tune}/stil/credit.rb +1 -1
  286. data/lib/badline/{storage → sid_tune}/stil.rb +3 -3
  287. data/lib/badline/sid_tune.rb +6 -0
  288. data/lib/badline/snapshot/c128_setup.rb +43 -0
  289. data/lib/badline/snapshot/c64_setup.rb +79 -0
  290. data/lib/badline/snapshot/image.rb +5 -25
  291. data/lib/badline/snapshot/machine_state.rb +10 -2
  292. data/lib/badline/snapshot/setup.rb +22 -66
  293. data/lib/badline/snapshot/state.rb +8 -17
  294. data/lib/badline/snapshot/storage_setup.rb +68 -0
  295. data/lib/badline/snapshot/vic20_setup.rb +37 -0
  296. data/lib/badline/snapshot/vice/c64_mem.rb +1 -1
  297. data/lib/badline/snapshot/vice/restore.rb +1 -1
  298. data/lib/badline/snapshot/vice/reu1764.rb +1 -1
  299. data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
  300. data/lib/badline/snapshot/vice.rb +7 -5
  301. data/lib/badline/snapshot.rb +13 -12
  302. data/lib/badline/storage/d64_image.rb +15 -9
  303. data/lib/badline/storage/d71_image.rb +0 -2
  304. data/lib/badline/storage/d81_image.rb +0 -2
  305. data/lib/badline/storage/disk_image/writing.rb +2 -2
  306. data/lib/badline/storage/disk_image.rb +3 -6
  307. data/lib/badline/storage/g64_image.rb +2 -2
  308. data/lib/badline/storage/host_directory.rb +0 -5
  309. data/lib/badline/storage/t64.rb +2 -8
  310. data/lib/badline/storage/unavailable.rb +1 -1
  311. data/lib/badline/storage.rb +0 -37
  312. data/lib/badline/support/c128_checkpoint.rb +39 -0
  313. data/lib/badline/support/checkpoint.rb +108 -0
  314. data/lib/badline/support/vic20_checkpoint.rb +38 -0
  315. data/lib/badline/support.rb +5 -0
  316. data/lib/badline/version.rb +1 -1
  317. data/lib/badline/vic20/attachments.rb +11 -81
  318. data/lib/badline/vic20/bus/saved_state.rb +35 -0
  319. data/lib/badline/vic20/bus.rb +3 -25
  320. data/lib/badline/vic20/cpu.rb +1 -1
  321. data/lib/badline/vic20/port_wiring.rb +4 -4
  322. data/lib/badline/vic20/saved_state.rb +16 -60
  323. data/lib/badline/vic20/user_via_ports.rb +2 -2
  324. data/lib/badline/vic20.rb +20 -51
  325. metadata +250 -221
  326. data/lib/badline/address_bus/extra_sids.rb +0 -30
  327. data/lib/badline/address_bus/fittings.rb +0 -38
  328. data/lib/badline/address_bus/pla.rb +0 -147
  329. data/lib/badline/address_bus/roms.rb +0 -39
  330. data/lib/badline/address_bus/saved_state.rb +0 -72
  331. data/lib/badline/address_bus/sid_slots.rb +0 -42
  332. data/lib/badline/address_bus.rb +0 -235
  333. data/lib/badline/cartridge/action_replay.rb +0 -126
  334. data/lib/badline/cartridge/atomic_power.rb +0 -24
  335. data/lib/badline/cartridge/bank.rb +0 -81
  336. data/lib/badline/cartridge/comal80.rb +0 -50
  337. data/lib/badline/cartridge/dinamic.rb +0 -34
  338. data/lib/badline/cartridge/easy_flash.rb +0 -145
  339. data/lib/badline/cartridge/epyx_fastload.rb +0 -79
  340. data/lib/badline/cartridge/final_cartridge3.rb +0 -89
  341. data/lib/badline/cartridge/flash.rb +0 -306
  342. data/lib/badline/cartridge/freezer.rb +0 -33
  343. data/lib/badline/cartridge/fun_play.rb +0 -38
  344. data/lib/badline/cartridge/g_mod2.rb +0 -74
  345. data/lib/badline/cartridge/game_system.rb +0 -40
  346. data/lib/badline/cartridge/geo_ram.rb +0 -79
  347. data/lib/badline/cartridge/kcs_power.rb +0 -75
  348. data/lib/badline/cartridge/mach5.rb +0 -32
  349. data/lib/badline/cartridge/magic_desk.rb +0 -30
  350. data/lib/badline/cartridge/ocean.rb +0 -35
  351. data/lib/badline/cartridge/pagefox.rb +0 -68
  352. data/lib/badline/cartridge/retro_replay.rb +0 -320
  353. data/lib/badline/cartridge/rex_utility.rb +0 -29
  354. data/lib/badline/cartridge/rgcd.rb +0 -58
  355. data/lib/badline/cartridge/simons_basic.rb +0 -35
  356. data/lib/badline/cartridge/standard.rb +0 -15
  357. data/lib/badline/cartridge/super_games.rb +0 -48
  358. data/lib/badline/cartridge/westermann.rb +0 -30
  359. data/lib/badline/cartridge/zaxxon.rb +0 -66
  360. data/lib/badline/cartridge.rb +0 -303
  361. data/lib/badline/checkpoint.rb +0 -98
  362. data/lib/badline/cia/fast_forward.rb +0 -60
  363. data/lib/badline/cia/interrupt_register.rb +0 -143
  364. data/lib/badline/cia/serial.rb +0 -275
  365. data/lib/badline/cia/state.rb +0 -47
  366. data/lib/badline/cia/timer.rb +0 -206
  367. data/lib/badline/cia.rb +0 -279
  368. data/lib/badline/color_memory.rb +0 -25
  369. data/lib/badline/computer/kernal_traps.rb +0 -29
  370. data/lib/badline/control_ports.rb +0 -76
  371. data/lib/badline/cpu/addressing.rb +0 -131
  372. data/lib/badline/cpu/boundary.rb +0 -54
  373. data/lib/badline/cpu/core.rb +0 -165
  374. data/lib/badline/cpu/microcode.rb +0 -177
  375. data/lib/badline/cpu/operations.rb +0 -88
  376. data/lib/badline/cpu/saved_state.rb +0 -115
  377. data/lib/badline/cpu/stack_operations.rb +0 -82
  378. data/lib/badline/cpu.rb +0 -10
  379. data/lib/badline/cycleable.rb +0 -38
  380. data/lib/badline/datasette.rb +0 -161
  381. data/lib/badline/drive/core.rb +0 -147
  382. data/lib/badline/drive/fast_serial.rb +0 -73
  383. data/lib/badline/drive/idle.rb +0 -125
  384. data/lib/badline/drive/idle_cpu.rb +0 -28
  385. data/lib/badline/drive/orbit.rb +0 -79
  386. data/lib/badline/drive/serial_lines.rb +0 -73
  387. data/lib/badline/drive/sleep.rb +0 -112
  388. data/lib/badline/drive/vias.rb +0 -84
  389. data/lib/badline/drive/watch.rb +0 -150
  390. data/lib/badline/drive.rb +0 -11
  391. data/lib/badline/drive1541/bus.rb +0 -86
  392. data/lib/badline/drive1541/byte_ready.rb +0 -48
  393. data/lib/badline/drive1541/cpu.rb +0 -11
  394. data/lib/badline/drive1541/disk.rb +0 -318
  395. data/lib/badline/drive1541/disk_state.rb +0 -94
  396. data/lib/badline/drive1541/disk_via.rb +0 -36
  397. data/lib/badline/drive1541/gcr.rb +0 -57
  398. data/lib/badline/drive1541/mechanism.rb +0 -313
  399. data/lib/badline/drive1541/mechanism_state.rb +0 -68
  400. data/lib/badline/drive1541/rotation.rb +0 -121
  401. data/lib/badline/drive1541/sector_reader.rb +0 -76
  402. data/lib/badline/drive1541/serial_port.rb +0 -18
  403. data/lib/badline/drive1541/track.rb +0 -98
  404. data/lib/badline/drive1541.rb +0 -111
  405. data/lib/badline/drive1571/bus.rb +0 -111
  406. data/lib/badline/drive1571/cpu.rb +0 -11
  407. data/lib/badline/drive1571/serial_port.rb +0 -37
  408. data/lib/badline/drive1571/serial_via.rb +0 -25
  409. data/lib/badline/drive1571/wd1770.rb +0 -120
  410. data/lib/badline/drive1571.rb +0 -175
  411. data/lib/badline/drive1581/bus.rb +0 -137
  412. data/lib/badline/drive1581/cpu.rb +0 -11
  413. data/lib/badline/drive1581/disk.rb +0 -135
  414. data/lib/badline/drive1581/disk_state.rb +0 -87
  415. data/lib/badline/drive1581/mechanism.rb +0 -117
  416. data/lib/badline/drive1581/serial_port.rb +0 -52
  417. data/lib/badline/drive1581/slot.rb +0 -78
  418. data/lib/badline/drive1581/track.rb +0 -100
  419. data/lib/badline/drive1581/track_bytes.rb +0 -75
  420. data/lib/badline/drive1581/wd1772/registers.rb +0 -89
  421. data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
  422. data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
  423. data/lib/badline/drive1581/wd1772/state.rb +0 -66
  424. data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
  425. data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
  426. data/lib/badline/drive1581/wd1772/turn.rb +0 -73
  427. data/lib/badline/drive1581/wd1772.rb +0 -216
  428. data/lib/badline/drive1581.rb +0 -233
  429. data/lib/badline/iec_bus.rb +0 -159
  430. data/lib/badline/instruction.rb +0 -334
  431. data/lib/badline/instruction_set/arithmetic.rb +0 -114
  432. data/lib/badline/instruction_set/bitwise.rb +0 -126
  433. data/lib/badline/instruction_set/branch.rb +0 -79
  434. data/lib/badline/instruction_set/flag.rb +0 -63
  435. data/lib/badline/instruction_set/illegal.rb +0 -270
  436. data/lib/badline/instruction_set/inc_dec.rb +0 -69
  437. data/lib/badline/instruction_set/stack.rb +0 -52
  438. data/lib/badline/instruction_set/transfer.rb +0 -137
  439. data/lib/badline/instruction_set.rb +0 -55
  440. data/lib/badline/interrupts.rb +0 -104
  441. data/lib/badline/joystick.rb +0 -25
  442. data/lib/badline/kernal_trap/channel.rb +0 -181
  443. data/lib/badline/keyboard.rb +0 -112
  444. data/lib/badline/ram_expansion/banking.rb +0 -30
  445. data/lib/badline/ram_expansion/plus256k.rb +0 -54
  446. data/lib/badline/ram_expansion/plus60k.rb +0 -43
  447. data/lib/badline/ram_expansion/unexpanded.rb +0 -28
  448. data/lib/badline/ram_expansion.rb +0 -21
  449. data/lib/badline/reu/dma/saved_state.rb +0 -50
  450. data/lib/badline/reu/dma.rb +0 -273
  451. data/lib/badline/reu/ram.rb +0 -107
  452. data/lib/badline/reu/saved_state.rb +0 -80
  453. data/lib/badline/reu/trigger.rb +0 -32
  454. data/lib/badline/reu.rb +0 -289
  455. data/lib/badline/sid/catch_up.rb +0 -120
  456. data/lib/badline/sid/decimator.rb +0 -64
  457. data/lib/badline/sid/envelope/state.rb +0 -68
  458. data/lib/badline/sid/envelope.rb +0 -239
  459. data/lib/badline/sid/filter.rb +0 -263
  460. data/lib/badline/sid/voice.rb +0 -77
  461. data/lib/badline/sid/waveform/combined.rb +0 -126
  462. data/lib/badline/sid/waveform/fast_forward.rb +0 -105
  463. data/lib/badline/sid/waveform/noise_writeback.rb +0 -122
  464. data/lib/badline/sid/waveform/state.rb +0 -66
  465. data/lib/badline/sid/waveform.rb +0 -305
  466. data/lib/badline/sid.rb +0 -303
  467. data/lib/badline/time_of_day.rb +0 -228
  468. data/lib/badline/traps.rb +0 -19
  469. data/lib/badline/via/control_lines.rb +0 -122
  470. data/lib/badline/via/fast_forward.rb +0 -53
  471. data/lib/badline/via/interrupt_register.rb +0 -67
  472. data/lib/badline/via/shift_register.rb +0 -180
  473. data/lib/badline/via/state.rb +0 -42
  474. data/lib/badline/via/timer1.rb +0 -131
  475. data/lib/badline/via/timer2.rb +0 -133
  476. data/lib/badline/via.rb +0 -266
  477. data/lib/badline/vic/bank.rb +0 -133
  478. data/lib/badline/vic/border_mask.rb +0 -86
  479. data/lib/badline/vic/collisions.rb +0 -115
  480. data/lib/badline/vic/color_patches.rb +0 -47
  481. data/lib/badline/vic/display_state.rb +0 -185
  482. data/lib/badline/vic/graphics_mode.rb +0 -164
  483. data/lib/badline/vic/graphics_shifter.rb +0 -207
  484. data/lib/badline/vic/register_log.rb +0 -81
  485. data/lib/badline/vic/registers.rb +0 -195
  486. data/lib/badline/vic/sequencer.rb +0 -275
  487. data/lib/badline/vic/sequencer_output.rb +0 -116
  488. data/lib/badline/vic/sequencer_state.rb +0 -89
  489. data/lib/badline/vic/sprite/internal_bus.rb +0 -68
  490. data/lib/badline/vic/sprite/saved_state.rb +0 -64
  491. data/lib/badline/vic/sprite/shifter.rb +0 -146
  492. data/lib/badline/vic/sprite/timing.rb +0 -56
  493. data/lib/badline/vic/sprite.rb +0 -337
  494. data/lib/badline/vic/sprites.rb +0 -282
  495. data/lib/badline/vic/sprites_state.rb +0 -57
  496. data/lib/badline/vic.rb +0 -852
  497. data/lib/badline/vic20/sound/output.rb +0 -83
  498. data/lib/badline/vic20/sound.rb +0 -233
  499. data/lib/badline/z80/arithmetic.rb +0 -117
  500. data/lib/badline/z80/bit_page.rb +0 -55
  501. data/lib/badline/z80/block_io.rb +0 -58
  502. data/lib/badline/z80/block_transfers.rb +0 -59
  503. data/lib/badline/z80/bus_cycles.rb +0 -111
  504. data/lib/badline/z80/core.rb +0 -113
  505. data/lib/badline/z80/exchanges.rb +0 -50
  506. data/lib/badline/z80/extended_page.rb +0 -89
  507. data/lib/badline/z80/flags.rb +0 -37
  508. data/lib/badline/z80/interrupt_acceptance.rb +0 -46
  509. data/lib/badline/z80/jumps.rb +0 -82
  510. data/lib/badline/z80/loads.rb +0 -98
  511. data/lib/badline/z80/main_page.rb +0 -134
  512. data/lib/badline/z80/registers.rb +0 -120
  513. data/lib/badline/z80/saved_state.rb +0 -69
  514. data/lib/badline/z80/shifts.rb +0 -64
  515. data/lib/badline/z80.rb +0 -11
  516. /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