badline 0.12.1 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (505) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -0
  3. data/CLAUDE.md +59 -31
  4. data/README.md +1 -1
  5. data/doc/library.md +9 -9
  6. data/doc/pinned-behaviour.md +105 -105
  7. data/doc/snapshots.md +1 -4
  8. data/lib/badline/audio/bare_player.rb +3 -3
  9. data/lib/badline/audio/cli.rb +6 -6
  10. data/lib/badline/audio/jukebox.rb +2 -2
  11. data/lib/badline/audio/machine_player.rb +2 -2
  12. data/lib/badline/{media → audio}/queue.rb +1 -1
  13. data/lib/badline/audio/queued_tune.rb +6 -6
  14. data/lib/badline/audio/renderer.rb +5 -5
  15. data/lib/badline/audio/stereo.rb +1 -1
  16. data/lib/badline/c128/{bus_state.rb → bus/saved_state.rb} +1 -1
  17. data/lib/badline/c128/bus.rb +18 -17
  18. data/lib/badline/c128/color_lines.rb +2 -2
  19. data/lib/badline/c128/cpu.rb +1 -1
  20. data/lib/badline/c128/drives.rb +10 -11
  21. data/lib/badline/c128/fast_serial.rb +5 -5
  22. data/lib/badline/c128/mmu_pages.rb +1 -1
  23. data/lib/badline/c128/modes.rb +2 -2
  24. data/lib/badline/c128/saved_state.rb +21 -47
  25. data/lib/badline/c128/z80.rb +2 -2
  26. data/lib/badline/c128.rb +14 -9
  27. data/lib/badline/{computer → c64}/attachments.rb +4 -6
  28. data/lib/badline/c64/banked_ram/banking.rb +32 -0
  29. data/lib/badline/c64/banked_ram/plus256k.rb +56 -0
  30. data/lib/badline/c64/banked_ram/plus60k.rb +45 -0
  31. data/lib/badline/c64/banked_ram/unexpanded.rb +30 -0
  32. data/lib/badline/c64/banked_ram.rb +23 -0
  33. data/lib/badline/c64/bus/extra_sids.rb +32 -0
  34. data/lib/badline/c64/bus/fittings.rb +40 -0
  35. data/lib/badline/c64/bus/pla.rb +149 -0
  36. data/lib/badline/c64/bus/roms.rb +41 -0
  37. data/lib/badline/c64/bus/saved_state.rb +68 -0
  38. data/lib/badline/c64/bus/sid_slots.rb +44 -0
  39. data/lib/badline/c64/bus.rb +218 -0
  40. data/lib/badline/c64/cartridge/action_replay.rb +128 -0
  41. data/lib/badline/c64/cartridge/atomic_power.rb +26 -0
  42. data/lib/badline/c64/cartridge/bank.rb +83 -0
  43. data/lib/badline/c64/cartridge/comal80.rb +52 -0
  44. data/lib/badline/c64/cartridge/dinamic.rb +36 -0
  45. data/lib/badline/c64/cartridge/easy_flash.rb +147 -0
  46. data/lib/badline/c64/cartridge/epyx_fastload.rb +81 -0
  47. data/lib/badline/c64/cartridge/final_cartridge3.rb +91 -0
  48. data/lib/badline/c64/cartridge/flash/saved_state.rb +40 -0
  49. data/lib/badline/c64/cartridge/flash.rb +279 -0
  50. data/lib/badline/c64/cartridge/freezer.rb +35 -0
  51. data/lib/badline/c64/cartridge/fun_play.rb +40 -0
  52. data/lib/badline/c64/cartridge/g_mod2.rb +76 -0
  53. data/lib/badline/c64/cartridge/game_system.rb +42 -0
  54. data/lib/badline/c64/cartridge/geo_ram.rb +81 -0
  55. data/lib/badline/c64/cartridge/kcs_power.rb +77 -0
  56. data/lib/badline/c64/cartridge/mach5.rb +34 -0
  57. data/lib/badline/c64/cartridge/magic_desk.rb +32 -0
  58. data/lib/badline/c64/cartridge/ocean.rb +37 -0
  59. data/lib/badline/c64/cartridge/pagefox.rb +70 -0
  60. data/lib/badline/c64/cartridge/retro_replay/saved_state.rb +47 -0
  61. data/lib/badline/c64/cartridge/retro_replay.rb +286 -0
  62. data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
  63. data/lib/badline/c64/cartridge/rgcd.rb +60 -0
  64. data/lib/badline/c64/cartridge/saved_state.rb +63 -0
  65. data/lib/badline/c64/cartridge/simons_basic.rb +37 -0
  66. data/lib/badline/c64/cartridge/standard.rb +17 -0
  67. data/lib/badline/c64/cartridge/super_games.rb +50 -0
  68. data/lib/badline/c64/cartridge/westermann.rb +32 -0
  69. data/lib/badline/c64/cartridge/zaxxon.rb +68 -0
  70. data/lib/badline/c64/cartridge.rb +258 -0
  71. data/lib/badline/c64/color_memory.rb +27 -0
  72. data/lib/badline/{computer → c64}/common.rb +2 -2
  73. data/lib/badline/{computer → c64}/kernal_traps.rb +18 -18
  74. data/lib/badline/c64/reu/dma/saved_state.rb +52 -0
  75. data/lib/badline/c64/reu/dma.rb +275 -0
  76. data/lib/badline/c64/reu/ram.rb +109 -0
  77. data/lib/badline/c64/reu/saved_state.rb +55 -0
  78. data/lib/badline/c64/reu/trigger.rb +34 -0
  79. data/lib/badline/c64/reu.rb +291 -0
  80. data/lib/badline/{computer → c64}/saved_state.rb +13 -18
  81. data/lib/badline/{computer → c64}/true_drives.rb +11 -11
  82. data/lib/badline/{computer.rb → c64.rb} +18 -13
  83. data/lib/badline/chips/cia/fast_forward.rb +62 -0
  84. data/lib/badline/chips/cia/interrupt_register.rb +145 -0
  85. data/lib/badline/chips/cia/saved_state.rb +49 -0
  86. data/lib/badline/chips/cia/serial/saved_state.rb +45 -0
  87. data/lib/badline/chips/cia/serial.rb +250 -0
  88. data/lib/badline/chips/cia/time_of_day.rb +232 -0
  89. data/lib/badline/chips/cia/timer.rb +208 -0
  90. data/lib/badline/chips/cia.rb +281 -0
  91. data/lib/badline/chips/cpu/addressing.rb +133 -0
  92. data/lib/badline/chips/cpu/boundary.rb +56 -0
  93. data/lib/badline/chips/cpu/core.rb +167 -0
  94. data/lib/badline/chips/cpu/instruction.rb +338 -0
  95. data/lib/badline/chips/cpu/instruction_set/arithmetic.rb +118 -0
  96. data/lib/badline/chips/cpu/instruction_set/bitwise.rb +130 -0
  97. data/lib/badline/chips/cpu/instruction_set/branch.rb +83 -0
  98. data/lib/badline/chips/cpu/instruction_set/flag.rb +67 -0
  99. data/lib/badline/chips/cpu/instruction_set/illegal.rb +274 -0
  100. data/lib/badline/chips/cpu/instruction_set/inc_dec.rb +73 -0
  101. data/lib/badline/chips/cpu/instruction_set/stack.rb +56 -0
  102. data/lib/badline/chips/cpu/instruction_set/transfer.rb +141 -0
  103. data/lib/badline/chips/cpu/instruction_set.rb +59 -0
  104. data/lib/badline/chips/cpu/interrupts.rb +108 -0
  105. data/lib/badline/chips/cpu/microcode.rb +179 -0
  106. data/lib/badline/chips/cpu/operations.rb +90 -0
  107. data/lib/badline/chips/cpu/port.rb +116 -0
  108. data/lib/badline/chips/cpu/saved_state.rb +117 -0
  109. data/lib/badline/chips/cpu/stack_operations.rb +84 -0
  110. data/lib/badline/chips/cpu/traps.rb +23 -0
  111. data/lib/badline/chips/cpu.rb +12 -0
  112. data/lib/badline/chips/sid/catch_up.rb +122 -0
  113. data/lib/badline/chips/sid/decimator.rb +66 -0
  114. data/lib/badline/chips/sid/envelope/saved_state.rb +70 -0
  115. data/lib/badline/chips/sid/envelope.rb +241 -0
  116. data/lib/badline/chips/sid/filter/saved_state.rb +42 -0
  117. data/lib/badline/chips/sid/filter.rb +241 -0
  118. data/lib/badline/chips/sid/saved_state.rb +52 -0
  119. data/lib/badline/chips/sid/voice.rb +79 -0
  120. data/lib/badline/chips/sid/waveform/combined.rb +128 -0
  121. data/lib/badline/chips/sid/waveform/fast_forward.rb +107 -0
  122. data/lib/badline/chips/sid/waveform/noise_writeback.rb +124 -0
  123. data/lib/badline/chips/sid/waveform/saved_state.rb +68 -0
  124. data/lib/badline/chips/sid/waveform.rb +307 -0
  125. data/lib/badline/chips/sid.rb +265 -0
  126. data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
  127. data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -1
  128. data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -1
  129. data/lib/badline/chips/vdc/saved_state.rb +36 -0
  130. data/lib/badline/{c128 → chips}/vdc/window.rb +1 -1
  131. data/lib/badline/{c128 → chips}/vdc.rb +7 -31
  132. data/lib/badline/chips/via/control_lines.rb +124 -0
  133. data/lib/badline/chips/via/fast_forward.rb +55 -0
  134. data/lib/badline/chips/via/interrupt_register.rb +69 -0
  135. data/lib/badline/chips/via/saved_state.rb +44 -0
  136. data/lib/badline/chips/via/shift_register.rb +182 -0
  137. data/lib/badline/chips/via/timer1.rb +133 -0
  138. data/lib/badline/chips/via/timer2.rb +135 -0
  139. data/lib/badline/chips/via.rb +268 -0
  140. data/lib/badline/chips/vic/bank.rb +135 -0
  141. data/lib/badline/chips/vic/border_mask.rb +88 -0
  142. data/lib/badline/chips/vic/collisions.rb +117 -0
  143. data/lib/badline/chips/vic/color_patches.rb +49 -0
  144. data/lib/badline/chips/vic/display_state.rb +187 -0
  145. data/lib/badline/chips/vic/graphics_mode.rb +166 -0
  146. data/lib/badline/chips/vic/graphics_shifter/saved_state.rb +40 -0
  147. data/lib/badline/chips/vic/graphics_shifter.rb +187 -0
  148. data/lib/badline/chips/vic/register_log.rb +83 -0
  149. data/lib/badline/chips/vic/registers.rb +197 -0
  150. data/lib/badline/chips/vic/saved_state.rb +82 -0
  151. data/lib/badline/chips/vic/sequencer/saved_state.rb +91 -0
  152. data/lib/badline/chips/vic/sequencer.rb +277 -0
  153. data/lib/badline/chips/vic/sequencer_output.rb +118 -0
  154. data/lib/badline/chips/vic/sprite/internal_bus.rb +70 -0
  155. data/lib/badline/chips/vic/sprite/saved_state.rb +66 -0
  156. data/lib/badline/chips/vic/sprite/shifter.rb +148 -0
  157. data/lib/badline/chips/vic/sprite/timing.rb +58 -0
  158. data/lib/badline/chips/vic/sprite.rb +339 -0
  159. data/lib/badline/chips/vic/sprites/saved_state.rb +59 -0
  160. data/lib/badline/chips/vic/sprites.rb +284 -0
  161. data/lib/badline/chips/vic.rb +783 -0
  162. data/lib/badline/chips/vic_i/painter/saved_state.rb +40 -0
  163. data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +6 -30
  164. data/lib/badline/{vic20/vic → chips/vic_i}/saved_state.rb +2 -2
  165. data/lib/badline/chips/vic_i/sound/output.rb +85 -0
  166. data/lib/badline/chips/vic_i/sound.rb +235 -0
  167. data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
  168. data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +5 -5
  169. data/lib/badline/chips/z80/arithmetic.rb +119 -0
  170. data/lib/badline/chips/z80/bit_page.rb +57 -0
  171. data/lib/badline/chips/z80/block_io.rb +60 -0
  172. data/lib/badline/chips/z80/block_transfers.rb +61 -0
  173. data/lib/badline/chips/z80/bus_cycles.rb +113 -0
  174. data/lib/badline/chips/z80/core.rb +115 -0
  175. data/lib/badline/chips/z80/exchanges.rb +52 -0
  176. data/lib/badline/chips/z80/extended_page.rb +91 -0
  177. data/lib/badline/chips/z80/flags.rb +39 -0
  178. data/lib/badline/chips/z80/interrupt_acceptance.rb +48 -0
  179. data/lib/badline/chips/z80/jumps.rb +84 -0
  180. data/lib/badline/chips/z80/loads.rb +100 -0
  181. data/lib/badline/chips/z80/main_page.rb +136 -0
  182. data/lib/badline/chips/z80/registers.rb +122 -0
  183. data/lib/badline/chips/z80/saved_state.rb +71 -0
  184. data/lib/badline/chips/z80/shifts.rb +66 -0
  185. data/lib/badline/chips/z80.rb +13 -0
  186. data/lib/badline/core.rb +26 -28
  187. data/lib/badline/drives/datasette/saved_state.rb +37 -0
  188. data/lib/badline/drives/datasette.rb +140 -0
  189. data/lib/badline/drives/engine/core.rb +149 -0
  190. data/lib/badline/drives/engine/fast_serial.rb +75 -0
  191. data/lib/badline/drives/engine/idle.rb +127 -0
  192. data/lib/badline/drives/engine/idle_cpu.rb +30 -0
  193. data/lib/badline/drives/engine/orbit.rb +81 -0
  194. data/lib/badline/drives/engine/serial_lines.rb +75 -0
  195. data/lib/badline/drives/engine/sleep.rb +114 -0
  196. data/lib/badline/drives/engine/vias.rb +86 -0
  197. data/lib/badline/drives/engine/watch.rb +152 -0
  198. data/lib/badline/drives/engine.rb +11 -0
  199. data/lib/badline/drives/model1541/bus.rb +88 -0
  200. data/lib/badline/drives/model1541/byte_ready.rb +50 -0
  201. data/lib/badline/drives/model1541/cpu.rb +13 -0
  202. data/lib/badline/drives/model1541/disk/saved_state.rb +88 -0
  203. data/lib/badline/drives/model1541/disk.rb +317 -0
  204. data/lib/badline/drives/model1541/disk_via.rb +38 -0
  205. data/lib/badline/drives/model1541/gcr.rb +59 -0
  206. data/lib/badline/drives/model1541/mechanism/saved_state.rb +72 -0
  207. data/lib/badline/drives/model1541/mechanism.rb +315 -0
  208. data/lib/badline/drives/model1541/rotation.rb +123 -0
  209. data/lib/badline/drives/model1541/saved_state.rb +44 -0
  210. data/lib/badline/drives/model1541/sector_reader.rb +78 -0
  211. data/lib/badline/drives/model1541/serial_port.rb +20 -0
  212. data/lib/badline/drives/model1541/track.rb +100 -0
  213. data/lib/badline/drives/model1541.rb +81 -0
  214. data/lib/badline/drives/model1571/bus.rb +113 -0
  215. data/lib/badline/drives/model1571/cpu.rb +13 -0
  216. data/lib/badline/drives/model1571/saved_state.rb +47 -0
  217. data/lib/badline/drives/model1571/serial_port.rb +39 -0
  218. data/lib/badline/drives/model1571/serial_via.rb +27 -0
  219. data/lib/badline/drives/model1571/wd1770.rb +122 -0
  220. data/lib/badline/drives/model1571.rb +142 -0
  221. data/lib/badline/drives/model1581/bus.rb +139 -0
  222. data/lib/badline/drives/model1581/cpu.rb +13 -0
  223. data/lib/badline/drives/model1581/disk/saved_state.rb +89 -0
  224. data/lib/badline/drives/model1581/disk.rb +137 -0
  225. data/lib/badline/drives/model1581/mechanism.rb +119 -0
  226. data/lib/badline/drives/model1581/saved_state.rb +42 -0
  227. data/lib/badline/drives/model1581/serial_port.rb +54 -0
  228. data/lib/badline/drives/model1581/slot.rb +79 -0
  229. data/lib/badline/drives/model1581/track.rb +102 -0
  230. data/lib/badline/drives/model1581/track_bytes.rb +77 -0
  231. data/lib/badline/drives/model1581/wd1772/registers.rb +91 -0
  232. data/lib/badline/drives/model1581/wd1772/saved_state.rb +68 -0
  233. data/lib/badline/drives/model1581/wd1772/sector_writes.rb +75 -0
  234. data/lib/badline/drives/model1581/wd1772/sectors.rb +152 -0
  235. data/lib/badline/drives/model1581/wd1772/stepping.rb +111 -0
  236. data/lib/badline/drives/model1581/wd1772/tracks.rb +127 -0
  237. data/lib/badline/drives/model1581/wd1772/turn.rb +75 -0
  238. data/lib/badline/drives/model1581/wd1772.rb +218 -0
  239. data/lib/badline/drives/model1581.rb +206 -0
  240. data/lib/badline/drives/serial_bus.rb +161 -0
  241. data/lib/badline/frontend/boot.rb +3 -3
  242. data/lib/badline/frontend/machine_window.rb +3 -1
  243. data/lib/badline/frontend/player/filter_view.rb +1 -1
  244. data/lib/badline/frontend/player/player_controller.rb +2 -2
  245. data/lib/badline/frontend/player/player_screen.rb +1 -0
  246. data/lib/badline/frontend/player/theme.rb +7 -7
  247. data/lib/badline/frontend/timeline.rb +3 -3
  248. data/lib/badline/input/control_ports.rb +78 -0
  249. data/lib/badline/input/joystick.rb +27 -0
  250. data/lib/badline/input/keyboard.rb +114 -0
  251. data/lib/badline/input.rb +3 -0
  252. data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
  253. data/lib/badline/kernal_trap/dos/channel.rb +183 -0
  254. data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -1
  255. data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -1
  256. data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
  257. data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -1
  258. data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -1
  259. data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
  260. data/lib/badline/kernal_trap/{drive.rb → dos.rb} +11 -10
  261. data/lib/badline/kernal_trap/load.rb +5 -5
  262. data/lib/badline/kernal_trap/save.rb +4 -4
  263. data/lib/badline/kernal_trap/serial.rb +7 -7
  264. data/lib/badline/kernal_trap.rb +1 -2
  265. data/lib/badline/machine/clocking.rb +1 -1
  266. data/lib/badline/machine.rb +5 -5
  267. data/lib/badline/media/true_drive.rb +1 -1
  268. data/lib/badline/media/tune.rb +2 -2
  269. data/lib/badline/media.rb +3 -3
  270. data/lib/badline/model.rb +1 -1
  271. data/lib/badline/roms/README +6 -6
  272. data/lib/badline/sdl.rb +1 -0
  273. data/lib/badline/{storage/sid_file.rb → sid_tune/file.rb} +3 -3
  274. data/lib/badline/{storage → sid_tune}/hvsc.rb +7 -7
  275. data/lib/badline/{storage → sid_tune}/song_lengths.rb +2 -2
  276. data/lib/badline/{storage → sid_tune}/stil/credit.rb +1 -1
  277. data/lib/badline/{storage → sid_tune}/stil.rb +3 -3
  278. data/lib/badline/sid_tune.rb +6 -0
  279. data/lib/badline/snapshot/c128_setup.rb +43 -0
  280. data/lib/badline/snapshot/c64_setup.rb +79 -0
  281. data/lib/badline/snapshot/image.rb +5 -25
  282. data/lib/badline/snapshot/machine_state.rb +1 -1
  283. data/lib/badline/snapshot/setup.rb +22 -66
  284. data/lib/badline/snapshot/state.rb +8 -18
  285. data/lib/badline/snapshot/storage_setup.rb +68 -0
  286. data/lib/badline/snapshot/vic20_setup.rb +37 -0
  287. data/lib/badline/snapshot/vice/c64_mem.rb +1 -1
  288. data/lib/badline/snapshot/vice/restore.rb +1 -1
  289. data/lib/badline/snapshot/vice/reu1764.rb +1 -1
  290. data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
  291. data/lib/badline/snapshot/vice.rb +7 -5
  292. data/lib/badline/snapshot.rb +3 -4
  293. data/lib/badline/storage/d64_image.rb +0 -2
  294. data/lib/badline/storage/d71_image.rb +0 -2
  295. data/lib/badline/storage/d81_image.rb +0 -2
  296. data/lib/badline/storage/disk_image.rb +3 -6
  297. data/lib/badline/storage/g64_image.rb +2 -2
  298. data/lib/badline/storage/host_directory.rb +0 -5
  299. data/lib/badline/storage/t64.rb +2 -8
  300. data/lib/badline/storage/unavailable.rb +1 -1
  301. data/lib/badline/storage.rb +0 -37
  302. data/lib/badline/support/c128_checkpoint.rb +39 -0
  303. data/lib/badline/support/checkpoint.rb +108 -0
  304. data/lib/badline/support/vic20_checkpoint.rb +38 -0
  305. data/lib/badline/support.rb +5 -0
  306. data/lib/badline/version.rb +1 -1
  307. data/lib/badline/vic20/attachments.rb +5 -5
  308. data/lib/badline/vic20/bus/saved_state.rb +35 -0
  309. data/lib/badline/vic20/bus.rb +3 -25
  310. data/lib/badline/vic20/cpu.rb +1 -1
  311. data/lib/badline/vic20/port_wiring.rb +4 -4
  312. data/lib/badline/vic20/saved_state.rb +16 -30
  313. data/lib/badline/vic20/user_via_ports.rb +2 -2
  314. data/lib/badline/vic20.rb +19 -14
  315. metadata +245 -221
  316. data/lib/badline/address_bus/extra_sids.rb +0 -30
  317. data/lib/badline/address_bus/fittings.rb +0 -38
  318. data/lib/badline/address_bus/pla.rb +0 -147
  319. data/lib/badline/address_bus/roms.rb +0 -39
  320. data/lib/badline/address_bus/saved_state.rb +0 -66
  321. data/lib/badline/address_bus/sid_slots.rb +0 -42
  322. data/lib/badline/address_bus.rb +0 -216
  323. data/lib/badline/cartridge/action_replay.rb +0 -126
  324. data/lib/badline/cartridge/atomic_power.rb +0 -24
  325. data/lib/badline/cartridge/bank.rb +0 -81
  326. data/lib/badline/cartridge/comal80.rb +0 -50
  327. data/lib/badline/cartridge/dinamic.rb +0 -34
  328. data/lib/badline/cartridge/easy_flash.rb +0 -145
  329. data/lib/badline/cartridge/epyx_fastload.rb +0 -79
  330. data/lib/badline/cartridge/final_cartridge3.rb +0 -89
  331. data/lib/badline/cartridge/flash.rb +0 -306
  332. data/lib/badline/cartridge/freezer.rb +0 -33
  333. data/lib/badline/cartridge/fun_play.rb +0 -38
  334. data/lib/badline/cartridge/g_mod2.rb +0 -74
  335. data/lib/badline/cartridge/game_system.rb +0 -40
  336. data/lib/badline/cartridge/geo_ram.rb +0 -79
  337. data/lib/badline/cartridge/kcs_power.rb +0 -75
  338. data/lib/badline/cartridge/mach5.rb +0 -32
  339. data/lib/badline/cartridge/magic_desk.rb +0 -30
  340. data/lib/badline/cartridge/ocean.rb +0 -35
  341. data/lib/badline/cartridge/pagefox.rb +0 -68
  342. data/lib/badline/cartridge/retro_replay.rb +0 -320
  343. data/lib/badline/cartridge/rex_utility.rb +0 -29
  344. data/lib/badline/cartridge/rgcd.rb +0 -58
  345. data/lib/badline/cartridge/simons_basic.rb +0 -35
  346. data/lib/badline/cartridge/standard.rb +0 -15
  347. data/lib/badline/cartridge/super_games.rb +0 -48
  348. data/lib/badline/cartridge/westermann.rb +0 -30
  349. data/lib/badline/cartridge/zaxxon.rb +0 -66
  350. data/lib/badline/cartridge.rb +0 -303
  351. data/lib/badline/checkpoint.rb +0 -98
  352. data/lib/badline/cia/fast_forward.rb +0 -60
  353. data/lib/badline/cia/interrupt_register.rb +0 -143
  354. data/lib/badline/cia/serial.rb +0 -275
  355. data/lib/badline/cia/state.rb +0 -47
  356. data/lib/badline/cia/timer.rb +0 -206
  357. data/lib/badline/cia.rb +0 -279
  358. data/lib/badline/color_memory.rb +0 -25
  359. data/lib/badline/control_ports.rb +0 -76
  360. data/lib/badline/cpu/addressing.rb +0 -131
  361. data/lib/badline/cpu/boundary.rb +0 -54
  362. data/lib/badline/cpu/core.rb +0 -165
  363. data/lib/badline/cpu/microcode.rb +0 -177
  364. data/lib/badline/cpu/operations.rb +0 -88
  365. data/lib/badline/cpu/saved_state.rb +0 -115
  366. data/lib/badline/cpu/stack_operations.rb +0 -82
  367. data/lib/badline/cpu.rb +0 -10
  368. data/lib/badline/cpu_port.rb +0 -112
  369. data/lib/badline/datasette.rb +0 -161
  370. data/lib/badline/drive/core.rb +0 -147
  371. data/lib/badline/drive/fast_serial.rb +0 -73
  372. data/lib/badline/drive/idle.rb +0 -125
  373. data/lib/badline/drive/idle_cpu.rb +0 -28
  374. data/lib/badline/drive/orbit.rb +0 -79
  375. data/lib/badline/drive/serial_lines.rb +0 -73
  376. data/lib/badline/drive/sleep.rb +0 -112
  377. data/lib/badline/drive/vias.rb +0 -84
  378. data/lib/badline/drive/watch.rb +0 -150
  379. data/lib/badline/drive.rb +0 -11
  380. data/lib/badline/drive1541/bus.rb +0 -86
  381. data/lib/badline/drive1541/byte_ready.rb +0 -48
  382. data/lib/badline/drive1541/cpu.rb +0 -11
  383. data/lib/badline/drive1541/disk.rb +0 -315
  384. data/lib/badline/drive1541/disk_state.rb +0 -86
  385. data/lib/badline/drive1541/disk_via.rb +0 -36
  386. data/lib/badline/drive1541/gcr.rb +0 -57
  387. data/lib/badline/drive1541/mechanism.rb +0 -313
  388. data/lib/badline/drive1541/mechanism_state.rb +0 -68
  389. data/lib/badline/drive1541/rotation.rb +0 -121
  390. data/lib/badline/drive1541/sector_reader.rb +0 -76
  391. data/lib/badline/drive1541/serial_port.rb +0 -18
  392. data/lib/badline/drive1541/track.rb +0 -98
  393. data/lib/badline/drive1541.rb +0 -111
  394. data/lib/badline/drive1571/bus.rb +0 -111
  395. data/lib/badline/drive1571/cpu.rb +0 -11
  396. data/lib/badline/drive1571/serial_port.rb +0 -37
  397. data/lib/badline/drive1571/serial_via.rb +0 -25
  398. data/lib/badline/drive1571/wd1770.rb +0 -120
  399. data/lib/badline/drive1571.rb +0 -175
  400. data/lib/badline/drive1581/bus.rb +0 -137
  401. data/lib/badline/drive1581/cpu.rb +0 -11
  402. data/lib/badline/drive1581/disk.rb +0 -135
  403. data/lib/badline/drive1581/disk_state.rb +0 -87
  404. data/lib/badline/drive1581/mechanism.rb +0 -117
  405. data/lib/badline/drive1581/serial_port.rb +0 -52
  406. data/lib/badline/drive1581/slot.rb +0 -78
  407. data/lib/badline/drive1581/track.rb +0 -100
  408. data/lib/badline/drive1581/track_bytes.rb +0 -75
  409. data/lib/badline/drive1581/wd1772/registers.rb +0 -89
  410. data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
  411. data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
  412. data/lib/badline/drive1581/wd1772/state.rb +0 -66
  413. data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
  414. data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
  415. data/lib/badline/drive1581/wd1772/turn.rb +0 -73
  416. data/lib/badline/drive1581/wd1772.rb +0 -216
  417. data/lib/badline/drive1581.rb +0 -233
  418. data/lib/badline/iec_bus.rb +0 -159
  419. data/lib/badline/instruction.rb +0 -334
  420. data/lib/badline/instruction_set/arithmetic.rb +0 -114
  421. data/lib/badline/instruction_set/bitwise.rb +0 -126
  422. data/lib/badline/instruction_set/branch.rb +0 -79
  423. data/lib/badline/instruction_set/flag.rb +0 -63
  424. data/lib/badline/instruction_set/illegal.rb +0 -270
  425. data/lib/badline/instruction_set/inc_dec.rb +0 -69
  426. data/lib/badline/instruction_set/stack.rb +0 -52
  427. data/lib/badline/instruction_set/transfer.rb +0 -137
  428. data/lib/badline/instruction_set.rb +0 -55
  429. data/lib/badline/interrupts.rb +0 -104
  430. data/lib/badline/joystick.rb +0 -25
  431. data/lib/badline/kernal_trap/channel.rb +0 -181
  432. data/lib/badline/keyboard.rb +0 -112
  433. data/lib/badline/ram_expansion/banking.rb +0 -30
  434. data/lib/badline/ram_expansion/plus256k.rb +0 -54
  435. data/lib/badline/ram_expansion/plus60k.rb +0 -43
  436. data/lib/badline/ram_expansion/unexpanded.rb +0 -28
  437. data/lib/badline/ram_expansion.rb +0 -21
  438. data/lib/badline/reu/dma/saved_state.rb +0 -50
  439. data/lib/badline/reu/dma.rb +0 -273
  440. data/lib/badline/reu/ram.rb +0 -107
  441. data/lib/badline/reu/saved_state.rb +0 -80
  442. data/lib/badline/reu/trigger.rb +0 -32
  443. data/lib/badline/reu.rb +0 -289
  444. data/lib/badline/sid/catch_up.rb +0 -120
  445. data/lib/badline/sid/decimator.rb +0 -64
  446. data/lib/badline/sid/envelope/state.rb +0 -68
  447. data/lib/badline/sid/envelope.rb +0 -239
  448. data/lib/badline/sid/filter.rb +0 -263
  449. data/lib/badline/sid/voice.rb +0 -77
  450. data/lib/badline/sid/waveform/combined.rb +0 -126
  451. data/lib/badline/sid/waveform/fast_forward.rb +0 -105
  452. data/lib/badline/sid/waveform/noise_writeback.rb +0 -122
  453. data/lib/badline/sid/waveform/state.rb +0 -66
  454. data/lib/badline/sid/waveform.rb +0 -305
  455. data/lib/badline/sid.rb +0 -303
  456. data/lib/badline/time_of_day.rb +0 -228
  457. data/lib/badline/traps.rb +0 -19
  458. data/lib/badline/via/control_lines.rb +0 -122
  459. data/lib/badline/via/fast_forward.rb +0 -53
  460. data/lib/badline/via/interrupt_register.rb +0 -67
  461. data/lib/badline/via/shift_register.rb +0 -180
  462. data/lib/badline/via/state.rb +0 -42
  463. data/lib/badline/via/timer1.rb +0 -131
  464. data/lib/badline/via/timer2.rb +0 -133
  465. data/lib/badline/via.rb +0 -266
  466. data/lib/badline/vic/bank.rb +0 -133
  467. data/lib/badline/vic/border_mask.rb +0 -86
  468. data/lib/badline/vic/collisions.rb +0 -115
  469. data/lib/badline/vic/color_patches.rb +0 -47
  470. data/lib/badline/vic/display_state.rb +0 -185
  471. data/lib/badline/vic/graphics_mode.rb +0 -164
  472. data/lib/badline/vic/graphics_shifter.rb +0 -207
  473. data/lib/badline/vic/register_log.rb +0 -81
  474. data/lib/badline/vic/registers.rb +0 -195
  475. data/lib/badline/vic/sequencer.rb +0 -275
  476. data/lib/badline/vic/sequencer_output.rb +0 -116
  477. data/lib/badline/vic/sequencer_state.rb +0 -89
  478. data/lib/badline/vic/sprite/internal_bus.rb +0 -68
  479. data/lib/badline/vic/sprite/saved_state.rb +0 -64
  480. data/lib/badline/vic/sprite/shifter.rb +0 -146
  481. data/lib/badline/vic/sprite/timing.rb +0 -56
  482. data/lib/badline/vic/sprite.rb +0 -337
  483. data/lib/badline/vic/sprites.rb +0 -282
  484. data/lib/badline/vic/sprites_state.rb +0 -57
  485. data/lib/badline/vic.rb +0 -853
  486. data/lib/badline/vic20/sound/output.rb +0 -83
  487. data/lib/badline/vic20/sound.rb +0 -233
  488. data/lib/badline/z80/arithmetic.rb +0 -117
  489. data/lib/badline/z80/bit_page.rb +0 -55
  490. data/lib/badline/z80/block_io.rb +0 -58
  491. data/lib/badline/z80/block_transfers.rb +0 -59
  492. data/lib/badline/z80/bus_cycles.rb +0 -111
  493. data/lib/badline/z80/core.rb +0 -113
  494. data/lib/badline/z80/exchanges.rb +0 -50
  495. data/lib/badline/z80/extended_page.rb +0 -89
  496. data/lib/badline/z80/flags.rb +0 -37
  497. data/lib/badline/z80/interrupt_acceptance.rb +0 -46
  498. data/lib/badline/z80/jumps.rb +0 -82
  499. data/lib/badline/z80/loads.rb +0 -98
  500. data/lib/badline/z80/main_page.rb +0 -134
  501. data/lib/badline/z80/registers.rb +0 -120
  502. data/lib/badline/z80/saved_state.rb +0 -69
  503. data/lib/badline/z80/shifts.rb +0 -64
  504. data/lib/badline/z80.rb +0 -11
  505. /data/lib/badline/snapshot/{fields.rb → vice/fields.rb} +0 -0
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Chips
5
+ class VICI
6
+ class Painter
7
+ # The painter's state for a snapshot.
8
+ module SavedState
9
+ # The colours, the line being painted and how far, what each line
10
+ # fetched, and the display, for a snapshot. Whether it renders is
11
+ # the host's, and a restored display is all changed.
12
+ def save_state(out)
13
+ out.int(@border).int(@background).int(@aux).boolean(@reverse)
14
+ out.int(@row).int(@painted).boolean(@written)
15
+ out.blob(@display).blob(@patterns).blob(@colors)
16
+ out.ints(@counts).ints(@starts).booleans(@stale).ints(@memo_keys)
17
+ end
18
+
19
+ def load_state(input)
20
+ @border = input.int
21
+ @background = input.int
22
+ @aux = input.int
23
+ @reverse = input.boolean?
24
+ @row = input.int
25
+ @painted = input.int
26
+ @written = input.boolean?
27
+ input.blob_into(@display)
28
+ input.blob_into(@patterns)
29
+ input.blob_into(@colors)
30
+ input.ints_into(@counts)
31
+ input.ints_into(@starts)
32
+ input.booleans_into(@stale)
33
+ input.ints_into(@memo_keys)
34
+ @dirty_lines.fill(true)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "badline/chips/vic_i/painter/saved_state"
4
+
3
5
  module Badline
