badline 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (516) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/CLAUDE.md +59 -31
  4. data/README.md +1 -1
  5. data/doc/library.md +9 -9
  6. data/doc/pinned-behaviour.md +105 -105
  7. data/doc/snapshots.md +1 -4
  8. data/lib/badline/audio/bare_player.rb +4 -4
  9. data/lib/badline/audio/cli.rb +6 -6
  10. data/lib/badline/audio/jukebox.rb +2 -2
  11. data/lib/badline/audio/machine_player.rb +2 -2
  12. data/lib/badline/{media → audio}/queue.rb +1 -1
  13. data/lib/badline/audio/queued_tune.rb +6 -6
  14. data/lib/badline/audio/renderer.rb +5 -5
  15. data/lib/badline/audio/stereo.rb +1 -1
  16. data/lib/badline/c128/{bus_state.rb → bus/saved_state.rb} +6 -6
  17. data/lib/badline/c128/bus.rb +30 -51
  18. data/lib/badline/c128/color_lines.rb +2 -2
  19. data/lib/badline/c128/cpu.rb +1 -1
  20. data/lib/badline/c128/drives.rb +10 -11
  21. data/lib/badline/c128/fast_serial.rb +5 -5
  22. data/lib/badline/c128/mmu_pages.rb +1 -1
  23. data/lib/badline/c128/modes.rb +2 -2
  24. data/lib/badline/c128/saved_state.rb +21 -47
  25. data/lib/badline/c128/z80.rb +2 -2
  26. data/lib/badline/c128.rb +18 -72
  27. data/lib/badline/{computer → c64}/attachments.rb +16 -47
  28. data/lib/badline/c64/banked_ram/banking.rb +32 -0
  29. data/lib/badline/c64/banked_ram/plus256k.rb +56 -0
  30. data/lib/badline/c64/banked_ram/plus60k.rb +45 -0
  31. data/lib/badline/c64/banked_ram/unexpanded.rb +30 -0
  32. data/lib/badline/c64/banked_ram.rb +23 -0
  33. data/lib/badline/c64/bus/extra_sids.rb +32 -0
  34. data/lib/badline/c64/bus/fittings.rb +40 -0
  35. data/lib/badline/c64/bus/pla.rb +149 -0
  36. data/lib/badline/c64/bus/roms.rb +41 -0
  37. data/lib/badline/c64/bus/saved_state.rb +68 -0
  38. data/lib/badline/c64/bus/sid_slots.rb +44 -0
  39. data/lib/badline/c64/bus.rb +218 -0
  40. data/lib/badline/c64/cartridge/action_replay.rb +128 -0
  41. data/lib/badline/c64/cartridge/atomic_power.rb +26 -0
  42. data/lib/badline/c64/cartridge/bank.rb +83 -0
  43. data/lib/badline/c64/cartridge/comal80.rb +52 -0
  44. data/lib/badline/c64/cartridge/dinamic.rb +36 -0
  45. data/lib/badline/c64/cartridge/easy_flash.rb +147 -0
  46. data/lib/badline/c64/cartridge/epyx_fastload.rb +81 -0
  47. data/lib/badline/c64/cartridge/final_cartridge3.rb +91 -0
  48. data/lib/badline/c64/cartridge/flash/saved_state.rb +40 -0
  49. data/lib/badline/c64/cartridge/flash.rb +279 -0
  50. data/lib/badline/c64/cartridge/freezer.rb +35 -0
  51. data/lib/badline/c64/cartridge/fun_play.rb +40 -0
  52. data/lib/badline/c64/cartridge/g_mod2.rb +76 -0
  53. data/lib/badline/c64/cartridge/game_system.rb +42 -0
  54. data/lib/badline/c64/cartridge/geo_ram.rb +81 -0
  55. data/lib/badline/c64/cartridge/kcs_power.rb +77 -0
  56. data/lib/badline/c64/cartridge/mach5.rb +34 -0
  57. data/lib/badline/c64/cartridge/magic_desk.rb +32 -0
  58. data/lib/badline/c64/cartridge/ocean.rb +37 -0
  59. data/lib/badline/c64/cartridge/pagefox.rb +70 -0
  60. data/lib/badline/c64/cartridge/retro_replay/saved_state.rb +47 -0
  61. data/lib/badline/c64/cartridge/retro_replay.rb +286 -0
  62. data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
  63. data/lib/badline/c64/cartridge/rgcd.rb +60 -0
  64. data/lib/badline/c64/cartridge/saved_state.rb +63 -0
  65. data/lib/badline/c64/cartridge/simons_basic.rb +37 -0
  66. data/lib/badline/c64/cartridge/standard.rb +17 -0
  67. data/lib/badline/c64/cartridge/super_games.rb +50 -0
  68. data/lib/badline/c64/cartridge/westermann.rb +32 -0
  69. data/lib/badline/c64/cartridge/zaxxon.rb +68 -0
  70. data/lib/badline/c64/cartridge.rb +258 -0
  71. data/lib/badline/c64/color_memory.rb +27 -0
  72. data/lib/badline/c64/common.rb +34 -0
  73. data/lib/badline/c64/kernal_traps.rb +89 -0
  74. data/lib/badline/c64/reu/dma/saved_state.rb +52 -0
  75. data/lib/badline/c64/reu/dma.rb +275 -0
  76. data/lib/badline/c64/reu/ram.rb +109 -0
  77. data/lib/badline/c64/reu/saved_state.rb +55 -0
  78. data/lib/badline/c64/reu/trigger.rb +34 -0
  79. data/lib/badline/c64/reu.rb +291 -0
  80. data/lib/badline/{computer → c64}/saved_state.rb +13 -18
  81. data/lib/badline/{computer → c64}/true_drives.rb +20 -31
  82. data/lib/badline/{computer.rb → c64.rb} +22 -80
  83. data/lib/badline/chips/cia/fast_forward.rb +62 -0
  84. data/lib/badline/chips/cia/interrupt_register.rb +145 -0
  85. data/lib/badline/chips/cia/saved_state.rb +49 -0
  86. data/lib/badline/chips/cia/serial/saved_state.rb +45 -0
  87. data/lib/badline/chips/cia/serial.rb +250 -0
  88. data/lib/badline/chips/cia/time_of_day.rb +232 -0
  89. data/lib/badline/chips/cia/timer.rb +208 -0
  90. data/lib/badline/chips/cia.rb +281 -0
  91. data/lib/badline/chips/cpu/addressing.rb +133 -0
  92. data/lib/badline/chips/cpu/boundary.rb +56 -0
  93. data/lib/badline/chips/cpu/core.rb +167 -0
  94. data/lib/badline/chips/cpu/instruction.rb +338 -0
  95. data/lib/badline/chips/cpu/instruction_set/arithmetic.rb +118 -0
  96. data/lib/badline/chips/cpu/instruction_set/bitwise.rb +130 -0
  97. data/lib/badline/chips/cpu/instruction_set/branch.rb +83 -0
  98. data/lib/badline/chips/cpu/instruction_set/flag.rb +67 -0
  99. data/lib/badline/chips/cpu/instruction_set/illegal.rb +274 -0
  100. data/lib/badline/chips/cpu/instruction_set/inc_dec.rb +73 -0
  101. data/lib/badline/chips/cpu/instruction_set/stack.rb +56 -0
  102. data/lib/badline/chips/cpu/instruction_set/transfer.rb +141 -0
  103. data/lib/badline/chips/cpu/instruction_set.rb +59 -0
  104. data/lib/badline/chips/cpu/interrupts.rb +108 -0
  105. data/lib/badline/chips/cpu/microcode.rb +179 -0
  106. data/lib/badline/chips/cpu/operations.rb +90 -0
  107. data/lib/badline/chips/cpu/port.rb +116 -0
  108. data/lib/badline/chips/cpu/saved_state.rb +117 -0
  109. data/lib/badline/chips/cpu/stack_operations.rb +84 -0
  110. data/lib/badline/chips/cpu/traps.rb +23 -0
  111. data/lib/badline/chips/cpu.rb +12 -0
  112. data/lib/badline/chips/sid/catch_up.rb +122 -0
  113. data/lib/badline/chips/sid/decimator.rb +66 -0
  114. data/lib/badline/chips/sid/envelope/saved_state.rb +70 -0
  115. data/lib/badline/chips/sid/envelope.rb +241 -0
  116. data/lib/badline/chips/sid/filter/saved_state.rb +42 -0
  117. data/lib/badline/chips/sid/filter.rb +241 -0
  118. data/lib/badline/chips/sid/saved_state.rb +52 -0
  119. data/lib/badline/chips/sid/voice.rb +79 -0
  120. data/lib/badline/chips/sid/waveform/combined.rb +128 -0
  121. data/lib/badline/chips/sid/waveform/fast_forward.rb +107 -0
  122. data/lib/badline/chips/sid/waveform/noise_writeback.rb +124 -0
  123. data/lib/badline/chips/sid/waveform/saved_state.rb +68 -0
  124. data/lib/badline/chips/sid/waveform.rb +307 -0
  125. data/lib/badline/chips/sid.rb +265 -0
  126. data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
  127. data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -1
  128. data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -1
  129. data/lib/badline/chips/vdc/saved_state.rb +36 -0
  130. data/lib/badline/{c128 → chips}/vdc/window.rb +1 -1
  131. data/lib/badline/{c128 → chips}/vdc.rb +7 -31
  132. data/lib/badline/chips/via/control_lines.rb +124 -0
  133. data/lib/badline/chips/via/fast_forward.rb +55 -0
  134. data/lib/badline/chips/via/interrupt_register.rb +69 -0
  135. data/lib/badline/chips/via/saved_state.rb +44 -0
  136. data/lib/badline/chips/via/shift_register.rb +182 -0
  137. data/lib/badline/chips/via/timer1.rb +133 -0
  138. data/lib/badline/chips/via/timer2.rb +135 -0
  139. data/lib/badline/chips/via.rb +268 -0
  140. data/lib/badline/chips/vic/bank.rb +135 -0
  141. data/lib/badline/chips/vic/border_mask.rb +88 -0
  142. data/lib/badline/chips/vic/collisions.rb +117 -0
  143. data/lib/badline/chips/vic/color_patches.rb +49 -0
  144. data/lib/badline/chips/vic/display_state.rb +187 -0
  145. data/lib/badline/chips/vic/graphics_mode.rb +166 -0
  146. data/lib/badline/chips/vic/graphics_shifter/saved_state.rb +40 -0
  147. data/lib/badline/chips/vic/graphics_shifter.rb +187 -0
  148. data/lib/badline/chips/vic/register_log.rb +83 -0
  149. data/lib/badline/chips/vic/registers.rb +197 -0
  150. data/lib/badline/chips/vic/saved_state.rb +82 -0
  151. data/lib/badline/chips/vic/sequencer/saved_state.rb +91 -0
  152. data/lib/badline/chips/vic/sequencer.rb +277 -0
  153. data/lib/badline/chips/vic/sequencer_output.rb +118 -0
  154. data/lib/badline/chips/vic/sprite/internal_bus.rb +70 -0
  155. data/lib/badline/chips/vic/sprite/saved_state.rb +66 -0
  156. data/lib/badline/chips/vic/sprite/shifter.rb +148 -0
  157. data/lib/badline/chips/vic/sprite/timing.rb +58 -0
  158. data/lib/badline/chips/vic/sprite.rb +339 -0
  159. data/lib/badline/chips/vic/sprites/saved_state.rb +59 -0
  160. data/lib/badline/chips/vic/sprites.rb +284 -0
  161. data/lib/badline/chips/vic.rb +783 -0
  162. data/lib/badline/chips/vic_i/painter/saved_state.rb +40 -0
  163. data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +6 -30
  164. data/lib/badline/{vic20/vic → chips/vic_i}/saved_state.rb +2 -2
  165. data/lib/badline/chips/vic_i/sound/output.rb +85 -0
  166. data/lib/badline/chips/vic_i/sound.rb +235 -0
  167. data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
  168. data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +5 -5
  169. data/lib/badline/chips/z80/arithmetic.rb +119 -0
  170. data/lib/badline/chips/z80/bit_page.rb +57 -0
  171. data/lib/badline/chips/z80/block_io.rb +60 -0
  172. data/lib/badline/chips/z80/block_transfers.rb +61 -0
  173. data/lib/badline/chips/z80/bus_cycles.rb +113 -0
  174. data/lib/badline/chips/z80/core.rb +115 -0
  175. data/lib/badline/chips/z80/exchanges.rb +52 -0
  176. data/lib/badline/chips/z80/extended_page.rb +91 -0
  177. data/lib/badline/chips/z80/flags.rb +39 -0
  178. data/lib/badline/chips/z80/interrupt_acceptance.rb +48 -0
  179. data/lib/badline/chips/z80/jumps.rb +84 -0
  180. data/lib/badline/chips/z80/loads.rb +100 -0
  181. data/lib/badline/chips/z80/main_page.rb +136 -0
  182. data/lib/badline/chips/z80/registers.rb +122 -0
  183. data/lib/badline/chips/z80/saved_state.rb +71 -0
  184. data/lib/badline/chips/z80/shifts.rb +66 -0
  185. data/lib/badline/chips/z80.rb +13 -0
  186. data/lib/badline/core.rb +27 -29
  187. data/lib/badline/drives/datasette/saved_state.rb +37 -0
  188. data/lib/badline/drives/datasette.rb +140 -0
  189. data/lib/badline/drives/engine/core.rb +149 -0
  190. data/lib/badline/drives/engine/fast_serial.rb +75 -0
  191. data/lib/badline/drives/engine/idle.rb +127 -0
  192. data/lib/badline/drives/engine/idle_cpu.rb +30 -0
  193. data/lib/badline/drives/engine/orbit.rb +81 -0
  194. data/lib/badline/drives/engine/serial_lines.rb +75 -0
  195. data/lib/badline/drives/engine/sleep.rb +114 -0
  196. data/lib/badline/drives/engine/vias.rb +86 -0
  197. data/lib/badline/drives/engine/watch.rb +152 -0
  198. data/lib/badline/drives/engine.rb +11 -0
  199. data/lib/badline/drives/model1541/bus.rb +88 -0
  200. data/lib/badline/drives/model1541/byte_ready.rb +50 -0
  201. data/lib/badline/drives/model1541/cpu.rb +13 -0
  202. data/lib/badline/drives/model1541/disk/saved_state.rb +88 -0
  203. data/lib/badline/drives/model1541/disk.rb +317 -0
  204. data/lib/badline/drives/model1541/disk_via.rb +38 -0
  205. data/lib/badline/drives/model1541/gcr.rb +59 -0
  206. data/lib/badline/drives/model1541/mechanism/saved_state.rb +72 -0
  207. data/lib/badline/drives/model1541/mechanism.rb +315 -0
  208. data/lib/badline/drives/model1541/rotation.rb +123 -0
  209. data/lib/badline/drives/model1541/saved_state.rb +44 -0
  210. data/lib/badline/drives/model1541/sector_reader.rb +78 -0
  211. data/lib/badline/drives/model1541/serial_port.rb +20 -0
  212. data/lib/badline/drives/model1541/track.rb +100 -0
  213. data/lib/badline/drives/model1541.rb +81 -0
  214. data/lib/badline/drives/model1571/bus.rb +113 -0
  215. data/lib/badline/drives/model1571/cpu.rb +13 -0
  216. data/lib/badline/drives/model1571/saved_state.rb +47 -0
  217. data/lib/badline/drives/model1571/serial_port.rb +39 -0
  218. data/lib/badline/drives/model1571/serial_via.rb +27 -0
  219. data/lib/badline/drives/model1571/wd1770.rb +122 -0
  220. data/lib/badline/drives/model1571.rb +142 -0
  221. data/lib/badline/drives/model1581/bus.rb +139 -0
  222. data/lib/badline/drives/model1581/cpu.rb +13 -0
  223. data/lib/badline/drives/model1581/disk/saved_state.rb +89 -0
  224. data/lib/badline/drives/model1581/disk.rb +137 -0
  225. data/lib/badline/drives/model1581/mechanism.rb +119 -0
  226. data/lib/badline/drives/model1581/saved_state.rb +42 -0
  227. data/lib/badline/drives/model1581/serial_port.rb +54 -0
  228. data/lib/badline/drives/model1581/slot.rb +79 -0
  229. data/lib/badline/drives/model1581/track.rb +102 -0
  230. data/lib/badline/drives/model1581/track_bytes.rb +77 -0
  231. data/lib/badline/drives/model1581/wd1772/registers.rb +91 -0
  232. data/lib/badline/drives/model1581/wd1772/saved_state.rb +68 -0
  233. data/lib/badline/drives/model1581/wd1772/sector_writes.rb +75 -0
  234. data/lib/badline/drives/model1581/wd1772/sectors.rb +152 -0
  235. data/lib/badline/drives/model1581/wd1772/stepping.rb +111 -0
  236. data/lib/badline/drives/model1581/wd1772/tracks.rb +127 -0
  237. data/lib/badline/drives/model1581/wd1772/turn.rb +75 -0
  238. data/lib/badline/drives/model1581/wd1772.rb +218 -0
  239. data/lib/badline/drives/model1581.rb +206 -0
  240. data/lib/badline/drives/serial_bus.rb +161 -0
  241. data/lib/badline/frontend/boot.rb +10 -61
  242. data/lib/badline/frontend/machine_window.rb +3 -1
  243. data/lib/badline/frontend/player/filter_view.rb +1 -1
  244. data/lib/badline/frontend/player/player_controller.rb +2 -2
  245. data/lib/badline/frontend/player/player_screen.rb +1 -0
  246. data/lib/badline/frontend/player/theme.rb +7 -7
  247. data/lib/badline/frontend/timeline.rb +3 -3
  248. data/lib/badline/input/control_ports.rb +78 -0
  249. data/lib/badline/input/joystick.rb +27 -0
  250. data/lib/badline/input/keyboard.rb +114 -0
  251. data/lib/badline/input.rb +3 -0
  252. data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
  253. data/lib/badline/kernal_trap/dos/channel.rb +183 -0
  254. data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -1
  255. data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -1
  256. data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
  257. data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -1
  258. data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -1
  259. data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
  260. data/lib/badline/kernal_trap/{drive.rb → dos.rb} +11 -10
  261. data/lib/badline/kernal_trap/{file.rb → file_routine.rb} +1 -1
  262. data/lib/badline/kernal_trap/load.rb +6 -6
  263. data/lib/badline/kernal_trap/save.rb +5 -5
  264. data/lib/badline/kernal_trap/serial.rb +7 -7
  265. data/lib/badline/kernal_trap.rb +2 -3
  266. data/lib/badline/machine/clocking.rb +50 -0
  267. data/lib/badline/machine.rb +63 -7
  268. data/lib/badline/media/boot_disk.rb +2 -2
  269. data/lib/badline/media/disk_list.rb +3 -3
  270. data/lib/badline/media/disk_set.rb +1 -1
  271. data/lib/badline/media/extensions.rb +33 -0
  272. data/lib/badline/media/program.rb +28 -0
  273. data/lib/badline/media/true_drive.rb +4 -3
  274. data/lib/badline/media/tune.rb +35 -0
  275. data/lib/badline/media/vic20_cartridge.rb +1 -7
  276. data/lib/badline/media/vic20_media.rb +38 -80
  277. data/lib/badline/media.rb +84 -81
  278. data/lib/badline/model.rb +1 -1
  279. data/lib/badline/options/event.rb +3 -1
  280. data/lib/badline/roms/README +6 -6
  281. data/lib/badline/sdl.rb +1 -0
  282. data/lib/badline/{storage/sid_file.rb → sid_tune/file.rb} +3 -3
  283. data/lib/badline/{storage → sid_tune}/hvsc.rb +7 -7
  284. data/lib/badline/{storage → sid_tune}/song_lengths.rb +2 -2
  285. data/lib/badline/{storage → sid_tune}/stil/credit.rb +1 -1
  286. data/lib/badline/{storage → sid_tune}/stil.rb +3 -3
  287. data/lib/badline/sid_tune.rb +6 -0
  288. data/lib/badline/snapshot/c128_setup.rb +43 -0
  289. data/lib/badline/snapshot/c64_setup.rb +79 -0
  290. data/lib/badline/snapshot/image.rb +5 -25
  291. data/lib/badline/snapshot/machine_state.rb +10 -2
  292. data/lib/badline/snapshot/setup.rb +22 -66
  293. data/lib/badline/snapshot/state.rb +8 -17
  294. data/lib/badline/snapshot/storage_setup.rb +68 -0
  295. data/lib/badline/snapshot/vic20_setup.rb +37 -0
  296. data/lib/badline/snapshot/vice/c64_mem.rb +1 -1
  297. data/lib/badline/snapshot/vice/restore.rb +1 -1
  298. data/lib/badline/snapshot/vice/reu1764.rb +1 -1
  299. data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
  300. data/lib/badline/snapshot/vice.rb +7 -5
  301. data/lib/badline/snapshot.rb +13 -12
  302. data/lib/badline/storage/d64_image.rb +15 -9
  303. data/lib/badline/storage/d71_image.rb +0 -2
  304. data/lib/badline/storage/d81_image.rb +0 -2
  305. data/lib/badline/storage/disk_image/writing.rb +2 -2
  306. data/lib/badline/storage/disk_image.rb +3 -6
  307. data/lib/badline/storage/g64_image.rb +2 -2
  308. data/lib/badline/storage/host_directory.rb +0 -5
  309. data/lib/badline/storage/t64.rb +2 -8
  310. data/lib/badline/storage/unavailable.rb +1 -1
  311. data/lib/badline/storage.rb +0 -37
  312. data/lib/badline/support/c128_checkpoint.rb +39 -0
  313. data/lib/badline/support/checkpoint.rb +108 -0
  314. data/lib/badline/support/vic20_checkpoint.rb +38 -0
  315. data/lib/badline/support.rb +5 -0
  316. data/lib/badline/version.rb +1 -1
  317. data/lib/badline/vic20/attachments.rb +11 -81
  318. data/lib/badline/vic20/bus/saved_state.rb +35 -0
  319. data/lib/badline/vic20/bus.rb +3 -25
  320. data/lib/badline/vic20/cpu.rb +1 -1
  321. data/lib/badline/vic20/port_wiring.rb +4 -4
  322. data/lib/badline/vic20/saved_state.rb +16 -60
  323. data/lib/badline/vic20/user_via_ports.rb +2 -2
  324. data/lib/badline/vic20.rb +20 -51
  325. metadata +250 -221
  326. data/lib/badline/address_bus/extra_sids.rb +0 -30
  327. data/lib/badline/address_bus/fittings.rb +0 -38
  328. data/lib/badline/address_bus/pla.rb +0 -147
  329. data/lib/badline/address_bus/roms.rb +0 -39
  330. data/lib/badline/address_bus/saved_state.rb +0 -72
  331. data/lib/badline/address_bus/sid_slots.rb +0 -42
  332. data/lib/badline/address_bus.rb +0 -235
  333. data/lib/badline/cartridge/action_replay.rb +0 -126
  334. data/lib/badline/cartridge/atomic_power.rb +0 -24
  335. data/lib/badline/cartridge/bank.rb +0 -81
  336. data/lib/badline/cartridge/comal80.rb +0 -50
  337. data/lib/badline/cartridge/dinamic.rb +0 -34
  338. data/lib/badline/cartridge/easy_flash.rb +0 -145
  339. data/lib/badline/cartridge/epyx_fastload.rb +0 -79
  340. data/lib/badline/cartridge/final_cartridge3.rb +0 -89
  341. data/lib/badline/cartridge/flash.rb +0 -306
  342. data/lib/badline/cartridge/freezer.rb +0 -33
  343. data/lib/badline/cartridge/fun_play.rb +0 -38
  344. data/lib/badline/cartridge/g_mod2.rb +0 -74
  345. data/lib/badline/cartridge/game_system.rb +0 -40
  346. data/lib/badline/cartridge/geo_ram.rb +0 -79
  347. data/lib/badline/cartridge/kcs_power.rb +0 -75
  348. data/lib/badline/cartridge/mach5.rb +0 -32
  349. data/lib/badline/cartridge/magic_desk.rb +0 -30
  350. data/lib/badline/cartridge/ocean.rb +0 -35
  351. data/lib/badline/cartridge/pagefox.rb +0 -68
  352. data/lib/badline/cartridge/retro_replay.rb +0 -320
  353. data/lib/badline/cartridge/rex_utility.rb +0 -29
  354. data/lib/badline/cartridge/rgcd.rb +0 -58
  355. data/lib/badline/cartridge/simons_basic.rb +0 -35
  356. data/lib/badline/cartridge/standard.rb +0 -15
  357. data/lib/badline/cartridge/super_games.rb +0 -48
  358. data/lib/badline/cartridge/westermann.rb +0 -30
  359. data/lib/badline/cartridge/zaxxon.rb +0 -66
  360. data/lib/badline/cartridge.rb +0 -303
  361. data/lib/badline/checkpoint.rb +0 -98
  362. data/lib/badline/cia/fast_forward.rb +0 -60
  363. data/lib/badline/cia/interrupt_register.rb +0 -143
  364. data/lib/badline/cia/serial.rb +0 -275
  365. data/lib/badline/cia/state.rb +0 -47
  366. data/lib/badline/cia/timer.rb +0 -206
  367. data/lib/badline/cia.rb +0 -279
  368. data/lib/badline/color_memory.rb +0 -25
  369. data/lib/badline/computer/kernal_traps.rb +0 -29
  370. data/lib/badline/control_ports.rb +0 -76
  371. data/lib/badline/cpu/addressing.rb +0 -131
  372. data/lib/badline/cpu/boundary.rb +0 -54
  373. data/lib/badline/cpu/core.rb +0 -165
  374. data/lib/badline/cpu/microcode.rb +0 -177
  375. data/lib/badline/cpu/operations.rb +0 -88
  376. data/lib/badline/cpu/saved_state.rb +0 -115
  377. data/lib/badline/cpu/stack_operations.rb +0 -82
  378. data/lib/badline/cpu.rb +0 -10
  379. data/lib/badline/cycleable.rb +0 -38
  380. data/lib/badline/datasette.rb +0 -161
  381. data/lib/badline/drive/core.rb +0 -147
  382. data/lib/badline/drive/fast_serial.rb +0 -73
  383. data/lib/badline/drive/idle.rb +0 -125
  384. data/lib/badline/drive/idle_cpu.rb +0 -28
  385. data/lib/badline/drive/orbit.rb +0 -79
  386. data/lib/badline/drive/serial_lines.rb +0 -73
  387. data/lib/badline/drive/sleep.rb +0 -112
  388. data/lib/badline/drive/vias.rb +0 -84
  389. data/lib/badline/drive/watch.rb +0 -150
  390. data/lib/badline/drive.rb +0 -11
  391. data/lib/badline/drive1541/bus.rb +0 -86
  392. data/lib/badline/drive1541/byte_ready.rb +0 -48
  393. data/lib/badline/drive1541/cpu.rb +0 -11
  394. data/lib/badline/drive1541/disk.rb +0 -318
  395. data/lib/badline/drive1541/disk_state.rb +0 -94
  396. data/lib/badline/drive1541/disk_via.rb +0 -36
  397. data/lib/badline/drive1541/gcr.rb +0 -57
  398. data/lib/badline/drive1541/mechanism.rb +0 -313
  399. data/lib/badline/drive1541/mechanism_state.rb +0 -68
  400. data/lib/badline/drive1541/rotation.rb +0 -121
  401. data/lib/badline/drive1541/sector_reader.rb +0 -76
  402. data/lib/badline/drive1541/serial_port.rb +0 -18
  403. data/lib/badline/drive1541/track.rb +0 -98
  404. data/lib/badline/drive1541.rb +0 -111
  405. data/lib/badline/drive1571/bus.rb +0 -111
  406. data/lib/badline/drive1571/cpu.rb +0 -11
  407. data/lib/badline/drive1571/serial_port.rb +0 -37
  408. data/lib/badline/drive1571/serial_via.rb +0 -25
  409. data/lib/badline/drive1571/wd1770.rb +0 -120
  410. data/lib/badline/drive1571.rb +0 -175
  411. data/lib/badline/drive1581/bus.rb +0 -137
  412. data/lib/badline/drive1581/cpu.rb +0 -11
  413. data/lib/badline/drive1581/disk.rb +0 -135
  414. data/lib/badline/drive1581/disk_state.rb +0 -87
  415. data/lib/badline/drive1581/mechanism.rb +0 -117
  416. data/lib/badline/drive1581/serial_port.rb +0 -52
  417. data/lib/badline/drive1581/slot.rb +0 -78
  418. data/lib/badline/drive1581/track.rb +0 -100
  419. data/lib/badline/drive1581/track_bytes.rb +0 -75
  420. data/lib/badline/drive1581/wd1772/registers.rb +0 -89
  421. data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
  422. data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
  423. data/lib/badline/drive1581/wd1772/state.rb +0 -66
  424. data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
  425. data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
  426. data/lib/badline/drive1581/wd1772/turn.rb +0 -73
  427. data/lib/badline/drive1581/wd1772.rb +0 -216
  428. data/lib/badline/drive1581.rb +0 -233
  429. data/lib/badline/iec_bus.rb +0 -159
  430. data/lib/badline/instruction.rb +0 -334
  431. data/lib/badline/instruction_set/arithmetic.rb +0 -114
  432. data/lib/badline/instruction_set/bitwise.rb +0 -126
  433. data/lib/badline/instruction_set/branch.rb +0 -79
  434. data/lib/badline/instruction_set/flag.rb +0 -63
  435. data/lib/badline/instruction_set/illegal.rb +0 -270
  436. data/lib/badline/instruction_set/inc_dec.rb +0 -69
  437. data/lib/badline/instruction_set/stack.rb +0 -52
  438. data/lib/badline/instruction_set/transfer.rb +0 -137
  439. data/lib/badline/instruction_set.rb +0 -55
  440. data/lib/badline/interrupts.rb +0 -104
  441. data/lib/badline/joystick.rb +0 -25
  442. data/lib/badline/kernal_trap/channel.rb +0 -181
  443. data/lib/badline/keyboard.rb +0 -112
  444. data/lib/badline/ram_expansion/banking.rb +0 -30
  445. data/lib/badline/ram_expansion/plus256k.rb +0 -54
  446. data/lib/badline/ram_expansion/plus60k.rb +0 -43
  447. data/lib/badline/ram_expansion/unexpanded.rb +0 -28
  448. data/lib/badline/ram_expansion.rb +0 -21
  449. data/lib/badline/reu/dma/saved_state.rb +0 -50
  450. data/lib/badline/reu/dma.rb +0 -273
  451. data/lib/badline/reu/ram.rb +0 -107
  452. data/lib/badline/reu/saved_state.rb +0 -80
  453. data/lib/badline/reu/trigger.rb +0 -32
  454. data/lib/badline/reu.rb +0 -289
  455. data/lib/badline/sid/catch_up.rb +0 -120
  456. data/lib/badline/sid/decimator.rb +0 -64
  457. data/lib/badline/sid/envelope/state.rb +0 -68
  458. data/lib/badline/sid/envelope.rb +0 -239
  459. data/lib/badline/sid/filter.rb +0 -263
  460. data/lib/badline/sid/voice.rb +0 -77
  461. data/lib/badline/sid/waveform/combined.rb +0 -126
  462. data/lib/badline/sid/waveform/fast_forward.rb +0 -105
  463. data/lib/badline/sid/waveform/noise_writeback.rb +0 -122
  464. data/lib/badline/sid/waveform/state.rb +0 -66
  465. data/lib/badline/sid/waveform.rb +0 -305
  466. data/lib/badline/sid.rb +0 -303
  467. data/lib/badline/time_of_day.rb +0 -228
  468. data/lib/badline/traps.rb +0 -19
  469. data/lib/badline/via/control_lines.rb +0 -122
  470. data/lib/badline/via/fast_forward.rb +0 -53
  471. data/lib/badline/via/interrupt_register.rb +0 -67
  472. data/lib/badline/via/shift_register.rb +0 -180
  473. data/lib/badline/via/state.rb +0 -42
  474. data/lib/badline/via/timer1.rb +0 -131
  475. data/lib/badline/via/timer2.rb +0 -133
  476. data/lib/badline/via.rb +0 -266
  477. data/lib/badline/vic/bank.rb +0 -133
  478. data/lib/badline/vic/border_mask.rb +0 -86
  479. data/lib/badline/vic/collisions.rb +0 -115
  480. data/lib/badline/vic/color_patches.rb +0 -47
  481. data/lib/badline/vic/display_state.rb +0 -185
  482. data/lib/badline/vic/graphics_mode.rb +0 -164
  483. data/lib/badline/vic/graphics_shifter.rb +0 -207
  484. data/lib/badline/vic/register_log.rb +0 -81
  485. data/lib/badline/vic/registers.rb +0 -195
  486. data/lib/badline/vic/sequencer.rb +0 -275
  487. data/lib/badline/vic/sequencer_output.rb +0 -116
  488. data/lib/badline/vic/sequencer_state.rb +0 -89
  489. data/lib/badline/vic/sprite/internal_bus.rb +0 -68
  490. data/lib/badline/vic/sprite/saved_state.rb +0 -64
  491. data/lib/badline/vic/sprite/shifter.rb +0 -146
  492. data/lib/badline/vic/sprite/timing.rb +0 -56
  493. data/lib/badline/vic/sprite.rb +0 -337
  494. data/lib/badline/vic/sprites.rb +0 -282
  495. data/lib/badline/vic/sprites_state.rb +0 -57
  496. data/lib/badline/vic.rb +0 -852
  497. data/lib/badline/vic20/sound/output.rb +0 -83
  498. data/lib/badline/vic20/sound.rb +0 -233
  499. data/lib/badline/z80/arithmetic.rb +0 -117
  500. data/lib/badline/z80/bit_page.rb +0 -55
  501. data/lib/badline/z80/block_io.rb +0 -58
  502. data/lib/badline/z80/block_transfers.rb +0 -59
  503. data/lib/badline/z80/bus_cycles.rb +0 -111
  504. data/lib/badline/z80/core.rb +0 -113
  505. data/lib/badline/z80/exchanges.rb +0 -50
  506. data/lib/badline/z80/extended_page.rb +0 -89
  507. data/lib/badline/z80/flags.rb +0 -37
  508. data/lib/badline/z80/interrupt_acceptance.rb +0 -46
  509. data/lib/badline/z80/jumps.rb +0 -82
  510. data/lib/badline/z80/loads.rb +0 -98
  511. data/lib/badline/z80/main_page.rb +0 -134
  512. data/lib/badline/z80/registers.rb +0 -120
  513. data/lib/badline/z80/saved_state.rb +0 -69
  514. data/lib/badline/z80/shifts.rb +0 -64
  515. data/lib/badline/z80.rb +0 -11
  516. /data/lib/badline/snapshot/{fields.rb → vice/fields.rb} +0 -0
