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,105 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class SID
5
- class Waveform
6
- # Running an oscillator many cycles in one step, for the catch-ups that
7
- # fast-forward the voices between whole cycles.
8
- module FastForward
9
- # Runs `cycles` cycles as #cycle! would, for an oscillator that is not
10
- # feeding back. What those cycles latch onto the output is left to the
11
- # whole cycle that follows, which latches over it.
12
- def fast_forward(cycles)
13
- drain_floating(cycles) if @selected.zero?
14
- if @test
15
- bleed_shift_register(cycles)
16
- else
17
- while @shift_pipeline != 0 && cycles != 0
18
- advance
19
- cycles -= 1
20
- end
21
- skip_ahead(cycles) if cycles != 0 && @frequency != 0
22
- compare_pulse(((@accumulator - @frequency) & 0xffffff) >> 12)
23
- end
24
- @stale = true
25
- end
26
-
27
- # The cycle on which the accumulator MSB next rises, counting the next
28
- # one as 1, or nil if it never will. The test bit leaves the last
29
- # rise standing for as long as it is held.
30
- def cycles_to_msb_rise
31
- return (@msb_rising ? 1 : nil) if @test
32
- return if @frequency.zero?
33
-
34
- distance = (MSB - @accumulator) & 0xffffff
35
- distance = 0x1000000 if distance.zero?
36
- (distance + @frequency - 1) / @frequency
37
- end
38
-
39
- # A combined waveform with sawtooth (on the 6581) or noise in the mix
40
- # writes back into the oscillator every cycle, so it cannot be
41
- # fast-forwarded. Triangle and pulse alone write nothing back.
42
- def feedback?
43
- combined_waveform? && (@selected.anybits?(0x8) || (@topbit_feedback && @selected.anybits?(0x2)))
44
- end
45
-
46
- # Whether a catch-up has to run this oscillator a cycle at a time.
47
- # While synthesizing, every combined waveform does, so the filter
48
- # integrates it a cycle at a time.
49
- def stepped?(synthesizing) = synthesizing ? combined_waveform? : feedback?
50
-
51
- private
52
-
53
- def combined_waveform? = !@test && combined?(@selected)
54
-
55
- # Advances an accumulator with no shift in flight. Each rise of bit 19
56
- # shifts the LFSR two cycles on, so a rise in the last two cycles
57
- # leaves its shift pending for the cycles after.
58
- def skip_ahead(cycles)
59
- previous = @accumulator
60
- @accumulator += @frequency * cycles
61
- rises = bit19_rises(previous, @accumulator)
62
- if rises != 0
63
- @shift_pipeline = pipeline_after(cycles)
64
- rises -= 1 if @shift_pipeline != 0
65
- rises.times { shift_noise }
66
- end
67
- @accumulator &= 0xffffff
68
- end
69
-
70
- # Bit 19 rises at most once a cycle, on each odd multiple of 2^19,
71
- # and at most once in any eight.
72
- def bit19_rises(from, to) = ((to + 0x80000) >> 20) - ((from + 0x80000) >> 20)
73
-
74
- # How far a rise on one of the last two cycles has come.
75
- def pipeline_after(cycles)
76
- last = @accumulator - @frequency
77
- return 2 if bit19_rises(last, @accumulator) != 0
78
- return 1 if cycles > 1 && bit19_rises(last - @frequency, last) != 0
79
-
80
- 0
81
- end
82
-
83
- def drain_floating(cycles)
84
- return if @floating_ttl.zero?
85
-
86
- @floating_ttl -= cycles
87
- return unless @floating_ttl <= 0
88
-
89
- @floating_ttl = 0
90
- @floating = 0x000
91
- end
92
-
93
- def bleed_shift_register(cycles = 1)
94
- return if @shift_register_reset.zero?
95
-
96
- @shift_register_reset -= cycles
97
- return unless @shift_register_reset <= 0
98
-
99
- @shift_register_reset = 0
100
- @shift_register = SHIFT_REGISTER_RESET
101
- end
102
- end
103
- end
104
- end
105
- end
@@ -1,122 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class SID
5
- class Waveform
6
- # Noise combined with other waveforms: the output lines write back into
7
- # the LFSR, and what they write is not always what OSC3 reads.
8
- module NoiseWriteback
9
- # The LFSR bits the noise shaper reads, paired with the output bit each
10
- # one drives (Dag Lem's diagram in SID/noise-reset_new). A combined
11
- # waveform drives the same lines, so a bit held low there is written
12
- # back into the register.
13
- NOISE_TAPS = [[0x100000, 0x800], [0x040000, 0x400], [0x004000, 0x200],
14
- [0x000800, 0x100], [0x000200, 0x080], [0x000020, 0x040],
15
- [0x000004, 0x020], [0x000001, 0x010]].freeze
16
-
17
- # Pulse+noise with the pulse high: the noise lines next to the four
18
- # below them, which nothing drives, are pulled low. The OSC3 read and
19
- # the LFSR writeback see the same lines against different thresholds,
20
- # so they lose a different number of bits. The 8580's pair is the one
21
- # that reproduces SID/wf12nsr's pulse+noise row (it reads $f8, and the
22
- # writeback leaves $fc behind), and SID/wb_testsuite's C->9 and C->E
23
- # rows need that same $fc written at release. The 6581 reads $00 of a
24
- # full register (SID/wf12nsr's pulse+noise row) and pulls nothing
25
- # while the register holds: wb_testsuite's 8->C and C->C rows run
26
- # pulse+noise and leave the register alone. Its lines only land
27
- # part way through a shift (#write_back_shift).
28
- PULSE_NOISE_READ = { mos6581: 0x000, mos8580: 0xf80 }.freeze
29
- PULSE_NOISE_WRITE = { mos6581: 0xff0, mos8580: 0xfc0 }.freeze
30
-
31
- # What a 6581 writes back when the test bit falls with only pulse+noise
32
- # common to the old waveform and the new one (SID/wb_testsuite's D->C,
33
- # E->C, F->C and D->E rows).
34
- PULSE_NOISE_RELEASE = 0xf80
35
-
36
- private
37
-
38
- # What the lines write into the LFSR, against a lower threshold than
39
- # OSC3 reads them by: a line left high between two low ones reads high
40
- # (SID/noisewriteback's noise_writeback_test2) but is written low
41
- # (SID/wf12nsr's noise+triangle and noise+sawtooth rows).
42
- def write_back(selected, value)
43
- return value & ((value << 1) | (value >> 1)) unless selected == 0xc
44
- return 0x000 if @pulse.zero?
45
-
46
- noise & @pulse_noise_write
47
- end
48
-
49
- # What the lines write while the register is part way through a
50
- # shift, where the 6581's pulse+noise writes its output as read.
51
- def write_back_mid_shift(selected, value)
52
- return value if pulse_noise_mid_shift?(selected)
53
-
54
- write_back(selected, value)
55
- end
56
-
57
- def pulse_noise_mid_shift?(selected) = @topbit_feedback && selected == 0xc
58
-
59
- def write_shift_register(value)
60
- NOISE_TAPS.each { |bit, line| @shift_register &= ~bit if value.nobits?(line) }
61
- end
62
-
63
- # The second phase of a shift writes back by the test bit release
64
- # rule with the waveform left alone. The 6581's pulse+noise, which
65
- # that rule leaves out, writes its lines too (SID/wf12nsr's
66
- # pulse+noise row).
67
- def write_back_shift
68
- return unless pulse_noise_mid_shift?(@selected) || release_writes_back?(@selected, @selected)
69
-
70
- write_shift_register(write_back_mid_shift(@selected, @output))
71
- end
72
-
73
- # Setting the test bit starts the bleed, and stalls the register part
74
- # way through a shift, where a noise combination writes its output
75
- # back first, from the accumulator it had. SID/noiselfsrinit's
76
- # $f8/$80 pairs set the bit onto all four from noise alone, and
77
- # SID/wf12nsr's pulse+noise row sets it onto pulse+noise.
78
- def raise_test
79
- @shift_register_reset = @shift_register_reset_delay
80
- return unless @selected.anybits?(0x8) && combined?(@selected) && @shift_pipeline != 1
81
-
82
- write_shift_register(write_back_mid_shift(@selected, shape(@selected)))
83
- end
84
-
85
- # Releasing the test bit finishes the shift it interrupted: the old
86
- # waveform's output may be written back first, then a bit clocks in
87
- # over the forced-high bit 22.
88
- def release_test(previous)
89
- value = release_write(previous)
90
- write_shift_register(value) if value
91
- shift_noise(1)
92
- end
93
-
94
- # What the release writes over the taps, or nil. On the 6581, a change
95
- # that keeps only pulse+noise of the old waveform writes the lowest
96
- # noise lines low. On the 8580, a change from pulse+noise to all four
97
- # writes every line low.
98
- def release_write(previous)
99
- if @topbit_feedback
100
- return noise & PULSE_NOISE_RELEASE if previous != 0xc && (previous & @selected) == 0xc
101
- elsif previous == 0xc && @selected == 0xf
102
- return 0x000
103
- end
104
- write_back(previous, shape(previous)) if release_writes_back?(previous, @selected)
105
- end
106
-
107
- # Which waveform changes write the old output back as the test bit
108
- # falls (SID/wb_testsuite, after libresidfp's do_writeback). Noise has
109
- # to have been combined before and still be combined after. Nothing
110
- # is written back on changing to pulse+noise or from pulse+noise to
111
- # sawtooth+noise, nor, on the 6581, on trading triangle for sawtooth
112
- # or back.
113
- def release_writes_back?(previous, selected)
114
- return false if previous <= 0x8 || selected <= 0x8
115
- return false if selected == 0xc || (previous == 0xc && selected == 0xa)
116
-
117
- !(@topbit_feedback && [previous & 0x3, selected & 0x3].sort == [0x1, 0x2])
118
- end
119
- end
120
- end
121
- end
122
- end
@@ -1,66 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class SID
5
- class Waveform
6
- # A snapshot of an oscillator: its phase, the noise register and the
7
- # output latch, and the same fields as reSID keeps them, for VICE's
8
- # SIDEXTENDED module. The model's tables and the voices it syncs with
9
- # are the SID's wiring.
10
- module State
11
- # The fields reSID keeps for an oscillator between cycles: the phase,
12
- # the noise register, its shift pipeline and reset countdown, the
13
- # floating output's countdown and the pulse level.
14
- def resid_fields
15
- [@accumulator, @shift_register, @shift_pipeline, @shift_register_reset, @floating_ttl, @pulse]
16
- end
17
-
18
- # Takes the fields resid_fields gives from `fields`, from `at` on.
19
- def restore_resid_fields(fields, at)
20
- @accumulator = fields[at]
21
- @shift_register = fields[at + 1]
22
- @shift_pipeline = fields[at + 2]
23
- @shift_register_reset = fields[at + 3]
24
- @floating_ttl = fields[at + 4]
25
- @pulse = fields[at + 5]
26
- @stale = true
27
- end
28
-
29
- def save_state(out)
30
- out.int(@accumulator).int(@delayed_triangle).int(@delayed_sawtooth)
31
- out.int(@shift_register).int(@shift_register_reset).int(@shift_pipeline)
32
- out.int(@frequency).int(@pulse_width).int(@selected)
33
- [@test, @ring, @sync, @msb_rising].each { |flag| out.boolean(flag) }
34
- out.int(@floating).int(@floating_ttl).int(@pulse).int(@output).boolean(@stale)
35
- end
36
-
37
- def load_state(input)
38
- @accumulator = input.int
39
- @delayed_triangle = input.int
40
- @delayed_sawtooth = input.int
41
- @shift_register = input.int
42
- @shift_register_reset = input.int
43
- @shift_pipeline = input.int
44
- @frequency = input.int
45
- @pulse_width = input.int
46
- @selected = input.int
47
- load_latches(input)
48
- end
49
-
50
- private
51
-
52
- def load_latches(input)
53
- @test = input.boolean?
54
- @ring = input.boolean?
55
- @sync = input.boolean?
56
- @msb_rising = input.boolean?
57
- @floating = input.int
58
- @floating_ttl = input.int
59
- @pulse = input.int
60
- @output = input.int
61
- @stale = input.boolean?
62
- end
63
- end
64
- end
65
- end
66
- end
@@ -1,305 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "badline/sid/waveform/combined"
4
- require "badline/sid/waveform/fast_forward"
5
- require "badline/sid/waveform/noise_writeback"
6
- require "badline/sid/waveform/state"
7
-
8
- module Badline
9
- class SID
10
- # Waveform generator: a 24-bit phase accumulator and the shapers that
11
- # read it.
12
- #
13
- # The accumulator advances by the 16-bit frequency every cycle, so every
14
- # waveform is a pure function of the phase. Bit 23 drives hard sync and
15
- # the triangle fold, bit 19 clocks the noise LFSR.
16
- #
17
- # Selecting more than one waveform shorts the shapers onto the lines the
18
- # oscillator itself reads back, so a combined waveform is not only a
19
- # shape: a low top bit reaches the accumulator MSB through the sawtooth
20
- # switch, and noise in the mix is written back into the LFSR. The shape
21
- # itself comes from Combined's model of the lines pulling on each other.
22
- #
23
- # The pulse comparator's output reaches the lines a cycle after the
24
- # accumulator it compared.
25
- #
26
- # With nothing selected the DAC input floats, holding the last value
27
- # driven onto it until the charge drains away.
28
- class Waveform
29
- include FastForward
30
- include NoiseWriteback
31
- include State
32
-
33
- # All bits high at power up, odd ones stored inverted (SID/oscinit).
34
- POWER_ON_ACCUMULATOR = 0x555555
35
-
36
- # Holding the test bit bleeds every LFSR bit high; the power-on state is
37
- # one shift further on, which is what releasing the bit leaves behind.
38
- SHIFT_REGISTER_RESET = 0x7fffff
39
- NOISE_SEED = 0x7ffffe
40
-
41
- # Cycles the test bit needs to bleed the LFSR high. SID/bitfade's
42
- # delaynoise measures ~$950000 on a real 8580. Nothing measures the
43
- # 6581: SID/resid-test's oscsample dumps show it holding its bits
44
- # through the ~$8800 cycles between runs, and the slow reset
45
- # (SID/noise-reset_old) allows it a second.
46
- SHIFT_REGISTER_RESET_DELAY = { mos6581: 0x80000, mos8580: 0x950000 }.freeze
47
-
48
- # Cycles the floating DAC input holds its charge (SID/osc3-wave0).
49
- FLOATING_OUTPUT_TTL = 0x4000
50
-
51
- MSB = 0x800000
52
-
53
- attr_accessor :sync_source, :sync_dest
54
- attr_reader :accumulator, :shift_register, :frequency, :pulse_width, :pulse
55
-
56
- def initialize(model: :mos6581)
57
- use_model(model)
58
- @tri_saw_delay = model == :mos8580
59
- @accumulator = POWER_ON_ACCUMULATOR
60
- @sync_source = @sync_dest = self
61
- reset!
62
- end
63
-
64
- # The running state carries over. A 6581 never delays its shapers, so
65
- # the 8580's delayed triangle and sawtooth start from the current phase.
66
- def model=(model)
67
- use_model(model)
68
- if model == :mos8580 && !@tri_saw_delay
69
- @delayed_sawtooth = sawtooth
70
- @delayed_triangle = triangle
71
- end
72
- @tri_saw_delay = model == :mos8580
73
- end
74
-
75
- # The RES line clears the registers and reseeds the LFSR, but leaves
76
- # the accumulator alone (SID/oscinit).
77
- def reset!
78
- @delayed_sawtooth = @delayed_triangle = 0x000
79
- @shift_register = NOISE_SEED
80
- @shift_register_reset = 0
81
- @shift_pipeline = 0
82
- @frequency = 0x0000
83
- @pulse_width = 0x000
84
- @selected = 0x0
85
- @test = false
86
- @ring = false
87
- @sync = false
88
- @msb_rising = false
89
- @floating = 0x000
90
- @floating_ttl = 0
91
- @pulse = 0xfff
92
- @output = 0x000
93
- @stale = true
94
- end
95
-
96
- def sync? = @sync
97
- def msb_rising? = @msb_rising
98
-
99
- def frequency_low=(value)
100
- @frequency = (@frequency & 0xff00) | value
101
- end
102
-
103
- def frequency_high=(value)
104
- @frequency = (value << 8) | (@frequency & 0x00ff)
105
- end
106
-
107
- def pulse_width_low=(value)
108
- @pulse_width = (@pulse_width & 0xf00) | value
109
- @stale = true
110
- end
111
-
112
- def pulse_width_high=(value)
113
- @pulse_width = ((value & 0x0f) << 8) | (@pulse_width & 0x0ff)
114
- @stale = true
115
- end
116
-
117
- # The test bit clears the accumulator and stalls the LFSR half way
118
- # through a shift, holding bit 22 high while its bits bleed up.
119
- def control=(value)
120
- previous = @selected
121
- @selected = (value >> 4) & 0x0f
122
- @ring = value.anybits?(0x04)
123
- @sync = value.anybits?(0x02)
124
- test = value.anybits?(0x08)
125
- if test
126
- raise_test unless @test
127
- @accumulator = 0x000000
128
- @pulse = 0xfff
129
- @shift_pipeline = 0
130
- elsif @test
131
- release_test(previous)
132
- end
133
- @test = test
134
- @stale = true
135
- end
136
-
137
- def cycle!
138
- latch_output
139
- compare_pulse
140
- @test ? bleed_shift_register : advance
141
- @stale = true
142
- end
143
-
144
- # Hard sync resets the next voice's accumulator when ours wraps. A
145
- # source that is itself synced on the cycle its own MSB rises does not
146
- # pass the sync on.
147
- def synchronize!
148
- return unless @msb_rising && @sync_dest.sync? &&
149
- !(@sync && @sync_source.msb_rising?)
150
-
151
- @sync_dest.reset_accumulator
152
- end
153
-
154
- def reset_accumulator
155
- @accumulator = 0x000000
156
- @stale = true
157
- end
158
-
159
- # Held for the rest of the cycle once computed, so the filter, OSC3 and
160
- # the oscillator's own feedback all see one value per cycle.
161
- def output
162
- return @output unless @stale
163
-
164
- @stale = false
165
- @output = @selected.zero? ? @floating : shape(@selected)
166
- end
167
-
168
- # What OSC3 reads. The 8580 delays the triangle and sawtooth shapers
169
- # by half a cycle, which OSC3 latches as a whole cycle late; pulse and
170
- # noise still reach the lines on time.
171
- def osc3
172
- return output unless @tri_saw_delay && @selected.anybits?(0x3)
173
-
174
- shape(@selected, @delayed_sawtooth, @delayed_triangle)
175
- end
176
-
177
- def sawtooth = @accumulator >> 12
178
-
179
- # The upper half of the ramp is folded back down, shifted left one bit
180
- # to keep the full 12-bit range.
181
- def triangle(selected = @selected)
182
- folded = inverted?(selected) ? @accumulator ^ 0xffffff : @accumulator
183
- (folded >> 11) & 0xfff
184
- end
185
-
186
- # Eight taps off the 23-bit LFSR, gathered into a 12-bit sample.
187
- def noise
188
- ((@shift_register & 0x100000) >> 9) |
189
- ((@shift_register & 0x040000) >> 8) |
190
- ((@shift_register & 0x004000) >> 5) |
191
- ((@shift_register & 0x000800) >> 3) |
192
- ((@shift_register & 0x000200) >> 2) |
193
- ((@shift_register & 0x000020) << 1) |
194
- ((@shift_register & 0x000004) << 3) |
195
- ((@shift_register & 0x000001) << 4)
196
- end
197
-
198
- private
199
-
200
- def use_model(model)
201
- @topbit_feedback = model != :mos8580
202
- @pulse_noise_read = PULSE_NOISE_READ.fetch(model)
203
- @pulse_noise_write = PULSE_NOISE_WRITE.fetch(model)
204
- @combined = Combined.tables(model)
205
- @shift_register_reset_delay = SHIFT_REGISTER_RESET_DELAY.fetch(model)
206
- end
207
-
208
- def shape(selected, saw = sawtooth, tri = triangle(selected))
209
- case selected
210
- when 0x1 then tri
211
- when 0x2 then saw
212
- when 0x4 then @pulse
213
- when 0x8 then noise
214
- else combined(selected, saw, tri)
215
- end
216
- end
217
-
218
- # A low pulse grounds every line. Noise with pulse alone loses its
219
- # lowest lines; noise with triangle or sawtooth is ANDed over the rest
220
- # of the mix.
221
- def combined(selected, saw, tri)
222
- return 0x000 if selected.anybits?(0x4) && @pulse.zero?
223
- return noise & @pulse_noise_read if selected == 0xc
224
-
225
- rest = selected & 0x7
226
- value = case rest
227
- when 0x1 then tri
228
- when 0x2 then saw
229
- when 0x4 then 0xfff
230
- else @combined[rest][rest == 0x5 ? tri : saw]
231
- end
232
- selected.anybits?(0x8) ? value & noise : value
233
- end
234
-
235
- def compare_pulse(phase = @accumulator >> 12) = (@pulse = @test || phase >= @pulse_width ? 0xfff : 0x000)
236
-
237
- # More than one bit set in the selection.
238
- def combined?(selected) = selected & (selected - 1) != 0
239
-
240
- # The one point in the cycle where the waveform selector drives the DAC:
241
- # either it latches a fresh value, or nothing drives the line and the
242
- # charge already on it drains a little further.
243
- def latch_output
244
- value = output
245
- if @tri_saw_delay
246
- @delayed_sawtooth = sawtooth
247
- @delayed_triangle = triangle
248
- end
249
- if @selected.zero?
250
- drain_floating(1)
251
- return
252
- end
253
-
254
- @floating = value
255
- @floating_ttl = FLOATING_OUTPUT_TTL
256
- feed_back(value) if combined?(@selected) && !@test
257
- end
258
-
259
- # A zero on the shared output lines travels back into the oscillator:
260
- # through the sawtooth switch it clears the accumulator MSB on the next
261
- # cycle, and with noise selected it lands in the LFSR, where a bit
262
- # pulled low can never come back. The 8580 buffers the top bit behind a
263
- # flip-flop before the sawtooth switch, so only the LFSR sees it. In the
264
- # first phase of a shift the register bits float, so nothing is pulled
265
- # down: the output is latched instead, for the second phase to write.
266
- def feed_back(value)
267
- @accumulator &= ~MSB if @topbit_feedback && @selected.anybits?(0x2) && value.nobits?(0x800)
268
- write_shift_register(write_back(@selected, value)) if @selected.anybits?(0x8) && @shift_pipeline != 1
269
- end
270
-
271
- # A rise of bit 19 starts a shift that takes two more cycles
272
- # (SID/noisewriteback's noise_writeback_test2, after libresidfp's shift
273
- # pipeline). The first phase latches the output, and the second writes
274
- # it over the taps before the register shifts.
275
- def advance
276
- previous = @accumulator
277
- @accumulator = (previous + @frequency) & 0xffffff
278
- @msb_rising = @accumulator & ~previous & MSB != 0
279
- if @accumulator & ~previous & 0x080000 != 0
280
- @shift_pipeline = 2
281
- elsif @shift_pipeline != 0 && (@shift_pipeline -= 1).zero?
282
- write_back_shift
283
- shift_noise
284
- end
285
- end
286
-
287
- # Bit 0 feeds back bits 22 and 17, with the test bit forcing bit 22 high.
288
- def shift_noise(forced = 0)
289
- bit0 = ((@shift_register >> 22) | forced) ^ (@shift_register >> 17)
290
- @shift_register = ((@shift_register << 1) & 0x7fffff) | (bit0 & 0x1)
291
- end
292
-
293
- # TriXOR = !Saw & ((!V3 & Ring) ^ bit23), where V3 is the modulating
294
- # voice's MSB (SID/ringmod).
295
- def inverted?(selected)
296
- return false if selected & 0x2 != 0
297
-
298
- msb = @accumulator & MSB != 0
299
- return msb unless @ring
300
-
301
- msb == (@sync_source.accumulator & MSB != 0)
302
- end
303
- end
304
- end
305
- end