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,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ class Cartridge
6
+ # 16K. Reading I/O 2 switches ROMH out (8K mode) until reset.
7
+ class Westermann < Cartridge
8
+ def readable_io_pages
9
+ [0xdf]
10
+ end
11
+
12
+ def peek(addr)
13
+ select_mode(:rom8k) if addr >= 0xdf00
14
+ open_bus(addr)
15
+ end
16
+
17
+ def reset
18
+ select_mode(:rom16k)
19
+ end
20
+
21
+ private
22
+
23
+ def install_chips(chips)
24
+ roml, romh = banks_from(chips)
25
+ @roml = bank(roml, 0)
26
+ @romh = bank(romh, 0)
27
+ reset
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ class Cartridge
6
+ # Zaxxon / Super Zaxxon: 16K mode with a 4K ROML mirrored across
7
+ # $8000-$9FFF and two 8K ROMH banks. A read through ROML selects the
8
+ # ROMH bank: $8000-$8FFF the first, $9000-$9FFF the second.
9
+ class Zaxxon < Cartridge
10
+ class Low
11
+ def initialize(rom, high)
12
+ @rom = rom
13
+ @high = high
14
+ end
15
+
16
+ def peek(addr)
17
+ @high.select(addr[12])
18
+ @rom.peek(addr)
19
+ end
20
+ end
21
+
22
+ class High
23
+ def initialize(banks)
24
+ @banks = banks
25
+ select(0)
26
+ end
27
+
28
+ def select(number)
29
+ @bank = @banks[number] || EMPTY_BANK
30
+ end
31
+
32
+ def peek(addr)
33
+ @bank.peek(addr)
34
+ end
35
+
36
+ def save_state(out)
37
+ out.int([*@banks, EMPTY_BANK].index { |bank| bank.equal?(@bank) })
38
+ end
39
+
40
+ def load_state(input)
41
+ @bank = [*@banks, EMPTY_BANK].fetch(input.int)
42
+ end
43
+ end
44
+
45
+ def reset
46
+ @romh.select(0)
47
+ end
48
+
49
+ private
50
+
51
+ def save_mapper(out)
52
+ @romh.save_state(out)
53
+ end
54
+
55
+ def load_mapper(input)
56
+ @romh.load_state(input)
57
+ end
58
+
59
+ def install_chips(chips)
60
+ roml, romh = banks_from(chips)
61
+ @romh = High.new(romh)
62
+ @roml = Low.new(roml.first || EMPTY_BANK, @romh)
63
+ self.mode = :rom16k
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,258 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "badline/c64/cartridge/bank"
4
+ require "badline/c64/cartridge/flash"
5
+ require "badline/c64/cartridge/standard"
6
+ require "badline/c64/cartridge/simons_basic"
7
+ require "badline/c64/cartridge/ocean"
8
+ require "badline/c64/cartridge/fun_play"
9
+ require "badline/c64/cartridge/super_games"
10
+ require "badline/c64/cartridge/epyx_fastload"
11
+ require "badline/c64/cartridge/westermann"
12
+ require "badline/c64/cartridge/rex_utility"
13
+ require "badline/c64/cartridge/game_system"
14
+ require "badline/c64/cartridge/dinamic"
15
+ require "badline/c64/cartridge/zaxxon"
16
+ require "badline/c64/cartridge/magic_desk"
17
+ require "badline/c64/cartridge/comal80"
18
+ require "badline/c64/cartridge/easy_flash"
19
+ require "badline/c64/cartridge/mach5"
20
+ require "badline/c64/cartridge/pagefox"
21
+ require "badline/c64/cartridge/rgcd"
22
+ require "badline/c64/cartridge/g_mod2"
23
+ require "badline/c64/cartridge/freezer"
24
+ require "badline/c64/cartridge/action_replay"
25
+ require "badline/c64/cartridge/atomic_power"
26
+ require "badline/c64/cartridge/final_cartridge3"
27
+ require "badline/c64/cartridge/retro_replay"
28
+ require "badline/c64/cartridge/kcs_power"
29
+ require "badline/c64/cartridge/geo_ram"
30
+ require "badline/c64/cartridge/saved_state"
31
+
32
+ module Badline
33
+ class C64
34
+ class Cartridge
35
+ include SavedState
36
+
37
+ class UnsupportedTypeError < StandardError; end
38
+
39
+ ROMH_START = 0xa000
40
+ BANK_SIZE = 0x2000
41
+
42
+ HARDWARE_TYPES = {
43
+ 0 => Standard, 1 => ActionReplay, 2 => KCSPower, 3 => FinalCartridge3,
44
+ 4 => SimonsBasic, 5 => Ocean, 7 => FunPlay, 8 => SuperGames,
45
+ 9 => AtomicPower, 10 => EpyxFastload, 11 => Westermann,
46
+ 12 => RexUtility, 15 => GameSystem, 17 => Dinamic, 18 => Zaxxon,
47
+ 19 => MagicDesk, 21 => Comal80, 32 => EasyFlash, 36 => RetroReplay,
48
+ 51 => Mach5, 53 => Pagefox, 57 => RGCD, 60 => GMod2
49
+ }.freeze
50
+
51
+ # The EXROM and GAME line levels of each memory configuration. The lines
52
+ # are active low.
53
+ MODES = {
54
+ rom8k: [0, 1].freeze, rom16k: [0, 0].freeze,
55
+ ultimax: [1, 0].freeze, off: [1, 1].freeze
56
+ }.freeze
57
+
58
+ attr_reader :name, :exrom, :game, :roml, :romh
59
+
60
+ # A callable returning the current cycle, for mappers with timed state.
61
+ attr_writer :clock
62
+
63
+ class << self
64
+ # Options set the cartridge's jumpers, for the mappers that have them.
65
+ def from_file(path, **)
66
+ from_crt(Storage::CRTFile.new(path), **)
67
+ end
68
+
69
+ def from_crt(crt, **)
70
+ mapper_for(crt).new(crt, **)
71
+ end
72
+
73
+ # A cartridge built afresh from what save_setup wrote, before
74
+ # load_state puts its state in.
75
+ def from_setup(input)
76
+ return GeoRAM.new(size: input.int) if input.int == GEO_RAM_SETUP
77
+
78
+ crt = Storage::CRTFile.new(bytes: input.string)
79
+ mapper_for(crt).from_jumpers(crt, input)
80
+ end
81
+
82
+ # A cartridge from its image and what save_jumpers wrote: whether
83
+ # there are jumpers, then their settings on a mapper that has them.
84
+ def from_jumpers(crt, input)
85
+ input.boolean?
86
+ new(crt)
87
+ end
88
+
89
+ def mapper_for(crt)
90
+ HARDWARE_TYPES.fetch(crt.hardware_type) do
91
+ raise UnsupportedTypeError,
92
+ "Unsupported cartridge hardware type #{crt.hardware_type}"
93
+ end
94
+ end
95
+ end
96
+
97
+ # What save_setup writes first: a cartridge from a CRT image, or a
98
+ # GEO-RAM.
99
+ CRT_SETUP = 0
100
+ GEO_RAM_SETUP = 1
101
+
102
+ # Keeps the image it was built from, so a snapshot's machine can build
103
+ # the same cartridge before the snapshot's state goes into it.
104
+ def initialize(crt)
105
+ @crt = crt
106
+ @name = crt.name
107
+ @exrom = crt.exrom
108
+ @game = crt.game
109
+ @roml = @romh = nil
110
+ @banks = nil
111
+ @on_change = nil
112
+ @on_nmi_change = nil
113
+ @nmi = false
114
+ @open_bus = nil
115
+ @clock = nil
116
+ install_chips(crt.chips)
117
+ end
118
+
119
+ def on_change(&block)
120
+ @on_change = block
121
+ end
122
+
123
+ # Called with the level of the cartridge's pull on the NMI line when it
124
+ # changes. The line is wired-OR with CIA 2's.
125
+ def on_nmi_change(&block)
126
+ @on_nmi_change = block
127
+ end
128
+
129
+ def nmi?
130
+ @nmi
131
+ end
132
+
133
+ # The address bus hands over the C64's RAM, for mappers that write
134
+ # through to it, and the open bus, for I/O reads the cartridge doesn't
135
+ # drive.
136
+ def connect(ram:, open_bus:)
137
+ @ram = ram
138
+ @open_bus = open_bus
139
+ end
140
+
141
+ def ultimax?
142
+ @game.zero? && @exrom == 1
143
+ end
144
+
145
+ # Whether the first half of the cycle, where the VIC does most of its
146
+ # fetching, sees Ultimax mode. Some cartridges drive GAME and EXROM
147
+ # differently in the two halves; #ultimax? is the second, the CPU's.
148
+ def phi1_ultimax?
149
+ ultimax?
150
+ end
151
+
152
+ # The I/O pages ($de, $df) whose reads the mapper drives. Reads of the
153
+ # others are open bus.
154
+ def readable_io_pages
155
+ []
156
+ end
157
+
158
+ def poke(_addr, _value); end
159
+
160
+ # A window taking writes to $E000-$FFFF while reads there see the C64's
161
+ # memory, for a cartridge that asserts Ultimax on write cycles only.
162
+ def romh_writes; end
163
+
164
+ # A window at $A000-$BFFF in Ultimax mode, where the C64 maps nothing.
165
+ def ultimax_a000; end
166
+
167
+ # The RES line on the expansion port.
168
+ def reset; end
169
+
170
+ # Whether the cartridge has a freeze button.
171
+ def freezer? = false
172
+
173
+ # The freeze button, which cartridges without one ignore.
174
+ def press_button; end
175
+
176
+ def release_button; end
177
+
178
+ private
179
+
180
+ # The banks and views ROML and ROMH can point at, which a snapshot
181
+ # names them by: the mapper's banks, or nothing for a mapper whose
182
+ # windows stay where install_chips put them.
183
+ def windows
184
+ [*@banks, EMPTY_BANK] if @banks
185
+ end
186
+
187
+ def window_index(window, windows)
188
+ return -1 if window.nil?
189
+
190
+ windows.index { |candidate| candidate.equal?(window) } ||
191
+ raise(ArgumentError, "#{self.class.name}: a window that isn't among its banks")
192
+ end
193
+
194
+ def window_at(index, windows) = index.negative? ? nil : windows.fetch(index)
195
+
196
+ def nmi=(level)
197
+ return if @nmi == level
198
+
199
+ @nmi = level
200
+ @on_nmi_change&.call(level)
201
+ end
202
+
203
+ def changed!
204
+ @on_change&.call
205
+ end
206
+
207
+ def mode=(mode)
208
+ @exrom, @game = MODES.fetch(mode)
209
+ end
210
+
211
+ # Sets the lines and tells the machine to map the cartridge again.
212
+ def select_mode(mode)
213
+ self.mode = mode
214
+ changed!
215
+ end
216
+
217
+ def open_bus(addr)
218
+ @open_bus ? @open_bus.peek(addr) : 0xff
219
+ end
220
+
221
+ def install_chips(_chips)
222
+ raise NotImplementedError
223
+ end
224
+
225
+ def rom_bank(data)
226
+ Bank.new(data)
227
+ end
228
+
229
+ # A bank the image leaves out reads as erased ROM.
230
+ def bank(banks, number)
231
+ banks[number] || EMPTY_BANK
232
+ end
233
+
234
+ # The bank register bits a ROM decodes. The ROM holds the highest bank
235
+ # in the image, and has address lines for the power of two that covers
236
+ # it; the register bits above those lines are ignored.
237
+ def bank_mask(banks)
238
+ (1 << (banks.length - 1).bit_length) - 1
239
+ end
240
+
241
+ # Sorts the CHIP packets into ROML and ROMH banks by load address. A 16K
242
+ # chip at $8000 spans both.
243
+ def banks_from(chips)
244
+ roml = []
245
+ romh = []
246
+ chips.each do |chip|
247
+ if chip.address >= ROMH_START
248
+ romh[chip.bank] = rom_bank(chip.data)
249
+ else
250
+ roml[chip.bank] = rom_bank(chip.data[0, BANK_SIZE])
251
+ romh[chip.bank] = rom_bank(chip.data[BANK_SIZE, BANK_SIZE]) if chip.data.length > BANK_SIZE
252
+ end
253
+ end
254
+ [roml, romh]
255
+ end
256
+ end
257
+ end
258
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ # Colour RAM is four bits wide. A CPU read takes the upper nibble off the
6
+ # open data bus, which still holds the byte the VIC fetched in phi1.
7
+ class ColorMemory < Memory
8
+ def initialize(vic, start: 0xd800, length: 2**10)
9
+ super(start:, length:)
10
+ @vic = vic
11
+ end
12
+
13
+ def peek(addr)
14
+ (@vic.phi1_data & 0xf0) | @storage[offset_of(addr)]
15
+ end
16
+
17
+ def poke(addr, value)
18
+ super(addr, value & 0x0f)
19
+ end
20
+
21
+ # The four bits the cell stores, as the VIC's c-access sees them.
22
+ def nibble(addr)
23
+ @storage[offset_of(addr)]
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ # What the C128 does as the C64 does: the NMI line, a PRG put into RAM
6
+ # and the region's timing. C64 and C128 each include it.
7
+ module Common
8
+ # The clock, the raster and the crop of the machine's region, a pixel
9
+ # to a window pixel.
10
+ def timing
11
+ region = address_bus.region
12
+ Timing.new(clock_hz: region.clock_hz, cycles_per_line: region.cycles_per_line,
13
+ lines_per_frame: region.lines_per_frame, crop: region.crop, pixel_width: 1)
14
+ end
15
+
16
+ def load_prg(data)
17
+ uint16(data[0], data[1]).tap do |load_addr|
18
+ ram.write(load_addr, data[2..])
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ # The NMI line is wired-OR between CIA 2, the cartridge and the RESTORE
25
+ # key, and the CPU takes an interrupt on its falling edge.
26
+ def drive_nmi
27
+ nmi = @cia2.interrupted? || @cartridge_nmi || @restore_pulse
28
+ @restore_pulse = false
29
+ @cpu.nmi = true if nmi && !@nmi_asserted
30
+ @nmi_asserted = nmi
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ # The disk device 8 serves through the LOAD, SAVE and serial traps, and
6
+ # CHROUT capture, on the KERNAL the machine runs. C64, Vic20 and
7
+ # C128 each include it and answer two private methods: #trap_layout,
8
+ # the KernalTrap::Layout of that KERNAL, and #trap_bus, the bus the
9
+ # traps read and write through.
10
+ module KernalTraps
11
+ # Puts the storage in device 8. Mounting again swaps the disk at any
12
+ # point while the machine runs: the drive keeps its RAM, which only a
13
+ # drive reset clears, and its status. The traps go on the KERNAL the
14
+ # machine runs (#trap_layout).
15
+ def mount(storage)
16
+ return @dos.insert(storage) if @dos
17
+
18
+ @dos = KernalTrap::DOS.new(storage)
19
+ install_kernal_traps(trap_layout)
20
+ end
21
+
22
+ # Takes device 8's mounted storage out, and with it the LOAD, SAVE and
23
+ # serial traps, so the KERNAL's routines go out over the serial bus.
24
+ # Mounting again starts a new drive, with its RAM cleared.
25
+ def unmount
26
+ return unless @dos
27
+
28
+ remove_kernal_traps
29
+ @dos = nil
30
+ end
31
+
32
+ # Whether device 8 serves a disk or directory through the traps.
33
+ def mounted? = !@dos.nil?
34
+
35
+ # The path of the disk or directory device 8 serves through the
36
+ # traps, or an empty one.
37
+ def mounted_path = @dos.nil? ? "" : @dos.path
38
+
39
+ # Records what the KERNAL prints through CHROUT (ChroutTrap).
40
+ def capture_output
41
+ @capture_output ||= ChroutTrap.new(cpu:, bus: trap_bus, layout: trap_layout).tap do |trap|
42
+ cpu.install_trap(ChroutTrap::ADDRESS) { trap.call }
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def install_kernal_traps(layout)
49
+ @trap_layout = layout
50
+ load_trap = KernalTrap::Load.new(cpu:, bus: trap_bus, layout:, dos: @dos)
51
+ cpu.install_trap(layout.load) { load_trap.call }
52
+ @serial_trap = KernalTrap::Serial.new(cpu:, bus: trap_bus, layout:, dos: @dos,
53
+ device: serial_trap_device).install
54
+ save_trap = @save_trap = KernalTrap::Save.new(cpu:, bus: trap_bus, layout:, dos: @dos)
55
+ cpu.install_trap(layout.save) { save_trap.call }
56
+ end
57
+
58
+ def remove_kernal_traps
59
+ cpu.remove_trap(@trap_layout.load)
60
+ cpu.remove_trap(@trap_layout.save)
61
+ @serial_trap.uninstall
62
+ @serial_trap = nil
63
+ @save_trap = nil
64
+ end
65
+
66
+ # The disk device 8 serves through the traps, with the traps' own
67
+ # state: open channels, the drive's status and RAM, a SAVE under way.
68
+ def save_trap_dos(out)
69
+ out.boolean(!@dos.nil?)
70
+ return unless @dos
71
+
72
+ @dos.save_state(out)
73
+ @serial_trap.save_state(out)
74
+ @save_trap.save_state(out)
75
+ end
76
+
77
+ def load_trap_dos(input)
78
+ return unmount unless input.boolean?
79
+
80
+ storage = Snapshot::StorageSetup.read(input)
81
+ unmount
82
+ mount(storage)
83
+ @dos.load_state(input)
84
+ @serial_trap.load_state(input)
85
+ @save_trap.load_state(input)
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ class REU
6
+ class DMA
7
+ # A transfer's state for a snapshot (REU::SavedState).
8
+ module SavedState
9
+ # Everything a transfer holds between cycles. Before the first
10
+ # transfer, the fields it sets on starting are empty.
11
+ def save_state(out)
12
+ out.int(@c64).int(@expansion).int(@length).int(@events)
13
+ [@type, @c64_step, @expansion_step, @last, @ba_low_after_writes, @swap_byte, @held_read].each do |value|
14
+ out.optional_int(value)
15
+ end
16
+ [@holding, @waiting, @stopped_after_write, @swap_write_due, @swap_read_again, @moved_all,
17
+ @extra_cycle].each do |flag|
18
+ out.boolean(flag)
19
+ end
20
+ end
21
+
22
+ def load_state(input)
23
+ @c64 = input.int
24
+ @expansion = input.int
25
+ @length = input.int
26
+ @events = input.int
27
+ load_steps(input)
28
+ @holding = input.boolean?
29
+ @waiting = input.boolean?
30
+ @stopped_after_write = input.boolean?
31
+ @swap_write_due = input.boolean?
32
+ @swap_read_again = input.boolean?
33
+ @moved_all = input.boolean?
34
+ @extra_cycle = input.boolean?
35
+ end
36
+
37
+ private
38
+
39
+ def load_steps(input)
40
+ @type = input.optional_int
41
+ @c64_step = input.optional_int
42
+ @expansion_step = input.optional_int
43
+ @last = input.optional_int
44
+ @ba_low_after_writes = input.optional_int
45
+ @swap_byte = input.optional_int
46
+ @held_read = input.optional_int
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end