@@ -0,0 +1,291 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "badline/c64/reu/ram"
4
+ require "badline/c64/reu/dma"
5
+ require "badline/c64/reu/trigger"
6
+ require "badline/c64/reu/saved_state"
7
+
8
+ module Badline
9
+ class C64
10
+ # A RAM Expansion Unit: the Commodore 1700 (128K), 1764 (256K) and 1750
11
+ # (512K), and the bigger units built around the same 8726 RAM Expansion
12
+ # Controller (REC), such as the CMD 1750XL, up to 16M.
13
+ #
14
+ # The REC's eleven registers sit in I/O 2 from $DF00, repeated every 32
15
+ # bytes up to $DFFF, as the 1764 and 1750 manuals map them. It moves
16
+ # bytes between the C64 and its RAM by DMA, one bus cycle each, with the
17
+ # CPU held off the bus. A command with the execute bit set starts a
18
+ # transfer, or with bit 4 clear arms the REC to start one on the next
19
+ # write to $FF00, so a program can bank the ROMs out first. A transfer
20
+ # waits for the CPU's next read cycle with BA high, and C64 then
21
+ # clocks it through #dma_cycle! until it hands the bus back.
22
+ class REU
23
+ include SavedState
24
+
25
+ SIZES_KB = [128, 256, 512, 1024, 2048, 4096, 8192, 16_384].freeze
26
+
27
+ # The registers, by offset.
28
+ STATUS = 0x00
29
+ COMMAND = 0x01
30
+ C64_LOW = 0x02
31
+ C64_HIGH = 0x03
32
+ EXPANSION_LOW = 0x04
33
+ EXPANSION_HIGH = 0x05
34
+ EXPANSION_BANK = 0x06
35
+ LENGTH_LOW = 0x07
36
+ LENGTH_HIGH = 0x08
37
+ INTERRUPT_MASK = 0x09
38
+ ADDRESS_CONTROL = 0x0a
39
+
40
+ # Status: an interrupt is pending, the block ended, a verify found a
41
+ # difference (the manual's fault bit), and the unit is built from 256K
42
+ # chips, which only the 1700 isn't. Reading the status clears the top
43
+ # three.
44
+ INTERRUPT_PENDING = 0x80
45
+ END_OF_BLOCK = 0x40
46
+ FAULT = 0x20
47
+ CHIPS_256K = 0x10
48
+
49
+ # Command: execute, reload the registers after the transfer, don't wait
50
+ # for $FF00, and the transfer type in the bottom two bits.
51
+ EXECUTE = 0x80
52
+ AUTOLOAD = 0x20
53
+ NO_FF00_TRIGGER = 0x10
54
+ TRANSFER_TYPE = 0x03
55
+
56
+ # Interrupt mask: interrupts on at all, then on the end of a block and
57
+ # on a fault. The low five bits aren't there and read as 1.
58
+ INTERRUPTS_ON = 0x80
59
+ INTERRUPT_ON_END = 0x40
60
+ INTERRUPT_ON_FAULT = 0x20
61
+
62
+ # Address control: hold the C64 address or the expansion address where
63
+ # it is. The low six bits aren't there and read as 1.
64
+ FIX_C64 = 0x80
65
+ FIX_EXPANSION = 0x40
66
+
67
+ # The REC's bank register has three bits, and the other five read as
68
+ # 1. A unit past 512K latches all eight onto its own address lines.
69
+ BANK_STUCK = 0xf8
70
+
71
+ attr_reader :trigger
72
+
73
+ # bus is the bus the REC reaches C64 memory through, and vic the VIC,
74
+ # whose phi1 fetch is what a register read finds on the bus during a
75
+ # transfer.
76
+ def initialize(size_kb, bus:, vic:)
77
+ raise ArgumentError, "No #{size_kb}K REU. Pick one of #{SIZES_KB.join(', ')}." unless SIZES_KB.include?(size_kb)
78
+
79
+ # The 1700's REC counts 17 address bits, the others' 19.
80
+ span = size_kb == 128 ? 0x20000 : 0x80000
81
+ @size_kb = size_kb
82
+ size = size_kb * 1024
83
+ @address_mask = [size, span].max - 1
84
+ @bank_bits = size > span ? 0xff : 0x07
85
+ @chips = size_kb == 128 ? 0 : CHIPS_256K
86
+ @ram = RAM.new(size, span)
87
+ @dma = DMA.new(@ram, span, bus)
88
+ @trigger = Trigger.new(self)
89
+ @vic = vic
90
+ @on_irq_change = nil
91
+ @on_dma = nil
92
+ @irq = false
93
+ reset!
94
+ end
95
+
96
+ def on_irq_change(&block)
97
+ @on_irq_change = block
98
+ end
99
+
100
+ # Called when the REC asks for the bus.
101
+ def on_dma(&block)
102
+ @on_dma = block
103
+ end
104
+
105
+ def irq? = @irq
106
+
107
+ # From the moment the REC asks for the bus until it hands it back.
108
+ def dma? = @requested || @running
109
+
110
+ # Whether the REC ran a transfer on the last cycle clocked, which it
111
+ # goes on doing until the cycle it lets go of the bus.
112
+ def holds_bus? = @running
113
+
114
+ def reset!
115
+ @status = @chips
116
+ @command = NO_FF00_TRIGGER
117
+ @c64 = @c64_start = 0
118
+ @expansion = @expansion_start = 0
119
+ @bank = @bank_start = 0
120
+ @length = @length_start = 0xffff
121
+ @interrupt_mask = 0x1f
122
+ @address_control = 0x3f
123
+ @armed = @requested = @running = @ba_was_low = false
124
+ interrupt(false)
125
+ end
126
+
127
+ def peek(addr)
128
+ return @vic.phi1_data if @running
129
+
130
+ register = addr & 0x1f
131
+ value = register_value(register)
132
+ read_status if register == STATUS
133
+ value
134
+ end
135
+
136
+ def poke(addr, value)
137
+ return if @running
138
+
139
+ register = addr & 0x1f
140
+ case register
141
+ when COMMAND then write_command(value)
142
+ when C64_LOW, C64_HIGH then @c64 = @c64_start = with_byte(@c64_start, value, register == C64_HIGH)
143
+ when EXPANSION_LOW, EXPANSION_HIGH
144
+ @expansion = @expansion_start = with_byte(@expansion_start, value, register == EXPANSION_HIGH)
145
+ when EXPANSION_BANK then @bank = @bank_start = value & @bank_bits
146
+ when LENGTH_LOW, LENGTH_HIGH
147
+ @length = @length_start = with_byte(@length_start, value, register == LENGTH_HIGH)
148
+ when INTERRUPT_MASK then write_interrupt_mask(value)
149
+ when ADDRESS_CONTROL then @address_control = value | 0x3f
150
+ end
151
+ end
152
+
153
+ # A write to $FF00 starts the transfer the command register armed.
154
+ def ff00_written
155
+ return unless @armed
156
+
157
+ @armed = false
158
+ request_bus
159
+ end
160
+
161
+ # Clocks the REC for a cycle, given the VIC's BA line. A requested
162
+ # transfer starts on the first cycle with BA high as the REC sees it,
163
+ # even one the CPU writes on. Pinned by REU/rmw-trigger. A fetch
164
+ # requested on the cycle before BA falls writes its first byte on the
165
+ # first BA-low cycle as well, and again when it starts. Pinned by
166
+ # REU/badoublewrite.
167
+ def dma_cycle!(ba_low)
168
+ late = ba_low && @vic.reu_ba_late?
169
+ if @requested
170
+ return hold_off if ba_low && !late
171
+
172
+ start_transfer
173
+ end
174
+ @dma.cycle!(ba_low, late, ba_low && @vic.reu_ba_handed_on?)
175
+ end_transfer unless @dma.holds_bus?
176
+ end
177
+
178
+ # The REU's RAM, at an address as the REC's registers give it.
179
+ def ram_peek(addr) = @ram.peek(addr)
180
+
181
+ def ram_poke(addr, value) = @ram.poke(addr, value)
182
+
183
+ private
184
+
185
+ def register_value(register)
186
+ case register
187
+ when STATUS then @status
188
+ when COMMAND then @command
189
+ when C64_LOW then @c64 & 0xff
190
+ when C64_HIGH then @c64 >> 8
191
+ when EXPANSION_LOW then @expansion & 0xff
192
+ when EXPANSION_HIGH then @expansion >> 8
193
+ when EXPANSION_BANK then @bank | BANK_STUCK
194
+ when LENGTH_LOW then @length & 0xff
195
+ when LENGTH_HIGH then @length >> 8
196
+ when INTERRUPT_MASK then @interrupt_mask
197
+ when ADDRESS_CONTROL then @address_control
198
+ else 0xff
199
+ end
200
+ end
201
+
202
+ def read_status
203
+ @status &= CHIPS_256K
204
+ interrupt(false)
205
+ end
206
+
207
+ # Writing either byte of an address or the length sets the value the
208
+ # transfer starts from, and puts the counter back to it.
209
+ def with_byte(word, value, high)
210
+ high ? (word & 0x00ff) | (value << 8) : (word & 0xff00) | value
211
+ end
212
+
213
+ def write_command(value)
214
+ @command = value
215
+ return if value.nobits?(EXECUTE)
216
+
217
+ @armed = value.nobits?(NO_FF00_TRIGGER)
218
+ request_bus unless @armed
219
+ end
220
+
221
+ # An interrupt enabled over a block that already ended, or a fault
222
+ # already found, fires at once.
223
+ def write_interrupt_mask(value)
224
+ @interrupt_mask = value | 0x1f
225
+ interrupt_on(@status)
226
+ end
227
+
228
+ def interrupt_on(events)
229
+ return unless @interrupt_mask.anybits?(INTERRUPTS_ON)
230
+ return unless (events.anybits?(END_OF_BLOCK) && @interrupt_mask.anybits?(INTERRUPT_ON_END)) ||
231
+ (events.anybits?(FAULT) && @interrupt_mask.anybits?(INTERRUPT_ON_FAULT))
232
+
233
+ @status |= INTERRUPT_PENDING
234
+ interrupt(true)
235
+ end
236
+
237
+ def interrupt(level)
238
+ return if @irq == level
239
+
240
+ @irq = level
241
+ @on_irq_change&.call(level)
242
+ end
243
+
244
+ def request_bus
245
+ @requested = true
246
+ @ba_was_low = @vic.ba_low?
247
+ @on_dma&.call
248
+ end
249
+
250
+ def hold_off
251
+ @dma.write_ahead(@command & TRANSFER_TYPE, @c64, @expansion | (@bank << 16)) unless @ba_was_low
252
+ @ba_was_low = true
253
+ end
254
+
255
+ def start_transfer
256
+ @requested = false
257
+ @running = true
258
+ @dma.start(@command & TRANSFER_TYPE, @c64, @expansion | (@bank << 16), @length, @address_control)
259
+ end
260
+
261
+ # The execute bit drops and the $FF00 trigger turns off. With autoload
262
+ # the addresses and the length go back to where the transfer started,
263
+ # and otherwise they stay where it stopped.
264
+ def end_transfer
265
+ @running = false
266
+ @command = (@command & ~EXECUTE & 0xff) | NO_FF00_TRIGGER
267
+ events = @dma.events
268
+ @status |= events
269
+ @command.anybits?(AUTOLOAD) ? reload : keep_counters
270
+ interrupt_on(events)
271
+ end
272
+
273
+ def reload
274
+ @c64 = @c64_start
275
+ @expansion = @expansion_start
276
+ @bank = @bank_start
277
+ @length = @length_start
278
+ end
279
+
280
+ def keep_counters
281
+ @c64 = @dma.c64 if @address_control.nobits?(FIX_C64)
282
+ @length = @dma.length & 0xffff
283
+ return if @address_control.anybits?(FIX_EXPANSION)
284
+
285
+ address = @dma.expansion & @address_mask
286
+ @expansion = address & 0xffff
287
+ @bank = (address >> 16) & 0xff
288
+ end
289
+ end
290
+ end
291
+ end
@@ -1,15 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Badline
4
- class Computer
5
- # The keyword arguments Computer.new takes to build the machine a
4
+ class C64
5
+ # The keyword arguments C64.new takes to build the machine a
6
6
  # State from #snapshot was taken of.
