badline 0.12.1 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (565) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -1
  3. data/CLAUDE.md +86 -38
  4. data/CONTRIBUTING.md +4 -3
  5. data/README.md +9 -6
  6. data/doc/library.md +9 -9
  7. data/doc/media.md +2 -1
  8. data/doc/pinned-behaviour.md +134 -105
  9. data/doc/snapshot-format.md +1047 -0
  10. data/doc/snapshots.md +73 -43
  11. data/lib/badline/audio/bare_player.rb +53 -20
  12. data/lib/badline/audio/cli.rb +6 -6
  13. data/lib/badline/audio/jukebox.rb +2 -2
  14. data/lib/badline/audio/machine_player.rb +16 -10
  15. data/lib/badline/{media → audio}/queue.rb +1 -1
  16. data/lib/badline/audio/queued_tune.rb +6 -6
  17. data/lib/badline/audio/renderer.rb +33 -22
  18. data/lib/badline/audio/stereo.rb +1 -1
  19. data/lib/badline/c128/banks.rb +6 -3
  20. data/lib/badline/c128/bus/keyed_state.rb +45 -0
  21. data/lib/badline/c128/bus.rb +35 -20
  22. data/lib/badline/c128/color_lines.rb +2 -2
  23. data/lib/badline/c128/cpu.rb +1 -1
  24. data/lib/badline/c128/drives.rb +14 -34
  25. data/lib/badline/c128/fast_serial.rb +5 -5
  26. data/lib/badline/c128/keyed_modules.rb +117 -0
  27. data/lib/badline/c128/keyed_state.rb +91 -0
  28. data/lib/badline/c128/keys.rb +9 -0
  29. data/lib/badline/c128/mmu.rb +9 -8
  30. data/lib/badline/c128/mmu_pages.rb +21 -1
  31. data/lib/badline/c128/modes.rb +21 -11
  32. data/lib/badline/c128/z80.rb +2 -2
  33. data/lib/badline/c128/z80_turns.rb +1 -1
  34. data/lib/badline/c128.rb +21 -16
  35. data/lib/badline/c64/attachments.rb +42 -0
  36. data/lib/badline/c64/banked_ram/banking.rb +32 -0
  37. data/lib/badline/c64/banked_ram/plus256k.rb +64 -0
  38. data/lib/badline/c64/banked_ram/plus60k.rb +47 -0
  39. data/lib/badline/c64/banked_ram/unexpanded.rb +30 -0
  40. data/lib/badline/c64/banked_ram.rb +23 -0
  41. data/lib/badline/c64/bus/debug_register.rb +32 -0
  42. data/lib/badline/c64/bus/extra_sids.rb +32 -0
  43. data/lib/badline/c64/bus/fittings.rb +40 -0
  44. data/lib/badline/c64/bus/keyed_state.rb +41 -0
  45. data/lib/badline/c64/bus/pla.rb +149 -0
  46. data/lib/badline/c64/bus/roms.rb +41 -0
  47. data/lib/badline/c64/bus/sid_slots.rb +44 -0
  48. data/lib/badline/c64/bus.rb +219 -0
  49. data/lib/badline/c64/cartridge/action_replay.rb +115 -0
  50. data/lib/badline/c64/cartridge/atomic_power.rb +26 -0
  51. data/lib/badline/c64/cartridge/bank.rb +83 -0
  52. data/lib/badline/c64/cartridge/comal80.rb +52 -0
  53. data/lib/badline/c64/cartridge/dinamic.rb +36 -0
  54. data/lib/badline/c64/cartridge/easy_flash.rb +132 -0
  55. data/lib/badline/c64/cartridge/epyx_fastload.rb +73 -0
  56. data/lib/badline/c64/cartridge/final_cartridge3.rb +79 -0
  57. data/lib/badline/c64/cartridge/flash.rb +279 -0
  58. data/lib/badline/c64/cartridge/freezer.rb +35 -0
  59. data/lib/badline/c64/cartridge/fun_play.rb +40 -0
  60. data/lib/badline/c64/cartridge/g_mod2.rb +64 -0
  61. data/lib/badline/c64/cartridge/game_system.rb +42 -0
  62. data/lib/badline/c64/cartridge/geo_ram.rb +65 -0
  63. data/lib/badline/c64/cartridge/kcs_power.rb +69 -0
  64. data/lib/badline/c64/cartridge/keyed_state.rb +393 -0
  65. data/lib/badline/c64/cartridge/mach5.rb +34 -0
  66. data/lib/badline/c64/cartridge/magic_desk.rb +32 -0
  67. data/lib/badline/c64/cartridge/ocean.rb +37 -0
  68. data/lib/badline/c64/cartridge/pagefox.rb +60 -0
  69. data/lib/badline/c64/cartridge/retro_replay.rb +278 -0
  70. data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
  71. data/lib/badline/c64/cartridge/rgcd.rb +50 -0
  72. data/lib/badline/c64/cartridge/simons_basic.rb +37 -0
  73. data/lib/badline/c64/cartridge/standard.rb +17 -0
  74. data/lib/badline/c64/cartridge/super_games.rb +40 -0
  75. data/lib/badline/c64/cartridge/westermann.rb +32 -0
  76. data/lib/badline/c64/cartridge/zaxxon.rb +52 -0
  77. data/lib/badline/c64/cartridge.rb +232 -0
  78. data/lib/badline/c64/color_memory.rb +27 -0
  79. data/lib/badline/{computer → c64}/common.rb +2 -2
  80. data/lib/badline/{computer → c64}/kernal_traps.rb +39 -36
  81. data/lib/badline/c64/keyed_modules.rb +111 -0
  82. data/lib/badline/c64/keyed_state.rb +68 -0
  83. data/lib/badline/c64/reu/dma.rb +271 -0
  84. data/lib/badline/c64/reu/keyed_state.rb +140 -0
  85. data/lib/badline/c64/reu/ram.rb +94 -0
  86. data/lib/badline/c64/reu/trigger.rb +34 -0
  87. data/lib/badline/c64/reu.rb +289 -0
  88. data/lib/badline/c64/true_drives.rb +120 -0
  89. data/lib/badline/{computer.rb → c64.rb} +24 -15
  90. data/lib/badline/chips/cia/fast_forward.rb +62 -0
  91. data/lib/badline/chips/cia/interrupt_register.rb +128 -0
  92. data/lib/badline/chips/cia/keyed_parts.rb +213 -0
  93. data/lib/badline/chips/cia/serial.rb +246 -0
  94. data/lib/badline/chips/cia/time_of_day.rb +210 -0
  95. data/lib/badline/chips/cia/timer.rb +188 -0
  96. data/lib/badline/chips/cia.rb +281 -0
  97. data/lib/badline/chips/cpu/addressing.rb +133 -0
  98. data/lib/badline/chips/cpu/boundary.rb +56 -0
  99. data/lib/badline/chips/cpu/core.rb +183 -0
  100. data/lib/badline/chips/cpu/instruction.rb +338 -0
  101. data/lib/badline/chips/cpu/instruction_set/arithmetic.rb +118 -0
  102. data/lib/badline/chips/cpu/instruction_set/bitwise.rb +130 -0
  103. data/lib/badline/chips/cpu/instruction_set/branch.rb +83 -0
  104. data/lib/badline/chips/cpu/instruction_set/flag.rb +67 -0
  105. data/lib/badline/chips/cpu/instruction_set/illegal.rb +274 -0
  106. data/lib/badline/chips/cpu/instruction_set/inc_dec.rb +73 -0
  107. data/lib/badline/chips/cpu/instruction_set/stack.rb +56 -0
  108. data/lib/badline/chips/cpu/instruction_set/transfer.rb +141 -0
  109. data/lib/badline/chips/cpu/instruction_set.rb +59 -0
  110. data/lib/badline/chips/cpu/interrupts.rb +108 -0
  111. data/lib/badline/chips/cpu/keyed_state.rb +177 -0
  112. data/lib/badline/chips/cpu/microcode.rb +195 -0
  113. data/lib/badline/chips/cpu/operations.rb +90 -0
  114. data/lib/badline/chips/cpu/port.rb +133 -0
  115. data/lib/badline/chips/cpu/stack_operations.rb +84 -0
  116. data/lib/badline/chips/cpu/traps.rb +23 -0
  117. data/lib/badline/chips/cpu.rb +17 -0
  118. data/lib/badline/chips/sid/catch_up.rb +122 -0
  119. data/lib/badline/chips/sid/decimator.rb +68 -0
  120. data/lib/badline/chips/sid/envelope.rb +236 -0
  121. data/lib/badline/chips/sid/filter.rb +227 -0
  122. data/lib/badline/chips/sid/keyed_parts.rb +286 -0
  123. data/lib/badline/chips/sid/voice.rb +69 -0
  124. data/lib/badline/chips/sid/waveform/combined.rb +128 -0
  125. data/lib/badline/chips/sid/waveform/fast_forward.rb +107 -0
  126. data/lib/badline/chips/sid/waveform/noise_writeback.rb +124 -0
  127. data/lib/badline/chips/sid/waveform.rb +305 -0
  128. data/lib/badline/chips/sid.rb +264 -0
  129. data/lib/badline/chips/ted/beam.rb +119 -0
  130. data/lib/badline/chips/ted/timers.rb +66 -0
  131. data/lib/badline/chips/ted.rb +143 -0
  132. data/lib/badline/chips/tia.rb +49 -0
  133. data/lib/badline/chips/vdc/keyed_parts.rb +105 -0
  134. data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
  135. data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -13
  136. data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -17
  137. data/lib/badline/{c128 → chips}/vdc/window.rb +1 -10
  138. data/lib/badline/{c128 → chips}/vdc.rb +6 -31
  139. data/lib/badline/chips/via/control_lines.rb +109 -0
  140. data/lib/badline/chips/via/fast_forward.rb +55 -0
  141. data/lib/badline/chips/via/interrupt_register.rb +60 -0
  142. data/lib/badline/chips/via/keyed_parts.rb +163 -0
  143. data/lib/badline/chips/via/shift_register.rb +168 -0
  144. data/lib/badline/chips/via/timer1.rb +120 -0
  145. data/lib/badline/chips/via/timer2.rb +117 -0
  146. data/lib/badline/chips/via.rb +267 -0
  147. data/lib/badline/chips/vic/bank.rb +135 -0
  148. data/lib/badline/chips/vic/border_mask.rb +78 -0
  149. data/lib/badline/chips/vic/collisions.rb +106 -0
  150. data/lib/badline/chips/vic/color_patches.rb +38 -0
  151. data/lib/badline/chips/vic/display_state.rb +168 -0
  152. data/lib/badline/chips/vic/graphics_mode.rb +166 -0
  153. data/lib/badline/chips/vic/graphics_shifter.rb +183 -0
  154. data/lib/badline/chips/vic/keyed_parts.rb +228 -0
  155. data/lib/badline/chips/vic/keyed_sprites.rb +225 -0
  156. data/lib/badline/chips/vic/keyed_state.rb +102 -0
  157. data/lib/badline/chips/vic/register_log.rb +65 -0
  158. data/lib/badline/chips/vic/registers.rb +188 -0
  159. data/lib/badline/chips/vic/sequencer.rb +275 -0
  160. data/lib/badline/chips/vic/sequencer_output.rb +118 -0
  161. data/lib/badline/chips/vic/sprite/internal_bus.rb +59 -0
  162. data/lib/badline/chips/vic/sprite/shifter.rb +148 -0
  163. data/lib/badline/chips/vic/sprite/timing.rb +58 -0
  164. data/lib/badline/chips/vic/sprite.rb +337 -0
  165. data/lib/badline/chips/vic/sprites.rb +281 -0
  166. data/lib/badline/chips/vic.rb +787 -0
  167. data/lib/badline/chips/vic_i/keyed_parts.rb +142 -0
  168. data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +2 -30
  169. data/lib/badline/chips/vic_i/sound/output.rb +85 -0
  170. data/lib/badline/chips/vic_i/sound.rb +227 -0
  171. data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
  172. data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +6 -6
  173. data/lib/badline/chips/z80/arithmetic.rb +119 -0
  174. data/lib/badline/chips/z80/bit_page.rb +57 -0
  175. data/lib/badline/chips/z80/block_io.rb +60 -0
  176. data/lib/badline/chips/z80/block_transfers.rb +61 -0
  177. data/lib/badline/chips/z80/bus_cycles.rb +113 -0
  178. data/lib/badline/chips/z80/core.rb +115 -0
  179. data/lib/badline/chips/z80/exchanges.rb +52 -0
  180. data/lib/badline/chips/z80/extended_page.rb +91 -0
  181. data/lib/badline/chips/z80/flags.rb +39 -0
  182. data/lib/badline/chips/z80/interrupt_acceptance.rb +48 -0
  183. data/lib/badline/chips/z80/jumps.rb +84 -0
  184. data/lib/badline/chips/z80/keyed_state.rb +73 -0
  185. data/lib/badline/chips/z80/loads.rb +100 -0
  186. data/lib/badline/chips/z80/main_page.rb +136 -0
  187. data/lib/badline/chips/z80/registers.rb +122 -0
  188. data/lib/badline/chips/z80/shifts.rb +66 -0
  189. data/lib/badline/chips/z80.rb +13 -0
  190. data/lib/badline/chips.rb +10 -0
  191. data/lib/badline/core.rb +13 -32
  192. data/lib/badline/drives/datasette/keyed_state.rb +38 -0
  193. data/lib/badline/drives/datasette.rb +173 -0
  194. data/lib/badline/drives/engine/core.rb +152 -0
  195. data/lib/badline/drives/engine/fast_serial.rb +75 -0
  196. data/lib/badline/drives/engine/idle.rb +127 -0
  197. data/lib/badline/drives/engine/idle_cpu.rb +30 -0
  198. data/lib/badline/drives/engine/orbit.rb +81 -0
  199. data/lib/badline/drives/engine/serial_lines.rb +72 -0
  200. data/lib/badline/drives/engine/sleep.rb +114 -0
  201. data/lib/badline/drives/engine/vias.rb +86 -0
  202. data/lib/badline/drives/engine/watch.rb +152 -0
  203. data/lib/badline/drives/engine.rb +11 -0
  204. data/lib/badline/drives/model1541/bus.rb +75 -0
  205. data/lib/badline/drives/model1541/byte_ready.rb +50 -0
  206. data/lib/badline/drives/model1541/cpu.rb +13 -0
  207. data/lib/badline/drives/model1541/disk.rb +318 -0
  208. data/lib/badline/drives/model1541/disk_via.rb +38 -0
  209. data/lib/badline/drives/model1541/gcr.rb +59 -0
  210. data/lib/badline/drives/model1541/keyed_state.rb +251 -0
  211. data/lib/badline/drives/model1541/mechanism.rb +313 -0
  212. data/lib/badline/drives/model1541/rotation.rb +123 -0
  213. data/lib/badline/drives/model1541/sector_reader.rb +78 -0
  214. data/lib/badline/drives/model1541/serial_port.rb +20 -0
  215. data/lib/badline/drives/model1541/track.rb +100 -0
  216. data/lib/badline/drives/model1541.rb +80 -0
  217. data/lib/badline/drives/model1571/bus.rb +100 -0
  218. data/lib/badline/drives/model1571/cpu.rb +13 -0
  219. data/lib/badline/drives/model1571/keyed_state.rb +108 -0
  220. data/lib/badline/drives/model1571/serial_port.rb +39 -0
  221. data/lib/badline/drives/model1571/serial_via.rb +27 -0
  222. data/lib/badline/drives/model1571/wd1770.rb +108 -0
  223. data/lib/badline/drives/model1571.rb +141 -0
  224. data/lib/badline/drives/model1581/bus.rb +126 -0
  225. data/lib/badline/drives/model1581/cpu.rb +13 -0
  226. data/lib/badline/drives/model1581/disk.rb +133 -0
  227. data/lib/badline/drives/model1581/keyed_state.rb +280 -0
  228. data/lib/badline/drives/model1581/mechanism.rb +98 -0
  229. data/lib/badline/drives/model1581/serial_port.rb +54 -0
  230. data/lib/badline/drives/model1581/slot.rb +61 -0
  231. data/lib/badline/drives/model1581/track.rb +102 -0
  232. data/lib/badline/drives/model1581/track_bytes.rb +77 -0
  233. data/lib/badline/drives/model1581/wd1772/registers.rb +91 -0
  234. data/lib/badline/drives/model1581/wd1772/sector_writes.rb +75 -0
  235. data/lib/badline/drives/model1581/wd1772/sectors.rb +152 -0
  236. data/lib/badline/drives/model1581/wd1772/stepping.rb +111 -0
  237. data/lib/badline/drives/model1581/wd1772/tracks.rb +127 -0
  238. data/lib/badline/drives/model1581/wd1772/turn.rb +75 -0
  239. data/lib/badline/drives/model1581/wd1772.rb +216 -0
  240. data/lib/badline/drives/model1581.rb +206 -0
  241. data/lib/badline/drives/serial_bus.rb +161 -0
  242. data/lib/badline/drives.rb +8 -0
  243. data/lib/badline/frontend/app.rb +3 -3
  244. data/lib/badline/frontend/boot.rb +4 -4
  245. data/lib/badline/frontend/controls.rb +19 -3
  246. data/lib/badline/frontend/drive_led.rb +44 -21
  247. data/lib/badline/frontend/machine_window.rb +3 -1
  248. data/lib/badline/frontend/menu/menu_dialogs.rb +2 -2
  249. data/lib/badline/frontend/player/filter_view.rb +1 -1
  250. data/lib/badline/frontend/player/player_controller.rb +2 -2
  251. data/lib/badline/frontend/player/player_screen.rb +1 -0
  252. data/lib/badline/frontend/player/theme.rb +7 -7
  253. data/lib/badline/frontend/snapshots.rb +12 -1
  254. data/lib/badline/frontend/timeline.rb +30 -12
  255. data/lib/badline/input/control_ports.rb +78 -0
  256. data/lib/badline/input/joystick.rb +27 -0
  257. data/lib/badline/input/keyboard.rb +114 -0
  258. data/lib/badline/input/matrix_typist.rb +98 -0
  259. data/lib/badline/input.rb +4 -0
  260. data/lib/badline/kernal_trap/chrout.rb +45 -0
  261. data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
  262. data/lib/badline/kernal_trap/dos/channel.rb +156 -0
  263. data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -26
  264. data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -10
  265. data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
  266. data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -9
  267. data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -19
  268. data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
  269. data/lib/badline/kernal_trap/{drive.rb → dos.rb} +9 -27
  270. data/lib/badline/kernal_trap/file_routine.rb +4 -4
  271. data/lib/badline/kernal_trap/keyed_state.rb +150 -0
  272. data/lib/badline/kernal_trap/layout.rb +75 -11
  273. data/lib/badline/kernal_trap/load.rb +19 -21
  274. data/lib/badline/kernal_trap/routine.rb +12 -0
  275. data/lib/badline/kernal_trap/save.rb +12 -22
  276. data/lib/badline/kernal_trap/serial.rb +8 -24
  277. data/lib/badline/kernal_trap.rb +3 -2
  278. data/lib/badline/machine/clocking.rb +1 -1
  279. data/lib/badline/machine/keyboard_buffer.rb +49 -0
  280. data/lib/badline/machine/settling.rb +29 -0
  281. data/lib/badline/machine.rb +10 -7
  282. data/lib/badline/media/boot_disk.rb +14 -2
  283. data/lib/badline/media/extensions.rb +10 -0
  284. data/lib/badline/media/true_drive.rb +1 -1
  285. data/lib/badline/media/tune.rb +2 -2
  286. data/lib/badline/media.rb +3 -3
  287. data/lib/badline/memory.rb +3 -6
  288. data/lib/badline/model.rb +1 -1
  289. data/lib/badline/options/family.rb +5 -2
  290. data/lib/badline/options/help.rb +42 -16
  291. data/lib/badline/options/table.rb +2 -0
  292. data/lib/badline/options/validation.rb +2 -0
  293. data/lib/badline/options.rb +6 -1
  294. data/lib/badline/plus4/acia.rb +45 -0
  295. data/lib/badline/plus4/bus.rb +312 -0
  296. data/lib/badline/plus4/cpu.rb +10 -0
  297. data/lib/badline/plus4/cpu_port.rb +93 -0
  298. data/lib/badline/plus4/keyboard_port.rb +51 -0
  299. data/lib/badline/plus4/model.rb +38 -0
  300. data/lib/badline/plus4/user_port.rb +31 -0
  301. data/lib/badline/plus4.rb +164 -0
  302. data/lib/badline/roms/README +44 -6
  303. data/lib/badline/roms/plus4/basic.rom +0 -0
  304. data/lib/badline/roms/plus4/function-high.rom +0 -0
  305. data/lib/badline/roms/plus4/function-low.rom +0 -0
  306. data/lib/badline/roms/plus4/kernal-ntsc.rom +0 -0
  307. data/lib/badline/roms/plus4/kernal-pal.rom +0 -0
  308. data/lib/badline/sdl.rb +1 -0
  309. data/lib/badline/{storage/sid_file.rb → sid_tune/file.rb} +3 -3
  310. data/lib/badline/{storage → sid_tune}/hvsc.rb +7 -7
  311. data/lib/badline/{storage → sid_tune}/song_lengths.rb +2 -2
  312. data/lib/badline/{storage → sid_tune}/stil/credit.rb +1 -1
  313. data/lib/badline/{storage → sid_tune}/stil.rb +3 -3
  314. data/lib/badline/sid_tune.rb +6 -0
  315. data/lib/badline/snapshot/c128_setup.rb +32 -0
  316. data/lib/badline/snapshot/c64_setup.rb +83 -0
  317. data/lib/badline/snapshot/container.rb +4 -0
  318. data/lib/badline/snapshot/field_doc/markdown.rb +112 -0
  319. data/lib/badline/snapshot/field_doc.rb +109 -0
  320. data/lib/badline/snapshot/image.rb +132 -46
  321. data/lib/badline/snapshot/keyed/cursor.rb +40 -0
  322. data/lib/badline/snapshot/keyed/modules.rb +66 -0
  323. data/lib/badline/snapshot/keyed/reader.rb +188 -0
  324. data/lib/badline/snapshot/keyed/recorder.rb +88 -0
  325. data/lib/badline/snapshot/keyed/report.rb +26 -0
  326. data/lib/badline/snapshot/keyed/writer.rb +55 -0
  327. data/lib/badline/snapshot/keyed.rb +64 -0
  328. data/lib/badline/snapshot/machine_state.rb +17 -64
  329. data/lib/badline/snapshot/storage_setup.rb +63 -0
  330. data/lib/badline/snapshot/vic20_setup.rb +28 -0
  331. data/lib/badline/snapshot/vice/c64_mem.rb +1 -1
  332. data/lib/badline/snapshot/vice/restore.rb +1 -1
  333. data/lib/badline/snapshot/vice/reu1764.rb +3 -3
  334. data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
  335. data/lib/badline/snapshot/vice.rb +13 -35
  336. data/lib/badline/snapshot.rb +44 -22
  337. data/lib/badline/storage/crt_file.rb +3 -1
  338. data/lib/badline/storage/d64_image.rb +0 -2
  339. data/lib/badline/storage/d71_image.rb +0 -2
  340. data/lib/badline/storage/d81_image.rb +0 -2
  341. data/lib/badline/storage/disk_image.rb +3 -6
  342. data/lib/badline/storage/g64_image.rb +10 -5
  343. data/lib/badline/storage/host_directory.rb +0 -5
  344. data/lib/badline/storage/t64.rb +2 -8
  345. data/lib/badline/storage/tap.rb +43 -15
  346. data/lib/badline/storage/unavailable.rb +1 -1
  347. data/lib/badline/storage.rb +0 -37
  348. data/lib/badline/support/c128_checkpoint.rb +39 -0
  349. data/lib/badline/support/checkpoint.rb +108 -0
  350. data/lib/badline/support/vic20_checkpoint.rb +38 -0
  351. data/lib/badline/support.rb +5 -0
  352. data/lib/badline/version.rb +1 -1
  353. data/lib/badline/vic20/attachments.rb +8 -5
  354. data/lib/badline/vic20/bus/keyed_state.rb +52 -0
  355. data/lib/badline/vic20/bus.rb +2 -25
  356. data/lib/badline/vic20/cpu.rb +1 -1
  357. data/lib/badline/vic20/keyed_modules.rb +73 -0
  358. data/lib/badline/vic20/keyed_state.rb +45 -0
  359. data/lib/badline/vic20/port_wiring.rb +4 -4
  360. data/lib/badline/vic20/user_via_ports.rb +2 -2
  361. data/lib/badline/vic20.rb +22 -17
  362. data/lib/badline.rb +1 -0
  363. metadata +271 -228
  364. data/lib/badline/address_bus/extra_sids.rb +0 -30
  365. data/lib/badline/address_bus/fittings.rb +0 -38
  366. data/lib/badline/address_bus/pla.rb +0 -147
  367. data/lib/badline/address_bus/roms.rb +0 -39
  368. data/lib/badline/address_bus/saved_state.rb +0 -66
  369. data/lib/badline/address_bus/sid_slots.rb +0 -42
  370. data/lib/badline/address_bus.rb +0 -216
  371. data/lib/badline/c128/bus_state.rb +0 -53
  372. data/lib/badline/c128/saved_state.rb +0 -143
  373. data/lib/badline/cartridge/action_replay.rb +0 -126
  374. data/lib/badline/cartridge/atomic_power.rb +0 -24
  375. data/lib/badline/cartridge/bank.rb +0 -81
  376. data/lib/badline/cartridge/comal80.rb +0 -50
  377. data/lib/badline/cartridge/dinamic.rb +0 -34
  378. data/lib/badline/cartridge/easy_flash.rb +0 -145
  379. data/lib/badline/cartridge/epyx_fastload.rb +0 -79
  380. data/lib/badline/cartridge/final_cartridge3.rb +0 -89
  381. data/lib/badline/cartridge/flash.rb +0 -306
  382. data/lib/badline/cartridge/freezer.rb +0 -33
  383. data/lib/badline/cartridge/fun_play.rb +0 -38
  384. data/lib/badline/cartridge/g_mod2.rb +0 -74
  385. data/lib/badline/cartridge/game_system.rb +0 -40
  386. data/lib/badline/cartridge/geo_ram.rb +0 -79
  387. data/lib/badline/cartridge/kcs_power.rb +0 -75
  388. data/lib/badline/cartridge/mach5.rb +0 -32
  389. data/lib/badline/cartridge/magic_desk.rb +0 -30
  390. data/lib/badline/cartridge/ocean.rb +0 -35
  391. data/lib/badline/cartridge/pagefox.rb +0 -68
  392. data/lib/badline/cartridge/retro_replay.rb +0 -320
  393. data/lib/badline/cartridge/rex_utility.rb +0 -29
  394. data/lib/badline/cartridge/rgcd.rb +0 -58
  395. data/lib/badline/cartridge/simons_basic.rb +0 -35
  396. data/lib/badline/cartridge/standard.rb +0 -15
  397. data/lib/badline/cartridge/super_games.rb +0 -48
  398. data/lib/badline/cartridge/westermann.rb +0 -30
  399. data/lib/badline/cartridge/zaxxon.rb +0 -66
  400. data/lib/badline/cartridge.rb +0 -303
  401. data/lib/badline/checkpoint.rb +0 -98
  402. data/lib/badline/chrout_trap.rb +0 -43
  403. data/lib/badline/cia/fast_forward.rb +0 -60
  404. data/lib/badline/cia/interrupt_register.rb +0 -143
  405. data/lib/badline/cia/serial.rb +0 -275
  406. data/lib/badline/cia/state.rb +0 -47
  407. data/lib/badline/cia/timer.rb +0 -206
  408. data/lib/badline/cia.rb +0 -279
  409. data/lib/badline/color_memory.rb +0 -25
  410. data/lib/badline/computer/attachments.rb +0 -88
  411. data/lib/badline/computer/saved_state.rb +0 -117
  412. data/lib/badline/computer/true_drives.rb +0 -69
  413. data/lib/badline/control_ports.rb +0 -76
  414. data/lib/badline/cpu/addressing.rb +0 -131
  415. data/lib/badline/cpu/boundary.rb +0 -54
  416. data/lib/badline/cpu/core.rb +0 -165
  417. data/lib/badline/cpu/microcode.rb +0 -177
  418. data/lib/badline/cpu/operations.rb +0 -88
  419. data/lib/badline/cpu/saved_state.rb +0 -115
  420. data/lib/badline/cpu/stack_operations.rb +0 -82
  421. data/lib/badline/cpu.rb +0 -10
  422. data/lib/badline/cpu_port.rb +0 -112
  423. data/lib/badline/datasette.rb +0 -161
  424. data/lib/badline/debug_register.rb +0 -28
  425. data/lib/badline/drive/core.rb +0 -147
  426. data/lib/badline/drive/fast_serial.rb +0 -73
  427. data/lib/badline/drive/idle.rb +0 -125
  428. data/lib/badline/drive/idle_cpu.rb +0 -28
  429. data/lib/badline/drive/orbit.rb +0 -79
  430. data/lib/badline/drive/serial_lines.rb +0 -73
  431. data/lib/badline/drive/sleep.rb +0 -112
  432. data/lib/badline/drive/vias.rb +0 -84
  433. data/lib/badline/drive/watch.rb +0 -150
  434. data/lib/badline/drive.rb +0 -11
  435. data/lib/badline/drive1541/bus.rb +0 -86
  436. data/lib/badline/drive1541/byte_ready.rb +0 -48
  437. data/lib/badline/drive1541/cpu.rb +0 -11
  438. data/lib/badline/drive1541/disk.rb +0 -315
  439. data/lib/badline/drive1541/disk_state.rb +0 -86
  440. data/lib/badline/drive1541/disk_via.rb +0 -36
  441. data/lib/badline/drive1541/gcr.rb +0 -57
  442. data/lib/badline/drive1541/mechanism.rb +0 -313
  443. data/lib/badline/drive1541/mechanism_state.rb +0 -68
  444. data/lib/badline/drive1541/rotation.rb +0 -121
  445. data/lib/badline/drive1541/sector_reader.rb +0 -76
  446. data/lib/badline/drive1541/serial_port.rb +0 -18
  447. data/lib/badline/drive1541/track.rb +0 -98
  448. data/lib/badline/drive1541.rb +0 -111
  449. data/lib/badline/drive1571/bus.rb +0 -111
  450. data/lib/badline/drive1571/cpu.rb +0 -11
  451. data/lib/badline/drive1571/serial_port.rb +0 -37
  452. data/lib/badline/drive1571/serial_via.rb +0 -25
  453. data/lib/badline/drive1571/wd1770.rb +0 -120
  454. data/lib/badline/drive1571.rb +0 -175
  455. data/lib/badline/drive1581/bus.rb +0 -137
  456. data/lib/badline/drive1581/cpu.rb +0 -11
  457. data/lib/badline/drive1581/disk.rb +0 -135
  458. data/lib/badline/drive1581/disk_state.rb +0 -87
  459. data/lib/badline/drive1581/mechanism.rb +0 -117
  460. data/lib/badline/drive1581/serial_port.rb +0 -52
  461. data/lib/badline/drive1581/slot.rb +0 -78
  462. data/lib/badline/drive1581/track.rb +0 -100
  463. data/lib/badline/drive1581/track_bytes.rb +0 -75
  464. data/lib/badline/drive1581/wd1772/registers.rb +0 -89
  465. data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
  466. data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
  467. data/lib/badline/drive1581/wd1772/state.rb +0 -66
  468. data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
  469. data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
  470. data/lib/badline/drive1581/wd1772/turn.rb +0 -73
  471. data/lib/badline/drive1581/wd1772.rb +0 -216
  472. data/lib/badline/drive1581.rb +0 -233
  473. data/lib/badline/iec_bus.rb +0 -159
  474. data/lib/badline/instruction.rb +0 -334
  475. data/lib/badline/instruction_set/arithmetic.rb +0 -114
  476. data/lib/badline/instruction_set/bitwise.rb +0 -126
  477. data/lib/badline/instruction_set/branch.rb +0 -79
  478. data/lib/badline/instruction_set/flag.rb +0 -63
  479. data/lib/badline/instruction_set/illegal.rb +0 -270
  480. data/lib/badline/instruction_set/inc_dec.rb +0 -69
  481. data/lib/badline/instruction_set/stack.rb +0 -52
  482. data/lib/badline/instruction_set/transfer.rb +0 -137
  483. data/lib/badline/instruction_set.rb +0 -55
  484. data/lib/badline/interrupts.rb +0 -104
  485. data/lib/badline/joystick.rb +0 -25
  486. data/lib/badline/kernal_trap/channel.rb +0 -181
  487. data/lib/badline/keyboard.rb +0 -112
  488. data/lib/badline/keyboard_buffer.rb +0 -33
  489. data/lib/badline/ram_expansion/banking.rb +0 -30
  490. data/lib/badline/ram_expansion/plus256k.rb +0 -54
  491. data/lib/badline/ram_expansion/plus60k.rb +0 -43
  492. data/lib/badline/ram_expansion/unexpanded.rb +0 -28
  493. data/lib/badline/ram_expansion.rb +0 -21
  494. data/lib/badline/reu/dma/saved_state.rb +0 -50
  495. data/lib/badline/reu/dma.rb +0 -273
  496. data/lib/badline/reu/ram.rb +0 -107
  497. data/lib/badline/reu/saved_state.rb +0 -80
  498. data/lib/badline/reu/trigger.rb +0 -32
  499. data/lib/badline/reu.rb +0 -289
  500. data/lib/badline/sid/catch_up.rb +0 -120
  501. data/lib/badline/sid/decimator.rb +0 -64
  502. data/lib/badline/sid/envelope/state.rb +0 -68
  503. data/lib/badline/sid/envelope.rb +0 -239
  504. data/lib/badline/sid/filter.rb +0 -263
  505. data/lib/badline/sid/voice.rb +0 -77
  506. data/lib/badline/sid/waveform/combined.rb +0 -126
  507. data/lib/badline/sid/waveform/fast_forward.rb +0 -105
  508. data/lib/badline/sid/waveform/noise_writeback.rb +0 -122
  509. data/lib/badline/sid/waveform/state.rb +0 -66
  510. data/lib/badline/sid/waveform.rb +0 -305
  511. data/lib/badline/sid.rb +0 -303
  512. data/lib/badline/snapshot/setup.rb +0 -75
  513. data/lib/badline/snapshot/state.rb +0 -189
  514. data/lib/badline/time_of_day.rb +0 -228
  515. data/lib/badline/traps.rb +0 -19
  516. data/lib/badline/via/control_lines.rb +0 -122
  517. data/lib/badline/via/fast_forward.rb +0 -53
  518. data/lib/badline/via/interrupt_register.rb +0 -67
  519. data/lib/badline/via/shift_register.rb +0 -180
  520. data/lib/badline/via/state.rb +0 -42
  521. data/lib/badline/via/timer1.rb +0 -131
  522. data/lib/badline/via/timer2.rb +0 -133
  523. data/lib/badline/via.rb +0 -266
  524. data/lib/badline/vic/bank.rb +0 -133
  525. data/lib/badline/vic/border_mask.rb +0 -86
  526. data/lib/badline/vic/collisions.rb +0 -115
  527. data/lib/badline/vic/color_patches.rb +0 -47
  528. data/lib/badline/vic/display_state.rb +0 -185
  529. data/lib/badline/vic/graphics_mode.rb +0 -164
  530. data/lib/badline/vic/graphics_shifter.rb +0 -207
  531. data/lib/badline/vic/register_log.rb +0 -81
  532. data/lib/badline/vic/registers.rb +0 -195
  533. data/lib/badline/vic/sequencer.rb +0 -275
  534. data/lib/badline/vic/sequencer_output.rb +0 -116
  535. data/lib/badline/vic/sequencer_state.rb +0 -89
  536. data/lib/badline/vic/sprite/internal_bus.rb +0 -68
  537. data/lib/badline/vic/sprite/saved_state.rb +0 -64
  538. data/lib/badline/vic/sprite/shifter.rb +0 -146
  539. data/lib/badline/vic/sprite/timing.rb +0 -56
  540. data/lib/badline/vic/sprite.rb +0 -337
  541. data/lib/badline/vic/sprites.rb +0 -282
  542. data/lib/badline/vic/sprites_state.rb +0 -57
  543. data/lib/badline/vic.rb +0 -853
  544. data/lib/badline/vic20/saved_state.rb +0 -124
  545. data/lib/badline/vic20/sound/output.rb +0 -83
  546. data/lib/badline/vic20/sound.rb +0 -233
  547. data/lib/badline/vic20/vic/saved_state.rb +0 -55
  548. data/lib/badline/z80/arithmetic.rb +0 -117
  549. data/lib/badline/z80/bit_page.rb +0 -55
  550. data/lib/badline/z80/block_io.rb +0 -58
  551. data/lib/badline/z80/block_transfers.rb +0 -59
  552. data/lib/badline/z80/bus_cycles.rb +0 -111
  553. data/lib/badline/z80/core.rb +0 -113
  554. data/lib/badline/z80/exchanges.rb +0 -50
  555. data/lib/badline/z80/extended_page.rb +0 -89
  556. data/lib/badline/z80/flags.rb +0 -37
  557. data/lib/badline/z80/interrupt_acceptance.rb +0 -46
  558. data/lib/badline/z80/jumps.rb +0 -82
  559. data/lib/badline/z80/loads.rb +0 -98
  560. data/lib/badline/z80/main_page.rb +0 -134
  561. data/lib/badline/z80/registers.rb +0 -120
  562. data/lib/badline/z80/saved_state.rb +0 -69
  563. data/lib/badline/z80/shifts.rb +0 -64
  564. data/lib/badline/z80.rb +0 -11
  565. /data/lib/badline/snapshot/{fields.rb → vice/fields.rb} +0 -0