4
- class Vic20
5
- class VIC
6
+ module Chips
7
+ class VICI
6
8
  # Paints the VIC-I's display a line at a time from what the VIC
7
9
  # fetched for it: each character's pattern byte and colour nibble, the
8
10
  # pixel its first character starts at and how many it fetched. Each
@@ -26,6 +28,8 @@ module Badline
26
28
  # nibble's low three bits) and 11 the auxiliary colour, whatever
27
29
  # $900F bit 3 says (MOS 6560/6561 datasheet, "Color operating modes").
28
30
  class Painter
31
+ include SavedState
32
+
29
33
  # The characters a line holds room for. A line fetches at most 34.
30
34
  SLOTS = 40
31
35
 
@@ -70,34 +74,6 @@ module Badline
70
74
  @dirty_lines.fill(false)
71
75
  end
72
76
 
73
- # The colours, the line being painted and how far, what each line
74
- # fetched, and the display, for a snapshot. Whether it renders is
75
- # the host's, and a restored display is all changed.
76
- def save_state(out)
77
- out.int(@border).int(@background).int(@aux).boolean(@reverse)
78
- out.int(@row).int(@painted).boolean(@written)
79
- out.blob(@display).blob(@patterns).blob(@colors)
80
- out.ints(@counts).ints(@starts).booleans(@stale).ints(@memo_keys)
81
- end
82
-
83
- def load_state(input)
84
- @border = input.int
85
- @background = input.int
86
- @aux = input.int
87
- @reverse = input.boolean?
88
- @row = input.int
89
- @painted = input.int
90
- @written = input.boolean?
91
- input.blob_into(@display)
92
- input.blob_into(@patterns)
93
- input.blob_into(@colors)
94
- input.ints_into(@counts)
95
- input.ints_into(@starts)
96
- input.booleans_into(@stale)
97
- input.ints_into(@memo_keys)
98
- @dirty_lines.fill(true)
99
- end
100
-
101
77
  # Painting can be turned off, and once it's back on every line is