7
- def self.setup(state)
8
- input = Snapshot::StateReader.new(state)
9
- input.marker("COMPUTER")
10
- input.check_stamp
11
- Snapshot::Setup.read(input)
12
- end
7
+ def self.setup(state) = Snapshot::C64Setup.from(state)
13
8
 
14
9
  # A new machine, built as the one a State from #snapshot was taken of,
15
10
  # at that state. `detached` builds it without the host's files
@@ -44,13 +39,13 @@ module Badline
44
39
  # The state goes into a new machine first, so one that fails leaves
45
40
  # this machine as it was.
46
41
  def restore(state)
47
- check_setup(Computer.setup(state))
48
- Computer.restored(state)
42
+ check_setup(C64.setup(state))
43
+ C64.restored(state)
49
44
  apply_state(state)
50
45
  end
51
46
 
52
47
  # Puts a State into the machine without trying it on a new one
53
- # first, for a machine built for it (Computer.restored): a state that
48
+ # first, for a machine built for it (C64.restored): a state that
54
49
  # fails leaves the machine part restored. `detached` restores it
55
50
  # without the host's files (Snapshot::StateReader).
56
51
  def apply_state(state, detached: false)
@@ -68,8 +63,8 @@ module Badline
68
63
  end
69
64
 
70
65
  def save_state(out)
