badline 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (516) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/CLAUDE.md +59 -31
  4. data/README.md +1 -1
  5. data/doc/library.md +9 -9
  6. data/doc/pinned-behaviour.md +105 -105
  7. data/doc/snapshots.md +1 -4
  8. data/lib/badline/audio/bare_player.rb +4 -4
  9. data/lib/badline/audio/cli.rb +6 -6
  10. data/lib/badline/audio/jukebox.rb +2 -2
  11. data/lib/badline/audio/machine_player.rb +2 -2
  12. data/lib/badline/{media → audio}/queue.rb +1 -1
  13. data/lib/badline/audio/queued_tune.rb +6 -6
  14. data/lib/badline/audio/renderer.rb +5 -5
  15. data/lib/badline/audio/stereo.rb +1 -1
  16. data/lib/badline/c128/{bus_state.rb → bus/saved_state.rb} +6 -6
  17. data/lib/badline/c128/bus.rb +30 -51
  18. data/lib/badline/c128/color_lines.rb +2 -2
  19. data/lib/badline/c128/cpu.rb +1 -1
  20. data/lib/badline/c128/drives.rb +10 -11
  21. data/lib/badline/c128/fast_serial.rb +5 -5
  22. data/lib/badline/c128/mmu_pages.rb +1 -1
  23. data/lib/badline/c128/modes.rb +2 -2
  24. data/lib/badline/c128/saved_state.rb +21 -47
  25. data/lib/badline/c128/z80.rb +2 -2
  26. data/lib/badline/c128.rb +18 -72
  27. data/lib/badline/{computer → c64}/attachments.rb +16 -47
  28. data/lib/badline/c64/banked_ram/banking.rb +32 -0
  29. data/lib/badline/c64/banked_ram/plus256k.rb +56 -0
  30. data/lib/badline/c64/banked_ram/plus60k.rb +45 -0
  31. data/lib/badline/c64/banked_ram/unexpanded.rb +30 -0
  32. data/lib/badline/c64/banked_ram.rb +23 -0
  33. data/lib/badline/c64/bus/extra_sids.rb +32 -0
  34. data/lib/badline/c64/bus/fittings.rb +40 -0
  35. data/lib/badline/c64/bus/pla.rb +149 -0
  36. data/lib/badline/c64/bus/roms.rb +41 -0
  37. data/lib/badline/c64/bus/saved_state.rb +68 -0
  38. data/lib/badline/c64/bus/sid_slots.rb +44 -0
  39. data/lib/badline/c64/bus.rb +218 -0
  40. data/lib/badline/c64/cartridge/action_replay.rb +128 -0
  41. data/lib/badline/c64/cartridge/atomic_power.rb +26 -0
  42. data/lib/badline/c64/cartridge/bank.rb +83 -0
  43. data/lib/badline/c64/cartridge/comal80.rb +52 -0
  44. data/lib/badline/c64/cartridge/dinamic.rb +36 -0
  45. data/lib/badline/c64/cartridge/easy_flash.rb +147 -0
  46. data/lib/badline/c64/cartridge/epyx_fastload.rb +81 -0
  47. data/lib/badline/c64/cartridge/final_cartridge3.rb +91 -0
  48. data/lib/badline/c64/cartridge/flash/saved_state.rb +40 -0
  49. data/lib/badline/c64/cartridge/flash.rb +279 -0
  50. data/lib/badline/c64/cartridge/freezer.rb +35 -0
  51. data/lib/badline/c64/cartridge/fun_play.rb +40 -0
  52. data/lib/badline/c64/cartridge/g_mod2.rb +76 -0
  53. data/lib/badline/c64/cartridge/game_system.rb +42 -0
  54. data/lib/badline/c64/cartridge/geo_ram.rb +81 -0
  55. data/lib/badline/c64/cartridge/kcs_power.rb +77 -0
  56. data/lib/badline/c64/cartridge/mach5.rb +34 -0
  57. data/lib/badline/c64/cartridge/magic_desk.rb +32 -0
  58. data/lib/badline/c64/cartridge/ocean.rb +37 -0
  59. data/lib/badline/c64/cartridge/pagefox.rb +70 -0
  60. data/lib/badline/c64/cartridge/retro_replay/saved_state.rb +47 -0
  61. data/lib/badline/c64/cartridge/retro_replay.rb +286 -0
  62. data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
  63. data/lib/badline/c64/cartridge/rgcd.rb +60 -0
  64. data/lib/badline/c64/cartridge/saved_state.rb +63 -0
  65. data/lib/badline/c64/cartridge/simons_basic.rb +37 -0
  66. data/lib/badline/c64/cartridge/standard.rb +17 -0
  67. data/lib/badline/c64/cartridge/super_games.rb +50 -0
  68. data/lib/badline/c64/cartridge/westermann.rb +32 -0
  69. data/lib/badline/c64/cartridge/zaxxon.rb +68 -0
  70. data/lib/badline/c64/cartridge.rb +258 -0
  71. data/lib/badline/c64/color_memory.rb +27 -0
  72. data/lib/badline/c64/common.rb +34 -0
  73. data/lib/badline/c64/kernal_traps.rb +89 -0
  74. data/lib/badline/c64/reu/dma/saved_state.rb +52 -0
  75. data/lib/badline/c64/reu/dma.rb +275 -0
  76. data/lib/badline/c64/reu/ram.rb +109 -0
  77. data/lib/badline/c64/reu/saved_state.rb +55 -0
  78. data/lib/badline/c64/reu/trigger.rb +34 -0
  79. data/lib/badline/c64/reu.rb +291 -0
  80. data/lib/badline/{computer → c64}/saved_state.rb +13 -18
  81. data/lib/badline/{computer → c64}/true_drives.rb +20 -31
  82. data/lib/badline/{computer.rb → c64.rb} +22 -80
  83. data/lib/badline/chips/cia/fast_forward.rb +62 -0
  84. data/lib/badline/chips/cia/interrupt_register.rb +145 -0
  85. data/lib/badline/chips/cia/saved_state.rb +49 -0
  86. data/lib/badline/chips/cia/serial/saved_state.rb +45 -0
  87. data/lib/badline/chips/cia/serial.rb +250 -0
  88. data/lib/badline/chips/cia/time_of_day.rb +232 -0
  89. data/lib/badline/chips/cia/timer.rb +208 -0
  90. data/lib/badline/chips/cia.rb +281 -0
  91. data/lib/badline/chips/cpu/addressing.rb +133 -0
  92. data/lib/badline/chips/cpu/boundary.rb +56 -0
  93. data/lib/badline/chips/cpu/core.rb +167 -0
  94. data/lib/badline/chips/cpu/instruction.rb +338 -0
  95. data/lib/badline/chips/cpu/instruction_set/arithmetic.rb +118 -0
  96. data/lib/badline/chips/cpu/instruction_set/bitwise.rb +130 -0
  97. data/lib/badline/chips/cpu/instruction_set/branch.rb +83 -0
  98. data/lib/badline/chips/cpu/instruction_set/flag.rb +67 -0
  99. data/lib/badline/chips/cpu/instruction_set/illegal.rb +274 -0
  100. data/lib/badline/chips/cpu/instruction_set/inc_dec.rb +73 -0
  101. data/lib/badline/chips/cpu/instruction_set/stack.rb +56 -0
  102. data/lib/badline/chips/cpu/instruction_set/transfer.rb +141 -0
  103. data/lib/badline/chips/cpu/instruction_set.rb +59 -0
  104. data/lib/badline/chips/cpu/interrupts.rb +108 -0
  105. data/lib/badline/chips/cpu/microcode.rb +179 -0
  106. data/lib/badline/chips/cpu/operations.rb +90 -0
  107. data/lib/badline/chips/cpu/port.rb +116 -0
  108. data/lib/badline/chips/cpu/saved_state.rb +117 -0
  109. data/lib/badline/chips/cpu/stack_operations.rb +84 -0
  110. data/lib/badline/chips/cpu/traps.rb +23 -0
  111. data/lib/badline/chips/cpu.rb +12 -0
  112. data/lib/badline/chips/sid/catch_up.rb +122 -0
  113. data/lib/badline/chips/sid/decimator.rb +66 -0
  114. data/lib/badline/chips/sid/envelope/saved_state.rb +70 -0
  115. data/lib/badline/chips/sid/envelope.rb +241 -0
  116. data/lib/badline/chips/sid/filter/saved_state.rb +42 -0
  117. data/lib/badline/chips/sid/filter.rb +241 -0
  118. data/lib/badline/chips/sid/saved_state.rb +52 -0
  119. data/lib/badline/chips/sid/voice.rb +79 -0
  120. data/lib/badline/chips/sid/waveform/combined.rb +128 -0
  121. data/lib/badline/chips/sid/waveform/fast_forward.rb +107 -0
  122. data/lib/badline/chips/sid/waveform/noise_writeback.rb +124 -0
  123. data/lib/badline/chips/sid/waveform/saved_state.rb +68 -0
  124. data/lib/badline/chips/sid/waveform.rb +307 -0
  125. data/lib/badline/chips/sid.rb +265 -0
  126. data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
  127. data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -1
  128. data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -1
  129. data/lib/badline/chips/vdc/saved_state.rb +36 -0
  130. data/lib/badline/{c128 → chips}/vdc/window.rb +1 -1
  131. data/lib/badline/{c128 → chips}/vdc.rb +7 -31
  132. data/lib/badline/chips/via/control_lines.rb +124 -0
  133. data/lib/badline/chips/via/fast_forward.rb +55 -0
  134. data/lib/badline/chips/via/interrupt_register.rb +69 -0
  135. data/lib/badline/chips/via/saved_state.rb +44 -0
  136. data/lib/badline/chips/via/shift_register.rb +182 -0
  137. data/lib/badline/chips/via/timer1.rb +133 -0
  138. data/lib/badline/chips/via/timer2.rb +135 -0
  139. data/lib/badline/chips/via.rb +268 -0
  140. data/lib/badline/chips/vic/bank.rb +135 -0
  141. data/lib/badline/chips/vic/border_mask.rb +88 -0
  142. data/lib/badline/chips/vic/collisions.rb +117 -0
  143. data/lib/badline/chips/vic/color_patches.rb +49 -0
  144. data/lib/badline/chips/vic/display_state.rb +187 -0
  145. data/lib/badline/chips/vic/graphics_mode.rb +166 -0
  146. data/lib/badline/chips/vic/graphics_shifter/saved_state.rb +40 -0
  147. data/lib/badline/chips/vic/graphics_shifter.rb +187 -0
  148. data/lib/badline/chips/vic/register_log.rb +83 -0
  149. data/lib/badline/chips/vic/registers.rb +197 -0
  150. data/lib/badline/chips/vic/saved_state.rb +82 -0
  151. data/lib/badline/chips/vic/sequencer/saved_state.rb +91 -0
  152. data/lib/badline/chips/vic/sequencer.rb +277 -0
  153. data/lib/badline/chips/vic/sequencer_output.rb +118 -0
  154. data/lib/badline/chips/vic/sprite/internal_bus.rb +70 -0
  155. data/lib/badline/chips/vic/sprite/saved_state.rb +66 -0
  156. data/lib/badline/chips/vic/sprite/shifter.rb +148 -0
  157. data/lib/badline/chips/vic/sprite/timing.rb +58 -0
  158. data/lib/badline/chips/vic/sprite.rb +339 -0
  159. data/lib/badline/chips/vic/sprites/saved_state.rb +59 -0
  160. data/lib/badline/chips/vic/sprites.rb +284 -0
  161. data/lib/badline/chips/vic.rb +783 -0
  162. data/lib/badline/chips/vic_i/painter/saved_state.rb +40 -0
  163. data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +6 -30
  164. data/lib/badline/{vic20/vic → chips/vic_i}/saved_state.rb +2 -2
  165. data/lib/badline/chips/vic_i/sound/output.rb +85 -0
  166. data/lib/badline/chips/vic_i/sound.rb +235 -0
  167. data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
  168. data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +5 -5
  169. data/lib/badline/chips/z80/arithmetic.rb +119 -0
  170. data/lib/badline/chips/z80/bit_page.rb +57 -0
  171. data/lib/badline/chips/z80/block_io.rb +60 -0
  172. data/lib/badline/chips/z80/block_transfers.rb +61 -0
  173. data/lib/badline/chips/z80/bus_cycles.rb +113 -0
  174. data/lib/badline/chips/z80/core.rb +115 -0
  175. data/lib/badline/chips/z80/exchanges.rb +52 -0
  176. data/lib/badline/chips/z80/extended_page.rb +91 -0
  177. data/lib/badline/chips/z80/flags.rb +39 -0
  178. data/lib/badline/chips/z80/interrupt_acceptance.rb +48 -0
  179. data/lib/badline/chips/z80/jumps.rb +84 -0
  180. data/lib/badline/chips/z80/loads.rb +100 -0
  181. data/lib/badline/chips/z80/main_page.rb +136 -0
  182. data/lib/badline/chips/z80/registers.rb +122 -0
  183. data/lib/badline/chips/z80/saved_state.rb +71 -0
  184. data/lib/badline/chips/z80/shifts.rb +66 -0
  185. data/lib/badline/chips/z80.rb +13 -0
  186. data/lib/badline/core.rb +27 -29
  187. data/lib/badline/drives/datasette/saved_state.rb +37 -0
  188. data/lib/badline/drives/datasette.rb +140 -0
  189. data/lib/badline/drives/engine/core.rb +149 -0
  190. data/lib/badline/drives/engine/fast_serial.rb +75 -0
  191. data/lib/badline/drives/engine/idle.rb +127 -0
  192. data/lib/badline/drives/engine/idle_cpu.rb +30 -0
  193. data/lib/badline/drives/engine/orbit.rb +81 -0
  194. data/lib/badline/drives/engine/serial_lines.rb +75 -0
  195. data/lib/badline/drives/engine/sleep.rb +114 -0
  196. data/lib/badline/drives/engine/vias.rb +86 -0
  197. data/lib/badline/drives/engine/watch.rb +152 -0
  198. data/lib/badline/drives/engine.rb +11 -0
  199. data/lib/badline/drives/model1541/bus.rb +88 -0
  200. data/lib/badline/drives/model1541/byte_ready.rb +50 -0
  201. data/lib/badline/drives/model1541/cpu.rb +13 -0
  202. data/lib/badline/drives/model1541/disk/saved_state.rb +88 -0
  203. data/lib/badline/drives/model1541/disk.rb +317 -0
  204. data/lib/badline/drives/model1541/disk_via.rb +38 -0
  205. data/lib/badline/drives/model1541/gcr.rb +59 -0
  206. data/lib/badline/drives/model1541/mechanism/saved_state.rb +72 -0
  207. data/lib/badline/drives/model1541/mechanism.rb +315 -0
  208. data/lib/badline/drives/model1541/rotation.rb +123 -0
  209. data/lib/badline/drives/model1541/saved_state.rb +44 -0
  210. data/lib/badline/drives/model1541/sector_reader.rb +78 -0
  211. data/lib/badline/drives/model1541/serial_port.rb +20 -0
  212. data/lib/badline/drives/model1541/track.rb +100 -0
  213. data/lib/badline/drives/model1541.rb +81 -0
  214. data/lib/badline/drives/model1571/bus.rb +113 -0
  215. data/lib/badline/drives/model1571/cpu.rb +13 -0
  216. data/lib/badline/drives/model1571/saved_state.rb +47 -0
  217. data/lib/badline/drives/model1571/serial_port.rb +39 -0
  218. data/lib/badline/drives/model1571/serial_via.rb +27 -0
  219. data/lib/badline/drives/model1571/wd1770.rb +122 -0
  220. data/lib/badline/drives/model1571.rb +142 -0
  221. data/lib/badline/drives/model1581/bus.rb +139 -0
  222. data/lib/badline/drives/model1581/cpu.rb +13 -0
  223. data/lib/badline/drives/model1581/disk/saved_state.rb +89 -0
  224. data/lib/badline/drives/model1581/disk.rb +137 -0
  225. data/lib/badline/drives/model1581/mechanism.rb +119 -0
  226. data/lib/badline/drives/model1581/saved_state.rb +42 -0
  227. data/lib/badline/drives/model1581/serial_port.rb +54 -0
  228. data/lib/badline/drives/model1581/slot.rb +79 -0
  229. data/lib/badline/drives/model1581/track.rb +102 -0
  230. data/lib/badline/drives/model1581/track_bytes.rb +77 -0
  231. data/lib/badline/drives/model1581/wd1772/registers.rb +91 -0
  232. data/lib/badline/drives/model1581/wd1772/saved_state.rb +68 -0
  233. data/lib/badline/drives/model1581/wd1772/sector_writes.rb +75 -0
  234. data/lib/badline/drives/model1581/wd1772/sectors.rb +152 -0
  235. data/lib/badline/drives/model1581/wd1772/stepping.rb +111 -0
  236. data/lib/badline/drives/model1581/wd1772/tracks.rb +127 -0
  237. data/lib/badline/drives/model1581/wd1772/turn.rb +75 -0
  238. data/lib/badline/drives/model1581/wd1772.rb +218 -0
  239. data/lib/badline/drives/model1581.rb +206 -0
  240. data/lib/badline/drives/serial_bus.rb +161 -0
  241. data/lib/badline/frontend/boot.rb +10 -61
  242. data/lib/badline/frontend/machine_window.rb +3 -1
  243. data/lib/badline/frontend/player/filter_view.rb +1 -1
  244. data/lib/badline/frontend/player/player_controller.rb +2 -2
  245. data/lib/badline/frontend/player/player_screen.rb +1 -0
  246. data/lib/badline/frontend/player/theme.rb +7 -7
  247. data/lib/badline/frontend/timeline.rb +3 -3
  248. data/lib/badline/input/control_ports.rb +78 -0
  249. data/lib/badline/input/joystick.rb +27 -0
  250. data/lib/badline/input/keyboard.rb +114 -0
  251. data/lib/badline/input.rb +3 -0
  252. data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
  253. data/lib/badline/kernal_trap/dos/channel.rb +183 -0
  254. data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -1
  255. data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -1
  256. data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
  257. data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -1
  258. data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -1
  259. data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
  260. data/lib/badline/kernal_trap/{drive.rb → dos.rb} +11 -10
  261. data/lib/badline/kernal_trap/{file.rb → file_routine.rb} +1 -1
  262. data/lib/badline/kernal_trap/load.rb +6 -6
  263. data/lib/badline/kernal_trap/save.rb +5 -5
  264. data/lib/badline/kernal_trap/serial.rb +7 -7
  265. data/lib/badline/kernal_trap.rb +2 -3
  266. data/lib/badline/machine/clocking.rb +50 -0
  267. data/lib/badline/machine.rb +63 -7
  268. data/lib/badline/media/boot_disk.rb +2 -2
  269. data/lib/badline/media/disk_list.rb +3 -3
  270. data/lib/badline/media/disk_set.rb +1 -1
  271. data/lib/badline/media/extensions.rb +33 -0
  272. data/lib/badline/media/program.rb +28 -0
  273. data/lib/badline/media/true_drive.rb +4 -3
  274. data/lib/badline/media/tune.rb +35 -0
  275. data/lib/badline/media/vic20_cartridge.rb +1 -7
  276. data/lib/badline/media/vic20_media.rb +38 -80
  277. data/lib/badline/media.rb +84 -81
  278. data/lib/badline/model.rb +1 -1
  279. data/lib/badline/options/event.rb +3 -1
  280. data/lib/badline/roms/README +6 -6
  281. data/lib/badline/sdl.rb +1 -0
  282. data/lib/badline/{storage/sid_file.rb → sid_tune/file.rb} +3 -3
  283. data/lib/badline/{storage → sid_tune}/hvsc.rb +7 -7
  284. data/lib/badline/{storage → sid_tune}/song_lengths.rb +2 -2
  285. data/lib/badline/{storage → sid_tune}/stil/credit.rb +1 -1
  286. data/lib/badline/{storage → sid_tune}/stil.rb +3 -3
  287. data/lib/badline/sid_tune.rb +6 -0
  288. data/lib/badline/snapshot/c128_setup.rb +43 -0
  289. data/lib/badline/snapshot/c64_setup.rb +79 -0
  290. data/lib/badline/snapshot/image.rb +5 -25
  291. data/lib/badline/snapshot/machine_state.rb +10 -2
  292. data/lib/badline/snapshot/setup.rb +22 -66
  293. data/lib/badline/snapshot/state.rb +8 -17
  294. data/lib/badline/snapshot/storage_setup.rb +68 -0
  295. data/lib/badline/snapshot/vic20_setup.rb +37 -0
  296. data/lib/badline/snapshot/vice/c64_mem.rb +1 -1
  297. data/lib/badline/snapshot/vice/restore.rb +1 -1
  298. data/lib/badline/snapshot/vice/reu1764.rb +1 -1
  299. data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
  300. data/lib/badline/snapshot/vice.rb +7 -5
  301. data/lib/badline/snapshot.rb +13 -12
  302. data/lib/badline/storage/d64_image.rb +15 -9
  303. data/lib/badline/storage/d71_image.rb +0 -2
  304. data/lib/badline/storage/d81_image.rb +0 -2
  305. data/lib/badline/storage/disk_image/writing.rb +2 -2
  306. data/lib/badline/storage/disk_image.rb +3 -6
  307. data/lib/badline/storage/g64_image.rb +2 -2
  308. data/lib/badline/storage/host_directory.rb +0 -5
  309. data/lib/badline/storage/t64.rb +2 -8
  310. data/lib/badline/storage/unavailable.rb +1 -1
  311. data/lib/badline/storage.rb +0 -37
  312. data/lib/badline/support/c128_checkpoint.rb +39 -0
  313. data/lib/badline/support/checkpoint.rb +108 -0
  314. data/lib/badline/support/vic20_checkpoint.rb +38 -0
  315. data/lib/badline/support.rb +5 -0
  316. data/lib/badline/version.rb +1 -1
  317. data/lib/badline/vic20/attachments.rb +11 -81
  318. data/lib/badline/vic20/bus/saved_state.rb +35 -0
  319. data/lib/badline/vic20/bus.rb +3 -25
  320. data/lib/badline/vic20/cpu.rb +1 -1
  321. data/lib/badline/vic20/port_wiring.rb +4 -4
  322. data/lib/badline/vic20/saved_state.rb +16 -60
  323. data/lib/badline/vic20/user_via_ports.rb +2 -2
  324. data/lib/badline/vic20.rb +20 -51
  325. metadata +250 -221
  326. data/lib/badline/address_bus/extra_sids.rb +0 -30
  327. data/lib/badline/address_bus/fittings.rb +0 -38
  328. data/lib/badline/address_bus/pla.rb +0 -147
  329. data/lib/badline/address_bus/roms.rb +0 -39
  330. data/lib/badline/address_bus/saved_state.rb +0 -72
  331. data/lib/badline/address_bus/sid_slots.rb +0 -42
  332. data/lib/badline/address_bus.rb +0 -235
  333. data/lib/badline/cartridge/action_replay.rb +0 -126
  334. data/lib/badline/cartridge/atomic_power.rb +0 -24
  335. data/lib/badline/cartridge/bank.rb +0 -81
  336. data/lib/badline/cartridge/comal80.rb +0 -50
  337. data/lib/badline/cartridge/dinamic.rb +0 -34
  338. data/lib/badline/cartridge/easy_flash.rb +0 -145
  339. data/lib/badline/cartridge/epyx_fastload.rb +0 -79
  340. data/lib/badline/cartridge/final_cartridge3.rb +0 -89
  341. data/lib/badline/cartridge/flash.rb +0 -306
  342. data/lib/badline/cartridge/freezer.rb +0 -33
  343. data/lib/badline/cartridge/fun_play.rb +0 -38
  344. data/lib/badline/cartridge/g_mod2.rb +0 -74
  345. data/lib/badline/cartridge/game_system.rb +0 -40
  346. data/lib/badline/cartridge/geo_ram.rb +0 -79
  347. data/lib/badline/cartridge/kcs_power.rb +0 -75
  348. data/lib/badline/cartridge/mach5.rb +0 -32
  349. data/lib/badline/cartridge/magic_desk.rb +0 -30
  350. data/lib/badline/cartridge/ocean.rb +0 -35
  351. data/lib/badline/cartridge/pagefox.rb +0 -68
  352. data/lib/badline/cartridge/retro_replay.rb +0 -320
  353. data/lib/badline/cartridge/rex_utility.rb +0 -29
  354. data/lib/badline/cartridge/rgcd.rb +0 -58
  355. data/lib/badline/cartridge/simons_basic.rb +0 -35
  356. data/lib/badline/cartridge/standard.rb +0 -15
  357. data/lib/badline/cartridge/super_games.rb +0 -48
  358. data/lib/badline/cartridge/westermann.rb +0 -30
  359. data/lib/badline/cartridge/zaxxon.rb +0 -66
  360. data/lib/badline/cartridge.rb +0 -303
  361. data/lib/badline/checkpoint.rb +0 -98
  362. data/lib/badline/cia/fast_forward.rb +0 -60
  363. data/lib/badline/cia/interrupt_register.rb +0 -143
  364. data/lib/badline/cia/serial.rb +0 -275
  365. data/lib/badline/cia/state.rb +0 -47
  366. data/lib/badline/cia/timer.rb +0 -206
  367. data/lib/badline/cia.rb +0 -279
  368. data/lib/badline/color_memory.rb +0 -25
  369. data/lib/badline/computer/kernal_traps.rb +0 -29
  370. data/lib/badline/control_ports.rb +0 -76
  371. data/lib/badline/cpu/addressing.rb +0 -131
  372. data/lib/badline/cpu/boundary.rb +0 -54
  373. data/lib/badline/cpu/core.rb +0 -165
  374. data/lib/badline/cpu/microcode.rb +0 -177
  375. data/lib/badline/cpu/operations.rb +0 -88
  376. data/lib/badline/cpu/saved_state.rb +0 -115
  377. data/lib/badline/cpu/stack_operations.rb +0 -82
  378. data/lib/badline/cpu.rb +0 -10
  379. data/lib/badline/cycleable.rb +0 -38
  380. data/lib/badline/datasette.rb +0 -161
  381. data/lib/badline/drive/core.rb +0 -147
  382. data/lib/badline/drive/fast_serial.rb +0 -73
  383. data/lib/badline/drive/idle.rb +0 -125
  384. data/lib/badline/drive/idle_cpu.rb +0 -28
  385. data/lib/badline/drive/orbit.rb +0 -79
  386. data/lib/badline/drive/serial_lines.rb +0 -73
  387. data/lib/badline/drive/sleep.rb +0 -112
  388. data/lib/badline/drive/vias.rb +0 -84
  389. data/lib/badline/drive/watch.rb +0 -150
  390. data/lib/badline/drive.rb +0 -11
  391. data/lib/badline/drive1541/bus.rb +0 -86
  392. data/lib/badline/drive1541/byte_ready.rb +0 -48
  393. data/lib/badline/drive1541/cpu.rb +0 -11
  394. data/lib/badline/drive1541/disk.rb +0 -318
  395. data/lib/badline/drive1541/disk_state.rb +0 -94
  396. data/lib/badline/drive1541/disk_via.rb +0 -36
  397. data/lib/badline/drive1541/gcr.rb +0 -57
  398. data/lib/badline/drive1541/mechanism.rb +0 -313
  399. data/lib/badline/drive1541/mechanism_state.rb +0 -68
  400. data/lib/badline/drive1541/rotation.rb +0 -121
  401. data/lib/badline/drive1541/sector_reader.rb +0 -76
  402. data/lib/badline/drive1541/serial_port.rb +0 -18
  403. data/lib/badline/drive1541/track.rb +0 -98
  404. data/lib/badline/drive1541.rb +0 -111
  405. data/lib/badline/drive1571/bus.rb +0 -111
  406. data/lib/badline/drive1571/cpu.rb +0 -11
  407. data/lib/badline/drive1571/serial_port.rb +0 -37
  408. data/lib/badline/drive1571/serial_via.rb +0 -25
  409. data/lib/badline/drive1571/wd1770.rb +0 -120
  410. data/lib/badline/drive1571.rb +0 -175
  411. data/lib/badline/drive1581/bus.rb +0 -137
  412. data/lib/badline/drive1581/cpu.rb +0 -11
  413. data/lib/badline/drive1581/disk.rb +0 -135
  414. data/lib/badline/drive1581/disk_state.rb +0 -87
  415. data/lib/badline/drive1581/mechanism.rb +0 -117
  416. data/lib/badline/drive1581/serial_port.rb +0 -52
  417. data/lib/badline/drive1581/slot.rb +0 -78
  418. data/lib/badline/drive1581/track.rb +0 -100
  419. data/lib/badline/drive1581/track_bytes.rb +0 -75
  420. data/lib/badline/drive1581/wd1772/registers.rb +0 -89
  421. data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
  422. data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
  423. data/lib/badline/drive1581/wd1772/state.rb +0 -66
  424. data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
  425. data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
  426. data/lib/badline/drive1581/wd1772/turn.rb +0 -73
  427. data/lib/badline/drive1581/wd1772.rb +0 -216
  428. data/lib/badline/drive1581.rb +0 -233
  429. data/lib/badline/iec_bus.rb +0 -159
  430. data/lib/badline/instruction.rb +0 -334
  431. data/lib/badline/instruction_set/arithmetic.rb +0 -114
  432. data/lib/badline/instruction_set/bitwise.rb +0 -126
  433. data/lib/badline/instruction_set/branch.rb +0 -79
  434. data/lib/badline/instruction_set/flag.rb +0 -63
  435. data/lib/badline/instruction_set/illegal.rb +0 -270
  436. data/lib/badline/instruction_set/inc_dec.rb +0 -69
  437. data/lib/badline/instruction_set/stack.rb +0 -52
  438. data/lib/badline/instruction_set/transfer.rb +0 -137
  439. data/lib/badline/instruction_set.rb +0 -55
  440. data/lib/badline/interrupts.rb +0 -104
  441. data/lib/badline/joystick.rb +0 -25
  442. data/lib/badline/kernal_trap/channel.rb +0 -181
  443. data/lib/badline/keyboard.rb +0 -112
  444. data/lib/badline/ram_expansion/banking.rb +0 -30
  445. data/lib/badline/ram_expansion/plus256k.rb +0 -54
  446. data/lib/badline/ram_expansion/plus60k.rb +0 -43
  447. data/lib/badline/ram_expansion/unexpanded.rb +0 -28
  448. data/lib/badline/ram_expansion.rb +0 -21
  449. data/lib/badline/reu/dma/saved_state.rb +0 -50
  450. data/lib/badline/reu/dma.rb +0 -273
  451. data/lib/badline/reu/ram.rb +0 -107
  452. data/lib/badline/reu/saved_state.rb +0 -80
  453. data/lib/badline/reu/trigger.rb +0 -32
  454. data/lib/badline/reu.rb +0 -289
  455. data/lib/badline/sid/catch_up.rb +0 -120
  456. data/lib/badline/sid/decimator.rb +0 -64
  457. data/lib/badline/sid/envelope/state.rb +0 -68
  458. data/lib/badline/sid/envelope.rb +0 -239
  459. data/lib/badline/sid/filter.rb +0 -263
  460. data/lib/badline/sid/voice.rb +0 -77
  461. data/lib/badline/sid/waveform/combined.rb +0 -126
  462. data/lib/badline/sid/waveform/fast_forward.rb +0 -105
  463. data/lib/badline/sid/waveform/noise_writeback.rb +0 -122
  464. data/lib/badline/sid/waveform/state.rb +0 -66
  465. data/lib/badline/sid/waveform.rb +0 -305
  466. data/lib/badline/sid.rb +0 -303
  467. data/lib/badline/time_of_day.rb +0 -228
  468. data/lib/badline/traps.rb +0 -19
  469. data/lib/badline/via/control_lines.rb +0 -122
  470. data/lib/badline/via/fast_forward.rb +0 -53
  471. data/lib/badline/via/interrupt_register.rb +0 -67
  472. data/lib/badline/via/shift_register.rb +0 -180
  473. data/lib/badline/via/state.rb +0 -42
  474. data/lib/badline/via/timer1.rb +0 -131
  475. data/lib/badline/via/timer2.rb +0 -133
  476. data/lib/badline/via.rb +0 -266
  477. data/lib/badline/vic/bank.rb +0 -133
  478. data/lib/badline/vic/border_mask.rb +0 -86
  479. data/lib/badline/vic/collisions.rb +0 -115
  480. data/lib/badline/vic/color_patches.rb +0 -47
  481. data/lib/badline/vic/display_state.rb +0 -185
  482. data/lib/badline/vic/graphics_mode.rb +0 -164
  483. data/lib/badline/vic/graphics_shifter.rb +0 -207
  484. data/lib/badline/vic/register_log.rb +0 -81
  485. data/lib/badline/vic/registers.rb +0 -195
  486. data/lib/badline/vic/sequencer.rb +0 -275
  487. data/lib/badline/vic/sequencer_output.rb +0 -116
  488. data/lib/badline/vic/sequencer_state.rb +0 -89
  489. data/lib/badline/vic/sprite/internal_bus.rb +0 -68
  490. data/lib/badline/vic/sprite/saved_state.rb +0 -64
  491. data/lib/badline/vic/sprite/shifter.rb +0 -146
  492. data/lib/badline/vic/sprite/timing.rb +0 -56
  493. data/lib/badline/vic/sprite.rb +0 -337
  494. data/lib/badline/vic/sprites.rb +0 -282
  495. data/lib/badline/vic/sprites_state.rb +0 -57
  496. data/lib/badline/vic.rb +0 -852
  497. data/lib/badline/vic20/sound/output.rb +0 -83
  498. data/lib/badline/vic20/sound.rb +0 -233
  499. data/lib/badline/z80/arithmetic.rb +0 -117
  500. data/lib/badline/z80/bit_page.rb +0 -55
  501. data/lib/badline/z80/block_io.rb +0 -58
  502. data/lib/badline/z80/block_transfers.rb +0 -59
  503. data/lib/badline/z80/bus_cycles.rb +0 -111
  504. data/lib/badline/z80/core.rb +0 -113
  505. data/lib/badline/z80/exchanges.rb +0 -50
  506. data/lib/badline/z80/extended_page.rb +0 -89
  507. data/lib/badline/z80/flags.rb +0 -37
  508. data/lib/badline/z80/interrupt_acceptance.rb +0 -46
  509. data/lib/badline/z80/jumps.rb +0 -82
  510. data/lib/badline/z80/loads.rb +0 -98
  511. data/lib/badline/z80/main_page.rb +0 -134
  512. data/lib/badline/z80/registers.rb +0 -120
  513. data/lib/badline/z80/saved_state.rb +0 -69
  514. data/lib/badline/z80/shifts.rb +0 -64
  515. data/lib/badline/z80.rb +0 -11
  516. /data/lib/badline/snapshot/{fields.rb → vice/fields.rb} +0 -0
@@ -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