102
78
  # painted afresh.
103
79
  def render=(value)
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Badline
4
- class Vic20
5
- class VIC
4
+ module Chips
5
+ class VICI
6
6
  # The VIC's state for a snapshot: the registers and what they set, the
7
7
  # raster, the text window and its fetches, and the picture with what
8
8
  # each line fetched. The sound saves its own.
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Chips
5
+ class VICI
6
+ class Sound
7
+ # The sound's level averaged over each sample of the audio rate, then
8
+ # through the machine's output stage: a one-pole low-pass at 1,420 Hz
9
+ # and a one-pole high-pass at 158 Hz, both run at the audio rate.
10
+ #
11
+ # The two corners are fitted to xvic's step response: a voice turned
12
+ # on at volume 15 rises and decays back to the line as those two RC
13
+ # stages do, within 6 parts in 11,000.
14
+ class Output
15
+ LOW_PASS_HZ = 1_420
16
+ HIGH_PASS_HZ = 158
17
+
18
+ # Scales the loudest level, four voices high at volume 15, to the
19
+ # top of a signed 16-bit sample.
20
+ SCALE = 32_767.0 / 570
21
+
22
+ attr_reader :samples
23
+
24
+ # `level` is the sound's level as the recording starts, which the
25
+ # stage takes as settled.
26
+ def initialize(clock_hz:, rate:, level:)
27
+ @clock_hz = clock_hz
28
+ @rate = rate
29
+ @remainder = 0
30
+ @window = next_window
31
+ @left = @window
32
+ @sum = 0
33
+ @low = @drift = level.to_f
34
+ @low_pass = 1.0 - Math.exp(-2.0 * Math::PI * LOW_PASS_HZ / rate)
35
+ @high_pass = 1.0 - Math.exp(-2.0 * Math::PI * HIGH_PASS_HZ / rate)
36
+ @samples = []
37
+ end
38
+
39
+ # Adds `cycles` cycles at `level`, closing every sample they finish.
40
+ def hold(level, cycles)
41
+ left = @left
42
+ while cycles >= left
43
+ @sum += level * left
44
+ cycles -= left
45
+ close
46
+ left = @left
47
+ end
48
+ @sum += level * cycles
49
+ @left = left - cycles
50
+ end
51
+
52
+ # The samples closed since the last drain.
53
+ def drain
54
+ samples = @samples
55
+ @samples = []
56
+ samples
57
+ end
58
+
59
+ private
60
+
61
+ def close
62
+ @low += @low_pass * (@sum.fdiv(@window) - @low)
63
+ @drift += @high_pass * (@low - @drift)
64
+ sample = ((@low - @drift) * SCALE).round
65
+ sample = 32_767 if sample > 32_767
66
+ sample = -32_768 if sample < -32_768
67
+ @samples << sample
68
+ @sum = 0
69
+ @window = next_window
70
+ @left = @window
71
+ end
72
+
73
+ # Each window is a whole number of cycles, and they add up to the
74
+ # clock's cycles over a second.
75
+ def next_window
76
+ @remainder += @clock_hz
77
+ cycles = @remainder / @rate
78
+ @remainder -= cycles * @rate
79
+ cycles
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,235 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "badline/chips/vic_i/sound/output"
4
+
5
+ module Badline
6
+ module Chips
7
+ class VICI
8
+ # The VIC-I's sound: three square-wave voices, bass, alto and soprano at
9
+ # $900A-$900C, a noise voice at $900D, and the volume in $900E bits 0-3.
10
+ #
11
+ # Each voice has a 7-bit counter, ticked every 16, 8, 4 or 2 cycles from
12
+ # bass to noise. It counts up from the low 7 bits of its register, and
13
+ # on the tick it would reach 127 it reloads from the register instead.
14
+ # So a voice's counter comes round every 128 - ((value + 1) & 127)
15
+ # ticks, and the register's new value takes hold at the next reload.
16
+ #
17
+ # A tone voice's counter shifts an 8-bit shift register at each reload,
18
+ # bit 7 out and back into bit 0 inverted while bit 7 of the register
19
+ # enables the voice, and a zero while it doesn't. Bit 0 is the voice's
20
+ # output: a square wave of 16 shifts while the voice is on, which a
21
+ # voice turned off shifts out to silence.
22
+ #
23
+ # The noise voice's counter shifts a 16-bit LFSR instead, bit 0 in from
24
+ # the XOR of bits 3, 12, 14 and 15 while the voice is on and a one
25
+ # while it's off. Each time the LFSR's bit 0 rises, it shifts the noise
26
+ # voice's own 8-bit shift register, bit 7 back into bit 0, inverted
27
+ # while the voice is on. Its bit 0 is the voice's output while the voice
28
+ # is on, and it is silent while it's off.
29
+ #
30
+ # The output is the voices that are high, plus a little more, times the
31
+ # volume, so a volume write steps the output even with every voice off.
32
+ #
33
+ # The voices only run while #record collects the output: nothing the
34
+ # CPU reads depends on them. Until then a write only sets the register.
35
+ # While recording, the voices catch up to the current cycle whenever a
36
+ # write lands or the samples are drained, one shift at a time.
37
+ class Sound
38
+ VOICES = 4
39
+ NOISE = 3
40
+
41
+ # The cycles between ticks of each voice's counter.
42
+ DIVIDERS = [16, 8, 4, 2].freeze
43
+
44
+ # What a voice that is high adds to the output's level, and what the
45
+ # output carries with every voice low, before the volume.
46
+ VOICE_LEVEL = 9
47
+ IDLE_LEVEL = 2
48
+
49
+ attr_reader :volume
50
+
51
+ # `clock` answers the machine's cycles, `clock_hz` the rate they run at.
52
+ def initialize(clock, clock_hz)
53
+ @clock = clock
54
+ @clock_hz = clock_hz
55
+ @output = nil
56
+ @time = 0
57
+ @shift_registers = Array.new(VOICES, 0)
58
+ @next_shifts = Array.new(VOICES, 0)
59
+ @frequencies = Array.new(VOICES, 0)
60
+ @enabled = Array.new(VOICES, false)
61
+ power_on!
62
+ end
63
+
64
+ def model = :mos6561
65
+
66
+ # The power-on state: every register clear and the tone voices' shift
67
+ # registers empty. The noise voice's LFSR and shift register start full
68
+ # of ones, as a noise voice left off fills them.
69
+ def power_on!
70
+ now = @clock.cycles
71
+ run_to(now)
72
+ @volume = 0
73
+ VOICES.times do |voice|
74
+ @frequencies[voice] = 0
75
+ @enabled[voice] = false
76
+ @shift_registers[voice] = 0
77
+ divider = DIVIDERS[voice]
78
+ @next_shifts[voice] = ((now / divider) + 128) * divider
79
+ end
80
+ @shift_registers[NOISE] = 0xff
81
+ @lfsr = 0xffff
82
+ @level = level_now
83
+ end
84
+
85
+ # Starts collecting the output, averaged down to `rate` samples a
86
+ # second, for #drain_samples. `clock_hz` is the rate the cycles are
87
+ # taken to run at.
88
+ def record(rate:, clock_hz: @clock_hz)
89
+ now = @clock.cycles
90
+ run_to(now)
91
+ resume(now)
92
+ @output = Output.new(clock_hz:, rate:, level: @level)
93
+ end
94
+
95
+ def recording? = !@output.nil?
96
+
97
+ # The samples recorded since the last drain.
98
+ def drain_samples
99
+ output = @output
100
+ return [] if output.nil?
101
+
102
+ run_to(@clock.cycles)
103
+ output.drain
104
+ end
105
+
106
+ # A write to $900A-$900E, which takes hold from the next cycle.
107
+ def write(register, value)
108
+ run_to(@clock.cycles + 1)
109
+ if register == 0x0e
110
+ @volume = value & 0x0f
111
+ else
112
+ voice = register - 0x0a
113
+ @frequencies[voice] = value & 0x7f
114
+ @enabled[voice] = value >= 0x80
115
+ end
116
+ @level = level_now
117
+ end
118
+
119
+ # The registers and the voices as they last ran, for a snapshot.
120
+ # Recording is the host's, and starts the voices again from the
121
+ # cycle it starts at.
122
+ def save_state(out)
123
+ run_to(@clock.cycles)
124
+ out.marker("VIC20 SOUND").int(@volume).ints(@frequencies).booleans(@enabled)
125
+ out.ints(@shift_registers).ints(@next_shifts).int(@lfsr).int(@level).int(@time)
126
+ end
127
+
128
+ def load_state(input)
129
+ input.marker("VIC20 SOUND")
130
+ @volume = input.int
131
+ input.ints_into(@frequencies)
132
+ input.booleans_into(@enabled)
133
+ input.ints_into(@shift_registers)
134
+ input.ints_into(@next_shifts)
135
+ @lfsr = input.int
136
+ @level = input.int
137
+ @time = input.int
138
+ resume(@clock.cycles) if recording?
139
+ end
140
+
141
+ # A voice's shift register as of the current cycle, while recording.
142
+ def shift_register(voice)
143
+ run_to(@clock.cycles)
144
+ @shift_registers[voice]
145
+ end
146
+
147
+ def lfsr
148
+ run_to(@clock.cycles)
149
+ @lfsr
150
+ end
151
+
152
+ private
153
+
154
+ # Moves each shift that the cycles since the voices last ran have
155
+ # passed to its next turn from `now`, keeping its phase.
156
+ def resume(now)
157
+ @time = now
158
+ VOICES.times do |voice|
159
+ due = @next_shifts[voice]
160
+ next if due >= now
161
+
162
+ interval = period(voice) * DIVIDERS[voice]
163
+ @next_shifts[voice] = due + ((now - due + interval - 1) / interval * interval)
164
+ end
165
+ end
166
+
167
+ # Runs the voices up to the start of cycle `target`, the output holding
168
+ # each level for the cycles it lasts.
169
+ def run_to(target)
170
+ time = @time
171
+ output = @output
172
+ return if output.nil? || target <= time
173
+
174
+ following = next_shift
175
+ while following < target
176
+ output.hold(@level, following - time)
177
+ time = following
178
+ shift_due(time)
179
+ @level = level_now
180
+ following = next_shift
181
+ end
182
+ output.hold(@level, target - time)
183
+ @time = target
184
+ end
185
+
186
+ def next_shift
187
+ shifts = @next_shifts
188
+ following = shifts[0]
189
+ following = shifts[1] if shifts[1] < following
190
+ following = shifts[2] if shifts[2] < following
191
+ following = shifts[3] if shifts[3] < following
192
+ following
193
+ end
194
+
195
+ def shift_due(time)
196
+ shifts = @next_shifts
197
+ VOICES.times do |voice|
198
+ next unless shifts[voice] == time
199
+
200
+ voice == NOISE ? step_noise : shift_tone(voice)
201
+ shifts[voice] = time + (period(voice) * DIVIDERS[voice])
202
+ end
203
+ end
204
+
205
+ def shift_tone(voice)
206
+ bits = @shift_registers[voice]
207
+ fill = @enabled[voice] && bits < 0x80 ? 1 : 0
208
+ @shift_registers[voice] = ((bits << 1) | fill) & 0xff
209
+ end
210
+
211
+ def step_noise
212
+ lfsr = @lfsr
213
+ enabled = @enabled[NOISE]
214
+ fill = enabled ? ((lfsr >> 3) ^ (lfsr >> 12) ^ (lfsr >> 14) ^ (lfsr >> 15)) & 1 : 1
215
+ @lfsr = ((lfsr << 1) | fill) & 0xffff
216
+ return unless fill == 1 && lfsr.even?
217
+
218
+ bits = @shift_registers[NOISE]
219
+ fill = (bits >> 7) ^ (enabled ? 1 : 0)
220
+ @shift_registers[NOISE] = ((bits << 1) | fill) & 0xff
221
+ end
222
+
223
+ # The ticks between two reloads of a voice's counter.
224
+ def period(voice) = 128 - ((@frequencies[voice] + 1) & 0x7f)
225
+
226
+ def level_now
227
+ registers = @shift_registers
228
+ high = (registers[0] & 1) + (registers[1] & 1) + (registers[2] & 1)
229
+ high += registers[NOISE] & 1 if @enabled[NOISE]
230
+ ((high * VOICE_LEVEL) + IDLE_LEVEL) * @volume
231
+ end
232
+ end
233
+ end
234
+ end
235
+ end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Badline
4
- class Vic20
5
- class VIC
4
+ module Chips
5
+ class VICI
6
6
  # The text window's rows: where it opens and closes, the video matrix