71
- out.marker("COMPUTER").stamp
72
- Snapshot::Setup.of(address_bus).write(out)
66
+ out.marker(Snapshot::C64Setup::MARKER).stamp
67
+ Snapshot::C64Setup.of(address_bus).write(out)
73
68
  out.int(@cycles).boolean(@nmi_asserted).boolean(@cartridge_nmi).boolean(@restore_pulse).boolean(@freezing)
74
69
  out.int(@freeze_writes).boolean(!@pending_keys.nil?)
75
70
  out.ints(@pending_keys) if @pending_keys
@@ -77,15 +72,15 @@ module Badline
77
72
  save_cartridge(out)
78
73
  address_bus.save_state(out)
79
74
  @cpu.save_state(out)
80
- save_trap_drive(out)
75
+ save_trap_dos(out)
81
76
  save_serial_bus(out)
82
77
  save_reu(out)
83
78
  end
84
79
 
85
80
  def load_state(input)
86
- input.marker("COMPUTER")
81
+ input.marker(Snapshot::C64Setup::MARKER)
87
82
  input.check_stamp
88
- check_setup(Snapshot::Setup.read(input))
83
+ check_setup(Snapshot::C64Setup.read(input))
89
84
  @cycles = input.int
90
85
  @nmi_asserted = input.boolean?
