badline 0.12.1 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (565) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -1
  3. data/CLAUDE.md +86 -38
  4. data/CONTRIBUTING.md +4 -3
  5. data/README.md +9 -6
  6. data/doc/library.md +9 -9
  7. data/doc/media.md +2 -1
  8. data/doc/pinned-behaviour.md +134 -105
  9. data/doc/snapshot-format.md +1047 -0
  10. data/doc/snapshots.md +73 -43
  11. data/lib/badline/audio/bare_player.rb +53 -20
  12. data/lib/badline/audio/cli.rb +6 -6
  13. data/lib/badline/audio/jukebox.rb +2 -2
  14. data/lib/badline/audio/machine_player.rb +16 -10
  15. data/lib/badline/{media → audio}/queue.rb +1 -1
  16. data/lib/badline/audio/queued_tune.rb +6 -6
  17. data/lib/badline/audio/renderer.rb +33 -22
  18. data/lib/badline/audio/stereo.rb +1 -1
  19. data/lib/badline/c128/banks.rb +6 -3
  20. data/lib/badline/c128/bus/keyed_state.rb +45 -0
  21. data/lib/badline/c128/bus.rb +35 -20
  22. data/lib/badline/c128/color_lines.rb +2 -2
  23. data/lib/badline/c128/cpu.rb +1 -1
  24. data/lib/badline/c128/drives.rb +14 -34
  25. data/lib/badline/c128/fast_serial.rb +5 -5
  26. data/lib/badline/c128/keyed_modules.rb +117 -0
  27. data/lib/badline/c128/keyed_state.rb +91 -0
  28. data/lib/badline/c128/keys.rb +9 -0
  29. data/lib/badline/c128/mmu.rb +9 -8
  30. data/lib/badline/c128/mmu_pages.rb +21 -1
  31. data/lib/badline/c128/modes.rb +21 -11
  32. data/lib/badline/c128/z80.rb +2 -2
  33. data/lib/badline/c128/z80_turns.rb +1 -1
  34. data/lib/badline/c128.rb +21 -16
  35. data/lib/badline/c64/attachments.rb +42 -0
  36. data/lib/badline/c64/banked_ram/banking.rb +32 -0
  37. data/lib/badline/c64/banked_ram/plus256k.rb +64 -0
  38. data/lib/badline/c64/banked_ram/plus60k.rb +47 -0
  39. data/lib/badline/c64/banked_ram/unexpanded.rb +30 -0
  40. data/lib/badline/c64/banked_ram.rb +23 -0
  41. data/lib/badline/c64/bus/debug_register.rb +32 -0
  42. data/lib/badline/c64/bus/extra_sids.rb +32 -0
  43. data/lib/badline/c64/bus/fittings.rb +40 -0
  44. data/lib/badline/c64/bus/keyed_state.rb +41 -0
  45. data/lib/badline/c64/bus/pla.rb +149 -0
  46. data/lib/badline/c64/bus/roms.rb +41 -0
  47. data/lib/badline/c64/bus/sid_slots.rb +44 -0
  48. data/lib/badline/c64/bus.rb +219 -0
  49. data/lib/badline/c64/cartridge/action_replay.rb +115 -0
  50. data/lib/badline/c64/cartridge/atomic_power.rb +26 -0
  51. data/lib/badline/c64/cartridge/bank.rb +83 -0
  52. data/lib/badline/c64/cartridge/comal80.rb +52 -0
  53. data/lib/badline/c64/cartridge/dinamic.rb +36 -0
  54. data/lib/badline/c64/cartridge/easy_flash.rb +132 -0
  55. data/lib/badline/c64/cartridge/epyx_fastload.rb +73 -0
  56. data/lib/badline/c64/cartridge/final_cartridge3.rb +79 -0
  57. data/lib/badline/c64/cartridge/flash.rb +279 -0
  58. data/lib/badline/c64/cartridge/freezer.rb +35 -0
  59. data/lib/badline/c64/cartridge/fun_play.rb +40 -0
  60. data/lib/badline/c64/cartridge/g_mod2.rb +64 -0
  61. data/lib/badline/c64/cartridge/game_system.rb +42 -0
  62. data/lib/badline/c64/cartridge/geo_ram.rb +65 -0
  63. data/lib/badline/c64/cartridge/kcs_power.rb +69 -0
  64. data/lib/badline/c64/cartridge/keyed_state.rb +393 -0
  65. data/lib/badline/c64/cartridge/mach5.rb +34 -0
  66. data/lib/badline/c64/cartridge/magic_desk.rb +32 -0
  67. data/lib/badline/c64/cartridge/ocean.rb +37 -0
  68. data/lib/badline/c64/cartridge/pagefox.rb +60 -0
  69. data/lib/badline/c64/cartridge/retro_replay.rb +278 -0
  70. data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
  71. data/lib/badline/c64/cartridge/rgcd.rb +50 -0
  72. data/lib/badline/c64/cartridge/simons_basic.rb +37 -0
  73. data/lib/badline/c64/cartridge/standard.rb +17 -0
  74. data/lib/badline/c64/cartridge/super_games.rb +40 -0
  75. data/lib/badline/c64/cartridge/westermann.rb +32 -0
  76. data/lib/badline/c64/cartridge/zaxxon.rb +52 -0
  77. data/lib/badline/c64/cartridge.rb +232 -0
  78. data/lib/badline/c64/color_memory.rb +27 -0
  79. data/lib/badline/{computer → c64}/common.rb +2 -2
  80. data/lib/badline/{computer → c64}/kernal_traps.rb +39 -36
  81. data/lib/badline/c64/keyed_modules.rb +111 -0
  82. data/lib/badline/c64/keyed_state.rb +68 -0
  83. data/lib/badline/c64/reu/dma.rb +271 -0
  84. data/lib/badline/c64/reu/keyed_state.rb +140 -0
  85. data/lib/badline/c64/reu/ram.rb +94 -0
  86. data/lib/badline/c64/reu/trigger.rb +34 -0
  87. data/lib/badline/c64/reu.rb +289 -0
  88. data/lib/badline/c64/true_drives.rb +120 -0
  89. data/lib/badline/{computer.rb → c64.rb} +24 -15
  90. data/lib/badline/chips/cia/fast_forward.rb +62 -0
  91. data/lib/badline/chips/cia/interrupt_register.rb +128 -0
  92. data/lib/badline/chips/cia/keyed_parts.rb +213 -0
  93. data/lib/badline/chips/cia/serial.rb +246 -0
  94. data/lib/badline/chips/cia/time_of_day.rb +210 -0
  95. data/lib/badline/chips/cia/timer.rb +188 -0
  96. data/lib/badline/chips/cia.rb +281 -0
  97. data/lib/badline/chips/cpu/addressing.rb +133 -0
  98. data/lib/badline/chips/cpu/boundary.rb +56 -0
  99. data/lib/badline/chips/cpu/core.rb +183 -0
  100. data/lib/badline/chips/cpu/instruction.rb +338 -0
  101. data/lib/badline/chips/cpu/instruction_set/arithmetic.rb +118 -0
  102. data/lib/badline/chips/cpu/instruction_set/bitwise.rb +130 -0
  103. data/lib/badline/chips/cpu/instruction_set/branch.rb +83 -0
  104. data/lib/badline/chips/cpu/instruction_set/flag.rb +67 -0
  105. data/lib/badline/chips/cpu/instruction_set/illegal.rb +274 -0
  106. data/lib/badline/chips/cpu/instruction_set/inc_dec.rb +73 -0
  107. data/lib/badline/chips/cpu/instruction_set/stack.rb +56 -0
  108. data/lib/badline/chips/cpu/instruction_set/transfer.rb +141 -0
  109. data/lib/badline/chips/cpu/instruction_set.rb +59 -0
  110. data/lib/badline/chips/cpu/interrupts.rb +108 -0
  111. data/lib/badline/chips/cpu/keyed_state.rb +177 -0
  112. data/lib/badline/chips/cpu/microcode.rb +195 -0
  113. data/lib/badline/chips/cpu/operations.rb +90 -0
  114. data/lib/badline/chips/cpu/port.rb +133 -0
  115. data/lib/badline/chips/cpu/stack_operations.rb +84 -0
  116. data/lib/badline/chips/cpu/traps.rb +23 -0
  117. data/lib/badline/chips/cpu.rb +17 -0
  118. data/lib/badline/chips/sid/catch_up.rb +122 -0
  119. data/lib/badline/chips/sid/decimator.rb +68 -0
  120. data/lib/badline/chips/sid/envelope.rb +236 -0
  121. data/lib/badline/chips/sid/filter.rb +227 -0
  122. data/lib/badline/chips/sid/keyed_parts.rb +286 -0
  123. data/lib/badline/chips/sid/voice.rb +69 -0
  124. data/lib/badline/chips/sid/waveform/combined.rb +128 -0
  125. data/lib/badline/chips/sid/waveform/fast_forward.rb +107 -0
  126. data/lib/badline/chips/sid/waveform/noise_writeback.rb +124 -0
  127. data/lib/badline/chips/sid/waveform.rb +305 -0
  128. data/lib/badline/chips/sid.rb +264 -0
  129. data/lib/badline/chips/ted/beam.rb +119 -0
  130. data/lib/badline/chips/ted/timers.rb +66 -0
  131. data/lib/badline/chips/ted.rb +143 -0
  132. data/lib/badline/chips/tia.rb +49 -0
  133. data/lib/badline/chips/vdc/keyed_parts.rb +105 -0
  134. data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
  135. data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -13
  136. data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -17
  137. data/lib/badline/{c128 → chips}/vdc/window.rb +1 -10
  138. data/lib/badline/{c128 → chips}/vdc.rb +6 -31
  139. data/lib/badline/chips/via/control_lines.rb +109 -0
  140. data/lib/badline/chips/via/fast_forward.rb +55 -0
  141. data/lib/badline/chips/via/interrupt_register.rb +60 -0
  142. data/lib/badline/chips/via/keyed_parts.rb +163 -0
  143. data/lib/badline/chips/via/shift_register.rb +168 -0
  144. data/lib/badline/chips/via/timer1.rb +120 -0
  145. data/lib/badline/chips/via/timer2.rb +117 -0
  146. data/lib/badline/chips/via.rb +267 -0
  147. data/lib/badline/chips/vic/bank.rb +135 -0
  148. data/lib/badline/chips/vic/border_mask.rb +78 -0
  149. data/lib/badline/chips/vic/collisions.rb +106 -0
  150. data/lib/badline/chips/vic/color_patches.rb +38 -0
  151. data/lib/badline/chips/vic/display_state.rb +168 -0
  152. data/lib/badline/chips/vic/graphics_mode.rb +166 -0
  153. data/lib/badline/chips/vic/graphics_shifter.rb +183 -0
  154. data/lib/badline/chips/vic/keyed_parts.rb +228 -0
  155. data/lib/badline/chips/vic/keyed_sprites.rb +225 -0
  156. data/lib/badline/chips/vic/keyed_state.rb +102 -0
  157. data/lib/badline/chips/vic/register_log.rb +65 -0
  158. data/lib/badline/chips/vic/registers.rb +188 -0
  159. data/lib/badline/chips/vic/sequencer.rb +275 -0
  160. data/lib/badline/chips/vic/sequencer_output.rb +118 -0
  161. data/lib/badline/chips/vic/sprite/internal_bus.rb +59 -0
  162. data/lib/badline/chips/vic/sprite/shifter.rb +148 -0
  163. data/lib/badline/chips/vic/sprite/timing.rb +58 -0
  164. data/lib/badline/chips/vic/sprite.rb +337 -0
  165. data/lib/badline/chips/vic/sprites.rb +281 -0
  166. data/lib/badline/chips/vic.rb +787 -0
  167. data/lib/badline/chips/vic_i/keyed_parts.rb +142 -0
  168. data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +2 -30
  169. data/lib/badline/chips/vic_i/sound/output.rb +85 -0
  170. data/lib/badline/chips/vic_i/sound.rb +227 -0
  171. data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
  172. data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +6 -6
  173. data/lib/badline/chips/z80/arithmetic.rb +119 -0
  174. data/lib/badline/chips/z80/bit_page.rb +57 -0
  175. data/lib/badline/chips/z80/block_io.rb +60 -0
  176. data/lib/badline/chips/z80/block_transfers.rb +61 -0
  177. data/lib/badline/chips/z80/bus_cycles.rb +113 -0
  178. data/lib/badline/chips/z80/core.rb +115 -0
  179. data/lib/badline/chips/z80/exchanges.rb +52 -0
  180. data/lib/badline/chips/z80/extended_page.rb +91 -0
  181. data/lib/badline/chips/z80/flags.rb +39 -0
  182. data/lib/badline/chips/z80/interrupt_acceptance.rb +48 -0
  183. data/lib/badline/chips/z80/jumps.rb +84 -0
  184. data/lib/badline/chips/z80/keyed_state.rb +73 -0
  185. data/lib/badline/chips/z80/loads.rb +100 -0
  186. data/lib/badline/chips/z80/main_page.rb +136 -0
  187. data/lib/badline/chips/z80/registers.rb +122 -0
  188. data/lib/badline/chips/z80/shifts.rb +66 -0
  189. data/lib/badline/chips/z80.rb +13 -0
  190. data/lib/badline/chips.rb +10 -0
  191. data/lib/badline/core.rb +13 -32
  192. data/lib/badline/drives/datasette/keyed_state.rb +38 -0
  193. data/lib/badline/drives/datasette.rb +173 -0
  194. data/lib/badline/drives/engine/core.rb +152 -0
  195. data/lib/badline/drives/engine/fast_serial.rb +75 -0
  196. data/lib/badline/drives/engine/idle.rb +127 -0
  197. data/lib/badline/drives/engine/idle_cpu.rb +30 -0
  198. data/lib/badline/drives/engine/orbit.rb +81 -0
  199. data/lib/badline/drives/engine/serial_lines.rb +72 -0
  200. data/lib/badline/drives/engine/sleep.rb +114 -0
  201. data/lib/badline/drives/engine/vias.rb +86 -0
  202. data/lib/badline/drives/engine/watch.rb +152 -0
  203. data/lib/badline/drives/engine.rb +11 -0
  204. data/lib/badline/drives/model1541/bus.rb +75 -0
  205. data/lib/badline/drives/model1541/byte_ready.rb +50 -0
  206. data/lib/badline/drives/model1541/cpu.rb +13 -0
  207. data/lib/badline/drives/model1541/disk.rb +318 -0
  208. data/lib/badline/drives/model1541/disk_via.rb +38 -0
  209. data/lib/badline/drives/model1541/gcr.rb +59 -0
  210. data/lib/badline/drives/model1541/keyed_state.rb +251 -0
  211. data/lib/badline/drives/model1541/mechanism.rb +313 -0
  212. data/lib/badline/drives/model1541/rotation.rb +123 -0
  213. data/lib/badline/drives/model1541/sector_reader.rb +78 -0
  214. data/lib/badline/drives/model1541/serial_port.rb +20 -0
  215. data/lib/badline/drives/model1541/track.rb +100 -0
  216. data/lib/badline/drives/model1541.rb +80 -0
  217. data/lib/badline/drives/model1571/bus.rb +100 -0
  218. data/lib/badline/drives/model1571/cpu.rb +13 -0
  219. data/lib/badline/drives/model1571/keyed_state.rb +108 -0
  220. data/lib/badline/drives/model1571/serial_port.rb +39 -0
  221. data/lib/badline/drives/model1571/serial_via.rb +27 -0
  222. data/lib/badline/drives/model1571/wd1770.rb +108 -0
  223. data/lib/badline/drives/model1571.rb +141 -0
  224. data/lib/badline/drives/model1581/bus.rb +126 -0
  225. data/lib/badline/drives/model1581/cpu.rb +13 -0
  226. data/lib/badline/drives/model1581/disk.rb +133 -0
  227. data/lib/badline/drives/model1581/keyed_state.rb +280 -0
  228. data/lib/badline/drives/model1581/mechanism.rb +98 -0
  229. data/lib/badline/drives/model1581/serial_port.rb +54 -0
  230. data/lib/badline/drives/model1581/slot.rb +61 -0
  231. data/lib/badline/drives/model1581/track.rb +102 -0
  232. data/lib/badline/drives/model1581/track_bytes.rb +77 -0
  233. data/lib/badline/drives/model1581/wd1772/registers.rb +91 -0
  234. data/lib/badline/drives/model1581/wd1772/sector_writes.rb +75 -0
  235. data/lib/badline/drives/model1581/wd1772/sectors.rb +152 -0
  236. data/lib/badline/drives/model1581/wd1772/stepping.rb +111 -0
  237. data/lib/badline/drives/model1581/wd1772/tracks.rb +127 -0
  238. data/lib/badline/drives/model1581/wd1772/turn.rb +75 -0
  239. data/lib/badline/drives/model1581/wd1772.rb +216 -0
  240. data/lib/badline/drives/model1581.rb +206 -0
  241. data/lib/badline/drives/serial_bus.rb +161 -0
  242. data/lib/badline/drives.rb +8 -0
  243. data/lib/badline/frontend/app.rb +3 -3
  244. data/lib/badline/frontend/boot.rb +4 -4
  245. data/lib/badline/frontend/controls.rb +19 -3
  246. data/lib/badline/frontend/drive_led.rb +44 -21
  247. data/lib/badline/frontend/machine_window.rb +3 -1
  248. data/lib/badline/frontend/menu/menu_dialogs.rb +2 -2
  249. data/lib/badline/frontend/player/filter_view.rb +1 -1
  250. data/lib/badline/frontend/player/player_controller.rb +2 -2
  251. data/lib/badline/frontend/player/player_screen.rb +1 -0
  252. data/lib/badline/frontend/player/theme.rb +7 -7
  253. data/lib/badline/frontend/snapshots.rb +12 -1
  254. data/lib/badline/frontend/timeline.rb +30 -12
  255. data/lib/badline/input/control_ports.rb +78 -0
  256. data/lib/badline/input/joystick.rb +27 -0
  257. data/lib/badline/input/keyboard.rb +114 -0
  258. data/lib/badline/input/matrix_typist.rb +98 -0
  259. data/lib/badline/input.rb +4 -0
  260. data/lib/badline/kernal_trap/chrout.rb +45 -0
  261. data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
  262. data/lib/badline/kernal_trap/dos/channel.rb +156 -0
  263. data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -26
  264. data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -10
  265. data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
  266. data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -9
  267. data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -19
  268. data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
  269. data/lib/badline/kernal_trap/{drive.rb → dos.rb} +9 -27
  270. data/lib/badline/kernal_trap/file_routine.rb +4 -4
  271. data/lib/badline/kernal_trap/keyed_state.rb +150 -0
  272. data/lib/badline/kernal_trap/layout.rb +75 -11
  273. data/lib/badline/kernal_trap/load.rb +19 -21
  274. data/lib/badline/kernal_trap/routine.rb +12 -0
  275. data/lib/badline/kernal_trap/save.rb +12 -22
  276. data/lib/badline/kernal_trap/serial.rb +8 -24
  277. data/lib/badline/kernal_trap.rb +3 -2
  278. data/lib/badline/machine/clocking.rb +1 -1
  279. data/lib/badline/machine/keyboard_buffer.rb +49 -0
  280. data/lib/badline/machine/settling.rb +29 -0
  281. data/lib/badline/machine.rb +10 -7
  282. data/lib/badline/media/boot_disk.rb +14 -2
  283. data/lib/badline/media/extensions.rb +10 -0
  284. data/lib/badline/media/true_drive.rb +1 -1
  285. data/lib/badline/media/tune.rb +2 -2
  286. data/lib/badline/media.rb +3 -3
  287. data/lib/badline/memory.rb +3 -6
  288. data/lib/badline/model.rb +1 -1
  289. data/lib/badline/options/family.rb +5 -2
  290. data/lib/badline/options/help.rb +42 -16
  291. data/lib/badline/options/table.rb +2 -0
  292. data/lib/badline/options/validation.rb +2 -0
  293. data/lib/badline/options.rb +6 -1
  294. data/lib/badline/plus4/acia.rb +45 -0
  295. data/lib/badline/plus4/bus.rb +312 -0
  296. data/lib/badline/plus4/cpu.rb +10 -0
  297. data/lib/badline/plus4/cpu_port.rb +93 -0
  298. data/lib/badline/plus4/keyboard_port.rb +51 -0
  299. data/lib/badline/plus4/model.rb +38 -0
  300. data/lib/badline/plus4/user_port.rb +31 -0
  301. data/lib/badline/plus4.rb +164 -0
  302. data/lib/badline/roms/README +44 -6
  303. data/lib/badline/roms/plus4/basic.rom +0 -0
  304. data/lib/badline/roms/plus4/function-high.rom +0 -0
  305. data/lib/badline/roms/plus4/function-low.rom +0 -0
  306. data/lib/badline/roms/plus4/kernal-ntsc.rom +0 -0
  307. data/lib/badline/roms/plus4/kernal-pal.rom +0 -0
  308. data/lib/badline/sdl.rb +1 -0
  309. data/lib/badline/{storage/sid_file.rb → sid_tune/file.rb} +3 -3
  310. data/lib/badline/{storage → sid_tune}/hvsc.rb +7 -7
  311. data/lib/badline/{storage → sid_tune}/song_lengths.rb +2 -2
  312. data/lib/badline/{storage → sid_tune}/stil/credit.rb +1 -1
  313. data/lib/badline/{storage → sid_tune}/stil.rb +3 -3
  314. data/lib/badline/sid_tune.rb +6 -0
  315. data/lib/badline/snapshot/c128_setup.rb +32 -0
  316. data/lib/badline/snapshot/c64_setup.rb +83 -0
  317. data/lib/badline/snapshot/container.rb +4 -0
  318. data/lib/badline/snapshot/field_doc/markdown.rb +112 -0
  319. data/lib/badline/snapshot/field_doc.rb +109 -0
  320. data/lib/badline/snapshot/image.rb +132 -46
  321. data/lib/badline/snapshot/keyed/cursor.rb +40 -0
  322. data/lib/badline/snapshot/keyed/modules.rb +66 -0
  323. data/lib/badline/snapshot/keyed/reader.rb +188 -0
  324. data/lib/badline/snapshot/keyed/recorder.rb +88 -0
  325. data/lib/badline/snapshot/keyed/report.rb +26 -0
  326. data/lib/badline/snapshot/keyed/writer.rb +55 -0
  327. data/lib/badline/snapshot/keyed.rb +64 -0
  328. data/lib/badline/snapshot/machine_state.rb +17 -64
  329. data/lib/badline/snapshot/storage_setup.rb +63 -0
  330. data/lib/badline/snapshot/vic20_setup.rb +28 -0
  331. data/lib/badline/snapshot/vice/c64_mem.rb +1 -1
  332. data/lib/badline/snapshot/vice/restore.rb +1 -1
  333. data/lib/badline/snapshot/vice/reu1764.rb +3 -3
  334. data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
  335. data/lib/badline/snapshot/vice.rb +13 -35
  336. data/lib/badline/snapshot.rb +44 -22
  337. data/lib/badline/storage/crt_file.rb +3 -1
  338. data/lib/badline/storage/d64_image.rb +0 -2
  339. data/lib/badline/storage/d71_image.rb +0 -2
  340. data/lib/badline/storage/d81_image.rb +0 -2
  341. data/lib/badline/storage/disk_image.rb +3 -6
  342. data/lib/badline/storage/g64_image.rb +10 -5
  343. data/lib/badline/storage/host_directory.rb +0 -5
  344. data/lib/badline/storage/t64.rb +2 -8
  345. data/lib/badline/storage/tap.rb +43 -15
  346. data/lib/badline/storage/unavailable.rb +1 -1
  347. data/lib/badline/storage.rb +0 -37
  348. data/lib/badline/support/c128_checkpoint.rb +39 -0
  349. data/lib/badline/support/checkpoint.rb +108 -0
  350. data/lib/badline/support/vic20_checkpoint.rb +38 -0
  351. data/lib/badline/support.rb +5 -0
  352. data/lib/badline/version.rb +1 -1
  353. data/lib/badline/vic20/attachments.rb +8 -5
  354. data/lib/badline/vic20/bus/keyed_state.rb +52 -0
  355. data/lib/badline/vic20/bus.rb +2 -25
  356. data/lib/badline/vic20/cpu.rb +1 -1
  357. data/lib/badline/vic20/keyed_modules.rb +73 -0
  358. data/lib/badline/vic20/keyed_state.rb +45 -0
  359. data/lib/badline/vic20/port_wiring.rb +4 -4
  360. data/lib/badline/vic20/user_via_ports.rb +2 -2
  361. data/lib/badline/vic20.rb +22 -17
  362. data/lib/badline.rb +1 -0
  363. metadata +271 -228
  364. data/lib/badline/address_bus/extra_sids.rb +0 -30
  365. data/lib/badline/address_bus/fittings.rb +0 -38
  366. data/lib/badline/address_bus/pla.rb +0 -147
  367. data/lib/badline/address_bus/roms.rb +0 -39
  368. data/lib/badline/address_bus/saved_state.rb +0 -66
  369. data/lib/badline/address_bus/sid_slots.rb +0 -42
  370. data/lib/badline/address_bus.rb +0 -216
  371. data/lib/badline/c128/bus_state.rb +0 -53
  372. data/lib/badline/c128/saved_state.rb +0 -143
  373. data/lib/badline/cartridge/action_replay.rb +0 -126
  374. data/lib/badline/cartridge/atomic_power.rb +0 -24
  375. data/lib/badline/cartridge/bank.rb +0 -81
  376. data/lib/badline/cartridge/comal80.rb +0 -50
  377. data/lib/badline/cartridge/dinamic.rb +0 -34
  378. data/lib/badline/cartridge/easy_flash.rb +0 -145
  379. data/lib/badline/cartridge/epyx_fastload.rb +0 -79
  380. data/lib/badline/cartridge/final_cartridge3.rb +0 -89
  381. data/lib/badline/cartridge/flash.rb +0 -306
  382. data/lib/badline/cartridge/freezer.rb +0 -33
  383. data/lib/badline/cartridge/fun_play.rb +0 -38
  384. data/lib/badline/cartridge/g_mod2.rb +0 -74
  385. data/lib/badline/cartridge/game_system.rb +0 -40
  386. data/lib/badline/cartridge/geo_ram.rb +0 -79
  387. data/lib/badline/cartridge/kcs_power.rb +0 -75
  388. data/lib/badline/cartridge/mach5.rb +0 -32
  389. data/lib/badline/cartridge/magic_desk.rb +0 -30
  390. data/lib/badline/cartridge/ocean.rb +0 -35
  391. data/lib/badline/cartridge/pagefox.rb +0 -68
  392. data/lib/badline/cartridge/retro_replay.rb +0 -320
  393. data/lib/badline/cartridge/rex_utility.rb +0 -29
  394. data/lib/badline/cartridge/rgcd.rb +0 -58
  395. data/lib/badline/cartridge/simons_basic.rb +0 -35
  396. data/lib/badline/cartridge/standard.rb +0 -15
  397. data/lib/badline/cartridge/super_games.rb +0 -48
  398. data/lib/badline/cartridge/westermann.rb +0 -30
  399. data/lib/badline/cartridge/zaxxon.rb +0 -66
  400. data/lib/badline/cartridge.rb +0 -303
  401. data/lib/badline/checkpoint.rb +0 -98
  402. data/lib/badline/chrout_trap.rb +0 -43
  403. data/lib/badline/cia/fast_forward.rb +0 -60
  404. data/lib/badline/cia/interrupt_register.rb +0 -143
  405. data/lib/badline/cia/serial.rb +0 -275
  406. data/lib/badline/cia/state.rb +0 -47
  407. data/lib/badline/cia/timer.rb +0 -206
  408. data/lib/badline/cia.rb +0 -279
  409. data/lib/badline/color_memory.rb +0 -25
  410. data/lib/badline/computer/attachments.rb +0 -88
  411. data/lib/badline/computer/saved_state.rb +0 -117
  412. data/lib/badline/computer/true_drives.rb +0 -69
  413. data/lib/badline/control_ports.rb +0 -76
  414. data/lib/badline/cpu/addressing.rb +0 -131
  415. data/lib/badline/cpu/boundary.rb +0 -54
  416. data/lib/badline/cpu/core.rb +0 -165
  417. data/lib/badline/cpu/microcode.rb +0 -177
  418. data/lib/badline/cpu/operations.rb +0 -88
  419. data/lib/badline/cpu/saved_state.rb +0 -115
  420. data/lib/badline/cpu/stack_operations.rb +0 -82
  421. data/lib/badline/cpu.rb +0 -10
  422. data/lib/badline/cpu_port.rb +0 -112
  423. data/lib/badline/datasette.rb +0 -161
  424. data/lib/badline/debug_register.rb +0 -28
  425. data/lib/badline/drive/core.rb +0 -147
  426. data/lib/badline/drive/fast_serial.rb +0 -73
  427. data/lib/badline/drive/idle.rb +0 -125
  428. data/lib/badline/drive/idle_cpu.rb +0 -28
  429. data/lib/badline/drive/orbit.rb +0 -79
  430. data/lib/badline/drive/serial_lines.rb +0 -73
  431. data/lib/badline/drive/sleep.rb +0 -112
  432. data/lib/badline/drive/vias.rb +0 -84
  433. data/lib/badline/drive/watch.rb +0 -150
  434. data/lib/badline/drive.rb +0 -11
  435. data/lib/badline/drive1541/bus.rb +0 -86
  436. data/lib/badline/drive1541/byte_ready.rb +0 -48
  437. data/lib/badline/drive1541/cpu.rb +0 -11
  438. data/lib/badline/drive1541/disk.rb +0 -315
  439. data/lib/badline/drive1541/disk_state.rb +0 -86
  440. data/lib/badline/drive1541/disk_via.rb +0 -36
  441. data/lib/badline/drive1541/gcr.rb +0 -57
  442. data/lib/badline/drive1541/mechanism.rb +0 -313
  443. data/lib/badline/drive1541/mechanism_state.rb +0 -68
  444. data/lib/badline/drive1541/rotation.rb +0 -121
  445. data/lib/badline/drive1541/sector_reader.rb +0 -76
  446. data/lib/badline/drive1541/serial_port.rb +0 -18
  447. data/lib/badline/drive1541/track.rb +0 -98
  448. data/lib/badline/drive1541.rb +0 -111
  449. data/lib/badline/drive1571/bus.rb +0 -111
  450. data/lib/badline/drive1571/cpu.rb +0 -11
  451. data/lib/badline/drive1571/serial_port.rb +0 -37
  452. data/lib/badline/drive1571/serial_via.rb +0 -25
  453. data/lib/badline/drive1571/wd1770.rb +0 -120
  454. data/lib/badline/drive1571.rb +0 -175
  455. data/lib/badline/drive1581/bus.rb +0 -137
  456. data/lib/badline/drive1581/cpu.rb +0 -11
  457. data/lib/badline/drive1581/disk.rb +0 -135
  458. data/lib/badline/drive1581/disk_state.rb +0 -87
  459. data/lib/badline/drive1581/mechanism.rb +0 -117
  460. data/lib/badline/drive1581/serial_port.rb +0 -52
  461. data/lib/badline/drive1581/slot.rb +0 -78
  462. data/lib/badline/drive1581/track.rb +0 -100
  463. data/lib/badline/drive1581/track_bytes.rb +0 -75
  464. data/lib/badline/drive1581/wd1772/registers.rb +0 -89
  465. data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
  466. data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
  467. data/lib/badline/drive1581/wd1772/state.rb +0 -66
  468. data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
  469. data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
  470. data/lib/badline/drive1581/wd1772/turn.rb +0 -73
  471. data/lib/badline/drive1581/wd1772.rb +0 -216
  472. data/lib/badline/drive1581.rb +0 -233
  473. data/lib/badline/iec_bus.rb +0 -159
  474. data/lib/badline/instruction.rb +0 -334
  475. data/lib/badline/instruction_set/arithmetic.rb +0 -114
  476. data/lib/badline/instruction_set/bitwise.rb +0 -126
  477. data/lib/badline/instruction_set/branch.rb +0 -79
  478. data/lib/badline/instruction_set/flag.rb +0 -63
  479. data/lib/badline/instruction_set/illegal.rb +0 -270
  480. data/lib/badline/instruction_set/inc_dec.rb +0 -69
  481. data/lib/badline/instruction_set/stack.rb +0 -52
  482. data/lib/badline/instruction_set/transfer.rb +0 -137
  483. data/lib/badline/instruction_set.rb +0 -55
  484. data/lib/badline/interrupts.rb +0 -104
  485. data/lib/badline/joystick.rb +0 -25
  486. data/lib/badline/kernal_trap/channel.rb +0 -181
  487. data/lib/badline/keyboard.rb +0 -112
  488. data/lib/badline/keyboard_buffer.rb +0 -33
  489. data/lib/badline/ram_expansion/banking.rb +0 -30
  490. data/lib/badline/ram_expansion/plus256k.rb +0 -54
  491. data/lib/badline/ram_expansion/plus60k.rb +0 -43
  492. data/lib/badline/ram_expansion/unexpanded.rb +0 -28
  493. data/lib/badline/ram_expansion.rb +0 -21
  494. data/lib/badline/reu/dma/saved_state.rb +0 -50
  495. data/lib/badline/reu/dma.rb +0 -273
  496. data/lib/badline/reu/ram.rb +0 -107
  497. data/lib/badline/reu/saved_state.rb +0 -80
  498. data/lib/badline/reu/trigger.rb +0 -32
  499. data/lib/badline/reu.rb +0 -289
  500. data/lib/badline/sid/catch_up.rb +0 -120
  501. data/lib/badline/sid/decimator.rb +0 -64
  502. data/lib/badline/sid/envelope/state.rb +0 -68
  503. data/lib/badline/sid/envelope.rb +0 -239
  504. data/lib/badline/sid/filter.rb +0 -263
  505. data/lib/badline/sid/voice.rb +0 -77
  506. data/lib/badline/sid/waveform/combined.rb +0 -126
  507. data/lib/badline/sid/waveform/fast_forward.rb +0 -105
  508. data/lib/badline/sid/waveform/noise_writeback.rb +0 -122
  509. data/lib/badline/sid/waveform/state.rb +0 -66
  510. data/lib/badline/sid/waveform.rb +0 -305
  511. data/lib/badline/sid.rb +0 -303
  512. data/lib/badline/snapshot/setup.rb +0 -75
  513. data/lib/badline/snapshot/state.rb +0 -189
  514. data/lib/badline/time_of_day.rb +0 -228
  515. data/lib/badline/traps.rb +0 -19
  516. data/lib/badline/via/control_lines.rb +0 -122
  517. data/lib/badline/via/fast_forward.rb +0 -53
  518. data/lib/badline/via/interrupt_register.rb +0 -67
  519. data/lib/badline/via/shift_register.rb +0 -180
  520. data/lib/badline/via/state.rb +0 -42
  521. data/lib/badline/via/timer1.rb +0 -131
  522. data/lib/badline/via/timer2.rb +0 -133
  523. data/lib/badline/via.rb +0 -266
  524. data/lib/badline/vic/bank.rb +0 -133
  525. data/lib/badline/vic/border_mask.rb +0 -86
  526. data/lib/badline/vic/collisions.rb +0 -115
  527. data/lib/badline/vic/color_patches.rb +0 -47
  528. data/lib/badline/vic/display_state.rb +0 -185
  529. data/lib/badline/vic/graphics_mode.rb +0 -164
  530. data/lib/badline/vic/graphics_shifter.rb +0 -207
  531. data/lib/badline/vic/register_log.rb +0 -81
  532. data/lib/badline/vic/registers.rb +0 -195
  533. data/lib/badline/vic/sequencer.rb +0 -275
  534. data/lib/badline/vic/sequencer_output.rb +0 -116
  535. data/lib/badline/vic/sequencer_state.rb +0 -89
  536. data/lib/badline/vic/sprite/internal_bus.rb +0 -68
  537. data/lib/badline/vic/sprite/saved_state.rb +0 -64
  538. data/lib/badline/vic/sprite/shifter.rb +0 -146
  539. data/lib/badline/vic/sprite/timing.rb +0 -56
  540. data/lib/badline/vic/sprite.rb +0 -337
  541. data/lib/badline/vic/sprites.rb +0 -282
  542. data/lib/badline/vic/sprites_state.rb +0 -57
  543. data/lib/badline/vic.rb +0 -853
  544. data/lib/badline/vic20/saved_state.rb +0 -124
  545. data/lib/badline/vic20/sound/output.rb +0 -83
  546. data/lib/badline/vic20/sound.rb +0 -233
  547. data/lib/badline/vic20/vic/saved_state.rb +0 -55
  548. data/lib/badline/z80/arithmetic.rb +0 -117
  549. data/lib/badline/z80/bit_page.rb +0 -55
  550. data/lib/badline/z80/block_io.rb +0 -58
  551. data/lib/badline/z80/block_transfers.rb +0 -59
  552. data/lib/badline/z80/bus_cycles.rb +0 -111
  553. data/lib/badline/z80/core.rb +0 -113
  554. data/lib/badline/z80/exchanges.rb +0 -50
  555. data/lib/badline/z80/extended_page.rb +0 -89
  556. data/lib/badline/z80/flags.rb +0 -37
  557. data/lib/badline/z80/interrupt_acceptance.rb +0 -46
  558. data/lib/badline/z80/jumps.rb +0 -82
  559. data/lib/badline/z80/loads.rb +0 -98
  560. data/lib/badline/z80/main_page.rb +0 -134
  561. data/lib/badline/z80/registers.rb +0 -120
  562. data/lib/badline/z80/saved_state.rb +0 -69
  563. data/lib/badline/z80/shifts.rb +0 -64
  564. data/lib/badline/z80.rb +0 -11
  565. /data/lib/badline/snapshot/{fields.rb → vice/fields.rb} +0 -0
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ class Cartridge
6
+ # C64 Game System / System 3: up to 64 8K banks. Any access to
7
+ # $DE00-$DEFF selects the bank from the low six address bits; the data
8
+ # is ignored.
9
+ class GameSystem < Cartridge
10
+ def readable_io_pages
11
+ [0xde]
12
+ end
13
+
14
+ def peek(addr)
15
+ select(addr) if addr < 0xdf00
16
+ open_bus(addr)
17
+ end
18
+
19
+ def poke(addr, _value)
20
+ select(addr) if addr < 0xdf00
21
+ end
22
+
23
+ def reset
24
+ select(0)
25
+ end
26
+
27
+ private
28
+
29
+ def select(addr)
30
+ @roml = bank(@banks, addr & 0x3f)
31
+ changed!
32
+ end
33
+
34
+ def install_chips(chips)
35
+ @banks = banks_from(chips).first
36
+ self.mode = :rom8k
37
+ reset
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ class Cartridge
6
+ # GEO-RAM: a RAM expansion on the expansion port, seen through a 256-byte
7
+ # window at $DE00-$DEFF. Two write-only registers pick the page the
8
+ # window shows: $DFFE selects one of the 64 pages of a 16K block, and
9
+ # $DFFF selects the block. As in VICE, the registers answer at every
10
+ # address from $DF80 up, even for $DFFE and odd for $DFFF, and the block
11
+ # number wraps at the number of blocks the RAM holds. Reads of I/O 2 are
12
+ # open bus. It leaves EXROM and GAME high, and RES clears both
13
+ # registers.
14
+ class GeoRAM < Cartridge
15
+ SIZES = [64, 128, 256, 512, 1024, 2048, 4096].freeze
16
+ BLOCK_SIZE = 0x4000
17
+ PAGE_MASK = 0x3f
18
+
19
+ attr_reader :size
20
+
21
+ # size is the RAM in kilobytes.
22
+ def initialize(size: 512)
23
+ raise ArgumentError, "Unsupported GEO-RAM size #{size}K" unless SIZES.include?(size)
24
+
25
+ @size = size
26
+ @block_mask = ((size * 1024) / BLOCK_SIZE) - 1
27
+ super(Storage::CRTFile::Image.new(hardware_type: nil, subtype: 0, exrom: 1, game: 1,
28
+ name: "GEO-RAM", chips: []))
29
+ end
30
+
31
+ def readable_io_pages
32
+ [0xde]
33
+ end
34
+
35
+ def peek(addr)
36
+ @ram_data[@window + (addr & 0xff)]
37
+ end
38
+
39
+ def poke(addr, value)
40
+ if addr <= 0xdeff
41
+ @ram_data[@window + (addr & 0xff)] = value
42
+ elsif addr >= 0xdf80
43
+ if addr.odd?
44
+ @block = value & @block_mask
45
+ else
46
+ @page = value & PAGE_MASK
47
+ end
48
+ @window = (@block * BLOCK_SIZE) + (@page * 0x100)
49
+ end
50
+ end
51
+
52
+ def reset
53
+ @block = @page = @window = 0
54
+ end
55
+
56
+ private
57
+
58
+ def install_chips(_chips)
59
+ @ram_data = Array.new(@size * 1024, 0)
60
+ reset
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ class Cartridge
6
+ # The KCS Power Cartridge: 16K of ROM, 128 bytes of RAM and a freeze
7
+ # button. It boots in 16K mode, and any access to I/O 1 sets the lines
8
+ # from address bit 1 and the direction:
9
+ #
10
+ # read, bit 1 clear 8K
11
+ # read, bit 1 set off
12
+ # write, bit 1 clear 16K
13
+ # write, bit 1 set Ultimax
14
+ #
15
+ # A read of I/O 1 returns the second last page of ROML. I/O 2 holds the
16
+ # RAM in its lower half, and the upper half reads the EXROM line in bit 7
17
+ # and GAME in bit 6, which the freezer checks to find the mode it
18
+ # interrupted. A freeze switches to Ultimax and lets go of NMI.
19
+ class KCSPower < Cartridge
20
+ include Freezer
21
+
22
+ IO1_ROM_PAGE = 0x1e00
23
+
24
+ def readable_io_pages
25
+ [0xde, 0xdf]
26
+ end
27
+
28
+ def peek(addr)
29
+ if addr < 0xdf00
30
+ select_mode(addr.anybits?(0x02) ? :off : :rom8k)
31
+ @roml.peek(IO1_ROM_PAGE | (addr & 0xff))
32
+ elsif addr.anybits?(0x80)
33
+ (@exrom << 7) | (@game << 6) | (open_bus(addr) & 0x3f)
34
+ else
35
+ @io_ram[addr & 0x7f]
36
+ end
37
+ end
38
+
39
+ def poke(addr, value)
40
+ if addr < 0xdf00
41
+ select_mode(addr.anybits?(0x02) ? :ultimax : :rom16k)
42
+ elsif addr.nobits?(0x80)
43
+ @io_ram[addr & 0x7f] = value
44
+ end
45
+ end
46
+
47
+ def reset
48
+ self.nmi = false
49
+ select_mode(:rom16k)
50
+ end
51
+
52
+ def freeze!
53
+ self.nmi = false
54
+ select_mode(:ultimax)
55
+ end
56
+
57
+ private
58
+
59
+ def install_chips(chips)
60
+ roml, romh = banks_from(chips)
61
+ @roml = roml.first || EMPTY_BANK
62
+ @romh = romh.first || EMPTY_BANK
63
+ @io_ram = Array.new(0x80, 0xff)
64
+ reset
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,393 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ class Cartridge
6
+ # A cartridge's fields in a keyed snapshot module (Snapshot::Keyed,
7
+ # BL-CART): the CRT image it was built from and its jumpers, which
8
+ # build it again (Cartridge.from_fields), the EXROM and GAME lines,
9
+ # its pull on NMI, the button, and where ROML and ROMH point, each by
10
+ # the name of the bank or view it shows (window_labels), and whatever
11
+ # each mapper adds.
12
+ module KeyedState
13
+ def save_fields(out)
14
+ save_setup_fields(out)
15
+ out.int("exrom", @exrom).int("game", @game).bool("nmi", @nmi).bool("button", @button == true)
16
+ save_mapper_fields(out)
17
+ out
18
+ end
19
+
20
+ def load_fields(input)
21
+ @exrom = input.masked("exrom", @exrom, 1)
22
+ @game = input.masked("game", @game, 1)
23
+ @nmi = input.bool("nmi", @nmi)
24
+ @button = input.bool("button", false)
25
+ load_mapper_fields(input)
26
+ end
27
+
28
+ private
29
+
30
+ def save_setup_fields(out)
31
+ out.bytes("crt", Storage::CRTFile.encode(@crt))
32
+ save_jumper_fields(out)
33
+ end
34
+
35
+ def save_jumper_fields(_out); end
36
+
37
+ def save_mapper_fields(out)
38
+ save_window_fields(out)
39
+ end
40
+
41
+ def load_mapper_fields(input)
42
+ load_window_fields(input)
43
+ end
44
+
45
+ # The name of each of `windows`, in the same order: bank<N> for the
46
+ # mapper's banks, and empty for erased ROM.
47
+ def window_labels
48
+ banks = @banks
49
+ return [] unless banks
50
+
51
+ [*Array.new(banks.length) { |number| "bank#{number}" }, "empty"]
52
+ end
53
+
54
+ def save_window_fields(out)
55
+ choices = windows
56
+ return unless choices
57
+
58
+ labels = window_labels
59
+ save_window(out, "roml", @roml, choices, labels)
60
+ save_window(out, "romh", @romh, choices, labels)
61
+ end
62
+
63
+ def save_window(out, key, window, choices, labels)
64
+ return if window.nil?
65
+
66
+ out.text(key, labels.fetch(window_index(window, choices)))
67
+ end
68
+
69
+ def load_window_fields(input)
70
+ choices = windows
71
+ return unless choices
72
+
73
+ labels = window_labels
74
+ @roml = window_named(input.choice("roml", [*labels, "none"], "none"), choices, labels)
75
+ @romh = window_named(input.choice("romh", [*labels, "none"], "none"), choices, labels)
76
+ end
77
+
78
+ def window_named(label, choices, labels)
79
+ index = labels.index(label)
80
+ index.nil? ? nil : choices.fetch(index)
81
+ end
82
+ end
83
+
84
+ include KeyedState
85
+
86
+ class << self
87
+ # A cartridge built afresh from the CRT image and the jumpers a
88
+ # keyed snapshot module holds, before load_fields puts its state in.
89
+ def from_fields(input)
90
+ kb = input.int("geo_ram_kb", 0)
91
+ return GeoRAM.new(size: kb) if kb.positive?
92
+
93
+ crt = Storage::CRTFile.new(bytes: input.bytes("crt", "".b))
94
+ mapper_for(crt).from_jumper_fields(crt, input)
95
+ end
96
+
97
+ def from_jumper_fields(crt, _input) = new(crt)
98
+ end
99
+
100
+ # Two banks of ROM, one behind each window: roml<N> and romh<N>.
101
+ module SplitBanks
102
+ private
103
+
104
+ def window_labels
105
+ [*Array.new(@roml_banks.length) { |number| "roml#{number}" },
106
+ *Array.new(@romh_banks.length) { |number| "romh#{number}" }, "empty"]
107
+ end
108
+ end
109
+
110
+ class SuperGames
111
+ include SplitBanks
112
+
113
+ private
114
+
115
+ def save_mapper_fields(out)
116
+ super
117
+ out.bool("locked", @locked)
118
+ end
119
+
120
+ def load_mapper_fields(input)
121
+ super
122
+ @locked = input.bool("locked", @locked)
123
+ end
124
+ end
125
+
126
+ class Comal80
127
+ include SplitBanks
128
+ end
129
+
130
+ class FinalCartridge3
131
+ include SplitBanks
132
+
133
+ private
134
+
135
+ def save_mapper_fields(out)
136
+ super
137
+ out.bool("register_visible", @register_visible).bool("phi1_ultimax", @phi1_ultimax)
138
+ end
139
+
140
+ def load_mapper_fields(input)
141
+ super
142
+ @io_bank = @roml
143
+ @register_visible = input.bool("register_visible", @register_visible)
144
+ @phi1_ultimax = input.bool("phi1_ultimax", @phi1_ultimax)
145
+ end
146
+ end
147
+
148
+ class RGCD
149
+ private
150
+
151
+ def save_mapper_fields(out)
152
+ super
153
+ out.bool("disabled", @disabled)
154
+ end
155
+
156
+ def load_mapper_fields(input)
157
+ super
158
+ @disabled = input.bool("disabled", @disabled)
159
+ end
160
+ end
161
+
162
+ class Zaxxon
163
+ class High
164
+ def save_fields(out)
165
+ out.int("high_bank", [*@banks, EMPTY_BANK].index { |bank| bank.equal?(@bank) }.to_i)
166
+ end
167
+
168
+ def load_fields(input)
169
+ choices = [*@banks, EMPTY_BANK]
170
+ @bank = choices.fetch(input.int("high_bank", 0).clamp(0, choices.length - 1))
171
+ end
172
+ end
173
+
174
+ private
175
+
176
+ def save_mapper_fields(out) = @romh.save_fields(out)
177
+
178
+ def load_mapper_fields(input) = @romh.load_fields(input)
179
+ end
180
+
181
+ class EpyxFastload
182
+ private
183
+
184
+ # How long ago the capacitor was discharged, on the machine's clock.
185
+ def save_mapper_fields(out)
186
+ out.int("discharged_ago", now_cycles - @discharged_at)
187
+ end
188
+
189
+ def load_mapper_fields(input)
190
+ @discharged_at = now_cycles - input.int("discharged_ago", now_cycles - @discharged_at)
191
+ end
192
+
193
+ def now_cycles
194
+ clock = @clock
195
+ clock ? clock.call : 0
196
+ end
197
+ end
198
+
199
+ class ActionReplay
200
+ private
201
+
202
+ def window_labels
203
+ ["through", "isolated", "contended", *Array.new(@rom_banks.length) { |number| "rom#{number}" }, "empty"]
204
+ end
205
+
206
+ def save_mapper_fields(out)
207
+ super
208
+ out.text("rom", window_labels.fetch(window_index(@rom, windows))).bool("active", @active)
209
+ out.bool("io2_ram", @io2_ram).bytes("ram", @ram_data)
210
+ end
211
+
212
+ def load_mapper_fields(input)
213
+ super
214
+ labels = window_labels
215
+ @rom = window_named(input.choice("rom", labels, "rom0"), windows, labels)
216
+ @active = input.bool("active", @active)
217
+ @io2_ram = input.bool("io2_ram", @io2_ram)
218
+ input.bytes_into("ram", @ram_data)
219
+ end
220
+ end
221
+
222
+ class KCSPower
223
+ private
224
+
225
+ def save_mapper_fields(out) = out.bytes("io_ram", @io_ram)
226
+
227
+ def load_mapper_fields(input) = input.bytes_into("io_ram", @io_ram)
228
+ end
229
+
230
+ class Pagefox
231
+ private
232
+
233
+ def window_labels
234
+ [*Array.new(@roml_banks.length) { |number| "roml#{number}" },
235
+ *Array.new(@romh_banks.length) { |number| "romh#{number}" },
236
+ *Array.new(@ram_banks.length) { |number| "ram#{number}" }, "open_bus", "empty"]
237
+ end
238
+
239
+ def save_mapper_fields(out)
240
+ super
241
+ @ram_banks.each_with_index { |ram, number| out.bytes("ram#{number}.data", ram.data) }
242
+ end
243
+
244
+ def load_mapper_fields(input)
245
+ super
246
+ @ram_banks.each_with_index { |ram, number| input.bytes_into("ram#{number}.data", ram.data) }
247
+ end
248
+ end
249
+
250
+ class GeoRAM
251
+ private
252
+
253
+ def save_setup_fields(out) = out.int("geo_ram_kb", @size)
254
+
255
+ def save_mapper_fields(out)
256
+ out.bytes("ram", @ram_data).int("block", @block).int("page", @page).int("window", @window)
257
+ end
258
+
259
+ def load_mapper_fields(input)
260
+ input.bytes_into("ram", @ram_data)
261
+ @block = input.int("block", @block)
262
+ @page = input.int("page", @page)
263
+ @window = input.int("window", @window)
264
+ end
265
+ end
266
+
267
+ class Flash
268
+ # The array, the command state by name, how far through a command
269
+ # sequence, the toggle bit, a timed operation's end in cycles from
270
+ # now, and the windows handed out so far, under `prefix`.
271
+ module KeyedState
272
+ STATE_NAMES = STATES.map(&:to_s).freeze
273
+
274
+ def save_fields(out, prefix)
275
+ out.bytes("#{prefix}data", @data).text("#{prefix}state", @state.to_s)
276
+ out.text("#{prefix}base_state", @base_state.to_s).int("#{prefix}cycle", @cycle)
277
+ out.int("#{prefix}toggle", @toggle)
278
+ done_at = @done_at
279
+ out.int("#{prefix}done_in", done_at - @clock.call) unless done_at.nil?
280
+ out.optional_int("#{prefix}programmed", @programmed).optional_int("#{prefix}remaining", @remaining)
281
+ sectors = @erasing_sectors
282
+ out.ints("#{prefix}erasing_sectors", sectors) if sectors
283
+ out.ints("#{prefix}windows", @windows.keys).ints("#{prefix}status_windows", @status_windows.keys)
284
+ end
285
+
286
+ def load_fields(input, prefix)
287
+ input.bytes_into("#{prefix}data", @data)
288
+ @state = state_named(input.choice("#{prefix}state", STATE_NAMES, "read"))
289
+ @base_state = state_named(input.choice("#{prefix}base_state", STATE_NAMES, "read"))
290
+ @cycle = input.int("#{prefix}cycle", @cycle)
291
+ @toggle = input.int("#{prefix}toggle", @toggle)
292
+ done_in = input.optional_int("#{prefix}done_in")
293
+ @done_at = done_in.nil? ? nil : @clock.call + done_in
294
+ @programmed = input.optional_int("#{prefix}programmed")
295
+ @remaining = input.optional_int("#{prefix}remaining")
296
+ sectors = input.ints("#{prefix}erasing_sectors", [])
297
+ @erasing_sectors = sectors.empty? ? nil : sectors.dup
298
+ rebuild_windows(input.ints("#{prefix}windows", []), input.ints("#{prefix}status_windows", []))
299
+ end
300
+
301
+ private
302
+
303
+ def state_named(name)
304
+ STATES.find { |state| state.to_s == name } || :read
305
+ end
306
+ end
307
+
308
+ include KeyedState
309
+ end
310
+
311
+ class GMod2
312
+ private
313
+
314
+ def save_mapper_fields(out)
315
+ out.int("bank", @bank).bool("flash_writes", @flash_writes)
316
+ @flash.save_fields(out, "flash.")
317
+ end
318
+
319
+ def load_mapper_fields(input)
320
+ @bank = input.int("bank", @bank)
321
+ @flash_writes = input.bool("flash_writes", @flash_writes)
322
+ @flash.load_fields(input, "flash.")
323
+ @roml = @flash.window(@bank * BANK_SIZE)
324
+ end
325
+ end
326
+
327
+ class EasyFlash
328
+ private
329
+
330
+ def save_mapper_fields(out)
331
+ out.int("bank", @bank).int("control", @control).bytes("io_ram", @io_ram)
332
+ @low_flash.save_fields(out, "flash_low.")
333
+ @high_flash.save_fields(out, "flash_high.")
334
+ end
335
+
336
+ def load_mapper_fields(input)
337
+ @bank = input.int("bank", @bank)
338
+ @control = input.byte("control", @control)
339
+ input.bytes_into("io_ram", @io_ram)
340
+ @low_flash.load_fields(input, "flash_low.")
341
+ @high_flash.load_fields(input, "flash_high.")
342
+ map_bank
343
+ end
344
+ end
345
+
346
+ class RetroReplay
347
+ CONFIG_NAMES = CONTROL_MODES.map(&:to_s).freeze
348
+
349
+ # The flash and bank jumpers, as the board has them set.
350
+ def self.from_jumper_fields(crt, input)
351
+ new(crt, flash_jumper: input.bool("jumper.flash", false), bank_jumper: input.bool("jumper.bank", false))
352
+ end
353
+
354
+ private
355
+
356
+ def save_jumper_fields(out)
357
+ out.bool("jumper.flash", @flash_jumper).bool("jumper.bank", @bank_jumper)
358
+ end
359
+
360
+ def save_mapper_fields(out)
361
+ out.bool("active", @active).bool("frozen", @frozen).bool("phi1_ultimax", @phi1_ultimax)
362
+ out.bool("ram_enabled", @ram_enabled).bool("ram_at_a000", @ram_at_a000).bool("allow_bank", @allow_bank)
363
+ out.bool("no_freeze", @no_freeze).bool("reu_mapping", @reu_mapping).bool("write_once", @write_once)
364
+ out.int("bank", @bank).text("config", @config.to_s)
365
+ @ram_data.each_with_index { |data, number| out.bytes("ram#{number}", data) }
366
+ @flash.save_fields(out, "flash.")
367
+ end
368
+
369
+ def load_mapper_fields(input)
370
+ load_flag_fields(input)
371
+ @bank = input.int("bank", @bank)
372
+ config = input.choice("config", CONFIG_NAMES, "rom8k")
373
+ @config = CONTROL_MODES.find { |mode| mode.to_s == config } || :rom8k
374
+ @ram_data.each_with_index { |data, number| input.bytes_into("ram#{number}", data) }
375
+ @flash.load_fields(input, "flash.")
376
+ map_windows
377
+ end
378
+
379
+ def load_flag_fields(input)
380
+ @active = input.bool("active", @active)
381
+ @frozen = input.bool("frozen", @frozen)
382
+ @phi1_ultimax = input.bool("phi1_ultimax", @phi1_ultimax)
383
+ @ram_enabled = input.bool("ram_enabled", @ram_enabled)
384
+ @ram_at_a000 = input.bool("ram_at_a000", @ram_at_a000)
385
+ @allow_bank = input.bool("allow_bank", @allow_bank)
386
+ @no_freeze = input.bool("no_freeze", @no_freeze)
387
+ @reu_mapping = input.bool("reu_mapping", @reu_mapping)
388
+ @write_once = input.bool("write_once", @write_once)
389
+ end
390
+ end
391
+ end
392
+ end
393
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ class Cartridge
6
+ # 8K. Writing I/O 1 switches the ROM in, writing I/O 2 switches it out.
7
+ # Both I/O pages read the last 512 bytes of the ROM.
8
+ class Mach5 < Cartridge
9
+ def readable_io_pages
10
+ [0xde, 0xdf]
11
+ end
12
+
13
+ def peek(addr)
14
+ @roml.peek(addr)
15
+ end
16
+
17
+ def poke(addr, _value)
18
+ select_mode(addr < 0xdf00 ? :rom8k : :off)
19
+ end
20
+
21
+ def reset
22
+ select_mode(:rom8k)
23
+ end
24
+
25
+ private
26
+
27
+ def install_chips(chips)
28
+ @roml = banks_from(chips).first.compact.first || EMPTY_BANK
29
+ reset
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ class Cartridge
6
+ # Magic Desk: up to 128 8K banks. A write to I/O 1 selects the bank from
7
+ # bits 0-6, masked to the size of the ROM and at least four banks, and
8
+ # switches the ROM out with bit 7.
9
+ class MagicDesk < Cartridge
10
+ def poke(addr, value)
11
+ return if addr > 0xdeff
12
+
13
+ @exrom = value.anybits?(0x80) ? 1 : 0
14
+ @roml = bank(@banks, value & @bank_mask)
15
+ changed!
16
+ end
17
+
18
+ def reset
19
+ poke(0xde00, 0)
20
+ end
21
+
22
+ private
23
+
24
+ def install_chips(chips)
25
+ @banks = banks_from(chips).first
26
+ @bank_mask = (bank_mask(@banks) | 0x03) & 0x7f
27
+ reset
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ class Cartridge
6
+ # Ocean: up to 64 8K banks. A write to I/O 1 selects the bank from bits
7
+ # 0-5, masked to the size of the ROM.
8
+ class Ocean < Cartridge
9
+ def poke(addr, value)
10
+ return if addr > 0xdeff
11
+
12
+ select_bank(value & @bank_mask)
13
+ changed!
14
+ end
15
+
16
+ def reset
17
+ select_bank(0)
18
+ changed!
19
+ end
20
+
21
+ private
22
+
23
+ # In 16K mode the selected bank shows through ROMH as well.
24
+ def select_bank(number)
25
+ @roml = bank(@banks, number)
26
+ @romh = @roml if game.zero?
27
+ end
28
+
29
+ def install_chips(chips)
30
+ @banks = banks_from(chips).first
31
+ @bank_mask = bank_mask(@banks) & 0x3f
32
+ reset
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end