7
7
  # counter and the character line, and the registers that place the
8
8
  # window and its memory.
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "badline/vic20/vic/painter"
4
- require "badline/vic20/vic/text_window"
5
- require "badline/vic20/vic/saved_state"
3
+ require "badline/chips/vic_i/painter"
4
+ require "badline/chips/vic_i/text_window"
5
+ require "badline/chips/vic_i/saved_state"
6
6
 
7
7
  module Badline
8
- class Vic20
8
+ module Chips
9
9
  # The VIC-I, the 6561 on PAL machines: its sixteen registers, the
10
10
  # raster, the text window's fetches over the V-bus and the picture. The
11
11
  # writes to the sound's registers, $900A-$900E, go on to the Sound
@@ -39,7 +39,7 @@ module Badline
39
39
  # display's lines start 6 cycles after the raster count moves, as
40
40
  # xvic's view of the frame does, so the character fetched 16 cycles
41
41
  # into the line lands 48 pixels in. Lines 0-27 are blanked.
42
- class VIC
42
+ class VICI
43
43
  include TextWindow
44
44
  include SavedState
45
45
 
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Chips
5
+ class Z80
6
+ # The ALU's 8- and 16-bit arithmetic. Bits 5 and 3 of F come from the
7
+ # result, except for CP, which takes them from the operand, and the
8
+ # 16-bit operations, which take them from the high byte.
9
+ module Arithmetic
10
+ private
11
+
12
+ # The eight operations an opcode's bits 5-3 pick: ADD ADC SUB SBC AND
13
+ # XOR OR CP.
14
+ def alu(operation, value)
15
+ case operation
16
+ when 0 then add_a(value, 0)
17
+ when 1 then add_a(value, @f & CF)
18
+ when 2 then @a = subtract(value, 0)
19
+ when 3 then @a = subtract(value, @f & CF)
20
+ when 4 then logic(@a & value, HF)
21
+ when 5 then logic(@a ^ value, 0)
22
+ when 6 then logic(@a | value, 0)
23
+ else compare(value)
24
+ end
25
+ end
26
+
27
+ def add_a(value, carry)
28
+ result = @a + value + carry
29
+ assign_flags(SZ53[result & 0xff] | (result >> 8) | ((@a ^ value ^ result) & HF) |
30
+ (((@a ^ value ^ 0x80) & (@a ^ result) & 0x80) >> 5))
31
+ @a = result & 0xff
32
+ end
33
+
34
+ def subtract(value, carry)
35
+ result = @a - value - carry
36
+ assign_flags(SZ53[result & 0xff] | NF | ((result >> 8) & CF) | ((@a ^ value ^ result) & HF) |
37
+ (((@a ^ value) & (@a ^ result) & 0x80) >> 5))
38
+ result & 0xff
39
+ end
40
+
41
+ def compare(value)
42
+ subtract(value, 0)
43
+ assign_flags((@f & ~XYF) | (value & XYF))
44
+ end
45
+
46
+ def logic(result, half)
47
+ @a = result
48
+ assign_flags(SZ53P[result] | half)
49
+ end
50
+
51
+ def increment(value)
52
+ result = (value + 1) & 0xff
53
+ assign_flags((@f & CF) | SZ53[result] | (result == 0x80 ? PF : 0) | (result.nobits?(0x0f) ? HF : 0))
54
+ result
55
+ end
56
+
57
+ def decrement(value)
58
+ result = (value - 1) & 0xff
59
+ assign_flags((@f & CF) | NF | SZ53[result] | (result == 0x7f ? PF : 0) | (value.nobits?(0x0f) ? HF : 0))
60
+ result
61
+ end
62
+
63
+ def add16(left, right)
64
+ result = left + right
65
+ @wz = (left + 1) & 0xffff
66
+ assign_flags((@f & (SF | ZF | PF)) | ((result >> 8) & XYF) | (((left ^ right ^ result) >> 8) & HF) |
67
+ (result >> 16))
68
+ result & 0xffff
69
+ end
70
+
71
+ def adc16(right)
72
+ left = hl
73
+ result = left + right + (@f & CF)
74
+ @wz = (left + 1) & 0xffff
75
+ self.hl = result & 0xffff
76
+ assign_flags(word_flags(result) | (((left ^ right ^ result) >> 8) & HF) |
77
+ (((left ^ right ^ 0x8000) & (left ^ result) & 0x8000) >> 13))
78
+ end
79
+
80
+ def sbc16(right)
81
+ left = hl
82
+ result = left - right - (@f & CF)
83
+ @wz = (left + 1) & 0xffff
84
+ self.hl = result & 0xffff
85
+ assign_flags(word_flags(result) | NF | (((left ^ right ^ result) >> 8) & HF) |
86
+ (((left ^ right) & (left ^ result) & 0x8000) >> 13))
87
+ end
88
+
89
+ def word_flags(result)
90
+ ((result >> 8) & (SF | XYF)) | (result.nobits?(0xffff) ? ZF : 0) | ((result >> 16) & CF)
91
+ end
92
+
93
+ def daa
94
+ low = @a & 0x0f
95
+ carry = @f.anybits?(CF) || @a > 0x99 ? CF : 0
96
+ correction = (carry.zero? ? 0 : 0x60) | (@f.anybits?(HF) || low > 9 ? 0x06 : 0)
97
+ subtracting = @f.anybits?(NF)
98
+ half = daa_half(low, subtracting)
99
+ @a = (subtracting ? @a - correction : @a + correction) & 0xff
100
+ assign_flags(SZ53P[@a] | (@f & NF) | carry | half)
101
+ end
102
+
103
+ def daa_half(low, subtracting)
104
+ if subtracting
105
+ @f.anybits?(HF) && low < 6 ? HF : 0
106
+ else
107
+ low > 9 ? HF : 0
108
+ end
109
+ end
110
+
111
+ def neg
112
+ value = @a
113
+ @a = 0
114
+ @a = subtract(value, 0)
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Chips
5
+ class Z80
6
+ # The CB page: rotates and shifts (quarter 0), BIT (1), RES (2) and SET
7
+ # (3) of the bit the row names, on the column's register or (HL). After
8
+ # DD or FD the operand is always (IX+d): the displacement comes before
9
+ # the opcode, and an opcode that names a register other than (HL) also
10
+ # copies the result into it.
11
+ module BitPage
12
+ private
13
+
14
+ def execute_bits(opcode)
15
+ operation = opcode >> 6
16
+ number = (opcode >> 3) & 7
17
+ index = opcode & 7
18
+ return bits_in_memory(operation, number, hl) if index == 6
19
+
20
+ value = register(index)
21
+ if operation == 1
22
+ bit(number, value, value)
23
+ else
24
+ set_register(index, bit_result(operation, number, value))
25
+ end
26
+ end
27
+
28
+ def execute_index_bits
29
+ displaced
30
+ opcode = fetch_byte
31
+ @cycles += 2
32
+ result = bits_in_memory(opcode >> 6, (opcode >> 3) & 7, @wz)
33
+ index = opcode & 7
34
+ set_plain_register(index, result) unless index == 6 || (opcode >> 6) == 1
35
+ end
36
+
37
+ def bits_in_memory(operation, number, address)
38
+ value = read_byte(address)
39
+ @cycles += 1
40
+ return bit(number, value, @wz >> 8) if operation == 1
41
+
42
+ result = bit_result(operation, number, value)
43
+ write_byte(address, result)
44
+ result
45
+ end
46
+
47
+ def bit_result(operation, number, value)
48
+ case operation
49
+ when 0 then shift(number, value)
50
+ when 2 then value & ~(1 << number) & 0xff
51
+ else value | (1 << number)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end