91
86
  @cartridge_nmi = input.boolean?
@@ -99,7 +94,7 @@ module Badline
99
94
  address_bus.load_state(input)
100
95
  push_serial_lines
101
96
  @cpu.load_state(input)
102
- load_trap_drive(input)
97
+ load_trap_dos(input)
103
98
  load_serial_bus(input)
104
99
  load_reu(input)
105
100
  end
@@ -107,7 +102,7 @@ module Badline
107
102
  private
108
103
 
109
104
  def check_setup(setup)
110
- ours = Snapshot::Setup.of(address_bus)
105
+ ours = Snapshot::C64Setup.of(address_bus)
111
106
  return if setup == ours
112
107
 
113
108
  raise Snapshot::FormatError, "the state is of a machine with #{setup}, not #{ours}"
@@ -1,38 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Badline
4
- class Computer
5
- # The true drives on the C64's serial bus: a Drive1541, and a Drive1581
6
- # (Drive1581::Slot), each in a field of its own, and their state for a
7
- # snapshot.
4
+ class C64
5
+ # The true drives on the machine's serial bus: a Drives::Model1541, and a
6
+ # Drives::Model1581 (Drives::Model1581::Slot), each in a field of its own. C64,
7
+ # Vic20 and C128 each include it.
8
8
  module TrueDrives
