badline 0.12.1 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (565) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -1
  3. data/CLAUDE.md +86 -38
  4. data/CONTRIBUTING.md +4 -3
  5. data/README.md +9 -6
  6. data/doc/library.md +9 -9
  7. data/doc/media.md +2 -1
  8. data/doc/pinned-behaviour.md +134 -105
  9. data/doc/snapshot-format.md +1047 -0
  10. data/doc/snapshots.md +73 -43
  11. data/lib/badline/audio/bare_player.rb +53 -20
  12. data/lib/badline/audio/cli.rb +6 -6
  13. data/lib/badline/audio/jukebox.rb +2 -2
  14. data/lib/badline/audio/machine_player.rb +16 -10
  15. data/lib/badline/{media → audio}/queue.rb +1 -1
  16. data/lib/badline/audio/queued_tune.rb +6 -6
  17. data/lib/badline/audio/renderer.rb +33 -22
  18. data/lib/badline/audio/stereo.rb +1 -1
  19. data/lib/badline/c128/banks.rb +6 -3
  20. data/lib/badline/c128/bus/keyed_state.rb +45 -0
  21. data/lib/badline/c128/bus.rb +35 -20
  22. data/lib/badline/c128/color_lines.rb +2 -2
  23. data/lib/badline/c128/cpu.rb +1 -1
  24. data/lib/badline/c128/drives.rb +14 -34
  25. data/lib/badline/c128/fast_serial.rb +5 -5
  26. data/lib/badline/c128/keyed_modules.rb +117 -0
  27. data/lib/badline/c128/keyed_state.rb +91 -0
  28. data/lib/badline/c128/keys.rb +9 -0
  29. data/lib/badline/c128/mmu.rb +9 -8
  30. data/lib/badline/c128/mmu_pages.rb +21 -1
  31. data/lib/badline/c128/modes.rb +21 -11
  32. data/lib/badline/c128/z80.rb +2 -2
  33. data/lib/badline/c128/z80_turns.rb +1 -1
  34. data/lib/badline/c128.rb +21 -16
  35. data/lib/badline/c64/attachments.rb +42 -0
  36. data/lib/badline/c64/banked_ram/banking.rb +32 -0
  37. data/lib/badline/c64/banked_ram/plus256k.rb +64 -0
  38. data/lib/badline/c64/banked_ram/plus60k.rb +47 -0
  39. data/lib/badline/c64/banked_ram/unexpanded.rb +30 -0
  40. data/lib/badline/c64/banked_ram.rb +23 -0
  41. data/lib/badline/c64/bus/debug_register.rb +32 -0
  42. data/lib/badline/c64/bus/extra_sids.rb +32 -0
  43. data/lib/badline/c64/bus/fittings.rb +40 -0
  44. data/lib/badline/c64/bus/keyed_state.rb +41 -0
  45. data/lib/badline/c64/bus/pla.rb +149 -0
  46. data/lib/badline/c64/bus/roms.rb +41 -0
  47. data/lib/badline/c64/bus/sid_slots.rb +44 -0
  48. data/lib/badline/c64/bus.rb +219 -0
  49. data/lib/badline/c64/cartridge/action_replay.rb +115 -0
  50. data/lib/badline/c64/cartridge/atomic_power.rb +26 -0
  51. data/lib/badline/c64/cartridge/bank.rb +83 -0
  52. data/lib/badline/c64/cartridge/comal80.rb +52 -0
  53. data/lib/badline/c64/cartridge/dinamic.rb +36 -0
  54. data/lib/badline/c64/cartridge/easy_flash.rb +132 -0
  55. data/lib/badline/c64/cartridge/epyx_fastload.rb +73 -0
  56. data/lib/badline/c64/cartridge/final_cartridge3.rb +79 -0
  57. data/lib/badline/c64/cartridge/flash.rb +279 -0
  58. data/lib/badline/c64/cartridge/freezer.rb +35 -0
  59. data/lib/badline/c64/cartridge/fun_play.rb +40 -0
  60. data/lib/badline/c64/cartridge/g_mod2.rb +64 -0
  61. data/lib/badline/c64/cartridge/game_system.rb +42 -0
  62. data/lib/badline/c64/cartridge/geo_ram.rb +65 -0
  63. data/lib/badline/c64/cartridge/kcs_power.rb +69 -0
  64. data/lib/badline/c64/cartridge/keyed_state.rb +393 -0
  65. data/lib/badline/c64/cartridge/mach5.rb +34 -0
  66. data/lib/badline/c64/cartridge/magic_desk.rb +32 -0
  67. data/lib/badline/c64/cartridge/ocean.rb +37 -0
  68. data/lib/badline/c64/cartridge/pagefox.rb +60 -0
  69. data/lib/badline/c64/cartridge/retro_replay.rb +278 -0
  70. data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
  71. data/lib/badline/c64/cartridge/rgcd.rb +50 -0
  72. data/lib/badline/c64/cartridge/simons_basic.rb +37 -0
  73. data/lib/badline/c64/cartridge/standard.rb +17 -0
  74. data/lib/badline/c64/cartridge/super_games.rb +40 -0
  75. data/lib/badline/c64/cartridge/westermann.rb +32 -0
  76. data/lib/badline/c64/cartridge/zaxxon.rb +52 -0
  77. data/lib/badline/c64/cartridge.rb +232 -0
  78. data/lib/badline/c64/color_memory.rb +27 -0
  79. data/lib/badline/{computer → c64}/common.rb +2 -2
  80. data/lib/badline/{computer → c64}/kernal_traps.rb +39 -36
  81. data/lib/badline/c64/keyed_modules.rb +111 -0
  82. data/lib/badline/c64/keyed_state.rb +68 -0
  83. data/lib/badline/c64/reu/dma.rb +271 -0
  84. data/lib/badline/c64/reu/keyed_state.rb +140 -0
  85. data/lib/badline/c64/reu/ram.rb +94 -0
  86. data/lib/badline/c64/reu/trigger.rb +34 -0
  87. data/lib/badline/c64/reu.rb +289 -0
  88. data/lib/badline/c64/true_drives.rb +120 -0
  89. data/lib/badline/{computer.rb → c64.rb} +24 -15
  90. data/lib/badline/chips/cia/fast_forward.rb +62 -0
  91. data/lib/badline/chips/cia/interrupt_register.rb +128 -0
  92. data/lib/badline/chips/cia/keyed_parts.rb +213 -0
  93. data/lib/badline/chips/cia/serial.rb +246 -0
  94. data/lib/badline/chips/cia/time_of_day.rb +210 -0
  95. data/lib/badline/chips/cia/timer.rb +188 -0
  96. data/lib/badline/chips/cia.rb +281 -0
  97. data/lib/badline/chips/cpu/addressing.rb +133 -0
  98. data/lib/badline/chips/cpu/boundary.rb +56 -0
  99. data/lib/badline/chips/cpu/core.rb +183 -0
  100. data/lib/badline/chips/cpu/instruction.rb +338 -0
  101. data/lib/badline/chips/cpu/instruction_set/arithmetic.rb +118 -0
  102. data/lib/badline/chips/cpu/instruction_set/bitwise.rb +130 -0
  103. data/lib/badline/chips/cpu/instruction_set/branch.rb +83 -0
  104. data/lib/badline/chips/cpu/instruction_set/flag.rb +67 -0
  105. data/lib/badline/chips/cpu/instruction_set/illegal.rb +274 -0
  106. data/lib/badline/chips/cpu/instruction_set/inc_dec.rb +73 -0
  107. data/lib/badline/chips/cpu/instruction_set/stack.rb +56 -0
  108. data/lib/badline/chips/cpu/instruction_set/transfer.rb +141 -0
  109. data/lib/badline/chips/cpu/instruction_set.rb +59 -0
  110. data/lib/badline/chips/cpu/interrupts.rb +108 -0
  111. data/lib/badline/chips/cpu/keyed_state.rb +177 -0
  112. data/lib/badline/chips/cpu/microcode.rb +195 -0
  113. data/lib/badline/chips/cpu/operations.rb +90 -0
  114. data/lib/badline/chips/cpu/port.rb +133 -0
  115. data/lib/badline/chips/cpu/stack_operations.rb +84 -0
  116. data/lib/badline/chips/cpu/traps.rb +23 -0
  117. data/lib/badline/chips/cpu.rb +17 -0
  118. data/lib/badline/chips/sid/catch_up.rb +122 -0
  119. data/lib/badline/chips/sid/decimator.rb +68 -0
  120. data/lib/badline/chips/sid/envelope.rb +236 -0
  121. data/lib/badline/chips/sid/filter.rb +227 -0
  122. data/lib/badline/chips/sid/keyed_parts.rb +286 -0
  123. data/lib/badline/chips/sid/voice.rb +69 -0
  124. data/lib/badline/chips/sid/waveform/combined.rb +128 -0
  125. data/lib/badline/chips/sid/waveform/fast_forward.rb +107 -0
  126. data/lib/badline/chips/sid/waveform/noise_writeback.rb +124 -0
  127. data/lib/badline/chips/sid/waveform.rb +305 -0
  128. data/lib/badline/chips/sid.rb +264 -0
  129. data/lib/badline/chips/ted/beam.rb +119 -0
  130. data/lib/badline/chips/ted/timers.rb +66 -0
  131. data/lib/badline/chips/ted.rb +143 -0
  132. data/lib/badline/chips/tia.rb +49 -0
  133. data/lib/badline/chips/vdc/keyed_parts.rb +105 -0
  134. data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
  135. data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -13
  136. data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -17
  137. data/lib/badline/{c128 → chips}/vdc/window.rb +1 -10
  138. data/lib/badline/{c128 → chips}/vdc.rb +6 -31
  139. data/lib/badline/chips/via/control_lines.rb +109 -0
  140. data/lib/badline/chips/via/fast_forward.rb +55 -0
  141. data/lib/badline/chips/via/interrupt_register.rb +60 -0
  142. data/lib/badline/chips/via/keyed_parts.rb +163 -0
  143. data/lib/badline/chips/via/shift_register.rb +168 -0
  144. data/lib/badline/chips/via/timer1.rb +120 -0
  145. data/lib/badline/chips/via/timer2.rb +117 -0
  146. data/lib/badline/chips/via.rb +267 -0
  147. data/lib/badline/chips/vic/bank.rb +135 -0
  148. data/lib/badline/chips/vic/border_mask.rb +78 -0
  149. data/lib/badline/chips/vic/collisions.rb +106 -0
  150. data/lib/badline/chips/vic/color_patches.rb +38 -0
  151. data/lib/badline/chips/vic/display_state.rb +168 -0
  152. data/lib/badline/chips/vic/graphics_mode.rb +166 -0
  153. data/lib/badline/chips/vic/graphics_shifter.rb +183 -0
  154. data/lib/badline/chips/vic/keyed_parts.rb +228 -0
  155. data/lib/badline/chips/vic/keyed_sprites.rb +225 -0
  156. data/lib/badline/chips/vic/keyed_state.rb +102 -0
  157. data/lib/badline/chips/vic/register_log.rb +65 -0
  158. data/lib/badline/chips/vic/registers.rb +188 -0
  159. data/lib/badline/chips/vic/sequencer.rb +275 -0
  160. data/lib/badline/chips/vic/sequencer_output.rb +118 -0
  161. data/lib/badline/chips/vic/sprite/internal_bus.rb +59 -0
  162. data/lib/badline/chips/vic/sprite/shifter.rb +148 -0
  163. data/lib/badline/chips/vic/sprite/timing.rb +58 -0
  164. data/lib/badline/chips/vic/sprite.rb +337 -0
  165. data/lib/badline/chips/vic/sprites.rb +281 -0
  166. data/lib/badline/chips/vic.rb +787 -0
  167. data/lib/badline/chips/vic_i/keyed_parts.rb +142 -0
  168. data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +2 -30
  169. data/lib/badline/chips/vic_i/sound/output.rb +85 -0
  170. data/lib/badline/chips/vic_i/sound.rb +227 -0
  171. data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
  172. data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +6 -6
  173. data/lib/badline/chips/z80/arithmetic.rb +119 -0
  174. data/lib/badline/chips/z80/bit_page.rb +57 -0
  175. data/lib/badline/chips/z80/block_io.rb +60 -0
  176. data/lib/badline/chips/z80/block_transfers.rb +61 -0
  177. data/lib/badline/chips/z80/bus_cycles.rb +113 -0
  178. data/lib/badline/chips/z80/core.rb +115 -0
  179. data/lib/badline/chips/z80/exchanges.rb +52 -0
  180. data/lib/badline/chips/z80/extended_page.rb +91 -0
  181. data/lib/badline/chips/z80/flags.rb +39 -0
  182. data/lib/badline/chips/z80/interrupt_acceptance.rb +48 -0
  183. data/lib/badline/chips/z80/jumps.rb +84 -0
  184. data/lib/badline/chips/z80/keyed_state.rb +73 -0
  185. data/lib/badline/chips/z80/loads.rb +100 -0
  186. data/lib/badline/chips/z80/main_page.rb +136 -0
  187. data/lib/badline/chips/z80/registers.rb +122 -0
  188. data/lib/badline/chips/z80/shifts.rb +66 -0
  189. data/lib/badline/chips/z80.rb +13 -0
  190. data/lib/badline/chips.rb +10 -0
  191. data/lib/badline/core.rb +13 -32
  192. data/lib/badline/drives/datasette/keyed_state.rb +38 -0
  193. data/lib/badline/drives/datasette.rb +173 -0
  194. data/lib/badline/drives/engine/core.rb +152 -0
  195. data/lib/badline/drives/engine/fast_serial.rb +75 -0
  196. data/lib/badline/drives/engine/idle.rb +127 -0
  197. data/lib/badline/drives/engine/idle_cpu.rb +30 -0
  198. data/lib/badline/drives/engine/orbit.rb +81 -0
  199. data/lib/badline/drives/engine/serial_lines.rb +72 -0
  200. data/lib/badline/drives/engine/sleep.rb +114 -0
  201. data/lib/badline/drives/engine/vias.rb +86 -0
  202. data/lib/badline/drives/engine/watch.rb +152 -0
  203. data/lib/badline/drives/engine.rb +11 -0
  204. data/lib/badline/drives/model1541/bus.rb +75 -0
  205. data/lib/badline/drives/model1541/byte_ready.rb +50 -0
  206. data/lib/badline/drives/model1541/cpu.rb +13 -0
  207. data/lib/badline/drives/model1541/disk.rb +318 -0
  208. data/lib/badline/drives/model1541/disk_via.rb +38 -0
  209. data/lib/badline/drives/model1541/gcr.rb +59 -0
  210. data/lib/badline/drives/model1541/keyed_state.rb +251 -0
  211. data/lib/badline/drives/model1541/mechanism.rb +313 -0
  212. data/lib/badline/drives/model1541/rotation.rb +123 -0
  213. data/lib/badline/drives/model1541/sector_reader.rb +78 -0
  214. data/lib/badline/drives/model1541/serial_port.rb +20 -0
  215. data/lib/badline/drives/model1541/track.rb +100 -0
  216. data/lib/badline/drives/model1541.rb +80 -0
  217. data/lib/badline/drives/model1571/bus.rb +100 -0
  218. data/lib/badline/drives/model1571/cpu.rb +13 -0
  219. data/lib/badline/drives/model1571/keyed_state.rb +108 -0
  220. data/lib/badline/drives/model1571/serial_port.rb +39 -0
  221. data/lib/badline/drives/model1571/serial_via.rb +27 -0
  222. data/lib/badline/drives/model1571/wd1770.rb +108 -0
  223. data/lib/badline/drives/model1571.rb +141 -0
  224. data/lib/badline/drives/model1581/bus.rb +126 -0
  225. data/lib/badline/drives/model1581/cpu.rb +13 -0
  226. data/lib/badline/drives/model1581/disk.rb +133 -0
  227. data/lib/badline/drives/model1581/keyed_state.rb +280 -0
  228. data/lib/badline/drives/model1581/mechanism.rb +98 -0
  229. data/lib/badline/drives/model1581/serial_port.rb +54 -0
  230. data/lib/badline/drives/model1581/slot.rb +61 -0
  231. data/lib/badline/drives/model1581/track.rb +102 -0
  232. data/lib/badline/drives/model1581/track_bytes.rb +77 -0
  233. data/lib/badline/drives/model1581/wd1772/registers.rb +91 -0
  234. data/lib/badline/drives/model1581/wd1772/sector_writes.rb +75 -0
  235. data/lib/badline/drives/model1581/wd1772/sectors.rb +152 -0
  236. data/lib/badline/drives/model1581/wd1772/stepping.rb +111 -0
  237. data/lib/badline/drives/model1581/wd1772/tracks.rb +127 -0
  238. data/lib/badline/drives/model1581/wd1772/turn.rb +75 -0
  239. data/lib/badline/drives/model1581/wd1772.rb +216 -0
  240. data/lib/badline/drives/model1581.rb +206 -0
  241. data/lib/badline/drives/serial_bus.rb +161 -0
  242. data/lib/badline/drives.rb +8 -0
  243. data/lib/badline/frontend/app.rb +3 -3
  244. data/lib/badline/frontend/boot.rb +4 -4
  245. data/lib/badline/frontend/controls.rb +19 -3
  246. data/lib/badline/frontend/drive_led.rb +44 -21
  247. data/lib/badline/frontend/machine_window.rb +3 -1
  248. data/lib/badline/frontend/menu/menu_dialogs.rb +2 -2
  249. data/lib/badline/frontend/player/filter_view.rb +1 -1
  250. data/lib/badline/frontend/player/player_controller.rb +2 -2
  251. data/lib/badline/frontend/player/player_screen.rb +1 -0
  252. data/lib/badline/frontend/player/theme.rb +7 -7
  253. data/lib/badline/frontend/snapshots.rb +12 -1
  254. data/lib/badline/frontend/timeline.rb +30 -12
  255. data/lib/badline/input/control_ports.rb +78 -0
  256. data/lib/badline/input/joystick.rb +27 -0
  257. data/lib/badline/input/keyboard.rb +114 -0
  258. data/lib/badline/input/matrix_typist.rb +98 -0
  259. data/lib/badline/input.rb +4 -0
  260. data/lib/badline/kernal_trap/chrout.rb +45 -0
  261. data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
  262. data/lib/badline/kernal_trap/dos/channel.rb +156 -0
  263. data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -26
  264. data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -10
  265. data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
  266. data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -9
  267. data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -19
  268. data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
  269. data/lib/badline/kernal_trap/{drive.rb → dos.rb} +9 -27
  270. data/lib/badline/kernal_trap/file_routine.rb +4 -4
  271. data/lib/badline/kernal_trap/keyed_state.rb +150 -0
  272. data/lib/badline/kernal_trap/layout.rb +75 -11
  273. data/lib/badline/kernal_trap/load.rb +19 -21
  274. data/lib/badline/kernal_trap/routine.rb +12 -0
  275. data/lib/badline/kernal_trap/save.rb +12 -22
  276. data/lib/badline/kernal_trap/serial.rb +8 -24
  277. data/lib/badline/kernal_trap.rb +3 -2
  278. data/lib/badline/machine/clocking.rb +1 -1
  279. data/lib/badline/machine/keyboard_buffer.rb +49 -0
  280. data/lib/badline/machine/settling.rb +29 -0
  281. data/lib/badline/machine.rb +10 -7
  282. data/lib/badline/media/boot_disk.rb +14 -2
  283. data/lib/badline/media/extensions.rb +10 -0
  284. data/lib/badline/media/true_drive.rb +1 -1
  285. data/lib/badline/media/tune.rb +2 -2
  286. data/lib/badline/media.rb +3 -3
  287. data/lib/badline/memory.rb +3 -6
  288. data/lib/badline/model.rb +1 -1
  289. data/lib/badline/options/family.rb +5 -2
  290. data/lib/badline/options/help.rb +42 -16
  291. data/lib/badline/options/table.rb +2 -0
  292. data/lib/badline/options/validation.rb +2 -0
  293. data/lib/badline/options.rb +6 -1
  294. data/lib/badline/plus4/acia.rb +45 -0
  295. data/lib/badline/plus4/bus.rb +312 -0
  296. data/lib/badline/plus4/cpu.rb +10 -0
  297. data/lib/badline/plus4/cpu_port.rb +93 -0
  298. data/lib/badline/plus4/keyboard_port.rb +51 -0
  299. data/lib/badline/plus4/model.rb +38 -0
  300. data/lib/badline/plus4/user_port.rb +31 -0
  301. data/lib/badline/plus4.rb +164 -0
  302. data/lib/badline/roms/README +44 -6
  303. data/lib/badline/roms/plus4/basic.rom +0 -0
  304. data/lib/badline/roms/plus4/function-high.rom +0 -0
  305. data/lib/badline/roms/plus4/function-low.rom +0 -0
  306. data/lib/badline/roms/plus4/kernal-ntsc.rom +0 -0
  307. data/lib/badline/roms/plus4/kernal-pal.rom +0 -0
  308. data/lib/badline/sdl.rb +1 -0
  309. data/lib/badline/{storage/sid_file.rb → sid_tune/file.rb} +3 -3
  310. data/lib/badline/{storage → sid_tune}/hvsc.rb +7 -7
  311. data/lib/badline/{storage → sid_tune}/song_lengths.rb +2 -2
  312. data/lib/badline/{storage → sid_tune}/stil/credit.rb +1 -1
  313. data/lib/badline/{storage → sid_tune}/stil.rb +3 -3
  314. data/lib/badline/sid_tune.rb +6 -0
  315. data/lib/badline/snapshot/c128_setup.rb +32 -0
  316. data/lib/badline/snapshot/c64_setup.rb +83 -0
  317. data/lib/badline/snapshot/container.rb +4 -0
  318. data/lib/badline/snapshot/field_doc/markdown.rb +112 -0
  319. data/lib/badline/snapshot/field_doc.rb +109 -0
  320. data/lib/badline/snapshot/image.rb +132 -46
  321. data/lib/badline/snapshot/keyed/cursor.rb +40 -0
  322. data/lib/badline/snapshot/keyed/modules.rb +66 -0
  323. data/lib/badline/snapshot/keyed/reader.rb +188 -0
  324. data/lib/badline/snapshot/keyed/recorder.rb +88 -0
  325. data/lib/badline/snapshot/keyed/report.rb +26 -0
  326. data/lib/badline/snapshot/keyed/writer.rb +55 -0
  327. data/lib/badline/snapshot/keyed.rb +64 -0
  328. data/lib/badline/snapshot/machine_state.rb +17 -64
  329. data/lib/badline/snapshot/storage_setup.rb +63 -0
  330. data/lib/badline/snapshot/vic20_setup.rb +28 -0
  331. data/lib/badline/snapshot/vice/c64_mem.rb +1 -1
  332. data/lib/badline/snapshot/vice/restore.rb +1 -1
  333. data/lib/badline/snapshot/vice/reu1764.rb +3 -3
  334. data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
  335. data/lib/badline/snapshot/vice.rb +13 -35
  336. data/lib/badline/snapshot.rb +44 -22
  337. data/lib/badline/storage/crt_file.rb +3 -1
  338. data/lib/badline/storage/d64_image.rb +0 -2
  339. data/lib/badline/storage/d71_image.rb +0 -2
  340. data/lib/badline/storage/d81_image.rb +0 -2
  341. data/lib/badline/storage/disk_image.rb +3 -6
  342. data/lib/badline/storage/g64_image.rb +10 -5
  343. data/lib/badline/storage/host_directory.rb +0 -5
  344. data/lib/badline/storage/t64.rb +2 -8
  345. data/lib/badline/storage/tap.rb +43 -15
  346. data/lib/badline/storage/unavailable.rb +1 -1
  347. data/lib/badline/storage.rb +0 -37
  348. data/lib/badline/support/c128_checkpoint.rb +39 -0
  349. data/lib/badline/support/checkpoint.rb +108 -0
  350. data/lib/badline/support/vic20_checkpoint.rb +38 -0
  351. data/lib/badline/support.rb +5 -0
  352. data/lib/badline/version.rb +1 -1
  353. data/lib/badline/vic20/attachments.rb +8 -5
  354. data/lib/badline/vic20/bus/keyed_state.rb +52 -0
  355. data/lib/badline/vic20/bus.rb +2 -25
  356. data/lib/badline/vic20/cpu.rb +1 -1
  357. data/lib/badline/vic20/keyed_modules.rb +73 -0
  358. data/lib/badline/vic20/keyed_state.rb +45 -0
  359. data/lib/badline/vic20/port_wiring.rb +4 -4
  360. data/lib/badline/vic20/user_via_ports.rb +2 -2
  361. data/lib/badline/vic20.rb +22 -17
  362. data/lib/badline.rb +1 -0
  363. metadata +271 -228
  364. data/lib/badline/address_bus/extra_sids.rb +0 -30
  365. data/lib/badline/address_bus/fittings.rb +0 -38
  366. data/lib/badline/address_bus/pla.rb +0 -147
  367. data/lib/badline/address_bus/roms.rb +0 -39
  368. data/lib/badline/address_bus/saved_state.rb +0 -66
  369. data/lib/badline/address_bus/sid_slots.rb +0 -42
  370. data/lib/badline/address_bus.rb +0 -216
  371. data/lib/badline/c128/bus_state.rb +0 -53
  372. data/lib/badline/c128/saved_state.rb +0 -143
  373. data/lib/badline/cartridge/action_replay.rb +0 -126
  374. data/lib/badline/cartridge/atomic_power.rb +0 -24
  375. data/lib/badline/cartridge/bank.rb +0 -81
  376. data/lib/badline/cartridge/comal80.rb +0 -50
  377. data/lib/badline/cartridge/dinamic.rb +0 -34
  378. data/lib/badline/cartridge/easy_flash.rb +0 -145
  379. data/lib/badline/cartridge/epyx_fastload.rb +0 -79
  380. data/lib/badline/cartridge/final_cartridge3.rb +0 -89
  381. data/lib/badline/cartridge/flash.rb +0 -306
  382. data/lib/badline/cartridge/freezer.rb +0 -33
  383. data/lib/badline/cartridge/fun_play.rb +0 -38
  384. data/lib/badline/cartridge/g_mod2.rb +0 -74
  385. data/lib/badline/cartridge/game_system.rb +0 -40
  386. data/lib/badline/cartridge/geo_ram.rb +0 -79
  387. data/lib/badline/cartridge/kcs_power.rb +0 -75
  388. data/lib/badline/cartridge/mach5.rb +0 -32
  389. data/lib/badline/cartridge/magic_desk.rb +0 -30
  390. data/lib/badline/cartridge/ocean.rb +0 -35
  391. data/lib/badline/cartridge/pagefox.rb +0 -68
  392. data/lib/badline/cartridge/retro_replay.rb +0 -320
  393. data/lib/badline/cartridge/rex_utility.rb +0 -29
  394. data/lib/badline/cartridge/rgcd.rb +0 -58
  395. data/lib/badline/cartridge/simons_basic.rb +0 -35
  396. data/lib/badline/cartridge/standard.rb +0 -15
  397. data/lib/badline/cartridge/super_games.rb +0 -48
  398. data/lib/badline/cartridge/westermann.rb +0 -30
  399. data/lib/badline/cartridge/zaxxon.rb +0 -66
  400. data/lib/badline/cartridge.rb +0 -303
  401. data/lib/badline/checkpoint.rb +0 -98
  402. data/lib/badline/chrout_trap.rb +0 -43
  403. data/lib/badline/cia/fast_forward.rb +0 -60
  404. data/lib/badline/cia/interrupt_register.rb +0 -143
  405. data/lib/badline/cia/serial.rb +0 -275
  406. data/lib/badline/cia/state.rb +0 -47
  407. data/lib/badline/cia/timer.rb +0 -206
  408. data/lib/badline/cia.rb +0 -279
  409. data/lib/badline/color_memory.rb +0 -25
  410. data/lib/badline/computer/attachments.rb +0 -88
  411. data/lib/badline/computer/saved_state.rb +0 -117
  412. data/lib/badline/computer/true_drives.rb +0 -69
  413. data/lib/badline/control_ports.rb +0 -76
  414. data/lib/badline/cpu/addressing.rb +0 -131
  415. data/lib/badline/cpu/boundary.rb +0 -54
  416. data/lib/badline/cpu/core.rb +0 -165
  417. data/lib/badline/cpu/microcode.rb +0 -177
  418. data/lib/badline/cpu/operations.rb +0 -88
  419. data/lib/badline/cpu/saved_state.rb +0 -115
  420. data/lib/badline/cpu/stack_operations.rb +0 -82
  421. data/lib/badline/cpu.rb +0 -10
  422. data/lib/badline/cpu_port.rb +0 -112
  423. data/lib/badline/datasette.rb +0 -161
  424. data/lib/badline/debug_register.rb +0 -28
  425. data/lib/badline/drive/core.rb +0 -147
  426. data/lib/badline/drive/fast_serial.rb +0 -73
  427. data/lib/badline/drive/idle.rb +0 -125
  428. data/lib/badline/drive/idle_cpu.rb +0 -28
  429. data/lib/badline/drive/orbit.rb +0 -79
  430. data/lib/badline/drive/serial_lines.rb +0 -73
  431. data/lib/badline/drive/sleep.rb +0 -112
  432. data/lib/badline/drive/vias.rb +0 -84
  433. data/lib/badline/drive/watch.rb +0 -150
  434. data/lib/badline/drive.rb +0 -11
  435. data/lib/badline/drive1541/bus.rb +0 -86
  436. data/lib/badline/drive1541/byte_ready.rb +0 -48
  437. data/lib/badline/drive1541/cpu.rb +0 -11
  438. data/lib/badline/drive1541/disk.rb +0 -315
  439. data/lib/badline/drive1541/disk_state.rb +0 -86
  440. data/lib/badline/drive1541/disk_via.rb +0 -36
  441. data/lib/badline/drive1541/gcr.rb +0 -57
  442. data/lib/badline/drive1541/mechanism.rb +0 -313
  443. data/lib/badline/drive1541/mechanism_state.rb +0 -68
  444. data/lib/badline/drive1541/rotation.rb +0 -121
  445. data/lib/badline/drive1541/sector_reader.rb +0 -76
  446. data/lib/badline/drive1541/serial_port.rb +0 -18
  447. data/lib/badline/drive1541/track.rb +0 -98
  448. data/lib/badline/drive1541.rb +0 -111
  449. data/lib/badline/drive1571/bus.rb +0 -111
  450. data/lib/badline/drive1571/cpu.rb +0 -11
  451. data/lib/badline/drive1571/serial_port.rb +0 -37
  452. data/lib/badline/drive1571/serial_via.rb +0 -25
  453. data/lib/badline/drive1571/wd1770.rb +0 -120
  454. data/lib/badline/drive1571.rb +0 -175
  455. data/lib/badline/drive1581/bus.rb +0 -137
  456. data/lib/badline/drive1581/cpu.rb +0 -11
  457. data/lib/badline/drive1581/disk.rb +0 -135
  458. data/lib/badline/drive1581/disk_state.rb +0 -87
  459. data/lib/badline/drive1581/mechanism.rb +0 -117
  460. data/lib/badline/drive1581/serial_port.rb +0 -52
  461. data/lib/badline/drive1581/slot.rb +0 -78
  462. data/lib/badline/drive1581/track.rb +0 -100
  463. data/lib/badline/drive1581/track_bytes.rb +0 -75
  464. data/lib/badline/drive1581/wd1772/registers.rb +0 -89
  465. data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
  466. data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
  467. data/lib/badline/drive1581/wd1772/state.rb +0 -66
  468. data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
  469. data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
  470. data/lib/badline/drive1581/wd1772/turn.rb +0 -73
  471. data/lib/badline/drive1581/wd1772.rb +0 -216
  472. data/lib/badline/drive1581.rb +0 -233
  473. data/lib/badline/iec_bus.rb +0 -159
  474. data/lib/badline/instruction.rb +0 -334
  475. data/lib/badline/instruction_set/arithmetic.rb +0 -114
  476. data/lib/badline/instruction_set/bitwise.rb +0 -126
  477. data/lib/badline/instruction_set/branch.rb +0 -79
  478. data/lib/badline/instruction_set/flag.rb +0 -63
  479. data/lib/badline/instruction_set/illegal.rb +0 -270
  480. data/lib/badline/instruction_set/inc_dec.rb +0 -69
  481. data/lib/badline/instruction_set/stack.rb +0 -52
  482. data/lib/badline/instruction_set/transfer.rb +0 -137
  483. data/lib/badline/instruction_set.rb +0 -55
  484. data/lib/badline/interrupts.rb +0 -104
  485. data/lib/badline/joystick.rb +0 -25
  486. data/lib/badline/kernal_trap/channel.rb +0 -181
  487. data/lib/badline/keyboard.rb +0 -112
  488. data/lib/badline/keyboard_buffer.rb +0 -33
  489. data/lib/badline/ram_expansion/banking.rb +0 -30
  490. data/lib/badline/ram_expansion/plus256k.rb +0 -54
  491. data/lib/badline/ram_expansion/plus60k.rb +0 -43
  492. data/lib/badline/ram_expansion/unexpanded.rb +0 -28
  493. data/lib/badline/ram_expansion.rb +0 -21
  494. data/lib/badline/reu/dma/saved_state.rb +0 -50
  495. data/lib/badline/reu/dma.rb +0 -273
  496. data/lib/badline/reu/ram.rb +0 -107
  497. data/lib/badline/reu/saved_state.rb +0 -80
  498. data/lib/badline/reu/trigger.rb +0 -32
  499. data/lib/badline/reu.rb +0 -289
  500. data/lib/badline/sid/catch_up.rb +0 -120
  501. data/lib/badline/sid/decimator.rb +0 -64
  502. data/lib/badline/sid/envelope/state.rb +0 -68
  503. data/lib/badline/sid/envelope.rb +0 -239
  504. data/lib/badline/sid/filter.rb +0 -263
  505. data/lib/badline/sid/voice.rb +0 -77
  506. data/lib/badline/sid/waveform/combined.rb +0 -126
  507. data/lib/badline/sid/waveform/fast_forward.rb +0 -105
  508. data/lib/badline/sid/waveform/noise_writeback.rb +0 -122
  509. data/lib/badline/sid/waveform/state.rb +0 -66
  510. data/lib/badline/sid/waveform.rb +0 -305
  511. data/lib/badline/sid.rb +0 -303
  512. data/lib/badline/snapshot/setup.rb +0 -75
  513. data/lib/badline/snapshot/state.rb +0 -189
  514. data/lib/badline/time_of_day.rb +0 -228
  515. data/lib/badline/traps.rb +0 -19
  516. data/lib/badline/via/control_lines.rb +0 -122
  517. data/lib/badline/via/fast_forward.rb +0 -53
  518. data/lib/badline/via/interrupt_register.rb +0 -67
  519. data/lib/badline/via/shift_register.rb +0 -180
  520. data/lib/badline/via/state.rb +0 -42
  521. data/lib/badline/via/timer1.rb +0 -131
  522. data/lib/badline/via/timer2.rb +0 -133
  523. data/lib/badline/via.rb +0 -266
  524. data/lib/badline/vic/bank.rb +0 -133
  525. data/lib/badline/vic/border_mask.rb +0 -86
  526. data/lib/badline/vic/collisions.rb +0 -115
  527. data/lib/badline/vic/color_patches.rb +0 -47
  528. data/lib/badline/vic/display_state.rb +0 -185
  529. data/lib/badline/vic/graphics_mode.rb +0 -164
  530. data/lib/badline/vic/graphics_shifter.rb +0 -207
  531. data/lib/badline/vic/register_log.rb +0 -81
  532. data/lib/badline/vic/registers.rb +0 -195
  533. data/lib/badline/vic/sequencer.rb +0 -275
  534. data/lib/badline/vic/sequencer_output.rb +0 -116
  535. data/lib/badline/vic/sequencer_state.rb +0 -89
  536. data/lib/badline/vic/sprite/internal_bus.rb +0 -68
  537. data/lib/badline/vic/sprite/saved_state.rb +0 -64
  538. data/lib/badline/vic/sprite/shifter.rb +0 -146
  539. data/lib/badline/vic/sprite/timing.rb +0 -56
  540. data/lib/badline/vic/sprite.rb +0 -337
  541. data/lib/badline/vic/sprites.rb +0 -282
  542. data/lib/badline/vic/sprites_state.rb +0 -57
  543. data/lib/badline/vic.rb +0 -853
  544. data/lib/badline/vic20/saved_state.rb +0 -124
  545. data/lib/badline/vic20/sound/output.rb +0 -83
  546. data/lib/badline/vic20/sound.rb +0 -233
  547. data/lib/badline/vic20/vic/saved_state.rb +0 -55
  548. data/lib/badline/z80/arithmetic.rb +0 -117
  549. data/lib/badline/z80/bit_page.rb +0 -55
  550. data/lib/badline/z80/block_io.rb +0 -58
  551. data/lib/badline/z80/block_transfers.rb +0 -59
  552. data/lib/badline/z80/bus_cycles.rb +0 -111
  553. data/lib/badline/z80/core.rb +0 -113
  554. data/lib/badline/z80/exchanges.rb +0 -50
  555. data/lib/badline/z80/extended_page.rb +0 -89
  556. data/lib/badline/z80/flags.rb +0 -37
  557. data/lib/badline/z80/interrupt_acceptance.rb +0 -46
  558. data/lib/badline/z80/jumps.rb +0 -82
  559. data/lib/badline/z80/loads.rb +0 -98
  560. data/lib/badline/z80/main_page.rb +0 -134
  561. data/lib/badline/z80/registers.rb +0 -120
  562. data/lib/badline/z80/saved_state.rb +0 -69
  563. data/lib/badline/z80/shifts.rb +0 -64
  564. data/lib/badline/z80.rb +0 -11
  565. /data/lib/badline/snapshot/{fields.rb → vice/fields.rb} +0 -0