@@ -1,228 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class TimeOfDay
5
- # The TOD pin is fed from the AC supply. A CIA passes its region's
6
- # clock and mains frequency, and these are PAL's.
7
- CLOCK_HZ = Region::PAL.clock_hz
8
- MAINS_HZ = Region::PAL.mains_hz
9
-
10
- FIELDS = %i[tenths seconds minutes hours].freeze
11
-
12
- def initialize(clock_hz: CLOCK_HZ, mains_hz: MAINS_HZ)
13
- # The accumulator advances mains_hz per cycle, so a TOD pin pulse has
14
- # arrived when it reaches clock_hz. Integer math keeps it exact.
15
- @cycles_per_pulse = clock_hz
16
- @mains_hz = mains_hz
17
- @accumulator = 0
18
- @pulses = 0
19
- @clock = { tenths: 0x00, seconds: 0x00, minutes: 0x00, hours: 0x01 }
20
- @alarm = { tenths: 0x00, seconds: 0x00, minutes: 0x00, hours: 0x00 }
21
- @latch = nil
22
- @stopped = true
23
- @alarm_pending = false
24
- self.fifty_hz = false
25
- end
26
-
27
- # CRA bit 7 divides the TOD pin by 5 instead of 6. The divider has to
28
- # match the pin frequency to keep time, so PAL software selects 50 Hz.
29
- def fifty_hz=(enabled)
30
- @match = enabled ? 4 : 5
31
- end
32
-
33
- # The clock and the alarm, field by field in FIELDS order, the latch,
34
- # and the divider's phase.
35
- def save_state(out)
36
- out.int(@accumulator).int(@pulses).int(@match).boolean(@stopped).boolean(@alarm_pending)
37
- FIELDS.each { |field| out.int(@clock[field]).int(@alarm[field]) }
38
- out.boolean(!@latch.nil?)
39
- FIELDS.each { |field| out.int(@latch[field]) } if @latch
40
- end
41
-
42
- def load_state(input)
43
- @accumulator = input.int
44
- @pulses = input.int
45
- @match = input.int
46
- @stopped = input.boolean?
47
- @alarm_pending = input.boolean?
48
- FIELDS.each do |field|
49
- @clock[field] = input.int
50
- @alarm[field] = input.int
51
- end
52
- @latch = input.boolean? ? FIELDS.to_h { |field| [field, input.int] } : nil
53
- end
54
-
55
- # Whether the clock is stopped, or gets no pulses on its pin, with no
56
- # alarm to raise, so its cycles move only the divider's phase.
57
- def quiet? = (@stopped || @mains_hz.zero?) && !@alarm_pending
58
-
59
- # Runs +cycles+ quiet cycles at once.
60
- def fast_forward(cycles)
61
- @accumulator = (@accumulator + (cycles * @mains_hz)) % @cycles_per_pulse
62
- end
63
-
64
- def cycle!
65
- @accumulator += @mains_hz
66
- pulse! if @accumulator >= @cycles_per_pulse
67
- return unless @alarm_pending
68
-
69
- @alarm_pending = false
70
- yield if block_given?
71
- end
72
-
73
- def tenths
74
- value = (@latch || @clock)[:tenths]
75
- @latch = nil
76
- value
77
- end
78
-
79
- def seconds = (@latch || @clock)[:seconds]
80
- def minutes = (@latch || @clock)[:minutes]
81
-
82
- def hours
83
- @latch ||= @clock.dup
84
- @latch[:hours]
85
- end
86
-
87
- attr_reader :pulses
88
-
89
- # The clock as a read of the tenths would see it: the latch while the
90
- # clock is latched. In FIELDS order.
91
- def latched_fields = FIELDS.map { |field| (@latch || @clock)[field] }
92
-
93
- # The cycles until the clock next steps a tenth, as VICE counts them.
94
- def cycles_to_tenth
95
- to_pulse = (@cycles_per_pulse - @accumulator + @mains_hz - 1) / @mains_hz
96
- to_pulse + ([@match - @pulses, 0].max * @cycles_per_pulse / @mains_hz)
97
- end
98
-
99
- # Sets the clock, the alarm and the latch from VICE's fields, in FIELDS
100
- # order, the latch nil while unlatched.
101
- def restore_fields(clock, alarm, latch)
102
- FIELDS.each_with_index do |field, i|
103
- @clock[field] = clock[i]
104
- @alarm[field] = alarm[i]
105
- end
106
- @latch = latch && FIELDS.each_with_index.to_h { |field, i| [field, latch[i]] }
107
- end
108
-
109
- # Sets whether the clock is stopped, the pulses counted towards the
110
- # next tenth and the cycles until it, placing the divider so the tenth
111
- # lands then.
112
- def restore_divider(stopped, pulses, cycles_to_tenth)
113
- @stopped = stopped
114
- @pulses = pulses
115
- to_pulse = cycles_to_tenth - ([@match - pulses, 0].max * @cycles_per_pulse / @mains_hz)
116
- @accumulator = (@cycles_per_pulse - (to_pulse * @mains_hz)).clamp(0, @cycles_per_pulse - 1)
117
- end
118
-
119
- # The clock and alarm as stored, read without latching the clock.
120
- def registers
121
- [@clock[:tenths], @clock[:seconds], @clock[:minutes], @clock[:hours],
122
- @alarm[:tenths], @alarm[:seconds], @alarm[:minutes], @alarm[:hours],
123
- @stopped ? 1 : 0, @latch ? 1 : 0]
124
- end
125
-
126
- def write(field, value, alarm:)
127
- # The frequency counter is held clear while the clock is stopped, and
128
- # starts counting again from the write to tenths that restarts it.
129
- if field == :tenths && !alarm && @stopped
130
- @pulses = 0
131
- @stopped = false
132
- end
133
- store(field, value & (field == :tenths ? 0x0f : 0x7f), alarm: alarm)
134
- end
135
-
136
- # 12-hour BCD value, bit 7 is the AM/PM flag.
137
- def write_hours(value, alarm:)
138
- value &= 0x9f
139
- # Writing 12 to the hour register flips the AM/PM bit, the same way a
140
- # carry into 12 does. Writing the alarm hours does not.
141
- value ^= 0x80 if !alarm && (value & 0x1f) == 0x12
142
- # Halt the clock when writing hours, so that it doesn't
143
- # advance mid-update.
144
- @stopped = true unless alarm
145
- store(:hours, value, alarm: alarm)
146
- end
147
-
148
- private
149
-
150
- def store(field, value, alarm:)
151
- target = alarm ? @alarm : @clock
152
- return if target[field] == value
153
-
154
- target[field] = value
155
- @alarm_pending = true if alarm?
156
- end
157
-
158
- def pulse!
159
- @accumulator -= @cycles_per_pulse
160
- return if @stopped
161
-
162
- # A three-bit ring counter with six states, compared against the
163
- # divider on each pin pulse rather than on its way past it.
164
- if @pulses == @match
165
- @pulses = 0
166
- advance
167
- else
168
- @pulses += 1
169
- @pulses = 0 if @pulses > 5
170
- end
171
- end
172
-
173
- def advance
174
- tenths = (@clock[:tenths] + 1) & 0x0f
175
- @clock[:tenths] = tenths == 10 ? 0 : tenths
176
- carry_seconds if tenths == 10
177
- @alarm_pending = true if alarm?
178
- end
179
-
180
- def carry_seconds
181
- return unless advance_pair(:seconds)
182
- return unless advance_pair(:minutes)
183
-
184
- advance_hours
185
- end
186
-
187
- # Seconds and minutes hold a four-bit low digit that carries at ten into
188
- # a three-bit high digit that carries out at six. Both are plain binary
189
- # counters, so out-of-range BCD counts up from where it was written.
190
- def advance_pair(field)
191
- low = ((@clock[field] & 0x0f) + 1) & 0x0f
192
- high = (@clock[field] >> 4) & 0x07
193
- carry = false
194
-
195
- if low == 10
196
- low = 0
197
- high = (high + 1) & 0x07
198
- if high == 6
199
- high = 0
200
- carry = true
201
- end
202
- end
203
-
204
- @clock[field] = (high << 4) | low
205
- carry
206
- end
207
-
208
- # The hour runs 9 -> 10 and 12 -> 1 by swapping its two digits, and the
209
- # AM/PM bit flips as it passes through 12.
210
- def advance_hours
211
- pm = @clock[:hours] & 0x80
212
- high = (@clock[:hours] >> 4) & 0x01
213
- low = @clock[:hours] & 0x0f
214
-
215
- if (high == 1 && low == 2) || (high.zero? && low == 9)
216
- low = high
217
- high ^= 1
218
- else
219
- low = (low + 1) & 0x0f
220
- pm ^= 0x80 if high == 1 && low == 2
221
- end
222
-
223
- @clock[:hours] = pm | (high << 4) | low
224
- end
225
-
226
- def alarm? = @clock == @alarm
227
- end
228
- end
data/lib/badline/traps.rb DELETED
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- module Traps
5
- def install_trap(addr, &handler)
6
- (@traps ||= {})[addr] = handler
7
- end
8
-
9
- def remove_trap(addr)
10
- @traps&.delete(addr)
11
- end
12
-
13
- private
14
-
15
- def run_traps
16
- @traps[@program_counter]&.call if @traps
17
- end
18
- end
19
- end
@@ -1,122 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class VIA
5
- # One port's pair of control lines, CA1 and CA2 or CB1 and CB2, set up
6
- # by a nibble of the peripheral control register, and their two
7
- # interrupt flags. Bit 0 picks the active edge of C1, rising when set.
8
- # Bits 3-1 pick the C2 mode:
9
- #
10
- # 000 input, falling edge 100 handshake output
11
- # 001 independent, falling 101 pulse output
12
- # 010 input, rising edge 110 low output
13
- # 011 independent, rising 111 high output
14
- #
15
- # A port access clears both flags, but an independent input keeps C2's.
16
- # In handshake mode C2 goes low on a port access and back high on the
17
- # next active C1 edge. In pulse mode it goes low for the cycle after the
18
- # access. Port A handshakes on reads and writes, port B on writes only.
19
- class ControlLines
20
- attr_reader :control, :c1_high, :c2_high
21
-
22
- # The level driven on C2, high while it is an input.
23
- attr_reader :c2_output
24
-
25
- def initialize(interrupts, c1_flag:, c2_flag:, handshake_on_read:)
26
- @interrupts = interrupts
27
- @c1_flag = c1_flag
28
- @c2_flag = c2_flag
29
- @handshake_on_read = handshake_on_read
30
- @c1_high = @c2_high = true
31
- reset!
32
- end
33
-
34
- # Back to input mode with both handshake outputs released. The input
35
- # levels carry over.
36
- def reset!
37
- @control = 0
38
- @handshake_low = false
39
- @pulse = 0
40
- drive
41
- end
42
-
43
- def control=(nibble)
44
- @control = nibble & 0x0f
45
- drive
46
- end
47
-
48
- # Only the pulse output needs the clock.
49
- def pulsing? = @pulse.positive?
50
-
51
- def cycle!
52
- @pulse -= 1
53
- drive if @pulse.zero?
54
- end
55
-
56
- def active_c1_edge?(high) = high == @control.anybits?(0x01)
57
-
58
- # The lines' levels and mode. Which flags they set, and whether reads
59
- # handshake, are the port's wiring.
60
- def save_state(out)
61
- out.int(@control).boolean(@c1_high).boolean(@c2_high).boolean(@handshake_low).int(@pulse).boolean(@c2_output)
62
- end
63
-
64
- def load_state(input)
65
- @control = input.int
66
- @c1_high = input.boolean?
67
- @c2_high = input.boolean?
68
- @handshake_low = input.boolean?
69
- @pulse = input.int
70
- @c2_output = input.boolean?
71
- end
72
-
73
- # Everything the lines hold, for comparing them at two points.
74
- def state = [@control, @c1_high, @c2_high, @handshake_low, @pulse, @c2_output]
75
-
76
- # A new C1 level. An active edge sets the flag and ends a handshake.
77
- def c1=(high)
78
- return if high == @c1_high
79
-
80
- @c1_high = high
81
- return unless active_c1_edge?(high)
82
-
83
- @handshake_low = false
84
- drive
85
- @interrupts.set(@c1_flag)
86
- end
87
-
88
- # A new C2 level. An active edge sets the flag while C2 is an input.
89
- def c2=(high)
90
- return if high == @c2_high
91
-
92
- @c2_high = high
93
- @interrupts.set(@c2_flag) if @control.nobits?(0x08) && high == @control.anybits?(0x04)
94
- end
95
-
96
- # A read or write of the handshaking port register.
97
- def access!(write)
98
- @interrupts.clear(independent? ? @c1_flag : @c1_flag | @c2_flag)
99
- return unless write || @handshake_on_read
100
-
101
- case @control >> 1
102
- when 4 then @handshake_low = true
103
- when 5 then @pulse = 2
104
- end
105
- drive
106
- end
107
-
108
- private
109
-
110
- def independent? = @control & 0x0a == 0x02
111
-
112
- def drive
113
- @c2_output = case @control >> 1
114
- when 4 then !@handshake_low
115
- when 5 then @pulse.zero?
116
- when 6 then false
117
- else true
118
- end
119
- end
120
- end
121
- end
122
- end
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class VIA
5
- # Running a VIA a stretch of cycles at once while nothing but its
6
- # counters would change, for Drive::Idle.
7
- module FastForward
8
- # quiet_cycles for a VIA that will never set a flag of its own.
9
- QUIET = 1 << 40
10
-
11
- # How many cycles the VIA can run with nothing but its counters
12
- # changing: no flag set, no pulse on a control line and no bit
13
- # shifted. See Drive::Idle.
14
- def quiet_cycles
15
- return 0 if @sr_uses_t2 || @shift_register.clocking? || @ca.pulsing? || @cb.pulsing?
16
-
17
- [@t1.quiet_cycles, @t2.quiet_cycles].min
18
- end
19
-
20
- # Runs +cycles+ cycles at once, as many as quiet_cycles allows, which
21
- # moves only the counters.
22
- def fast_forward(cycles)
23
- return if cycles.zero?
24
-
25
- @t1.fast_forward(cycles)
26
- @t2.fast_forward(cycles)
27
- end
28
-
29
- # The counters an orbit (see Drive::Idle) has to bring back: those
30
- # of the armed timers, and of the timers +touched+ names (bit 0 for
31
- # timer 1, bit 1 for timer 2). The others only count.
32
- def counter_state(touched)
33
- [(@t1.count_state if @t1.armed? || touched.anybits?(1)),
34
- (@t2.count_state if @t2.armed? || touched.anybits?(2))]
35
- end
36
-
37
- # Runs +cycles+ cycles of whole orbits at once: the counters
38
- # counter_state leaves out move on, and the rest come back round.
39
- def skip_orbits(cycles, touched)
40
- @t1.fast_forward(cycles) unless @t1.armed? || touched.anybits?(1)
41
- @t2.fast_forward(cycles) unless @t2.armed? || touched.anybits?(2)
42
- end
43
-
44
- # Everything the VIA holds but its counters, for comparing it at two
45
- # points. Timer 1's PB7 level counts only while ACR bit 7 puts it on
46
- # the pin: nothing reads it otherwise.
47
- def idle_state
48
- [@ora, @orb, @ddra, @ddrb, @latch_a, @latch_b, @acr, @pcr, @pb6_high, @ifr.flags, @ifr.enable,
49
- @acr.anybits?(0x80) && @t1.pb7, *@t1.state, *@t2.state, *@ca.state, *@cb.state, *@shift_register.state]
50
- end
51
- end
52
- end
53
- end
@@ -1,67 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class VIA
5
- # The interrupt flag and enable registers. Each source has a flag bit,
6
- # and IRQ is pulled low while any flag is set with its enable bit.
7
- class InterruptRegister
8
- CA2 = 0x01
9
- CA1 = 0x02
10
- SR = 0x04
11
- CB2 = 0x08
12
- CB1 = 0x10
13
- TIMER2 = 0x20
14
- TIMER1 = 0x40
15
-
16
- attr_reader :flags, :enable
17
-
18
- def initialize
19
- reset!
20
- end
21
-
22
- def reset!
23
- @flags = 0x00
24
- @enable = 0x00
25
- end
26
-
27
- def save_state(out)
28
- out.int(@flags).int(@enable)
29
- end
30
-
31
- def load_state(input)
32
- @flags = input.int
33
- @enable = input.int
34
- end
35
-
36
- def set(bits)
37
- @flags |= bits
38
- end
39
-
40
- def clear(bits)
41
- @flags &= ~bits
42
- end
43
-
44
- def irq? = @flags.anybits?(@enable)
45
-
46
- # Bit 7 reads the IRQ output.
47
- def read = irq? ? @flags | 0x80 : @flags
48
-
49
- # Writing 1s clears the flags; bit 7 is ignored.
50
- def write(value)
51
- clear(value & 0x7f)
52
- end
53
-
54
- # Bit 7 reads as 1.
55
- def read_enable = @enable | 0x80
56
-
57
- # Bit 7 picks between setting and clearing the enable bits given.
58
- def write_enable(value)
59
- if value.anybits?(0x80)
60
- @enable |= value & 0x7f
61
- else
62
- @enable &= ~value & 0x7f
63
- end
64
- end
65
- end
66
- end
67
- end
@@ -1,180 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class VIA
5
- # The 6522's shift register, with the CB1 clock and CB2 data lines it
6
- # takes over in every mode but the first.
7
- #
8
- # ACR bits 4-2 pick the mode. Modes 1 to 3 shift in, left, with the new
9
- # bit taken from CB2 into bit 0 on each rising CB1 edge. Modes 4 to 7
10
- # shift out: each falling CB1 edge puts bit 7 on CB2 and rotates it back
11
- # round into bit 0, so after eight bits the byte is back where it
12
- # started. Modes 1, 4 and 5 clock off timer 2, modes 2 and 6 off φ2, and
13
- # modes 3 and 7 off whatever drives CB1 from outside.
14
- #
15
- # Under its own clock the register drives CB1, idling high. Reading or
16
- # writing the data register starts a byte, but only while the register
17
- # is idle and enabled: an access in mode 0, or one before the eighth bit
18
- # is in, leaves the count alone. CB1 falls on the first clock tick of
19
- # the byte and rises on the second, and so on, so a byte is eight pulses
20
- # over sixteen ticks. The interrupt flag is set on the tick that raises
21
- # CB1 over the eighth bit, and CB1 then stays high until the next
22
- # access.
23
- #
24
- # In modes 2 and 6 a tick is a φ2 cycle, from the second cycle after
25
- # the access on, which makes a byte sixteen cycles. In modes 1, 4 and 5
26
- # it comes two cycles after each timer 2 low byte underflow, on the
27
- # cycle after the low byte reloads, which makes a byte sixteen
28
- # underflows. Mode 4 never stops and never interrupts: its counter is
29
- # disabled, and the byte goes round and round.
30
- #
31
- # Under an external clock the register shifts on every CB1 edge, access
32
- # or not. The access only arms the counter: the flag is set on the eighth
33
- # rising edge after it, and the counter then waits for the next access.
34
- class ShiftRegister
35
- DISABLED = 0
36
- IN_T2 = 1
37
- IN_PHI2 = 2
38
- IN_EXTERNAL = 3
39
- OUT_FREE_RUNNING = 4
40
- OUT_T2 = 5
41
- OUT_PHI2 = 6
42
- OUT_EXTERNAL = 7
43
-
44
- attr_reader :mode, :data
45
- attr_accessor :cb2_input
46
-
47
- def initialize
48
- @mode = DISABLED
49
- @data = 0x00
50
- # Bits still to count before the flag, zero when the counter is idle.
51
- @bits = 0
52
- # The clock's last two cycles, newest in bit 0: timer 2 low byte
53
- # underflows in modes 1, 4 and 5, and whether the byte has started
54
- # in modes 2 and 6.
55
- @delay = 0
56
- @clock = true
57
- @cb2 = true
58
- # Nothing drives CB2 from outside, so it floats high.
59
- @cb2_input = true
60
- end
61
-
62
- def mode=(value)
63
- @mode = value & 0x07
64
- end
65
-
66
- def data=(value)
67
- @data = value & 0xff
68
- end
69
-
70
- # A read or write of the data register, which starts a byte if the
71
- # register is idle and enabled.
72
- def access!
73
- return if @mode == DISABLED || @bits.nonzero?
74
-
75
- @bits = 8
76
- @delay = 0 if @mode == IN_PHI2 || @mode == OUT_PHI2
77
- end
78
-
79
- # Whether the register is counting bits off its own clock, which
80
- # changes it from cycle to cycle.
81
- def clocking? = @bits.nonzero? && internal_clock?
82
-
83
- def save_state(out)
84
- out.int(@mode).int(@data).int(@bits).int(@delay).boolean(@clock).boolean(@cb2).boolean(@cb2_input)
85
- end
86
-
87
- def load_state(input)
88
- @mode = input.int
89
- @data = input.int
90
- @bits = input.int
91
- @delay = input.schema > 4 ? input.int : 0
92
- @clock = input.boolean?
93
- @cb2 = input.boolean?
94
- @cb2_input = input.boolean?
95
- end
96
-
97
- # Everything the register holds, for comparing it at two points.
98
- def state = [@mode, @data, @bits, @delay, @clock, @cb2, @cb2_input]
99
-
100
- # The CB1 level the register drives, or nil when CB1 is an input.
101
- def cb1_output
102
- internal_clock? ? @clock : nil
103
- end
104
-
105
- # The CB2 level the register drives, or nil when it doesn't.
106
- def cb2_output
107
- @mode >= OUT_FREE_RUNNING ? @cb2 : nil
108
- end
109
-
110
- # Clocked once per φ2 cycle, with whether timer 2's low byte underflowed
111
- # on it. Returns true on the cycle that sets the interrupt flag.
112
- def cycle!(t2_low_underflow)
113
- case @mode
114
- when IN_PHI2, OUT_PHI2 then @bits.nonzero? && phi2_tick
115
- when IN_T2, OUT_T2, OUT_FREE_RUNNING then t2_tick(t2_low_underflow)
116
- else false
117
- end
118
- end
119
-
120
- # A level change on CB1 from outside. Only the external clock modes
121
- # listen: shifting in samples CB2 as CB1 rises, and shifting out puts
122
- # the next bit on CB2 as it falls. Returns true when the edge sets the
123
- # interrupt flag.
124
- def cb1_edge!(rising)
125
- return false unless @mode == IN_EXTERNAL || @mode == OUT_EXTERNAL
126
-
127
- shift_in if rising && @mode == IN_EXTERNAL
128
- shift_out if !rising && @mode == OUT_EXTERNAL
129
- rising && eighth_bit?
130
- end
131
-
132
- private
133
-
134
- def internal_clock?
135
- @mode != DISABLED && @mode != IN_EXTERNAL && @mode != OUT_EXTERNAL
136
- end
137
-
138
- # A φ2 cycle of a byte: every one but the first ticks.
139
- def phi2_tick
140
- started = @delay.nonzero?
141
- @delay = 1
142
- started && tick
143
- end
144
-
145
- # Ticks on the underflow from two cycles back, while a byte is under
146
- # way.
147
- def t2_tick(underflow)
148
- due = @delay.anybits?(2)
149
- @delay = ((@delay << 1) & 2) | (underflow ? 1 : 0)
150
- due && @bits.nonzero? && tick
151
- end
152
-
153
- # One half period of the register's own clock: a falling edge puts a
154
- # bit out, and a rising one takes a bit in and counts it.
155
- def tick
156
- @clock = !@clock
157
- shift_out if !@clock && @mode >= OUT_FREE_RUNNING
158
- shift_in if @clock && @mode < IN_EXTERNAL
159
- @clock && @mode != OUT_FREE_RUNNING && eighth_bit?
160
- end
161
-
162
- # Counts a bit, and says whether it was the eighth since the access.
163
- def eighth_bit?
164
- return false if @bits.zero?
165
-
166
- @bits -= 1
167
- @bits.zero?
168
- end
169
-
170
- def shift_in
171
- @data = ((@data << 1) | (@cb2_input ? 1 : 0)) & 0xff
172
- end
173
-
174
- def shift_out
175
- @cb2 = @data.anybits?(0x80)
176
- @data = ((@data << 1) | (@cb2 ? 1 : 0)) & 0xff
177
- end
178
- end
179
- end
180
- end