9
- include Drive1581::Slot
9
+ include Drives::Model1581::Slot
10
10
 
11
- # Plugs in a Drive1541, which then runs alongside the C64 on its own
12
- # clock and talks to it over the serial bus. The serial traps stop
11
+ # Plugs in a Drives::Model1541, which then runs alongside the machine on its
12
+ # own clock and talks to it over the serial bus. The serial traps stop
13
13
  # answering the drive's device number, so the KERNAL's TALK, LISTEN and
14
14
  # byte transfers reach the drive. The LOAD and SAVE traps stay, and
15
15
  # still serve a mounted image.
16
16
  def attach_drive1541(drive)
17
17
  @iec_bus.detach(@drive1541) if @drive1541
18
- drive.host_clock_hz = region.clock_hz
18
+ drive.host_clock_hz = timing.clock_hz
19
19
  @drive1541 = drive
20
- drive.connect(iec_bus)
20
+ drive.connect(@iec_bus)
21
21
  @serial_trap&.device = serial_trap_device
22
+ drive1541_attached
22
23
  end
23
24
 
24
- # The true drive on the serial bus: the Drive1581 ahead of the
25
- # Drive1541, or nil.
25
+ # The true drive on the serial bus: the Drives::Model1581 ahead of the
26
+ # Drives::Model1541, or nil.
26
27
  def true_drive = @drive1581 || @drive1541