@@ -1,86 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class VIC
5
- # Border coverage per 8-pixel group, tracked as the sequencer outputs
6
- # a line.
7
- #
8
- # The border is repainted over composited sprites from a snapshot of
9
- # the finished line, which keeps mid-line border color splits intact.
10
- class BorderMask
11
- FULL = 0
12
- NONE = 1
13
- MIXED = 2
14
-
15
- # The group table and per-pixel mask are exposed so the sequencer's
16
- # pixel loops can write them without a method call per column.
17
- attr_reader :groups, :mask
18
-
19
- def initialize(width)
20
- @width = width
21
- @groups = Array.new(width / 8, FULL)
22
- @mask = Array.new(width, true)
23
- @snapshot = Array.new(width, 0)
24
- end
25
-
26
- def reset
27
- @groups.fill(FULL)
28
- end
29
-
30
- def save_state(out)
31
- out.ints(@groups).booleans(@mask).blob(@snapshot)
32
- end
33
-
34
- def load_state(input)
35
- input.ints_into(@groups)
36
- input.booleans_into(@mask)
37
- input.blob_into(@snapshot)
38
- end
39
-
40
- def at?(pixel_x)
41
- case @groups[pixel_x >> 3]
42
- when FULL then true
43
- when MIXED then @mask[pixel_x]
44
- else false
45
- end
46
- end
47
-
48
- def snapshot(colors)
49
- @snapshot[0, @width] = colors
50
- end
51
-
52
- def restore(colors)
53
- group = 0
54
- while group < @groups.length
55
- case @groups[group]
56
- when FULL then group = restore_full(colors, group)
57
- when MIXED then restore_mixed(colors, group * 8)
58
- end
59
- group += 1
60
- end
61
- end
62
-
63
- private
64
-
65
- # Copies a run of full-border groups in one splice and returns its
66
- # last group.
67
- def restore_full(colors, first)
68
- last = first
69
- last += 1 while @groups[last + 1] == FULL
70
- x_pos = first * 8
71
- length = (last - first + 1) * 8
72
- colors[x_pos, length] = @snapshot[x_pos, length]
73
- last
74
- end
75
-
76
- def restore_mixed(colors, x_pos)
77
- i = 0
78
- while i < 8
79
- x = x_pos + i
80
- colors[x] = @snapshot[x] if @mask[x]
81
- i += 1
82
- end
83
- end
84
- end
85
- end
86
- end
@@ -1,115 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class VIC
5
- # = Sprite collisions
6
- #
7
- # The $D01E/$D01F latches and the per-pixel sprite coverage that feeds
8
- # them. Collisions latch as the beam passes each covered pixel, so a
9
- # read mid-line sees the pixels drawn before the reading cycle and none
10
- # of the ones after it.
11
- class Collisions
12
- # $D019 latch bits raised by the collision registers.
13
- SPRITE_COLLISION_IRQ = 0x04 # IMMC, mirrors $D01E
14
- DATA_COLLISION_IRQ = 0x02 # IMBC, mirrors $D01F
15
-
16
- # A read holds the register's reset asserted past the cycle that
17
- # issued it, so the pixels drawn under it never reach the register.
18
- # The read still reports only the pixels drawn before its own cycle,
19
- # which is why the two numbers do not cancel out.
20
- CLEAR_OVERRUN = 12
21
-
22
- # The pixel the last fold reached, so the sprites know whether a read
23
- # has anything left to latch.
24
- attr_reader :folded
25
-
26
- # One bitmask per pixel of the line, written straight by the sprite
27
- # merge and read back here and by the composite.
28
- attr_reader :hits
29
-
30
- def initialize(registers, width)
31
- @registers = registers
32
- @width = width
33
- @hits = Array.new(width, 0)
34
- @folded = 0
35
- @cleared_sprite = 0
36
- @cleared_data = 0
37
- end
38
-
39
- def save_state(out)
40
- out.blob(@hits).int(@folded).int(@cleared_sprite).int(@cleared_data)
41
- end
42
-
43
- def load_state(input)
44
- input.blob_into(@hits)
45
- @folded = input.int
46
- @cleared_sprite = input.int
47
- @cleared_data = input.int
48
- end
49
-
50
- def start_line
51
- @folded = 0
52
- @cleared_sprite = carry(@cleared_sprite)
53
- @cleared_data = carry(@cleared_data)
54
- end
55
-
56
- # Latch every covered pixel between the last fold and the beam. The
57
- # sprites' touched span bounds the scan; the coverage is zero outside
58
- # it either way.
59
- def fold(mask, upto, low, high)
60
- from = [@folded, low].max
61
- @folded = upto
62
- scan(mask, from, [upto, high].min)
63
- end
64
-
65
- # A read resets its register for the pixels that follow the reading
66
- # cycle as well as for everything before it.
67
- def clear(reg, beam_x)
68
- if reg == 0x1e
69
- @cleared_sprite = beam_x + CLEAR_OVERRUN
70
- else
71
- @cleared_data = beam_x + CLEAR_OVERRUN
72
- end
73
- end
74
-
75
- private
76
-
77
- # Two or more sprites on a pixel collide with each other; any sprite
78
- # over a foreground pixel collides with the graphics. Pixels still
79
- # under a read's reset are dropped rather than latched.
80
- def scan(mask, from, upto)
81
- sprite_clash = 0
82
- data_clash = 0
83
- pos = from
84
- while pos < upto
85
- bits = @hits[pos]
86
- unless bits.zero?
87
- sprite_clash |= bits if pos >= @cleared_sprite && bits.anybits?(bits - 1)
88
- data_clash |= bits if pos >= @cleared_data && mask[pos]
89
- end
90
- pos += 1
91
- end
92
- latch(sprite_clash, data_clash)
93
- end
94
-
95
- def latch(sprite_clash, data_clash)
96
- latch_one(0x1e, sprite_clash, SPRITE_COLLISION_IRQ)
97
- latch_one(0x1f, data_clash, DATA_COLLISION_IRQ)
98
- end
99
-
100
- # The IRQ is raised on the edge out of an empty register, so a
101
- # collision folded on top of an unread one raises nothing.
102
- def latch_one(reg, clash, irq)
103
- return if clash.zero?
104
- return unless @registers.collide!(reg, clash)
105
-
106
- @registers.latch_irq!(irq)
107
- end
108
-
109
- # A reset still asserted at the line wrap carries into the new line.
110
- def carry(cleared)
111
- cleared > @width ? cleared - @width : 0
112
- end
113
- end
114
- end
115
- end
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class VIC
5
- # A mid-line color register write becomes visible one pixel into the
6
- # column emitted the cycle after the write. That emit paints the whole
7
- # column with the new color, so the boundary pixel is patched back to
8
- # the old one before the line is finished. On the 8565 the boundary
9
- # pixel shows light grey instead, the grey dot, whatever the old and new
10
- # colors are.
11
- class ColorPatches
12
- def initialize(sequencer, grey_dots: false)
13
- @sequencer = sequencer
14
- @grey_dots = grey_dots
15
- @patches = []
16
- end
17
-
18
- def clear = @patches.clear
19
-
20
- # Each patch as its four numbers: the boundary pixel, the register,
21
- # the old colour and the new.
22
- def save_state(out)
23
- out.int(@patches.length)
24
- @patches.each { |patch| out.ints(patch) }
25
- end
26
-
27
- def load_state(input)
28
- @patches.replace(Array.new(input.int) { input.ints })
29
- end
30
-
31
- def log(reg, old, value, boundary_x)
32
- @patches << [boundary_x, reg, @grey_dots ? GREY_DOT : old & 0x0f, value & 0x0f]
33
- end
34
-
35
- def apply(colors, fg_mask)
36
- @patches.each do |(x, reg, old, value)|
37
- border = @sequencer.border_at?(x)
38
- if reg == 0x20
39
- colors[x] = old if border
40
- elsif !border && !fg_mask[x] && colors[x] == value
41
- colors[x] = old
42
- end
43
- end
44
- end
45
- end
46
- end
47
- end
@@ -1,185 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class VIC
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
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