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,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ class Bus
6
+ # Stands in for a page of I/O that a second or third SID shares: each 32
7
+ # bytes of it go to the SID placed there, or else to the first SID's
8
+ # mirrors in `$d400-$d7ff`, and to the open bus in I/O 1 and 2.
9
+ class SIDSlots
10
+ attr_reader :page
11
+
12
+ def initialize(page, first, open_bus)
13
+ @page = page
14
+ @io = page >= 0xde
15
+ @first = first
16
+ @open_bus = open_bus
17
+ @sids = []
18
+ @slots = Array.new(8, -1)
19
+ end
20
+
21
+ def place(sid)
22
+ @slots[(sid.start >> 5) & 7] = @sids.size
23
+ @sids << sid
24
+ end
25
+
26
+ def peek(addr)
27
+ index = @slots[(addr >> 5) & 7]
28
+ return @sids[index].peek(addr) unless index.negative?
29
+
30
+ @io ? @open_bus.peek(addr) : @first.peek(addr)
31
+ end
32
+
33
+ def poke(addr, value)
34
+ index = @slots[(addr >> 5) & 7]
35
+ if !index.negative?
36
+ @sids[index].poke(addr, value)
37
+ elsif !@io
38
+ @first.poke(addr, value)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,219 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "badline/c64/bus/keyed_state"
4
+ require "badline/c64/bus/sid_slots"
5
+ require "badline/c64/bus/extra_sids"
6
+ require "badline/c64/bus/pla"
7
+ require "badline/c64/bus/roms"
8
+ require "badline/c64/bus/fittings"
9
+ require "badline/c64/bus/debug_register"
10
+
11
+ module Badline
12
+ # Memory layout:
13
+ #
14
+ # 0x0000-0x00FF - Page 0 - Zeropage
15
+ # 0x0100-0x01FF - Page 1 - Stack
16
+ # 0x0200-0x02FF - Page 2 - OS/BASIC pointers
17
+ # 0x0300-0x03FF - Page 3 - OS/BASIC pointers
18
+ # 0x0400-0x07FF - Page 4-7 - Screen memory
19
+ # 0x0800-0x9FFF - Page 8-159 - BASIC program storage area
20
+ # 0xA000-0xBFFF - Page 160-191 - Machine code program storage (ROM overlay)
21
+ # 0xC000-0xCFFF - Page 192-207 - Machine code program storage
22
+ # 0xD000-0xD3FF - Page 208-211 - VIC II registers
23
+ # 0xD400-0xD7FF - Page 212-215 - SID registers
24
+ # 0xD800-0xDBFF - Page 216-219 - Color memory
25
+ # 0xDC00-0xDCFF - Page 220 - CIA 1
26
+ # 0xDD00-0xDDFF - Page 221 - CIA 2
27
+ # 0xDE00-0xDEFF - Page 222 - I/O 1
28
+ # 0xDF00-0xDFFF - Page 223 - I/O 2
29
+ # 0xE000-0xFFFF - Page 224-255 - Machine code program storage (ROM overlay)
30
+
31
+ class C64
32
+ # Overlays:
33
+ #
34
+ # 0x8000-0x9FFF - Cartridge ROM (low) - 8kb
35
+ # 0xA000-0xBFFF - BASIC ROM / Cartridge ROM (high) - 8kb
36
+ # 0xD000-0xDFFF - Character ROM / I/O - 4kb
37
+ # 0xE000-0xFFFF - KERNAL ROM / Cartridge ROM (high) - 8kb
38
+ class Bus
39
+ include Addressable
40
+ include PLA
41
+ include ExtraSIDs
42
+ include ROMs
43
+ include Fittings
44
+
45
+ # I/O 1 and 2, and the Ultimax holes, with nothing on the bus. A read
46
+ # picks up the byte the VIC fetched in the preceding phi1 half-cycle,
47
+ # and a write goes nowhere.
48
+ class OpenBus
49
+ def initialize(vic)
50
+ @vic = vic
51
+ end
52
+
53
+ def peek(_addr) = @vic.phi1_data
54
+ def poke(_addr, _value); end
55
+ end
56
+
57
+ # The 6510's port pins with pull-ups, and the floating ones (CPU::Port).
58
+ PORT_PULLUPS = 0b0001_0111
59
+ PORT_FLOATING = 0b1100_1000
60
+
61
+ # RAM powers on in runs of $00 $00 $FF $FF $FF $FF $00 $00, inverted in
62
+ # the second and fourth 16K: a C64C (ASSY 250469 R4) from
63
+ # C64/raminitpattern/readme.txt, without its occasional random bytes.
64
+ # See doc/pinned-behaviour.md.
65
+ RAM_POWER_ON = Array.new(2**16) { |addr| (((addr + 2) / 4) ^ (addr / 0x4000)).odd? ? 0xff : 0x00 }.freeze
66
+
67
+ attr_reader :io_port, :ram,
68
+ :vic, :sid, :color_ram, :cia1, :cia2, :keyboard, :joystick1, :joystick2,
69
+ :control_ports, :cartridge, :ultimax, :phi1_ultimax, :datasette, :region, :video_ram, :reu
70
+
71
+ # ram_expansion fits a +60K (:plus60k) or +256K (:plus256k).
72
+ def initialize(sid_model: :mos6581, cia_model: :mos6526, vic_model: :mos6569, region: Region::PAL,
73
+ ram_expansion: nil)
74
+ @region = region
75
+ @board = :c64
76
+ @ram = Memory.new(RAM_POWER_ON, length: 2**16, start: 0)
77
+ @ram_expansion = BankedRAM.build(ram_expansion, @ram) { update_overlays! }
78
+ @cartridge = @reu = nil
79
+ @debug_register = nil
80
+
81
+ load_roms
82
+
83
+ @keyboard = Input::Keyboard.new
84
+ @joystick1 = Input::Joystick.new
85
+ @joystick2 = Input::Joystick.new
86
+ @control_ports = Input::ControlPorts.new(keyboard: @keyboard, joystick1: @joystick1, joystick2: @joystick2)
87
+ @vic = Chips::VIC.new(model: vic_model, region:)
88
+ @cia1 = Chips::CIA.new(start: 0xdc00, peripheral: @control_ports, model: cia_model, region:)
89
+ @cia2 = Chips::CIA.new(start: 0xdd00, model: cia_model, region:)
90
+ @control_ports.port_a_source = @cia1
91
+ @cia1.on_port_b4_change { |high| @vic.lightpen_level(high) }
92
+ @sid = Chips::SID.new(model: sid_model, pots: @control_ports)
93
+ @sid_slots = []
94
+
95
+ @datasette = Drives::Datasette.new
96
+ @datasette.on_flag { @cia1.flag! }
97
+ @datasette.on_sense_change { @cpu_port.refresh }
98
+
99
+ @color_ram = ColorMemory.new(@vic)
100
+ @vic.vic_bank.connect(cia2: @cia2, color_ram: @color_ram)
101
+ @vic.vic_bank.map_character_rom(character_rom)
102
+ @open_bus = OpenBus.new(@vic)
103
+ @cpu_off_bus = false
104
+
105
+ @cpu_port = Chips::CPU::Port.new(@datasette, pullups: PORT_PULLUPS, floating: PORT_FLOATING)
106
+ @cpu_port.on_change { update_overlays! }
107
+ @io_port = @cpu_port.status
108
+
109
+ @read_pages = Array.new(256)
110
+ @write_pages = Array.new(256)
111
+ update_overlays!
112
+ end
113
+
114
+ def attach_cartridge(cartridge)
115
+ @cartridge = cartridge
116
+ cartridge.connect(ram: @ram, open_bus: @open_bus)
117
+ cartridge.on_change { update_overlays! }
118
+ update_overlays!
119
+ end
120
+
121
+ # An REU takes I/O 2 unless a cartridge claims it, and watches writes
122
+ # to $FF00 for the one that starts an armed transfer.
123
+ def attach_reu(reu)
124
+ @reu = reu
125
+ update_overlays!
126
+ end
127
+
128
+ def power_on!
129
+ @ram.clear!(RAM_POWER_ON)
130
+ @ram_expansion.power_on!
131
+ end
132
+
133
+ # The RES line clears the 6510 port's direction and output registers,
134
+ # and a RAM expansion's bank register. The port's floating bits keep
135
+ # their charge.
136
+ def reset!
137
+ @ram_expansion.reset!
138
+ @cpu_port.reset!
139
+ end
140
+
141
+ def disable_overlays!
142
+ poke(0, 0x2f)
143
+ poke(1, 0)
144
+ end
145
+
146
+ def install_debug_register(&)
147
+ @debug_register = DebugRegister.new(@sid, &)
148
+ update_overlays!
149
+ end
150
+
151
+ def peek(addr)
152
+ return @cpu_port.ddr if addr.zero?
153
+ return @io_port.value if addr == 0x01
154
+
155
+ @read_pages[addr >> 8].peek(addr)
156
+ end
157
+
158
+ # A write to $00 or $01 goes to the port, but the RAM below is still
159
+ # write-enabled, and takes whatever is left on the bus: the byte the VIC
160
+ # fetched in the phi1 half of the cycle.
161
+ def poke(addr, value)
162
+ if addr < 0x02
163
+ @ram.poke(addr, @vic.phi1_data)
164
+ addr.zero? ? @cpu_port.write_ddr(value) : @cpu_port.write_data(value)
165
+ elsif !@cpu_off_bus
166
+ @write_pages[addr >> 8].poke(addr, value)
167
+ end
168
+ end
169
+
170
+ # Runs a CPU cycle with the CPU off the bus, as an REU's /DMA line
171
+ # holds it: a write it makes reaches nothing but its own port.
172
+ def cycle_cpu_off_bus(cpu)
173
+ @cpu_off_bus = true
174
+ cpu.cycle!
175
+ @cpu_off_bus = false
176
+ end
177
+
178
+ def inspect
179
+ "#<#{self.class.name} port=#{format('0x%02x', @io_port.value)} " \
180
+ "cartridge=#{@cartridge ? @cartridge.class.name : 'none'} " \
181
+ "ultimax=#{@ultimax}>"
182
+ end
183
+
184
+ private
185
+
186
+ # Banking changes only on $01 writes and cartridge line/bank changes,
187
+ # so reads and writes dispatch through per-page handler tables instead
188
+ # of range checks.
189
+ def update_overlays!
190
+ max = @board == :max
191
+ @ultimax = max || (@cartridge ? @cartridge.ultimax? : false)
192
+ @phi1_ultimax = max || (@cartridge ? @cartridge.phi1_ultimax? : false)
193
+ @video_ram = @ram_expansion.video_ram
194
+ @vic.vic_bank.map(@video_ram, phi1_ultimax: @phi1_ultimax, ultimax: @ultimax, romh: @cartridge&.romh)
195
+
196
+ map_pla_pages
197
+ @write_pages[0xff] = @reu.trigger.wrap(@write_pages[0xff]) if @reu
198
+ end
199
+
200
+ def map_ram_pages
201
+ @ram_expansion.map(@read_pages, @write_pages)
202
+ end
203
+
204
+ def map_io_pages
205
+ {
206
+ vic => 0xd0..0xd3, sid => 0xd4..0xd7, color_ram => 0xd8..0xdb,
207
+ cia1 => 0xdc..0xdc, cia2 => 0xdd..0xdd, @open_bus => 0xde..0xdf
208
+ }.each do |chip, pages|
209
+ pages.each { |p| @read_pages[p] = @write_pages[p] = chip }
210
+ end
211
+ @ram_expansion.map_io(@read_pages, @write_pages)
212
+ @read_pages[0xd7] = @write_pages[0xd7] = @debug_register if @debug_register
213
+ @read_pages[0xdf] = @write_pages[0xdf] = @reu if @reu
214
+ map_cartridge_io if @cartridge
215
+ map_extra_sids unless @sid_slots.empty?
216
+ end
217
+ end
218
+ end
219
+ end
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ class Cartridge
6
+ # Action Replay v4.2 to v6: four 8K ROM banks and 8K of RAM. A write to
7
+ # I/O 1 sets the control register:
8
+ #
9
+ # bit 0 pulls GAME low
10
+ # bit 1 releases EXROM
11
+ # bit 2 switches the register off until the next freeze or reset
12
+ # bits 3-4 ROM bank
13
+ # bit 5 RAM instead of ROM at ROML and I/O 2
14
+ # bit 6 acknowledges a freeze and lets go of NMI
15
+ #
16
+ # I/O 2 shows the last page of the RAM or of the ROM bank. The register
17
+ # doesn't decode R/W, so a read of I/O 1 writes whatever is on the bus
18
+ # into it. RAM with only EXROM released ($22) selects the cartridge RAM
19
+ # and the C64's together at ROML. A freeze switches the cartridge back
20
+ # on, in Ultimax mode with the RAM at ROML and the first bank at ROMH.
21
+ class ActionReplay < Cartridge
22
+ include Freezer
23
+
24
+ CONTROL_MODES = %i[rom8k rom16k off ultimax].freeze
25
+ IO2_PAGE = 0x1f00
26
+
27
+ def connect(ram:, open_bus:)
28
+ super
29
+ @through.backing = ram
30
+ @contended.backing = ram
31
+ end
32
+
33
+ def readable_io_pages
34
+ [0xde, 0xdf]
35
+ end
36
+
37
+ def peek(addr)
38
+ return open_bus(addr) unless @active
39
+ return io2_peek(addr) if addr >= 0xdf00
40
+
41
+ open_bus(addr).tap { |value| control(value) }
42
+ end
43
+
44
+ def poke(addr, value)
45
+ return unless @active
46
+
47
+ if addr < 0xdf00
48
+ control(value)
49
+ elsif @io2_ram
50
+ @ram_data[IO2_PAGE | (addr & 0xff)] = value
51
+ end
52
+ end
53
+
54
+ def reset
55
+ @active = true
56
+ self.nmi = false
57
+ control(0)
58
+ end
59
+
60
+ def freeze!
61
+ @active = true
62
+ @rom = bank(@rom_banks, 0)
63
+ select(:ultimax, @isolated, io2_ram: true)
64
+ end
65
+
66
+ private
67
+
68
+ def windows = [@through, @isolated, @contended, *@rom_banks, EMPTY_BANK]
69
+
70
+ def io2_peek(addr)
71
+ @io2_ram ? @ram_data[IO2_PAGE | (addr & 0xff)] : @rom.peek(addr)
72
+ end
73
+
74
+ def control(value)
75
+ self.nmi = false if value.anybits?(0x40)
76
+ @rom = bank(@rom_banks, (value >> 3) & 0x03)
77
+ configure(value)
78
+ @active = false if value.anybits?(0x04)
79
+ end
80
+
81
+ def configure(value)
82
+ return select(:rom8k, @contended, io2_ram: true) if (value & 0x23) == 0x22
83
+
84
+ configure_standard(value)
85
+ end
86
+
87
+ def configure_standard(value)
88
+ mode = CONTROL_MODES[value & 0x03]
89
+ if value.anybits?(0x20)
90
+ select(mode, mode == :ultimax ? @isolated : @through, io2_ram: true)
91
+ else
92
+ select(mode, @rom, io2_ram: false)
93
+ end
94
+ end
95
+
96
+ def select(mode, roml, io2_ram:, romh: @rom)
97
+ self.mode = mode
98
+ @roml = roml
99
+ @romh = romh
100
+ @io2_ram = io2_ram
101
+ changed!
102
+ end
103
+
104
+ def install_chips(chips)
105
+ @rom_banks = banks_from(chips).first
106
+ @ram_data = Array.new(BANK_SIZE, 0)
107
+ @through = RAMBank.new(@ram_data)
108
+ @isolated = RAMBank.new(@ram_data)
109
+ @contended = ContendedRAM.new(@ram_data)
110
+ reset
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ class Cartridge
6
+ # Atomic Power, sold as Nordic Power: an Action Replay 5 with one more
7
+ # configuration. RAM with only EXROM released and bits 2, 6 and 7 clear
8
+ # ($22) selects 16K mode with the ROM bank at ROML and the RAM at ROMH
9
+ # and I/O 2. Writes to that RAM don't reach the C64's. The VIC never
10
+ # sees Ultimax mode.
11
+ class AtomicPower < ActionReplay
12
+ def phi1_ultimax?
13
+ false
14
+ end
15
+
16
+ private
17
+
18
+ def configure(value)
19
+ return select(:rom16k, @rom, romh: @isolated, io2_ram: true) if (value & 0xe7) == 0x22
20
+
21
+ configure_standard(value)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ class Cartridge
6
+ # One 8K bank of cartridge ROM. The chip decodes only the low address
7
+ # lines, so the same bank answers at $8000, $A000 or $E000, and a smaller
8
+ # chip mirrors across the window.
9
+ class Bank
10
+ def initialize(data)
11
+ size = [1 << (data.length - 1).bit_length, 1].max
12
+ @mask = size - 1
13
+ @data = (data + ([0xff] * (size - data.length))).freeze
14
+ end
15
+
16
+ def peek(addr)
17
+ @data[addr & @mask]
18
+ end
19
+ alias [] peek
20
+ end
21
+
22
+ # Cartridge RAM mapped into the ROML or ROMH window. Writes land in the
23
+ # C64's RAM underneath as well, when there is a backing. Banks built on
24
+ # the same data are views of the same RAM.
25
+ class RAMBank
26
+ attr_reader :data
27
+ attr_writer :backing
28
+
29
+ def initialize(data = Array.new(BANK_SIZE, 0))
30
+ @data = data
31
+ @backing = nil
32
+ end
33
+
34
+ def peek(addr)
35
+ @data[addr & 0x1fff]
36
+ end
37
+ alias [] peek
38
+
39
+ def poke(addr, value)
40
+ @data[addr & 0x1fff] = value
41
+ @backing&.poke(addr, value)
42
+ end
43
+ alias []= poke
44
+ end
45
+
46
+ # Cartridge RAM the window reads, where the cartridge ignores writes.
47
+ class RAMReader
48
+ def initialize(data)
49
+ @data = data
50
+ end
51
+
52
+ def peek(addr)
53
+ @data[addr & 0x1fff]
54
+ end
55
+ alias [] peek
56
+ end
57
+
58
+ # Cartridge RAM that takes writes while the window reads something else.
59
+ class WriteOnlyRAM < RAMBank
60
+ def initialize(data, reader)
61
+ super(data)
62
+ @reader = reader
63
+ end
64
+
65
+ def peek(addr)
66
+ @reader.peek(addr)
67
+ end
68
+ alias [] peek
69
+ end
70
+
71
+ # Cartridge RAM selected together with the C64's RAM, both driving the
72
+ # bus on a read. The result is ORed, as VICE has it.
73
+ class ContendedRAM < RAMBank
74
+ def peek(addr)
75
+ @data[addr & 0x1fff] | @backing.peek(addr)
76
+ end
77
+ alias [] peek
78
+ end
79
+
80
+ EMPTY_BANK = Bank.new([0xff])
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ class Cartridge
6
+ # Comal-80: four 16K banks, or eight with the extra ROMs. A write to
7
+ # I/O 1 selects the bank and the memory configuration. The black board
8
+ # (subtype 0) takes the bank from bits 0-2 and switches the ROM out with
9
+ # bit 6; the grey one (subtype 1) takes the bank from bits 0-1 and the
10
+ # configuration from bits 5-6.
11
+ class Comal80 < Cartridge
12
+ GREY_MODES = %i[rom16k ultimax rom8k off].freeze
13
+
14
+ def initialize(crt)
15
+ @grey = crt.subtype == 1
16
+ super
17
+ end
18
+
19
+ def poke(addr, value)
20
+ return if addr > 0xdeff
21
+
22
+ if @grey
23
+ select(value & 0x03, GREY_MODES[(value >> 5) & 0x03])
24
+ else
25
+ select(value & 0x07, value.anybits?(0x40) ? :off : :rom16k)
26
+ end
27
+ changed!
28
+ end
29
+
30
+ def reset
31
+ select(0, :rom16k)
32
+ changed!
33
+ end
34
+
35
+ private
36
+
37
+ def windows = [*@roml_banks, *@romh_banks, EMPTY_BANK]
38
+
39
+ def select(number, mode)
40
+ @roml = bank(@roml_banks, number)
41
+ @romh = bank(@romh_banks, number)
42
+ self.mode = mode
43
+ end
44
+
45
+ def install_chips(chips)
46
+ @roml_banks, @romh_banks = banks_from(chips)
47
+ reset
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ class C64
5
+ class Cartridge
6
+ # Dinamic: up to 16 8K banks. Reading $DE00-$DE0F selects the bank from
7
+ # the low address bits.
8
+ class Dinamic < Cartridge
9
+ def readable_io_pages
10
+ [0xde]
11
+ end
12
+
13
+ def peek(addr)
14
+ if addr < 0xde10
15
+ @roml = bank(@banks, addr & 0x0f)
16
+ changed!
17
+ end
18
+ open_bus(addr)
19
+ end
20
+
21
+ def reset
22
+ @roml = bank(@banks, 0)
23
+ changed!
24
+ end
25
+
26
+ private
27
+
28
+ def install_chips(chips)
29
+ @banks = banks_from(chips).first
30
+ self.mode = :rom8k
31
+ reset
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end