27
28
 
28
- # Plugs a Drive1541 in as device 8, in place of a 1581 there, and
29
+ # Plugs a Drives::Model1541 in as device 8, in place of a 1581 there, and
29
30
  # returns it.
30
31
  def plug_true_drive
31
32
  detach_drive1581 if drive1581_on_device8?
32
- Drive1541.new.tap { |drive| attach_drive1541(drive) }
33
+ Drives::Model1541.new.tap { |drive| attach_drive1541(drive) }
33
34
  end
34
35
 
35
- # Unplugs the Drive1541, leaving the serial bus with nothing on it.
36
+ # Unplugs the Drives::Model1541, leaving the serial bus with nothing on it.
36
37
  def detach_drive1541
37
38
  return unless @drive1541
38
39
 
@@ -50,29 +51,17 @@ module Badline
50
51
  @drive1541&.device == device || drive1581_on_device8? ? nil : device
51
52
  end
52
53
 
53
- # A true 1541 on the serial bus, then a 1581. The leading flag is the
54
- # bus itself, which every machine now has.
55
- def save_serial_bus(out)
56
- out.boolean(true).boolean(!@drive1541.nil?)
57
- if @drive1541
58
- out.int(@drive1541.device)
59
- @drive1541.save_state(out)
60
- end
61
- save_drive1581(out)
62
- end
63
-
64
- def load_serial_bus(input)
65
- input.boolean?
66
- load_drive1541(input)
67
- load_drive1581(input)
68
- end
54
+ # What the machine does as a 1541 goes on its bus. The VIC-20 waits
55
+ # for its DOS to boot before typing.
56
+ def drive1541_attached = nil
69
57
 
58
+ # A true 1541 on the serial bus, with its device number.
70
59
  def load_drive1541(input)
71
60
  return detach_drive1541 unless input.boolean?
72
61
 
73
62
  device = input.int
