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
@@ -1,185 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class VIC < Cycleable
5
- # = VIC-II display state
6
- #
7
- # The bad line condition, the video counters it drives, and the DMA it
8
- # starts. A condition that arrives mid-line opens the row late, which is
9
- # what makes the screen scroll sideways or lose a column of cells.
10
- class DisplayState
11
- FIRST_LINE = 0x30 # 48: bad lines and the DEN-at-$30 latch begin here
12
- LAST_LINE = 0xf7 # 247
13
- COLUMNS_PER_ROW = 40
14
-
15
- # AEC follows BA three cycles later; the c-accesses before it read
16
- # the bus the CPU still drives.
17
- BA_DELAY = 3
18
-
19
- # Columns run two ahead of Bauer's cycle numbers: column 10 is his
20
- # cycle 12. BA falls on a match in columns 10-52, the c-accesses run
21
- # in 13-52 and the g-accesses in 14-53. VC and VMLI reload in column
22
- # 12 and the row counter steps in column 56.
23
- DMA_FIRST = 10
24
- DMA_LAST = 52
25
- FETCH_FIRST = 13
26
- GRAPHICS_FIRST = 14
27
- GRAPHICS_LAST = 53
28
- LOAD_COLUMN = 12
29
- RC_COLUMN = 56
30
-
31
- GRAPHICS_COLUMNS = Array.new(65) { |column| column.between?(GRAPHICS_FIRST, GRAPHICS_LAST) }.freeze
32
-
33
- attr_reader :vc_base, :vc, :vmli, :rc, :bad_lines_enabled
34
-
35
- # The wrap column is the last column of a rasterline, 62 on the 6569,
36
- # which already compares against the line about to start, the same
37
- # wrap the raster IRQ latch uses.
38
- def initialize(registers, wrap_column = 62)
39
- @registers = registers
40
- @wrap_column = wrap_column
41
- @vc_base = 0
42
- @vc = 0
43
- @vmli = 0
44
- @rc = 0
45
- @display = false
46
- @bad_lines_enabled = false
47
- @matched = false
48
- @ba = nil
49
- new_line(0)
50
- end
51
-
52
- def display? = @display
53
-
54
- # Sets VCBASE, VC, RC and VMLI, in that order, and the display and
55
- # bad-line flags, as a VICE snapshot gives them.
56
- def restore_counters(counters, display, bad_lines_enabled)
57
- @vc_base, @vc, @rc, @vmli = counters
58
- @display = display
59
- @bad_lines_enabled = bad_lines_enabled
60
- end
61
-
62
- def idle? = !@display
63
- def bad_line? = !@ba.nil?
64
-
65
- # The bad line condition as the last column compared it.
66
- def bad_line_condition? = @matched
67
-
68
- # True once AEC has followed BA down and the VIC owns the bus.
69
- def bus_taken?(column) = @ba ? column >= @ba + BA_DELAY : false
70
-
71
- # The CPU kept the bus through the cycle before +column+, so on a bad
72
- # line AEC falls BA_DELAY cycles after it at the earliest.
73
- def keep_bus(column)
74
- @ba &&= column
75
- end
76
-
77
- def fetching?(column)
78
- @matched && column >= FETCH_FIRST && column <= DMA_LAST
79
- end
80
-
81
- def save_state(out)
82
- out.int(@vc_base).int(@vc).int(@vmli).int(@rc).boolean(@display).boolean(@bad_lines_enabled)
83
- out.boolean(@matched).optional_int(@ba).int(@line_bits).boolean(@den_line).boolean(@in_window)
84
- end
85
-
86
- def load_state(input)
87
- @vc_base = input.int
88
- @vc = input.int
89
- @vmli = input.int
90
- @rc = input.int
91
- @display = input.boolean?
92
- @bad_lines_enabled = input.boolean?
93
- @matched = input.boolean?
94
- @ba = input.optional_int
95
- @line_bits = input.int
96
- @den_line = input.boolean?
97
- @in_window = input.boolean?
98
- end
99
-
100
- def new_frame
101
- @vc_base = 0
102
- @bad_lines_enabled = false
103
- end
104
-
105
- def new_line(line)
106
- @ba = nil
107
- raster_step(line)
108
- end
109
-
110
- # The raster counter moved on to +line+, at the line's start or, under
111
- # the VIC-IIe's TEST bit, within it.
112
- def raster_step(line)
113
- @line_bits = line & 0b111
114
- @den_line = line == FIRST_LINE
115
- @in_window = line.between?(FIRST_LINE, LAST_LINE)
116
- end
117
-
118
- # Returns true when this compare opened display state.
119
- def cycle(rasterline, column)
120
- match = column == @wrap_column ? wrap_match(rasterline + 1) : line_match
121
- @matched = match
122
- opened = false
123
- if match
124
- opened = !@display
125
- @display = true
126
- @ba = column if @ba.nil? && column >= DMA_FIRST && column <= DMA_LAST
127
- end
128
- load_counters(match) if column == LOAD_COLUMN
129
- check_row_counter(match) if column == RC_COLUMN
130
- opened
131
- end
132
-
133
- # A g-access in display state consumes one buffer cell and one video
134
- # matrix address. A row that opens mid-line makes fewer of them, and
135
- # the shortfall carries into VCBASE.
136
- def graphics_column?(column) = GRAPHICS_COLUMNS[column]
137
-
138
- def graphics_access(column)
139
- return unless graphics_column?(column)
140
-
141
- @vc = (@vc + 1) & 0x3ff
142
- @vmli += 1
143
- end
144
-
145
- private
146
-
147
- def line_match
148
- latch_den if @den_line
149
- @bad_lines_enabled && @in_window && @line_bits == @registers.yscroll
150
- end
151
-
152
- # The wrap column compares against the line about to start. The DEN
153
- # latch is level-sensitive across the counter's increment, so this one
154
- # column sees both the line ending and the line starting.
155
- def wrap_match(line)
156
- latch_den if @den_line || line == FIRST_LINE
157
- return false unless line.between?(FIRST_LINE, LAST_LINE)
158
-
159
- @bad_lines_enabled && (line & 0b111) == @registers.yscroll
160
- end
161
-
162
- def latch_den
163
- @bad_lines_enabled = true if @registers.display_enabled?
164
- end
165
-
166
- def load_counters(match)
167
- @vc = @vc_base
168
- @vmli = 0
169
- @rc = 0 if match
170
- end
171
-
172
- # A condition still standing when the row counter wraps puts the logic
173
- # straight back into display state, so a forced row rolls into the
174
- # next one instead of leaving the line idle (Bauer 3.7.2 step 5).
175
- def check_row_counter(match)
176
- if @rc == 7
177
- @display = false
178
- @vc_base = @vc
179
- end
180
- @display ||= match
181
- @rc = (@rc + 1) & 0b111 if @display
182
- end
183
- end
184
- end
185
- end
@@ -1,164 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class VIC < Cycleable
5
- module GraphicsMode
6
- # Foreground masks depend only on the data byte, so each byte maps to a
7
- # precomputed frozen pattern shared by reference instead of being
8
- # written out pixel by pixel.
9
- HIRES_FG = Array.new(256) do |data|
10
- Array.new(8) { |i| data.anybits?(1 << (7 - i)) }.freeze
11
- end.freeze
12
-
13
- # The high bit of each 2-bit pair (10/11) is foreground.
14
- PAIR_FG = Array.new(256) do |data|
15
- Array.new(8) { |i| (data >> (6 - (i & ~1))).allbits?(0b10) }.freeze
16
- end.freeze
17
-
18
- # The same patterns as masks, all bits set for a foreground pixel.
19
- HIRES_MASK = Array.new(256) do |data|
20
- Array.new(8) { |i| data.anybits?(1 << (7 - i)) ? -1 : 0 }.freeze
21
- end.freeze
22
-
23
- NO_FG = HIRES_FG[0]
24
-
25
- module Hires
26
- def paint_hires(data, color, background, seq)
27
- seq.cur_fg = HIRES_FG[data]
28
- colors = seq.cur_colors
29
- return colors.fill(background) if data.zero?
30
-
31
- mask = HIRES_MASK[data]
32
- flip = color ^ background
33
- colors[0] = background ^ (flip & mask[0])
34
- colors[1] = background ^ (flip & mask[1])
35
- colors[2] = background ^ (flip & mask[2])
36
- colors[3] = background ^ (flip & mask[3])
37
- colors[4] = background ^ (flip & mask[4])
38
- colors[5] = background ^ (flip & mask[5])
39
- colors[6] = background ^ (flip & mask[6])
40
- colors[7] = background ^ (flip & mask[7])
41
- end
42
- end
43
-
44
- # Decodes 2-bit pixel pairs into double-wide pixels, each pair indexing
45
- # the four colours in the mode's palette.
46
- module Multicolor
47
- def paint_pairs(data, seq)
48
- seq.cur_fg = PAIR_FG[data]
49
- colors = seq.cur_colors
50
- palette = @palette
51
- colors[0] = colors[1] = palette[data >> 6]
52
- colors[2] = colors[3] = palette[(data >> 4) & 0b11]
53
- colors[4] = colors[5] = palette[(data >> 2) & 0b11]
54
- colors[6] = colors[7] = palette[data & 0b11]
55
- end
56
- end
57
-
58
- # Each mode paints the byte a g-access read with the screen byte and
59
- # colour nibble it latched. The VIC reads the byte itself, in the
60
- # g-access column. #fg gives the foreground mask #paint would leave,
61
- # without the colours.
62
- class Text
63
- include Hires
64
-
65
- def paint(data, _screencode, color, seq)
66
- paint_hires(data, color, seq.registers.background, seq)
67
- end
68
-
69
- def fg(data, _screencode, _color) = HIRES_FG[data]
70
- end
71
-
72
- class MulticolorText
73
- include Hires
74
- include Multicolor
75
-
76
- def initialize
77
- @palette = Array.new(4, 0)
78
- end
79
-
80
- def paint(data, _screencode, color, seq)
81
- registers = seq.registers
82
- if color.anybits?(0x08)
83
- palette = @palette
84
- palette[0] = registers.background(0)
85
- palette[1] = registers.background(1)
86
- palette[2] = registers.background(2)
87
- palette[3] = color & 0x07
88
- paint_pairs(data, seq)
89
- else
90
- paint_hires(data, color & 0x07, registers.background, seq)
91
- end
92
- end
93
-
94
- def fg(data, _screencode, color) = color.anybits?(0x08) ? PAIR_FG[data] : HIRES_FG[data]
95
- end
96
-
97
- class ExtendedBackgroundText
98
- include Hires
99
-
100
- def paint(data, screencode, color, seq)
101
- background = seq.registers.background((screencode >> 6) & 0b11)
102
- paint_hires(data, color, background, seq)
103
- end
104
-
105
- def fg(data, _screencode, _color) = HIRES_FG[data]
106
- end
107
-
108
- class Bitmap
109
- include Hires
110
-
111
- def paint(data, screencode, _color, seq)
112
- foreground = (screencode >> 4) & 0x0f
113
- background = screencode & 0x0f
114
- paint_hires(data, foreground, background, seq)
115
- end
116
-
117
- def fg(data, _screencode, _color) = HIRES_FG[data]
118
- end
119
-
120
- class MulticolorBitmap
121
- include Multicolor
122
-
123
- def initialize
124
- @palette = Array.new(4, 0)
125
- end
126
-
127
- def paint(data, screencode, color, seq)
128
- palette = @palette
129
- palette[0] = seq.registers.background(0)
130
- palette[1] = (screencode >> 4) & 0x0f
131
- palette[2] = screencode & 0x0f
132
- palette[3] = color & 0x0f
133
- paint_pairs(data, seq)
134
- end
135
-
136
- def fg(data, _screencode, _color) = PAIR_FG[data]
137
- end
138
-
139
- class Null
140
- def paint(_data, _screencode, _color, seq)
141
- seq.cur_fg = NO_FG
142
- seq.cur_colors.fill(0)
143
- end
144
-
145
- def fg(_data, _screencode, _color) = NO_FG
146
- end
147
-
148
- NULL_MODE = Null.new
149
-
150
- # Indexed by ECM/BMM/MCM; the three invalid combinations decode to
151
- # black.
152
- MODES = [
153
- Text.new, # 000 standard text
154
- MulticolorText.new, # 001 multicolour text
155
- Bitmap.new, # 010 standard bitmap
156
- MulticolorBitmap.new, # 011 multicolour bitmap
157
- ExtendedBackgroundText.new, # 100 ECM text
158
- NULL_MODE, # 101 invalid
159
- NULL_MODE, # 110 invalid
160
- NULL_MODE # 111 invalid
161
- ].freeze
162
- end
163
- end
164
- end
@@ -1,207 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class VIC < Cycleable
5
- # The graphics shift register, pixel by pixel, for the groups where a
6
- # mode or XSCROLL change lands (VICE x64sc `draw_graphics`). The
7
- # sequencer paints whole bytes everywhere else, which comes to the same
8
- # thing while nothing changes.
9
- #
10
- # The byte a group draws loads at pixel XSCROLL. ECM and BMM take hold at
11
- # pixel 4 as they rise and at pixel 6 as they fall (the 6569's colour
12
- # latency), except that BMM falls at pixel 5 out of any mode but hi-res
13
- # bitmap. MCM takes hold at pixel 4 for the colour lookup but only at
14
- # pixel 7 for how the register is read, where a rising MCM also resets
15
- # the multicolour flip-flop. An MCM that falls out of the invalid
16
- # ECM+MCM mode is a pixel later on both counts: the lookup changes at
17
- # pixel 5 and the read at the next group's pixel 0. The mode bits are
18
- # the sequencer's: ECM 4, BMM 2, MCM 1.
19
- #
20
- # The 8565 has no colour latency: ECM and BMM take hold, rising or
21
- # falling, at the next group's pixel 0, and an MCM that falls out of
22
- # ECM+MCM does so on time. Where that pixel 0 takes the group out of an
23
- # invalid mode, it is still black into hi-res text, and so is a
24
- # background pixel into multicolour bitmap.
25
- class GraphicsShifter
26
- ECM = 0b100
27
- ECM_BMM = 0b110
28
- MULTICOLOR_BITMAP = 0b011
29
- ECM_MCM = 0b101
30
- BMM = 0b010
31
-
32
- # The group #draw painted, and which of its pixels are foreground.
33
- attr_reader :colors, :fg
34
-
35
- def initialize(registers, model: :mos6569)
36
- @registers = registers
37
- @latency = model != :mos8565
38
- @next_ecm_bmm = 0
39
- @black_below = 0
40
- @colors = Array.new(8, 0)
41
- @fg = Array.new(8, false)
42
- @gbuf = 0
43
- @vbuf = 0
44
- @cbuf = 0
45
- @flop = 0
46
- @pixel = 0
47
- @mode_lookup = 0
48
- @mode_read = 0
49
- @late_mcm = false
50
- @late_read = false
51
- end
52
-
53
- def save_state(out)
54
- out.int(@next_ecm_bmm).int(@black_below).ints(@colors).booleans(@fg)
55
- out.int(@gbuf).int(@vbuf).int(@cbuf).int(@flop).int(@pixel)
56
- out.int(@mode_lookup).int(@mode_read).boolean(@late_mcm).boolean(@late_read)
57
- end
58
-
59
- def load_state(input)
60
- @next_ecm_bmm = input.int
61
- @black_below = input.int
62
- input.ints_into(@colors)
63
- input.booleans_into(@fg)
64
- load_buffers(input)
65
- @mode_lookup = input.int
66
- @mode_read = input.int
67
- @late_mcm = input.boolean?
68
- @late_read = input.boolean?
69
- end
70
-
71
- # Rebuilds the state at the end of a group that painted whole bytes:
72
- # the byte loaded at pixel shift under an unchanging mode.
73
- def prime(data, screencode, color, shift, mode)
74
- @mode_lookup = mode
75
- @next_ecm_bmm = mode & ECM_BMM
76
- @mode_read = mode & 1
77
- @late_read = false
78
- load(data, screencode, color)
79
- (8 - shift).times { read_pixel }
80
- end
81
-
82
- # Draws one group, loading the byte at pixel shift.
83
- def draw(data, screencode, color, shift, mode)
84
- i = 0
85
- while i < 8
86
- step_mode(i, mode)
87
- load(data, screencode, color) if i == shift
88
- pixel = read_pixel
89
- @colors[i] = pixel < @black_below ? 0 : lookup(pixel)
90
- @black_below = 0
91
- @fg[i] = pixel >= 2
92
- i += 1
93
- end
94
- @next_ecm_bmm = mode & ECM_BMM
95
- end
96
-
97
- private
98
-
99
- def load_buffers(input)
100
- @gbuf = input.int
101
- @vbuf = input.int
102
- @cbuf = input.int
103
- @flop = input.int
104
- @pixel = input.int
105
- end
106
-
107
- def step_mode(pixel, mode)
108
- case pixel
109
- when 0 then start_group
110
- when 4 then step_lookup(mode)
111
- when 5 then step_early_fall(mode)
112
- when 6 then @mode_lookup &= mode | 1 if @latency
113
- when 7 then step_read
114
- end
115
- end
116
-
117
- def start_group
118
- end_late_read
119
- return if @latency
120
-
121
- invalid = @mode_lookup > ECM
122
- @mode_lookup = (@mode_lookup & ~ECM_BMM) | @next_ecm_bmm
123
- @black_below = black_pixels_out_of_invalid if invalid
124
- end
125
-
126
- # The pixel values below which pixel 0 stays black as the group leaves
127
- # an invalid mode: all four into hi-res text, the background ones into
128
- # multicolour bitmap.
129
- def black_pixels_out_of_invalid
130
- case @mode_lookup
131
- when 0 then 4
132
- when MULTICOLOR_BITMAP then 2
133
- else 0
134
- end
135
- end
136
-
137
- def step_lookup(mode)
138
- @late_mcm = @latency && @mode_lookup.allbits?(ECM_MCM) && mode.nobits?(1)
139
- rising = @latency ? mode & ECM_BMM : 0
140
- @mode_lookup = (@mode_lookup & ~1) | (mode & 1) | (@late_mcm ? 1 : 0) | rising
141
- end
142
-
143
- def step_early_fall(mode)
144
- @mode_lookup &= ~1 if @late_mcm
145
- @mode_lookup &= mode | ~BMM if @latency && @mode_lookup != BMM
146
- end
147
-
148
- def step_read
149
- return @late_read = true if @late_mcm
150
-
151
- mcm = @mode_lookup & 1
152
- @flop = 0 if mcm == 1 && @mode_read.zero?
153
- @mode_read = mcm
154
- end
155
-
156
- def end_late_read
157
- return unless @late_read
158
-
159
- @mode_read = 0
160
- @late_read = false
161
- end
162
-
163
- def load(data, screencode, color)
164
- @gbuf = data
165
- @vbuf = screencode
166
- @cbuf = color & 0x0f
167
- @flop = 1
168
- end
169
-
170
- def read_pixel
171
- multicolor = multicolor?
172
- if @mode_read == 1 && multicolor
173
- @pixel = @gbuf >> 6 if @flop == 1
174
- elsif @gbuf.anybits?(0x80)
175
- @pixel = multicolor && @mode_read.zero? ? 2 : 3
176
- else
177
- @pixel = 0
178
- end
179
- @gbuf = (@gbuf << 1) & 0xff
180
- @flop ^= 1
181
- @pixel
182
- end
183
-
184
- def multicolor? = @mode_lookup.anybits?(BMM) || @cbuf.anybits?(0x08)
185
-
186
- def lookup(pixel)
187
- case @mode_lookup
188
- when 0 then pixel < 2 ? @registers.background : @cbuf
189
- when 1 then pixel == 3 ? @cbuf & 0x07 : @registers.background(pixel)
190
- when 2 then pixel < 2 ? @vbuf & 0x0f : @vbuf >> 4
191
- when 3 then multicolor_bitmap(pixel)
192
- when 4 then pixel < 2 ? @registers.background(@vbuf >> 6) : @cbuf
193
- else 0
194
- end
195
- end
196
-
197
- def multicolor_bitmap(pixel)
198
- case pixel
199
- when 0 then @registers.background
200
- when 1 then @vbuf >> 4
201
- when 2 then @vbuf & 0x0f
202
- else @cbuf
203
- end
204
- end
205
- end
206
- end
207
- end
@@ -1,81 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class VIC < Cycleable
5
- # Mid-line writes to the sprite registers, keyed by the pixel at which
6
- # they become visible. Compositing replays the line through the log, so
7
- # each pixel is drawn with the register values that were in effect when
8
- # the VIC reached it.
9
- class RegisterLog
10
- def initialize(registers)
11
- @registers = registers
12
- @entries = []
13
- @seed = []
14
- @values = Array.new(2**6, 0)
15
- @cursor = 0
16
- @next_x = 0
17
- end
18
-
19
- # The pixel at which the next logged write takes effect.
20
- attr_reader :next_x
21
-
22
- # The entries as pixel, register and value in turn, the seed with -1
23
- # for a register the line hasn't logged, and a next pixel past the
24
- # last entry as -1.
25
- def save_state(out)
26
- out.ints(@entries.flatten)
27
- out.ints(@seed.map { |value| value.nil? ? -1 : value })
28
- out.ints(@values).int(@cursor).int(@next_x.infinite? ? -1 : @next_x)
29
- end
30
-
31
- def load_state(input)
32
- @entries.replace(input.ints.each_slice(3).to_a)
33
- @seed.replace(input.ints.map { |value| value.negative? ? nil : value })
34
- input.ints_into(@values)
35
- @cursor = input.int
36
- next_x = input.int
37
- @next_x = next_x.negative? ? Float::INFINITY : next_x
38
- end
39
-
40
- def empty? = @entries.empty?
41
- def length = @entries.length
42
-
43
- def clear
44
- return if @entries.empty?
45
-
46
- @entries.clear
47
- @seed.clear
48
- end
49
-
50
- def log(pixel_x, reg, old, value)
51
- @seed[reg] = old if @seed[reg].nil?
52
- @entries << [pixel_x, reg, value]
53
- end
54
-
55
- def prepare
56
- @entries.sort_by! { |entry| entry[0] }
57
- end
58
-
59
- # Restart the cursor before the line's first pixel, with every logged
60
- # register back at the value it held when the line started.
61
- def rewind
62
- @values.length.times { |reg| @values[reg] = @registers[reg] }
63
- @seed.each_with_index { |value, reg| @values[reg] = value unless value.nil? }
64
- @cursor = 0
65
- @next_x = @entries.empty? ? Float::INFINITY : @entries[0][0]
66
- end
67
-
68
- def [](reg) = @values[reg]
69
-
70
- # Apply every write visible at or before pixel_x.
71
- def advance(pixel_x)
72
- while @cursor < @entries.length && @entries[@cursor][0] <= pixel_x
73
- entry = @entries[@cursor]
74
- @values[entry[1]] = entry[2]
75
- @cursor += 1
76
- end
77
- @next_x = @cursor < @entries.length ? @entries[@cursor][0] : Float::INFINITY
78
- end
79
- end
80
- end
81
- end