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,124 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Vic20
5
- MARKER = "VIC20"
6
-
7
- # The RAM expansion of the machine a State from #snapshot was taken
8
- # of, a key of Bus::RAM_CONFIGURATIONS.
9
- def self.setup(state)
10
- input = Snapshot::StateReader.new(state)
11
- input.marker(MARKER)
12
- input.check_stamp
13
- SavedState.read_ram(input)
14
- end
15
-
16
- # A new machine, built as the one a State from #snapshot was taken of,
17
- # at that state.
18
- def self.restored(state) = new(ram: setup(state)).apply_state(state)
19
-
20
- # The whole machine's state for a snapshot, as Computer's: the
21
- # machine's own latches, the bus with its RAM and cartridge ROM, the
22
- # VIC with its sound, both VIAs, the CPU, the datasette and its tape,
23
- # the disk device 8 serves through the traps, and a true 1541. The
24
- # serial lines go back into the bus from the restored VIAs. What the
25
- # host holds stays out: the keyboard, the joystick, RESTORE, the traps
26
- # and callbacks, whether the display renders, whether the sound
27
- # records, and whether the datasette records.
28
- module SavedState
29
- RAM_CONFIGURATIONS = Bus::RAM_CONFIGURATIONS.keys.freeze
30
-
31
- def self.read_ram(input)
32
- RAM_CONFIGURATIONS.fetch(input.int)
33
- rescue IndexError
34
- raise Snapshot::FormatError, "the state names a VIC-20 RAM expansion badline doesn't know"
35
- end
36
-
37
- # How many more on_init handlers the machine a State was taken of had
38
- # yet to run than this one has. Nil until the machine is restored.
39
- attr_reader :init_handlers_lost
40
-
41
- def snapshot
42
- out = Snapshot::StateWriter.new
43
- save_state(out)
44
- out.state
45
- end
46
-
47
- # Takes the machine back to a State from #snapshot, trying it on a new
48
- # machine first, so one that fails leaves this machine as it was.
49
- # Raises Snapshot::FormatError for a state of another machine or RAM
50
- # expansion.
51
- def restore(state)
52
- check_ram(Vic20.setup(state))
53
- Vic20.restored(state)
54
- apply_state(state)
55
- end
56
-
57
- # Puts a State into the machine without trying it on a new one first.
58
- def apply_state(state)
59
- input = Snapshot::StateReader.new(state)
60
- load_state(input)
61
- raise Snapshot::FormatError, "the state goes on past the machine" unless input.finished?
62
-
63
- self
64
- end
65
-
66
- def save_state(out)
67
- out.marker(MARKER).stamp
68
- out.int(RAM_CONFIGURATIONS.index(@ram_configuration))
69
- out.int(@cycles).boolean(@nmi_asserted).boolean(!@pending_keys.nil?)
70
- out.ints(@pending_keys) if @pending_keys
71
- out.int(@cycles <= @init_threshold ? @init_handlers.length : 0)
72
- @bus.save_state(out)
73
- @vic.save_state(out)
74
- @sound.save_state(out)
75
- @via1.save_state(out)
76
- @via2.save_state(out)
77
- @cpu.save_state(out)
78
- @datasette.save_state(out)
79
- save_trap_drive(out)
80
- save_drive1541(out)
81
- save_drive1581(out)
82
- end
83
-
84
- def load_state(input)
85
- input.marker(MARKER)
86
- input.check_stamp
87
- check_ram(SavedState.read_ram(input))
88
- @cycles = input.int
89
- @nmi_asserted = input.boolean?
90
- @pending_keys = nil
91
- @pending_keys = input.ints if input.boolean?
92
- @init_handlers_lost = [input.int - @init_handlers.length, 0].max
93
- @bus.load_state(input)
94
- @vic.load_state(input)
95
- @sound.load_state(input)
96
- @via1.load_state(input)
97
- @via2.load_state(input)
98
- @cpu.load_state(input)
99
- via_written
100
- @datasette.load_state(input)
101
- load_trap_drive(input)
102
- load_drive1541(input)
103
- load_drive1581(input)
104
- end
105
-
106
- private
107
-
108
- # A true 1541 on the serial bus, with its device number.
109
- def save_drive1541(out)
110
- out.boolean(!@drive1541.nil?)
111
- return unless @drive1541
112
-
113
- out.int(@drive1541.device)
114
- @drive1541.save_state(out)
115
- end
116
-
117
- def check_ram(ram)
118
- return if ram == @ram_configuration
119
-
120
- raise Snapshot::FormatError, "the state is of a VIC-20 with #{ram} RAM, not #{@ram_configuration}"
121
- end
122
- end
123
- end
124
- end
@@ -1,83 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Vic20
5
- class Sound
6
- # The sound's level averaged over each sample of the audio rate, then
7
- # through the machine's output stage: a one-pole low-pass at 1,420 Hz
8
- # and a one-pole high-pass at 158 Hz, both run at the audio rate.
9
- #
10
- # The two corners are fitted to xvic's step response: a voice turned
11
- # on at volume 15 rises and decays back to the line as those two RC
12
- # stages do, within 6 parts in 11,000.
13
- class Output
14
- LOW_PASS_HZ = 1_420
15
- HIGH_PASS_HZ = 158
16
-
17
- # Scales the loudest level, four voices high at volume 15, to the
18
- # top of a signed 16-bit sample.
19
- SCALE = 32_767.0 / 570
20
-
21
- attr_reader :samples
22
-
23
- # `level` is the sound's level as the recording starts, which the
24
- # stage takes as settled.
25
- def initialize(clock_hz:, rate:, level:)
26
- @clock_hz = clock_hz
27
- @rate = rate
28
- @remainder = 0
29
- @window = next_window
30
- @left = @window
31
- @sum = 0
32
- @low = @drift = level.to_f
33
- @low_pass = 1.0 - Math.exp(-2.0 * Math::PI * LOW_PASS_HZ / rate)
34
- @high_pass = 1.0 - Math.exp(-2.0 * Math::PI * HIGH_PASS_HZ / rate)
35
- @samples = []
36
- end
37
-
38
- # Adds `cycles` cycles at `level`, closing every sample they finish.
39
- def hold(level, cycles)
40
- left = @left
41
- while cycles >= left
42
- @sum += level * left
43
- cycles -= left
44
- close
45
- left = @left
46
- end
47
- @sum += level * cycles
48
- @left = left - cycles
49
- end
50
-
51
- # The samples closed since the last drain.
52
- def drain
53
- samples = @samples
54
- @samples = []
55
- samples
56
- end
57
-
58
- private
59
-
60
- def close
61
- @low += @low_pass * (@sum.fdiv(@window) - @low)
62
- @drift += @high_pass * (@low - @drift)
63
- sample = ((@low - @drift) * SCALE).round
64
- sample = 32_767 if sample > 32_767
65
- sample = -32_768 if sample < -32_768
66
- @samples << sample
67
- @sum = 0
68
- @window = next_window
69
- @left = @window
70
- end
71
-
72
- # Each window is a whole number of cycles, and they add up to the
73
- # clock's cycles over a second.
74
- def next_window
75
- @remainder += @clock_hz
76
- cycles = @remainder / @rate
77
- @remainder -= cycles * @rate
78
- cycles
79
- end
80
- end
81
- end
82
- end
83
- end
@@ -1,233 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "badline/vic20/sound/output"
4
-
5
- module Badline
6
- class Vic20
7
- # The VIC-I's sound: three square-wave voices, bass, alto and soprano at
8
- # $900A-$900C, a noise voice at $900D, and the volume in $900E bits 0-3.
9
- #
10
- # Each voice has a 7-bit counter, ticked every 16, 8, 4 or 2 cycles from
11
- # bass to noise. It counts up from the low 7 bits of its register, and
12
- # on the tick it would reach 127 it reloads from the register instead.
13
- # So a voice's counter comes round every 128 - ((value + 1) & 127)
14
- # ticks, and the register's new value takes hold at the next reload.
15
- #
16
- # A tone voice's counter shifts an 8-bit shift register at each reload,
17
- # bit 7 out and back into bit 0 inverted while bit 7 of the register
18
- # enables the voice, and a zero while it doesn't. Bit 0 is the voice's
19
- # output: a square wave of 16 shifts while the voice is on, which a
20
- # voice turned off shifts out to silence.
21
- #
22
- # The noise voice's counter shifts a 16-bit LFSR instead, bit 0 in from
23
- # the XOR of bits 3, 12, 14 and 15 while the voice is on and a one
24
- # while it's off. Each time the LFSR's bit 0 rises, it shifts the noise
25
- # voice's own 8-bit shift register, bit 7 back into bit 0, inverted
26
- # while the voice is on. Its bit 0 is the voice's output while the voice
27
- # is on, and it is silent while it's off.
28
- #
29
- # The output is the voices that are high, plus a little more, times the
30
- # volume, so a volume write steps the output even with every voice off.
31
- #
32
- # The voices only run while #record collects the output: nothing the
33
- # CPU reads depends on them. Until then a write only sets the register.
34
- # While recording, the voices catch up to the current cycle whenever a
35
- # write lands or the samples are drained, one shift at a time.
36
- class Sound
37
- VOICES = 4
38
- NOISE = 3
39
-
40
- # The cycles between ticks of each voice's counter.
41
- DIVIDERS = [16, 8, 4, 2].freeze
42
-
43
- # What a voice that is high adds to the output's level, and what the
44
- # output carries with every voice low, before the volume.
45
- VOICE_LEVEL = 9
46
- IDLE_LEVEL = 2
47
-
48
- attr_reader :volume
49
-
50
- # `clock` answers the machine's cycles, `clock_hz` the rate they run at.
51
- def initialize(clock, clock_hz)
52
- @clock = clock
53
- @clock_hz = clock_hz
54
- @output = nil
55
- @time = 0
56
- @shift_registers = Array.new(VOICES, 0)
57
- @next_shifts = Array.new(VOICES, 0)
58
- @frequencies = Array.new(VOICES, 0)
59
- @enabled = Array.new(VOICES, false)
60
- power_on!
61
- end
62
-
63
- def model = :mos6561
64
-
65
- # The power-on state: every register clear and the tone voices' shift
66
- # registers empty. The noise voice's LFSR and shift register start full
67
- # of ones, as a noise voice left off fills them.
68
- def power_on!
69
- now = @clock.cycles
70
- run_to(now)
71
- @volume = 0
72
- VOICES.times do |voice|
73
- @frequencies[voice] = 0
74
- @enabled[voice] = false
75
- @shift_registers[voice] = 0
76
- divider = DIVIDERS[voice]
77
- @next_shifts[voice] = ((now / divider) + 128) * divider
78
- end
79
- @shift_registers[NOISE] = 0xff
80
- @lfsr = 0xffff
81
- @level = level_now
82
- end
83
-
84
- # Starts collecting the output, averaged down to `rate` samples a
85
- # second, for #drain_samples. `clock_hz` is the rate the cycles are
86
- # taken to run at.
87
- def record(rate:, clock_hz: @clock_hz)
88
- now = @clock.cycles
89
- run_to(now)
90
- resume(now)
91
- @output = Output.new(clock_hz:, rate:, level: @level)
92
- end
93
-
94
- def recording? = !@output.nil?
95
-
96
- # The samples recorded since the last drain.
97
- def drain_samples
98
- output = @output
99
- return [] if output.nil?
100
-
101
- run_to(@clock.cycles)
102
- output.drain
103
- end
104
-
105
- # A write to $900A-$900E, which takes hold from the next cycle.
106
- def write(register, value)
107
- run_to(@clock.cycles + 1)
108
- if register == 0x0e
109
- @volume = value & 0x0f
110
- else
111
- voice = register - 0x0a
112
- @frequencies[voice] = value & 0x7f
113
- @enabled[voice] = value >= 0x80
114
- end
115
- @level = level_now
116
- end
117
-
118
- # The registers and the voices as they last ran, for a snapshot.
119
- # Recording is the host's, and starts the voices again from the
120
- # cycle it starts at.
121
- def save_state(out)
122
- run_to(@clock.cycles)
123
- out.marker("VIC20 SOUND").int(@volume).ints(@frequencies).booleans(@enabled)
124
- out.ints(@shift_registers).ints(@next_shifts).int(@lfsr).int(@level).int(@time)
125
- end
126
-
127
- def load_state(input)
128
- input.marker("VIC20 SOUND")
129
- @volume = input.int
130
- input.ints_into(@frequencies)
131
- input.booleans_into(@enabled)
132
- input.ints_into(@shift_registers)
133
- input.ints_into(@next_shifts)
134
- @lfsr = input.int
135
- @level = input.int
136
- @time = input.int
137
- resume(@clock.cycles) if recording?
138
- end
139
-
140
- # A voice's shift register as of the current cycle, while recording.
141
- def shift_register(voice)
142
- run_to(@clock.cycles)
143
- @shift_registers[voice]
144
- end
145
-
146
- def lfsr
147
- run_to(@clock.cycles)
148
- @lfsr
149
- end
150
-
151
- private
152
-
153
- # Moves each shift that the cycles since the voices last ran have
154
- # passed to its next turn from `now`, keeping its phase.
155
- def resume(now)
156
- @time = now
157
- VOICES.times do |voice|
158
- due = @next_shifts[voice]
159
- next if due >= now
160
-
161
- interval = period(voice) * DIVIDERS[voice]
162
- @next_shifts[voice] = due + ((now - due + interval - 1) / interval * interval)
163
- end
164
- end
165
-
166
- # Runs the voices up to the start of cycle `target`, the output holding
167
- # each level for the cycles it lasts.
168
- def run_to(target)
169
- time = @time
170
- output = @output
171
- return if output.nil? || target <= time
172
-
173
- following = next_shift
174
- while following < target
175
- output.hold(@level, following - time)
176
- time = following
177
- shift_due(time)
178
- @level = level_now
179
- following = next_shift
180
- end
181
- output.hold(@level, target - time)
182
- @time = target
183
- end
184
-
185
- def next_shift
186
- shifts = @next_shifts
187
- following = shifts[0]
188
- following = shifts[1] if shifts[1] < following
189
- following = shifts[2] if shifts[2] < following
190
- following = shifts[3] if shifts[3] < following
191
- following
192
- end
193
-
194
- def shift_due(time)
195
- shifts = @next_shifts
196
- VOICES.times do |voice|
197
- next unless shifts[voice] == time
198
-
199
- voice == NOISE ? step_noise : shift_tone(voice)
200
- shifts[voice] = time + (period(voice) * DIVIDERS[voice])
201
- end
202
- end
203
-
204
- def shift_tone(voice)
205
- bits = @shift_registers[voice]
206
- fill = @enabled[voice] && bits < 0x80 ? 1 : 0
207
- @shift_registers[voice] = ((bits << 1) | fill) & 0xff
208
- end
209
-
210
- def step_noise
211
- lfsr = @lfsr
212
- enabled = @enabled[NOISE]
213
- fill = enabled ? ((lfsr >> 3) ^ (lfsr >> 12) ^ (lfsr >> 14) ^ (lfsr >> 15)) & 1 : 1
214
- @lfsr = ((lfsr << 1) | fill) & 0xffff
215
- return unless fill == 1 && lfsr.even?
216
-
217
- bits = @shift_registers[NOISE]
218
- fill = (bits >> 7) ^ (enabled ? 1 : 0)
219
- @shift_registers[NOISE] = ((bits << 1) | fill) & 0xff
220
- end
221
-
222
- # The ticks between two reloads of a voice's counter.
223
- def period(voice) = 128 - ((@frequencies[voice] + 1) & 0x7f)
224
-
225
- def level_now
226
- registers = @shift_registers
227
- high = (registers[0] & 1) + (registers[1] & 1) + (registers[2] & 1)
228
- high += registers[NOISE] & 1 if @enabled[NOISE]
229
- ((high * VOICE_LEVEL) + IDLE_LEVEL) * @volume
230
- end
231
- end
232
- end
233
- end
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Vic20
5
- class VIC
6
- # The VIC's state for a snapshot: the registers and what they set, the
7
- # raster, the text window and its fetches, and the picture with what
8
- # each line fetched. The sound saves its own.
9
- module SavedState
10
- def save_state(out)
11
- out.marker("VIC20 VIC")
12
- out.ints(@registers).int(@rasterline).int(@column).int(@next_event)
13
- [@origin_x, @origin_y, @columns, @rows, @char_shift, @screen_base, @char_base].each { |value| out.int(value) }
14
- out.boolean(@window_open).boolean(@window_done)
15
- [@row_start, @matrix, @char_line, @text_rows].each { |value| out.int(value) }
16
- [@fetch_from, @fetch_to, @fetched, @slot, @code].each { |value| out.int(value) }
17
- @painter.save_state(out)
18
- end
19
-
20
- def load_state(input)
21
- input.marker("VIC20 VIC")
22
- input.ints_into(@registers)
23
- @rasterline = input.int
24
- @column = input.int
25
- @next_event = input.int
26
- load_window(input)
27
- @fetch_from = input.int
28
- @fetch_to = input.int
29
- @fetched = input.int
30
- @slot = input.int
31
- @code = input.int
32
- @painter.load_state(input)
33
- end
34
-
35
- private
36
-
37
- def load_window(input)
38
- @origin_x = input.int
39
- @origin_y = input.int
40
- @columns = input.int
41
- @rows = input.int
42
- @char_shift = input.int
43
- @screen_base = input.int
44
- @char_base = input.int
45
- @window_open = input.boolean?
46
- @window_done = input.boolean?
47
- @row_start = input.int
48
- @matrix = input.int
49
- @char_line = input.int
50
- @text_rows = input.int
51
- end
52
- end
53
- end
54
- end
55
- end
@@ -1,117 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Z80
5
- # The ALU's 8- and 16-bit arithmetic. Bits 5 and 3 of F come from the
6
- # result, except for CP, which takes them from the operand, and the
7
- # 16-bit operations, which take them from the high byte.
8
- module Arithmetic
9
- private
10
-
11
- # The eight operations an opcode's bits 5-3 pick: ADD ADC SUB SBC AND
12
- # XOR OR CP.
13
- def alu(operation, value)
14
- case operation
15
- when 0 then add_a(value, 0)
16
- when 1 then add_a(value, @f & CF)
17
- when 2 then @a = subtract(value, 0)
18
- when 3 then @a = subtract(value, @f & CF)
19
- when 4 then logic(@a & value, HF)
20
- when 5 then logic(@a ^ value, 0)
21
- when 6 then logic(@a | value, 0)
22
- else compare(value)
23
- end
24
- end
25
-
26
- def add_a(value, carry)
27
- result = @a + value + carry
28
- assign_flags(SZ53[result & 0xff] | (result >> 8) | ((@a ^ value ^ result) & HF) |
29
- (((@a ^ value ^ 0x80) & (@a ^ result) & 0x80) >> 5))
30
- @a = result & 0xff
31
- end
32
-
33
- def subtract(value, carry)
34
- result = @a - value - carry
35
- assign_flags(SZ53[result & 0xff] | NF | ((result >> 8) & CF) | ((@a ^ value ^ result) & HF) |
36
- (((@a ^ value) & (@a ^ result) & 0x80) >> 5))
37
- result & 0xff
38
- end
39
-
40
- def compare(value)
41
- subtract(value, 0)
42
- assign_flags((@f & ~XYF) | (value & XYF))
43
- end
44
-
45
- def logic(result, half)
46
- @a = result
47
- assign_flags(SZ53P[result] | half)
48
- end
49
-
50
- def increment(value)
51
- result = (value + 1) & 0xff
52
- assign_flags((@f & CF) | SZ53[result] | (result == 0x80 ? PF : 0) | (result.nobits?(0x0f) ? HF : 0))
53
- result
54
- end
55
-
56
- def decrement(value)
57
- result = (value - 1) & 0xff
58
- assign_flags((@f & CF) | NF | SZ53[result] | (result == 0x7f ? PF : 0) | (value.nobits?(0x0f) ? HF : 0))
59
- result
60
- end
61
-
62
- def add16(left, right)
63
- result = left + right
64
- @wz = (left + 1) & 0xffff
65
- assign_flags((@f & (SF | ZF | PF)) | ((result >> 8) & XYF) | (((left ^ right ^ result) >> 8) & HF) |
66
- (result >> 16))
67
- result & 0xffff
68
- end
69
-
70
- def adc16(right)
71
- left = hl
72
- result = left + right + (@f & CF)
73
- @wz = (left + 1) & 0xffff
74
- self.hl = result & 0xffff
75
- assign_flags(word_flags(result) | (((left ^ right ^ result) >> 8) & HF) |
76
- (((left ^ right ^ 0x8000) & (left ^ result) & 0x8000) >> 13))
77
- end
78
-
79
- def sbc16(right)
80
- left = hl
81
- result = left - right - (@f & CF)
82
- @wz = (left + 1) & 0xffff
83
- self.hl = result & 0xffff
84
- assign_flags(word_flags(result) | NF | (((left ^ right ^ result) >> 8) & HF) |
85
- (((left ^ right) & (left ^ result) & 0x8000) >> 13))
86
- end
87
-
88
- def word_flags(result)
89
- ((result >> 8) & (SF | XYF)) | (result.nobits?(0xffff) ? ZF : 0) | ((result >> 16) & CF)
90
- end
91
-
92
- def daa
93
- low = @a & 0x0f
94
- carry = @f.anybits?(CF) || @a > 0x99 ? CF : 0
95
- correction = (carry.zero? ? 0 : 0x60) | (@f.anybits?(HF) || low > 9 ? 0x06 : 0)
96
- subtracting = @f.anybits?(NF)
97
- half = daa_half(low, subtracting)
98
- @a = (subtracting ? @a - correction : @a + correction) & 0xff
99
- assign_flags(SZ53P[@a] | (@f & NF) | carry | half)
100
- end
101
-
102
- def daa_half(low, subtracting)
103
- if subtracting
104
- @f.anybits?(HF) && low < 6 ? HF : 0
105
- else
106
- low > 9 ? HF : 0
107
- end
108
- end
109
-
110
- def neg
111
- value = @a
112
- @a = 0
113
- @a = subtract(value, 0)
114
- end
115
- end
116
- end
117
- end
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Z80
5
- # The CB page: rotates and shifts (quarter 0), BIT (1), RES (2) and SET
6
- # (3) of the bit the row names, on the column's register or (HL). After
7
- # DD or FD the operand is always (IX+d): the displacement comes before
8
- # the opcode, and an opcode that names a register other than (HL) also
9
- # copies the result into it.
10
- module BitPage
11
- private
12
-
13
- def execute_bits(opcode)
14
- operation = opcode >> 6
15
- number = (opcode >> 3) & 7
16
- index = opcode & 7
17
- return bits_in_memory(operation, number, hl) if index == 6
18
-
19
- value = register(index)
20
- if operation == 1
21
- bit(number, value, value)
22
- else
23
- set_register(index, bit_result(operation, number, value))
24
- end
25
- end
26
-
27
- def execute_index_bits
28
- displaced
29
- opcode = fetch_byte
30
- @cycles += 2
31
- result = bits_in_memory(opcode >> 6, (opcode >> 3) & 7, @wz)
32
- index = opcode & 7
33
- set_plain_register(index, result) unless index == 6 || (opcode >> 6) == 1
34
- end
35
-
36
- def bits_in_memory(operation, number, address)
37
- value = read_byte(address)
38
- @cycles += 1
39
- return bit(number, value, @wz >> 8) if operation == 1
40
-
41
- result = bit_result(operation, number, value)
42
- write_byte(address, result)
43
- result
44
- end
45
-
46
- def bit_result(operation, number, value)
47
- case operation
48
- when 0 then shift(number, value)
49
- when 2 then value & ~(1 << number) & 0xff
50
- else value | (1 << number)
51
- end
52
- end
53
- end
54
- end
55
- end