74
63
  detach_drive1541 if @drive1541 && @drive1541.device != device
75
- attach_drive1541(Drive1541.new(device:)) unless @drive1541
64
+ attach_drive1541(Drives::Model1541.new(device:)) unless @drive1541
76
65
  @drive1541.load_state(input)
77
66
  end
78
67
  end
@@ -1,24 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "badline/computer/true_drives"
4
- require "badline/computer/attachments"
5
- require "badline/computer/kernal_traps"
6
- require "badline/computer/saved_state"
3
+ require "badline/c64/common"
4
+ require "badline/c64/true_drives"
5
+ require "badline/c64/attachments"
6
+ require "badline/c64/kernal_traps"
7
+ require "badline/c64/saved_state"
7
8
 
8
9
  module Badline
9
- class Computer
10
+ class C64
10
11
  include IntegerHelper
11
12
  include KeyboardBuffer
13
+ include Machine::Clocking
14
+ include Common
12
15
  include Attachments
13
16
  include KernalTraps
14
17
  include SavedState
15
18
 
16
19
  attr_reader :address_bus, :cpu, :cycles, :drive1541
17
20
 
18
- # The path of the disk or directory device 8 serves through the traps
19
- # (Attachments), or an empty one.
20
- def mounted_path = @drive.nil? ? "" : @drive.path
21
-
22
21
  def family = :c64
23
22
 
24
23
  def region = address_bus.region
@@ -33,6 +32,11 @@ module Badline
33
32
 
34
33
  def ram = address_bus.ram
35
34
 
35
+ # Reads and writes memory as the CPU sees it, through the bus.
36
+ def peek(addr) = address_bus.peek(addr)
37
+
38
+ def poke(addr, value) = address_bus.poke(addr, value)
39
+
36
40
  def keyboard = address_bus.keyboard
37
41
 
38
42
  def joystick1 = address_bus.joystick1
@@ -46,18 +50,18 @@ module Badline
46
50
  def install_debug_register(&) = address_bus.install_debug_register(&)
47
51
 
48
52
  # The machine options (sid_model:, cia_model:, vic_model:, region: and
49
- # ram_expansion:) configure the AddressBus. The region sets the clock,
53
+ # ram_expansion:) configure the C64::Bus. The region sets the clock,
50
54
  # the VIC's raster and sprite timing, and the mains frequency the CIAs'
51
55
  # TOD clocks count. The KERNAL tells PAL from NTSC by the raster, so
52
56
  # every region boots the same ROMs. reu plugs an REU of that many K
53
57
  # into the expansion port, where it drives the IRQ line and takes the
54
58
  # bus for its transfers. kernal:, datasette: and board: fit the bus
55
- # afterwards (AddressBus::Fittings): the KERNAL ROM, the cassette port,
59
+ # afterwards (C64::Bus::Fittings): the KERNAL ROM, the cassette port,
56
60
  # which is empty on the SX-64, and the board and case.
57
61
  def initialize(debug: false, reu: nil, **machine)
58
- @address_bus = AddressBus.new(**machine.except(*AddressBus::Fittings::NAMES))
59
- @address_bus.fit(**machine.slice(*AddressBus::Fittings::NAMES))
60
- @cpu = CPU.new(@address_bus, debug:)
62
+ @address_bus = Bus.new(**machine.except(*Bus::Fittings::NAMES))
63
+ @address_bus.fit(**machine.slice(*Bus::Fittings::NAMES))
64
+ @cpu = Chips::CPU.new(@address_bus, debug:)
61
65
  @vic = @address_bus.vic
62
66
  @vic.open_bus = -> { @address_bus.ram.peek(@cpu.program_counter) }
63
67
  @cia1 = @address_bus.cia1
@@ -74,7 +78,7 @@ module Badline
74
78
  @freeze_writes = 0
75
79
  @init_handlers = []
76
80
  @pending_keys = nil
77
- @drive = nil
81
+ @dos = nil
78
82
  @serial_trap = nil
79
83
  @save_trap = nil
80
84
  @drive1541 = nil
@@ -108,46 +112,17 @@ module Badline
108
112
  @cycles += 1
109
113
  end
110
114
 
111
- # Runs `count` cycles, one #cycle! after another.
112
- def run_cycles(count)
113
- i = 0
114
- while i < count
115
- cycle!
116
- i += 1
117
- end
118
- end
119
-
120
- # Runs cycles until the block returns true or the cycle count passes
121
- # `limit`, checking before each cycle.
122
- def run_until(limit)
123
- cycle! until yield || @cycles > limit
124
- end
125
-
126
115
  # The cycle at which #on_init's handlers run, once the KERNAL has booted.
127
116
  def init_threshold
128
117
  INIT_THRESHOLD
129
118
  end
130
119
 
131
- # The clock, the raster and the crop of the machine's region, a pixel
132
- # to a window pixel.
133
- def timing
134
- region = address_bus.region
135
- Timing.new(clock_hz: region.clock_hz, cycles_per_line: region.cycles_per_line,
136
- lines_per_frame: region.lines_per_frame, crop: region.crop, pixel_width: 1)
137
- end
138
-
139
120
  # The chip whose #display a front end shows.
140
121
  def video = @vic
141
122
 
142
123
  # The chip a front end records the machine's sound from.
143
124
  def sound_source = @sid
144
125
 
145
- def load_prg(data)
146
- uint16(data[0], data[1]).tap do |load_addr|
147
- ram.write(load_addr, data[2..])
148
- end
149
- end
150
-
151
126
  def attach_cartridge(cartridge)
152
127
  connect_cartridge(cartridge)
153
128
  power_cycle!
@@ -175,7 +150,7 @@ module Badline
175
150
  address_bus.cartridge&.reset
176
151
  @reu&.reset!
177
152
  @dma = false
178
- @drive&.reset!
153
+ @dos&.reset!
179
154
  @drive1541&.reset!
180
155
  @drive1581&.reset!
181
156
  @freezing = false
@@ -208,37 +183,12 @@ module Badline
208
183
  # The one-shot has pulsed already, so letting go does nothing.
209
184
  def release_restore; end
210
185
 
211
- def capture_output
212
- @capture_output ||= ChroutTrap.new(cpu:, bus: address_bus, layout: KernalTrap::C64_LAYOUT).tap do |trap|
213
- cpu.install_trap(ChroutTrap::ADDRESS) { trap.call }
214
- end
215
- end
216
-
217
- def inspect
218
- "#<#{self.class.name} cycles=#{@cycles} cpu=(#{@cpu.inspect})>"
219
- end
220
-
221
- def on_init(&block)
222
- if booting?
223
- @init_handlers << block
224
- else
225
- block.call
226
- end
227
- end
228
-
229
186
  private
230
187
 
231
- # The KERNAL the traps stand in for (Attachments#mount).
188
+ # The KERNAL the traps stand in for (KernalTraps#mount).
232
189
  def trap_layout = KernalTrap::C64_LAYOUT
233
190
 
234
- # The NMI line is wired-OR between CIA 2, the cartridge and the RESTORE
235
- # key, and the CPU takes an interrupt on its falling edge.
236
- def drive_nmi
237
- nmi = @cia2.interrupted? || @cartridge_nmi || @restore_pulse
238
- @restore_pulse = false
239
- @cpu.nmi = true if nmi && !@nmi_asserted
240
- @nmi_asserted = nmi
241
- end
191
+ def trap_bus = address_bus
242
192
 
243
193
  def plug_reu(size_kb)
244
194
  reu = REU.new(size_kb, bus: @address_bus, vic: @vic)
@@ -278,13 +228,5 @@ module Badline
278
228
  @freezing = false
279
229
  address_bus.cartridge.freeze!
280
230
  end
281
-
282
- def booting?
283
- @cycles < init_threshold
284
- end
285
-
286
- def handle_init
287
- @init_handlers.each(&:call)
288
- end
289
231
  end
290
232
  end