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,115 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class CPU
5
- # The CPU's state for a snapshot: the registers, the interrupt lines and
6
- # their pipeline, and the step of the instruction in flight, named by
7
- # where its plan comes from.
8
- module SavedState
9
- # Writes everything the CPU holds, down to the step of the instruction
10
- # it is in, for load_state to put back. The interrupt lines, BA stalls
11
- # and SO are state too; the traps and the debug flag belong to the host.
12
- def save_state(out)
13
- out.marker("CPU")
14
- out.int(@program_counter).int(@stack_pointer).int(@a).int(@x).int(@y).int(@status.value)
15
- [@irq, @nmi, @irq_sample, @irq_pending, @nmi_sample, @nmi_pending, @skip_poll, @boundary_irq,
16
- @boundary_nmi, @boundary_crossed, @brk, @pending_write, @so_high, @optional_dummy,
17
- @branch_taken].each { |flag| out.boolean(flag) }
18
- out.optional_int(@interrupt).optional_int(@stalled_at).int(@cycles).int(@instructions)
19
- out.int(plan_source).int(@index).int(OPERATIONS.index(@operation) || -1)
20
- [@address, @dummy_address, @value, @rmw_result, @pointer].each { |register| out.optional_int(register) }
21
- end
22
-
23
- def load_state(input)
24
- input.marker("CPU")
25
- @program_counter = input.int
26
- @stack_pointer = input.int
27
- @a = input.int
28
- @x = input.int
29
- @y = input.int
30
- @status.value = input.int
31
- load_flags(input)
32
- @interrupt = input.optional_int
33
- @stalled_at = input.optional_int
34
- @cycles = input.int
35
- @instructions = input.int
36
- load_plan(input.int)
37
- @index = input.int
38
- operation = input.int
39
- @operation = operation.negative? ? nil : OPERATIONS.fetch(operation)
40
- load_working_registers(input)
41
- end
42
-
43
- # Drops the instruction or interrupt sequence in flight and the
44
- # interrupt lines' pipeline, so the next cycle fetches an opcode at the
45
- # program counter, and sets the cycle count. A snapshot taken between
46
- # instructions, as VICE's are, restores through here.
47
- def resume(cycles)
48
- @irq_sample = @irq_pending = false
49
- @nmi_sample = @nmi_pending = false
50
- @skip_poll = false
51
- @interrupt = nil
52
- @brk = false
53
- @stalled_at = nil
54
- @cycles = cycles
55
- end_sequence
56
- @pending_write = false
57
- end
58
-
59
- private
60
-
61
- # Where the plan running comes from: an opcode's microcode, or FETCH,
62
- # INTERRUPT or JAMMED below it.
63
- def plan_source
64
- return FETCH if @plan.equal?(FETCH_PLAN)
65
- return INTERRUPT if @plan.equal?(INTERRUPT_PLAN)
66
- return JAMMED if @plan.equal?(JAMMED_PLAN)
67
-
68
- MICROCODE.index { |micro| micro.plan.equal?(@plan) && micro.operation == @operation } ||
69
- MICROCODE.index { |micro| micro.plan.equal?(@plan) }
70
- end
71
-
72
- def load_plan(source)
73
- case source
74
- when FETCH then use_plan(FETCH_PLAN, FETCH_WRITES)
75
- when INTERRUPT then use_plan(INTERRUPT_PLAN, INTERRUPT_WRITES)
76
- when JAMMED then use_plan(JAMMED_PLAN, JAMMED_WRITES)
77
- else
78
- micro = MICROCODE.fetch(source)
79
- use_plan(micro.plan, micro.writes)
80
- end
81
- end
82
-
83
- def use_plan(plan, writes)
84
- @plan = plan
85
- @writes = writes
86
- end
87
-
88
- def load_flags(input)
89
- @irq = input.boolean?
90
- @nmi = input.boolean?
91
- @irq_sample = input.boolean?
92
- @irq_pending = input.boolean?
93
- @nmi_sample = input.boolean?
94
- @nmi_pending = input.boolean?
95
- @skip_poll = input.boolean?
96
- @boundary_irq = input.boolean?
97
- @boundary_nmi = input.boolean?
98
- @boundary_crossed = input.boolean?
99
- @brk = input.boolean?
100
- @pending_write = input.boolean?
101
- @so_high = input.boolean?
102
- @optional_dummy = input.boolean?
103
- @branch_taken = input.boolean?
104
- end
105
-
106
- def load_working_registers(input)
107
- @address = input.optional_int
108
- @dummy_address = input.optional_int
109
- @value = input.optional_int
110
- @rmw_result = input.optional_int
111
- @pointer = input.optional_int
112
- end
113
- end
114
- end
115
- end
@@ -1,82 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class CPU
5
- # Steps that use the stack: PHA, PHP, PLA, PLP, JSR, RTS and RTI.
6
- module StackOperations
7
- private
8
-
9
- def op_push_exec
10
- send(@operation, nil, nil)
11
- end_instruction
12
- end
13
-
14
- def op_pull_dummy
15
- @memory.peek(stack_address)
16
- end
17
-
18
- def op_pull_exec
19
- send(@operation, nil, nil)
20
- end_instruction
21
- end
22
-
23
- def op_pull_low
24
- @stack_pointer = (@stack_pointer + 1) & 0xff
25
- @address = @memory.peek(stack_address)
26
- end
27
-
28
- def op_pull_high
29
- @stack_pointer = (@stack_pointer + 1) & 0xff
30
- @address |= @memory.peek(stack_address) << 8
31
- end
32
-
33
- def op_rts_fixup
34
- @memory.peek(@address)
35
- @program_counter = (@address + 1) & 0xffff
36
- end_instruction
37
- end
38
-
39
- def op_rti_pull_status
40
- @stack_pointer = (@stack_pointer + 1) & 0xff
41
- @status.value = @memory.peek(stack_address)
42
- @status.break = false
43
- end
44
-
45
- def op_rti_pull_high
46
- @stack_pointer = (@stack_pointer + 1) & 0xff
47
- @program_counter = @address | (@memory.peek(stack_address) << 8)
48
- end_instruction
49
- end
50
-
51
- def op_jsr_low
52
- @address = @memory.peek(@program_counter)
53
- @program_counter = (@program_counter + 2) & 0xffff
54
- end
55
-
56
- def op_jsr_dummy
57
- @memory.peek(stack_address)
58
- end
59
-
60
- def op_jsr_push_high
61
- @memory.poke(stack_address, high_byte(return_address))
62
- end
63
-
64
- def op_jsr_push_low
65
- @memory.poke(stack_address(-1), low_byte(return_address))
66
- @stack_pointer = (@stack_pointer - 2) & 0xff
67
- end
68
-
69
- # JSR reads its target's high byte after pushing the return address.
70
- # A JSR running from the stack page can overwrite its own operand
71
- # with that push, and then jumps to the overwritten address.
72
- def op_jsr_high
73
- @program_counter = @address | (@memory.peek(return_address) << 8)
74
- end_instruction
75
- end
76
-
77
- def return_address
78
- (@program_counter - 1) & 0xffff
79
- end
80
- end
81
- end
82
- end
data/lib/badline/cpu.rb DELETED
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "badline/cpu/core"
4
-
5
- module Badline
6
- # The C64's 6510, on the AddressBus.
7
- class CPU
8
- include Core
9
- end
10
- end
@@ -1,112 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- # The I/O port of the 6510 and the 8502 at $00 (direction) and $01
5
- # (data). An input pin reads its pull-up, P4 reads the datasette's sense
6
- # line, and a pin without a pull-up holds the charge last driven onto
7
- # it. P5 drives the datasette motor through an inverter: low runs it.
8
- #
9
- # The 6510 has pull-ups on P0-P2 and P4 and leaves P3, P6 and P7
10
- # floating. The 8502 adds a CAPS LOCK pin on P6, high while the key is
11
- # up.
12
- class CPUPort
13
- TAPE_SENSE = 0b0001_0000
14
-
15
- # The direction and output registers, and the charge on the floating
16
- # pins.
17
- attr_reader :ddr, :data, :floating
18
-
19
- # The port as the banking logic reads it (PortStatus).
20
- attr_reader :status
21
-
22
- # Whether CAPS LOCK is down, holding its pin low.
23
- attr_reader :caps_lock
24
-
25
- # +pullups+ and +floating+ are the masks of the pins with a pull-up and
26
- # of the floating ones, and +caps_lock+ the CAPS LOCK pin's, 0 where
27
- # there is none.
28
- def initialize(datasette, pullups:, floating:, caps_lock: 0)
29
- @datasette = datasette
30
- @pullups = pullups
31
- @floating_mask = floating
32
- @caps_lock_pin = caps_lock
33
- @caps_lock = false
34
- @ddr = 0x00
35
- @data = 0x00
36
- @floating = 0x00
37
- @change_handler = nil
38
- @status = PortStatus.new(%i[basic kernal io tape_out tape_switch tape_motor], value: input_value)
39
- end
40
-
41
- # Calls the block after every write to the port, for the bus to remap
42
- # its banks.
43
- def on_change(&handler)
44
- @change_handler = handler
45
- end
46
-
47
- # What a read of $01 sees.
48
- def value = @status.value
49
-
50
- def write_ddr(value)
51
- @ddr = value
52
- update
53
- end
54
-
55
- def write_data(value)
56
- @data = value
57
- update
58
- end
59
-
60
- # The RES line clears the direction and output registers. The floating
61
- # pins keep their charge.
62
- def reset!
63
- @ddr = 0x00
64
- @data = 0x00
65
- update
66
- end
67
-
68
- # Sets the registers and the charge, as a snapshot restores them, and
69
- # drives the motor and calls the change handler as a write does.
70
- def restore(ddr, data, floating)
71
- load(ddr, data, floating)
72
- update
73
- end
74
-
75
- # Sets the registers and the charge, as a snapshot loads them, without
76
- # driving the motor or calling the change handler.
77
- def load(ddr, data, floating)
78
- @ddr = ddr
79
- @data = data
80
- @floating = floating
81
- refresh
82
- end
83
-
84
- # Holds CAPS LOCK down, or lets it up.
85
- def caps_lock=(down)
86
- @caps_lock = down
87
- refresh
88
- end
89
-
90
- # Reads the inputs again, after the datasette's sense line changes.
91
- def refresh
92
- @status.value = input_value
93
- end
94
-
95
- private
96
-
97
- def update
98
- driven = @ddr & @floating_mask
99
- @floating = (@floating & ~driven) | (@data & driven)
100
- refresh
101
- @datasette.motor = !@status.tape_motor?
102
- @change_handler&.call
103
- end
104
-
105
- def input_value
106
- input = @pullups | (@floating & @floating_mask)
107
- input |= @caps_lock_pin unless @caps_lock
108
- input &= ~TAPE_SENSE if @datasette.sense_low?
109
- (@data & @ddr) | (input & ~@ddr & 0xff)
110
- end
111
- end
112
- end
@@ -1,161 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- # The 1530 datasette. Plays a pulse stream into CIA 1's FLAG pin while the
5
- # motor runs with a key pressed, and reports the keys through the cassette
6
- # sense line on the $01 port. With RECORD down too, it records the
7
- # machine's write line onto the tape instead.
8
- class Datasette
9
- # What inserting a tape raises on a machine without a cassette port.
10
- class Missing < ArgumentError; end
11
-
12
- attr_reader :tape
13
- attr_writer :motor
14
-
15
- def initialize(tape = nil)
16
- @tape = tape
17
- @connected = true
18
- @playing = false
19
- @recording = false
20
- @write_high = true
21
- @since = 0
22
- @motor = false
23
- @countdown = 0
24
- @flag_handler = nil
25
- @sense_handler = nil
26
- end
27
-
28
- # Falling edges on the tape read line.
29
- def on_flag(&handler)
30
- @flag_handler = handler
31
- end
32
-
33
- # The cassette sense line, which the $01 port reads back.
34
- def on_sense_change(&handler)
35
- @sense_handler = handler
36
- end
37
-
38
- # Whether the machine has a datasette at its cassette port. The SX-64
39
- # has none: its keys stay up and it takes no tape.
40
- def connected? = @connected
41
-
42
- def disconnect!
43
- eject
44
- @connected = false
45
- end
46
-
47
- def insert(tape)
48
- raise Missing, "this machine has no datasette" unless @connected
49
-
50
- @tape = tape
51
- rewind
52
- end
53
-
54
- def eject
55
- stop!
56
- @tape = nil
57
- end
58
-
59
- def rewind
60
- @tape&.rewind
61
- @countdown = 0
62
- end
63
-
64
- def play! = press(true)
65
- def stop! = press(false)
66
-
67
- # Presses RECORD and PLAY together.
68
- def record!
69
- return if !@connected || @tape.nil?
70
-
71
- press(true)
72
- @recording = true
73
- @since = 0
74
- end
75
-
76
- def recording? = @recording
77
-
78
- # The machine's tape write line. While the deck records with its motor
79
- # running, each rising edge ends a pulse on the tape, as long as the
80
- # time since the edge before, and plays back as a falling edge on the
81
- # read line.
82
- def write_line=(high)
83
- rose = high && !@write_high
84
- @write_high = high
85
- return unless rose && @recording && running?
86
-
87
- @tape.record_pulse(@since)
88
- @since = 0
89
- end
90
-
91
- def playing? = @playing
92
-
93
- # Sense reads low while a key is down on the deck.
94
- def sense_low? = @playing
95
-
96
- def motor? = @motor
97
-
98
- def running? = @playing && @motor && !@tape.nil?
99
-
100
- # The keys, the motor, the countdown to the next pulse and the tape:
101
- # its path, its bytes and how far it has played.
102
- def save_state(out)
103
- out.marker("DATASETTE")
104
- out.boolean(@playing).boolean(@motor).int(@countdown).boolean(!@tape.nil?)
105
- return unless @tape
106
-
107
- out.string(@tape.path).blob(@tape.bytes).int(@tape.position)
108
- end
109
-
110
- # The tape goes back in from the bytes the state holds, without its
111
- # host file, unless the tape in is the same one. The sense and flag
112
- # handlers don't fire.
113
- def load_state(input)
114
- input.marker("DATASETTE")
115
- @playing = input.boolean?
116
- @motor = input.boolean?
117
- @countdown = input.int
118
- return @tape = nil unless input.boolean?
119
-
120
- path = input.string
121
- bytes = input.blob
122
- position = input.int
123
- @tape = Storage::TAP.new(path, bytes:) unless @tape&.path&.b == path && @tape.bytes == bytes
124
- @tape.position = position
125
- end
126
-
127
- def cycle!
128
- return unless running?
129
- return @since += 1 if @recording
130
-
131
- @countdown = @tape.next_pulse.to_i if @countdown.zero?
132
- return if @countdown.zero?
133
-
134
- @countdown -= 1
135
- @flag_handler&.call if @countdown.zero?
136
- end
137
-
138
- def inspect
139
- "#<#{self.class.name} tape=#{@tape ? @tape.class.name : 'none'} " \
140
- "playing=#{@playing} motor=#{@motor}>"
141
- end
142
-
143
- private
144
-
145
- def press(down)
146
- return if down == @playing || !@connected
147
-
148
- finish_recording unless down
149
- @playing = down
150
- @sense_handler&.call
151
- end
152
-
153
- # Releasing the keys ends a recording, and writes the tape out.
154
- def finish_recording
155
- return unless @recording
156
-
157
- @recording = false
158
- @tape.save
159
- end
160
- end
161
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- # The VICE debug cartridge register, mapped at $D7FF on the C64. It is a
5
- # VICE facility rather than real hardware, enabled there with -debugcart:
6
- # writing a byte ends the run with that value as the exit code. The VICE
7
- # test suites write $00 for success and $ff for failure.
8
- #
9
- # Wraps the SID's top mirror page, so every other access falls through.
10
- class DebugRegister
11
- ADDRESS = 0xd7ff
12
-
13
- def initialize(sid, &handler)
14
- @sid = sid
15
- @handler = handler
16
- end
17
-
18
- def peek(addr)
19
- @sid.peek(addr)
20
- end
21
-
22
- def poke(addr, value)
23
- return @handler.call(value) if addr == ADDRESS
24
-
25
- @sid.poke(addr, value)
26
- end
27
- end
28
- end
@@ -1,147 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- module Drive
5
- # What every Commodore disk drive here shares: a 6502 running the DOS
6
- # ROM, with chips on its bus facing the serial bus and the disk
7
- # mechanism, on a clock of its own.
8
- #
9
- # The drive runs on its own crystal, so it clocks against the host's
10
- # clock through a fractional accumulator: each host cycle adds the
11
- # drive's clock rate worth of phase, and every whole host period in it
12
- # runs a drive cycle. Against the PAL C64's 985,248 Hz a drive at
13
- # 1 MHz runs one drive cycle per host cycle and a second one about
14
- # every 67. The host sets its clock on attaching the drive, and until
15
- # then a 1 MHz drive runs one cycle per host cycle.
16
- #
17
- # The Mechanism reads a Disk put in with insert.
18
- #
19
- # While the DOS idles, host_cycle! skips the drive's cycles and catches
20
- # up on them later, exactly (see Idle). The readers of the drive's parts
21
- # catch up first, so they find the drive as running every cycle would
22
- # have left it. Once the DOS's timer interrupts come round, the drive
23
- # sleeps through them too (see Orbit).
24
- #
25
- # A model includes Core and builds its parts, sets @clock_hz and
26
- # @idle_loop, and runs one drive cycle in step. It hears ATN on
27
- # connecting (hear_atn), drives the serial bus (serial_output), and
28
- # answers Idle's and Orbit's questions about its chips, as VIAs does
29
- # for the 1541 and the 1571.
30
- module Core
31
- include Sleep
32
- include Idle
33
- include Orbit
34
-
35
- attr_reader :device, :serial_bus
36
-
37
- def cpu
38
- settle!
39
- @cpu
40
- end
41
-
42
- def bus
43
- settle!
44
- @bus
45
- end
46
-
47
- def mechanism
48
- settle!
49
- @mechanism
50
- end
51
-
52
- def cycles
53
- settle!
54
- @cycles
55
- end
56
-
57
- def ram = bus.ram
58
-
59
- def host_clock_hz=(clock_hz)
60
- settle!
61
- @host_clock_hz = clock_hz
62
- end
63
-
64
- # Plugs the drive into a serial bus, leaving the one it was on. A drive
65
- # starts out on a bus of its own, with nothing else on it.
66
- def connect(serial_bus)
67
- settle!
68
- @serial_bus&.detach(self)
69
- @serial_bus = serial_bus
70
- @serial_port.bus = serial_bus
71
- serial_bus.attach(self)
72
- hear_atn
73
- end
74
-
75
- # Puts a Disk in the drive (Disk.from_d64 makes one from an image).
76
- # Nil takes the disk out.
77
- def insert(disk)
78
- settle!
79
- @mechanism.insert(disk)
80
- end
81
-
82
- def disk = mechanism.disk
83
-
84
- # Whether the LED is lit. Reading it leaves the drive asleep: the LED
85
- # is the same at the end of every pass the drive sleeps through.
86
- def led_on? = @mechanism.led_on?
87
-
88
- # Stores what the head wrote since the motor last stopped in the
89
- # disk's image, as the motor stopping does.
90
- def flush
91
- settle!
92
- @mechanism.flush
93
- end
94
-
95
- # Runs the drive cycles that fall in one host cycle: none, one or two.
96
- # The host has run this cycle already, and the drive sees what it did
97
- # from the next one on (see SerialPort). Asleep, the drive owes the
98
- # cycles instead, until ATN moves or its counters are due (see Idle).
99
- # It looks at ATN only after the machine pushed its lines into the bus
100
- # (see host_written!).
101
- def host_cycle!
102
- if @asleep
103
- return if (@slept += 1) != @wake_at && @host_still
104
-
105
- return doze
106
- end
107
-
108
- phase = @phase + @clock_hz
109
- while phase >= @host_clock_hz
110
- @asleep ? @owed += 1 : run_cycle
111
- phase -= @host_clock_hz
112
- end
113
- @phase = phase
114
- settle! if @serial_port.atn_moved?
115
- @serial_port.latch_host
116
- plan_wake if @asleep
117
- end
118
-
119
- # The machine pushed its lines into the bus, so ATN may have moved.
120
- def host_written!
121
- @host_still = false
122
- end
123
-
124
- # The host moved its fast serial pins, which a 1541 has none to hear.
125
- def fast_lines_moved = nil
126
-
127
- # Runs one drive cycle, catching up first on any the drive owes (see
128
- # step).
129
- def cycle!
130
- settle!
131
- step
132
- end
133
-
134
- def inspect
135
- "#<#{self.class.name} cycles=#{cycles} cpu=(#{cpu.inspect})>"
136
- end
137
-
138
- private
139
-
140
- # A drive cycle from host_cycle!, which may find the idle loop.
141
- def run_cycle
142
- step
143
- idle_loop_reached if @cpu.program_counter == @idle_loop && @idle_skip
144
- end
145
- end
146
- end
147
- end