badline 0.12.1 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (565) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -1
  3. data/CLAUDE.md +86 -38
  4. data/CONTRIBUTING.md +4 -3
  5. data/README.md +9 -6
  6. data/doc/library.md +9 -9
  7. data/doc/media.md +2 -1
  8. data/doc/pinned-behaviour.md +134 -105
  9. data/doc/snapshot-format.md +1047 -0
  10. data/doc/snapshots.md +73 -43
  11. data/lib/badline/audio/bare_player.rb +53 -20
  12. data/lib/badline/audio/cli.rb +6 -6
  13. data/lib/badline/audio/jukebox.rb +2 -2
  14. data/lib/badline/audio/machine_player.rb +16 -10
  15. data/lib/badline/{media → audio}/queue.rb +1 -1
  16. data/lib/badline/audio/queued_tune.rb +6 -6
  17. data/lib/badline/audio/renderer.rb +33 -22
  18. data/lib/badline/audio/stereo.rb +1 -1
  19. data/lib/badline/c128/banks.rb +6 -3
  20. data/lib/badline/c128/bus/keyed_state.rb +45 -0
  21. data/lib/badline/c128/bus.rb +35 -20
  22. data/lib/badline/c128/color_lines.rb +2 -2
  23. data/lib/badline/c128/cpu.rb +1 -1
  24. data/lib/badline/c128/drives.rb +14 -34
  25. data/lib/badline/c128/fast_serial.rb +5 -5
  26. data/lib/badline/c128/keyed_modules.rb +117 -0
  27. data/lib/badline/c128/keyed_state.rb +91 -0
  28. data/lib/badline/c128/keys.rb +9 -0
  29. data/lib/badline/c128/mmu.rb +9 -8
  30. data/lib/badline/c128/mmu_pages.rb +21 -1
  31. data/lib/badline/c128/modes.rb +21 -11
  32. data/lib/badline/c128/z80.rb +2 -2
  33. data/lib/badline/c128/z80_turns.rb +1 -1
  34. data/lib/badline/c128.rb +21 -16
  35. data/lib/badline/c64/attachments.rb +42 -0
  36. data/lib/badline/c64/banked_ram/banking.rb +32 -0
  37. data/lib/badline/c64/banked_ram/plus256k.rb +64 -0
  38. data/lib/badline/c64/banked_ram/plus60k.rb +47 -0
  39. data/lib/badline/c64/banked_ram/unexpanded.rb +30 -0
  40. data/lib/badline/c64/banked_ram.rb +23 -0
  41. data/lib/badline/c64/bus/debug_register.rb +32 -0
  42. data/lib/badline/c64/bus/extra_sids.rb +32 -0
  43. data/lib/badline/c64/bus/fittings.rb +40 -0
  44. data/lib/badline/c64/bus/keyed_state.rb +41 -0
  45. data/lib/badline/c64/bus/pla.rb +149 -0
  46. data/lib/badline/c64/bus/roms.rb +41 -0
  47. data/lib/badline/c64/bus/sid_slots.rb +44 -0
  48. data/lib/badline/c64/bus.rb +219 -0
  49. data/lib/badline/c64/cartridge/action_replay.rb +115 -0
  50. data/lib/badline/c64/cartridge/atomic_power.rb +26 -0
  51. data/lib/badline/c64/cartridge/bank.rb +83 -0
  52. data/lib/badline/c64/cartridge/comal80.rb +52 -0
  53. data/lib/badline/c64/cartridge/dinamic.rb +36 -0
  54. data/lib/badline/c64/cartridge/easy_flash.rb +132 -0
  55. data/lib/badline/c64/cartridge/epyx_fastload.rb +73 -0
  56. data/lib/badline/c64/cartridge/final_cartridge3.rb +79 -0
  57. data/lib/badline/c64/cartridge/flash.rb +279 -0
  58. data/lib/badline/c64/cartridge/freezer.rb +35 -0
  59. data/lib/badline/c64/cartridge/fun_play.rb +40 -0
  60. data/lib/badline/c64/cartridge/g_mod2.rb +64 -0
  61. data/lib/badline/c64/cartridge/game_system.rb +42 -0
  62. data/lib/badline/c64/cartridge/geo_ram.rb +65 -0
  63. data/lib/badline/c64/cartridge/kcs_power.rb +69 -0
  64. data/lib/badline/c64/cartridge/keyed_state.rb +393 -0
  65. data/lib/badline/c64/cartridge/mach5.rb +34 -0
  66. data/lib/badline/c64/cartridge/magic_desk.rb +32 -0
  67. data/lib/badline/c64/cartridge/ocean.rb +37 -0
  68. data/lib/badline/c64/cartridge/pagefox.rb +60 -0
  69. data/lib/badline/c64/cartridge/retro_replay.rb +278 -0
  70. data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
  71. data/lib/badline/c64/cartridge/rgcd.rb +50 -0
  72. data/lib/badline/c64/cartridge/simons_basic.rb +37 -0
  73. data/lib/badline/c64/cartridge/standard.rb +17 -0
  74. data/lib/badline/c64/cartridge/super_games.rb +40 -0
  75. data/lib/badline/c64/cartridge/westermann.rb +32 -0
  76. data/lib/badline/c64/cartridge/zaxxon.rb +52 -0
  77. data/lib/badline/c64/cartridge.rb +232 -0
  78. data/lib/badline/c64/color_memory.rb +27 -0
  79. data/lib/badline/{computer → c64}/common.rb +2 -2
  80. data/lib/badline/{computer → c64}/kernal_traps.rb +39 -36
  81. data/lib/badline/c64/keyed_modules.rb +111 -0
  82. data/lib/badline/c64/keyed_state.rb +68 -0
  83. data/lib/badline/c64/reu/dma.rb +271 -0
  84. data/lib/badline/c64/reu/keyed_state.rb +140 -0
  85. data/lib/badline/c64/reu/ram.rb +94 -0
  86. data/lib/badline/c64/reu/trigger.rb +34 -0
  87. data/lib/badline/c64/reu.rb +289 -0
  88. data/lib/badline/c64/true_drives.rb +120 -0
  89. data/lib/badline/{computer.rb → c64.rb} +24 -15
  90. data/lib/badline/chips/cia/fast_forward.rb +62 -0
  91. data/lib/badline/chips/cia/interrupt_register.rb +128 -0
  92. data/lib/badline/chips/cia/keyed_parts.rb +213 -0
  93. data/lib/badline/chips/cia/serial.rb +246 -0
  94. data/lib/badline/chips/cia/time_of_day.rb +210 -0
  95. data/lib/badline/chips/cia/timer.rb +188 -0
  96. data/lib/badline/chips/cia.rb +281 -0
  97. data/lib/badline/chips/cpu/addressing.rb +133 -0
  98. data/lib/badline/chips/cpu/boundary.rb +56 -0
  99. data/lib/badline/chips/cpu/core.rb +183 -0
  100. data/lib/badline/chips/cpu/instruction.rb +338 -0
  101. data/lib/badline/chips/cpu/instruction_set/arithmetic.rb +118 -0
  102. data/lib/badline/chips/cpu/instruction_set/bitwise.rb +130 -0
  103. data/lib/badline/chips/cpu/instruction_set/branch.rb +83 -0
  104. data/lib/badline/chips/cpu/instruction_set/flag.rb +67 -0
  105. data/lib/badline/chips/cpu/instruction_set/illegal.rb +274 -0
  106. data/lib/badline/chips/cpu/instruction_set/inc_dec.rb +73 -0
  107. data/lib/badline/chips/cpu/instruction_set/stack.rb +56 -0
  108. data/lib/badline/chips/cpu/instruction_set/transfer.rb +141 -0
  109. data/lib/badline/chips/cpu/instruction_set.rb +59 -0
  110. data/lib/badline/chips/cpu/interrupts.rb +108 -0
  111. data/lib/badline/chips/cpu/keyed_state.rb +177 -0
  112. data/lib/badline/chips/cpu/microcode.rb +195 -0
  113. data/lib/badline/chips/cpu/operations.rb +90 -0
  114. data/lib/badline/chips/cpu/port.rb +133 -0
  115. data/lib/badline/chips/cpu/stack_operations.rb +84 -0
  116. data/lib/badline/chips/cpu/traps.rb +23 -0
  117. data/lib/badline/chips/cpu.rb +17 -0
  118. data/lib/badline/chips/sid/catch_up.rb +122 -0
  119. data/lib/badline/chips/sid/decimator.rb +68 -0
  120. data/lib/badline/chips/sid/envelope.rb +236 -0
  121. data/lib/badline/chips/sid/filter.rb +227 -0
  122. data/lib/badline/chips/sid/keyed_parts.rb +286 -0
  123. data/lib/badline/chips/sid/voice.rb +69 -0
  124. data/lib/badline/chips/sid/waveform/combined.rb +128 -0
  125. data/lib/badline/chips/sid/waveform/fast_forward.rb +107 -0
  126. data/lib/badline/chips/sid/waveform/noise_writeback.rb +124 -0
  127. data/lib/badline/chips/sid/waveform.rb +305 -0
  128. data/lib/badline/chips/sid.rb +264 -0
  129. data/lib/badline/chips/ted/beam.rb +119 -0
  130. data/lib/badline/chips/ted/timers.rb +66 -0
  131. data/lib/badline/chips/ted.rb +143 -0
  132. data/lib/badline/chips/tia.rb +49 -0
  133. data/lib/badline/chips/vdc/keyed_parts.rb +105 -0
  134. data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
  135. data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -13
  136. data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -17
  137. data/lib/badline/{c128 → chips}/vdc/window.rb +1 -10
  138. data/lib/badline/{c128 → chips}/vdc.rb +6 -31
  139. data/lib/badline/chips/via/control_lines.rb +109 -0
  140. data/lib/badline/chips/via/fast_forward.rb +55 -0
  141. data/lib/badline/chips/via/interrupt_register.rb +60 -0
  142. data/lib/badline/chips/via/keyed_parts.rb +163 -0
  143. data/lib/badline/chips/via/shift_register.rb +168 -0
  144. data/lib/badline/chips/via/timer1.rb +120 -0
  145. data/lib/badline/chips/via/timer2.rb +117 -0
  146. data/lib/badline/chips/via.rb +267 -0
  147. data/lib/badline/chips/vic/bank.rb +135 -0
  148. data/lib/badline/chips/vic/border_mask.rb +78 -0
  149. data/lib/badline/chips/vic/collisions.rb +106 -0
  150. data/lib/badline/chips/vic/color_patches.rb +38 -0
  151. data/lib/badline/chips/vic/display_state.rb +168 -0
  152. data/lib/badline/chips/vic/graphics_mode.rb +166 -0
  153. data/lib/badline/chips/vic/graphics_shifter.rb +183 -0
  154. data/lib/badline/chips/vic/keyed_parts.rb +228 -0
  155. data/lib/badline/chips/vic/keyed_sprites.rb +225 -0
  156. data/lib/badline/chips/vic/keyed_state.rb +102 -0
  157. data/lib/badline/chips/vic/register_log.rb +65 -0
  158. data/lib/badline/chips/vic/registers.rb +188 -0
  159. data/lib/badline/chips/vic/sequencer.rb +275 -0
  160. data/lib/badline/chips/vic/sequencer_output.rb +118 -0
  161. data/lib/badline/chips/vic/sprite/internal_bus.rb +59 -0
  162. data/lib/badline/chips/vic/sprite/shifter.rb +148 -0
  163. data/lib/badline/chips/vic/sprite/timing.rb +58 -0
  164. data/lib/badline/chips/vic/sprite.rb +337 -0
  165. data/lib/badline/chips/vic/sprites.rb +281 -0
  166. data/lib/badline/chips/vic.rb +787 -0
  167. data/lib/badline/chips/vic_i/keyed_parts.rb +142 -0
  168. data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +2 -30
  169. data/lib/badline/chips/vic_i/sound/output.rb +85 -0
  170. data/lib/badline/chips/vic_i/sound.rb +227 -0
  171. data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
  172. data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +6 -6
  173. data/lib/badline/chips/z80/arithmetic.rb +119 -0
  174. data/lib/badline/chips/z80/bit_page.rb +57 -0
  175. data/lib/badline/chips/z80/block_io.rb +60 -0
  176. data/lib/badline/chips/z80/block_transfers.rb +61 -0
  177. data/lib/badline/chips/z80/bus_cycles.rb +113 -0
  178. data/lib/badline/chips/z80/core.rb +115 -0
  179. data/lib/badline/chips/z80/exchanges.rb +52 -0
  180. data/lib/badline/chips/z80/extended_page.rb +91 -0
  181. data/lib/badline/chips/z80/flags.rb +39 -0
  182. data/lib/badline/chips/z80/interrupt_acceptance.rb +48 -0
  183. data/lib/badline/chips/z80/jumps.rb +84 -0
  184. data/lib/badline/chips/z80/keyed_state.rb +73 -0
  185. data/lib/badline/chips/z80/loads.rb +100 -0
  186. data/lib/badline/chips/z80/main_page.rb +136 -0
  187. data/lib/badline/chips/z80/registers.rb +122 -0
  188. data/lib/badline/chips/z80/shifts.rb +66 -0
  189. data/lib/badline/chips/z80.rb +13 -0
  190. data/lib/badline/chips.rb +10 -0
  191. data/lib/badline/core.rb +13 -32
  192. data/lib/badline/drives/datasette/keyed_state.rb +38 -0
  193. data/lib/badline/drives/datasette.rb +173 -0
  194. data/lib/badline/drives/engine/core.rb +152 -0
  195. data/lib/badline/drives/engine/fast_serial.rb +75 -0
  196. data/lib/badline/drives/engine/idle.rb +127 -0
  197. data/lib/badline/drives/engine/idle_cpu.rb +30 -0
  198. data/lib/badline/drives/engine/orbit.rb +81 -0
  199. data/lib/badline/drives/engine/serial_lines.rb +72 -0
  200. data/lib/badline/drives/engine/sleep.rb +114 -0
  201. data/lib/badline/drives/engine/vias.rb +86 -0
  202. data/lib/badline/drives/engine/watch.rb +152 -0
  203. data/lib/badline/drives/engine.rb +11 -0
  204. data/lib/badline/drives/model1541/bus.rb +75 -0
  205. data/lib/badline/drives/model1541/byte_ready.rb +50 -0
  206. data/lib/badline/drives/model1541/cpu.rb +13 -0
  207. data/lib/badline/drives/model1541/disk.rb +318 -0
  208. data/lib/badline/drives/model1541/disk_via.rb +38 -0
  209. data/lib/badline/drives/model1541/gcr.rb +59 -0
  210. data/lib/badline/drives/model1541/keyed_state.rb +251 -0
  211. data/lib/badline/drives/model1541/mechanism.rb +313 -0
  212. data/lib/badline/drives/model1541/rotation.rb +123 -0
  213. data/lib/badline/drives/model1541/sector_reader.rb +78 -0
  214. data/lib/badline/drives/model1541/serial_port.rb +20 -0
  215. data/lib/badline/drives/model1541/track.rb +100 -0
  216. data/lib/badline/drives/model1541.rb +80 -0
  217. data/lib/badline/drives/model1571/bus.rb +100 -0
  218. data/lib/badline/drives/model1571/cpu.rb +13 -0
  219. data/lib/badline/drives/model1571/keyed_state.rb +108 -0
  220. data/lib/badline/drives/model1571/serial_port.rb +39 -0
  221. data/lib/badline/drives/model1571/serial_via.rb +27 -0
  222. data/lib/badline/drives/model1571/wd1770.rb +108 -0
  223. data/lib/badline/drives/model1571.rb +141 -0
  224. data/lib/badline/drives/model1581/bus.rb +126 -0
  225. data/lib/badline/drives/model1581/cpu.rb +13 -0
  226. data/lib/badline/drives/model1581/disk.rb +133 -0
  227. data/lib/badline/drives/model1581/keyed_state.rb +280 -0
  228. data/lib/badline/drives/model1581/mechanism.rb +98 -0
  229. data/lib/badline/drives/model1581/serial_port.rb +54 -0
  230. data/lib/badline/drives/model1581/slot.rb +61 -0
  231. data/lib/badline/drives/model1581/track.rb +102 -0
  232. data/lib/badline/drives/model1581/track_bytes.rb +77 -0
  233. data/lib/badline/drives/model1581/wd1772/registers.rb +91 -0
  234. data/lib/badline/drives/model1581/wd1772/sector_writes.rb +75 -0
  235. data/lib/badline/drives/model1581/wd1772/sectors.rb +152 -0
  236. data/lib/badline/drives/model1581/wd1772/stepping.rb +111 -0
  237. data/lib/badline/drives/model1581/wd1772/tracks.rb +127 -0
  238. data/lib/badline/drives/model1581/wd1772/turn.rb +75 -0
  239. data/lib/badline/drives/model1581/wd1772.rb +216 -0
  240. data/lib/badline/drives/model1581.rb +206 -0
  241. data/lib/badline/drives/serial_bus.rb +161 -0
  242. data/lib/badline/drives.rb +8 -0
  243. data/lib/badline/frontend/app.rb +3 -3
  244. data/lib/badline/frontend/boot.rb +4 -4
  245. data/lib/badline/frontend/controls.rb +19 -3
  246. data/lib/badline/frontend/drive_led.rb +44 -21
  247. data/lib/badline/frontend/machine_window.rb +3 -1
  248. data/lib/badline/frontend/menu/menu_dialogs.rb +2 -2
  249. data/lib/badline/frontend/player/filter_view.rb +1 -1
  250. data/lib/badline/frontend/player/player_controller.rb +2 -2
  251. data/lib/badline/frontend/player/player_screen.rb +1 -0
  252. data/lib/badline/frontend/player/theme.rb +7 -7
  253. data/lib/badline/frontend/snapshots.rb +12 -1
  254. data/lib/badline/frontend/timeline.rb +30 -12
  255. data/lib/badline/input/control_ports.rb +78 -0
  256. data/lib/badline/input/joystick.rb +27 -0
  257. data/lib/badline/input/keyboard.rb +114 -0
  258. data/lib/badline/input/matrix_typist.rb +98 -0
  259. data/lib/badline/input.rb +4 -0
  260. data/lib/badline/kernal_trap/chrout.rb +45 -0
  261. data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
  262. data/lib/badline/kernal_trap/dos/channel.rb +156 -0
  263. data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -26
  264. data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -10
  265. data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
  266. data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -9
  267. data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -19
  268. data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
  269. data/lib/badline/kernal_trap/{drive.rb → dos.rb} +9 -27
  270. data/lib/badline/kernal_trap/file_routine.rb +4 -4
  271. data/lib/badline/kernal_trap/keyed_state.rb +150 -0
  272. data/lib/badline/kernal_trap/layout.rb +75 -11
  273. data/lib/badline/kernal_trap/load.rb +19 -21
  274. data/lib/badline/kernal_trap/routine.rb +12 -0
  275. data/lib/badline/kernal_trap/save.rb +12 -22
  276. data/lib/badline/kernal_trap/serial.rb +8 -24
  277. data/lib/badline/kernal_trap.rb +3 -2
  278. data/lib/badline/machine/clocking.rb +1 -1
  279. data/lib/badline/machine/keyboard_buffer.rb +49 -0
  280. data/lib/badline/machine/settling.rb +29 -0
  281. data/lib/badline/machine.rb +10 -7
  282. data/lib/badline/media/boot_disk.rb +14 -2
  283. data/lib/badline/media/extensions.rb +10 -0
  284. data/lib/badline/media/true_drive.rb +1 -1
  285. data/lib/badline/media/tune.rb +2 -2
  286. data/lib/badline/media.rb +3 -3
  287. data/lib/badline/memory.rb +3 -6
  288. data/lib/badline/model.rb +1 -1
  289. data/lib/badline/options/family.rb +5 -2
  290. data/lib/badline/options/help.rb +42 -16
  291. data/lib/badline/options/table.rb +2 -0
  292. data/lib/badline/options/validation.rb +2 -0
  293. data/lib/badline/options.rb +6 -1
  294. data/lib/badline/plus4/acia.rb +45 -0
  295. data/lib/badline/plus4/bus.rb +312 -0
  296. data/lib/badline/plus4/cpu.rb +10 -0
  297. data/lib/badline/plus4/cpu_port.rb +93 -0
  298. data/lib/badline/plus4/keyboard_port.rb +51 -0
  299. data/lib/badline/plus4/model.rb +38 -0
  300. data/lib/badline/plus4/user_port.rb +31 -0
  301. data/lib/badline/plus4.rb +164 -0
  302. data/lib/badline/roms/README +44 -6
  303. data/lib/badline/roms/plus4/basic.rom +0 -0
  304. data/lib/badline/roms/plus4/function-high.rom +0 -0
  305. data/lib/badline/roms/plus4/function-low.rom +0 -0
  306. data/lib/badline/roms/plus4/kernal-ntsc.rom +0 -0
  307. data/lib/badline/roms/plus4/kernal-pal.rom +0 -0
  308. data/lib/badline/sdl.rb +1 -0
  309. data/lib/badline/{storage/sid_file.rb → sid_tune/file.rb} +3 -3
  310. data/lib/badline/{storage → sid_tune}/hvsc.rb +7 -7
  311. data/lib/badline/{storage → sid_tune}/song_lengths.rb +2 -2
  312. data/lib/badline/{storage → sid_tune}/stil/credit.rb +1 -1
  313. data/lib/badline/{storage → sid_tune}/stil.rb +3 -3
  314. data/lib/badline/sid_tune.rb +6 -0
  315. data/lib/badline/snapshot/c128_setup.rb +32 -0
  316. data/lib/badline/snapshot/c64_setup.rb +83 -0
  317. data/lib/badline/snapshot/container.rb +4 -0
  318. data/lib/badline/snapshot/field_doc/markdown.rb +112 -0
  319. data/lib/badline/snapshot/field_doc.rb +109 -0
  320. data/lib/badline/snapshot/image.rb +132 -46
  321. data/lib/badline/snapshot/keyed/cursor.rb +40 -0
  322. data/lib/badline/snapshot/keyed/modules.rb +66 -0
  323. data/lib/badline/snapshot/keyed/reader.rb +188 -0
  324. data/lib/badline/snapshot/keyed/recorder.rb +88 -0
  325. data/lib/badline/snapshot/keyed/report.rb +26 -0
  326. data/lib/badline/snapshot/keyed/writer.rb +55 -0
  327. data/lib/badline/snapshot/keyed.rb +64 -0
  328. data/lib/badline/snapshot/machine_state.rb +17 -64
  329. data/lib/badline/snapshot/storage_setup.rb +63 -0
  330. data/lib/badline/snapshot/vic20_setup.rb +28 -0
  331. data/lib/badline/snapshot/vice/c64_mem.rb +1 -1
  332. data/lib/badline/snapshot/vice/restore.rb +1 -1
  333. data/lib/badline/snapshot/vice/reu1764.rb +3 -3
  334. data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
  335. data/lib/badline/snapshot/vice.rb +13 -35
  336. data/lib/badline/snapshot.rb +44 -22
  337. data/lib/badline/storage/crt_file.rb +3 -1
  338. data/lib/badline/storage/d64_image.rb +0 -2
  339. data/lib/badline/storage/d71_image.rb +0 -2
  340. data/lib/badline/storage/d81_image.rb +0 -2
  341. data/lib/badline/storage/disk_image.rb +3 -6
  342. data/lib/badline/storage/g64_image.rb +10 -5
  343. data/lib/badline/storage/host_directory.rb +0 -5
  344. data/lib/badline/storage/t64.rb +2 -8
  345. data/lib/badline/storage/tap.rb +43 -15
  346. data/lib/badline/storage/unavailable.rb +1 -1
  347. data/lib/badline/storage.rb +0 -37
  348. data/lib/badline/support/c128_checkpoint.rb +39 -0
  349. data/lib/badline/support/checkpoint.rb +108 -0
  350. data/lib/badline/support/vic20_checkpoint.rb +38 -0
  351. data/lib/badline/support.rb +5 -0
  352. data/lib/badline/version.rb +1 -1
  353. data/lib/badline/vic20/attachments.rb +8 -5
  354. data/lib/badline/vic20/bus/keyed_state.rb +52 -0
  355. data/lib/badline/vic20/bus.rb +2 -25
  356. data/lib/badline/vic20/cpu.rb +1 -1
  357. data/lib/badline/vic20/keyed_modules.rb +73 -0
  358. data/lib/badline/vic20/keyed_state.rb +45 -0
  359. data/lib/badline/vic20/port_wiring.rb +4 -4
  360. data/lib/badline/vic20/user_via_ports.rb +2 -2
  361. data/lib/badline/vic20.rb +22 -17
  362. data/lib/badline.rb +1 -0
  363. metadata +271 -228
  364. data/lib/badline/address_bus/extra_sids.rb +0 -30
  365. data/lib/badline/address_bus/fittings.rb +0 -38
  366. data/lib/badline/address_bus/pla.rb +0 -147
  367. data/lib/badline/address_bus/roms.rb +0 -39
  368. data/lib/badline/address_bus/saved_state.rb +0 -66
  369. data/lib/badline/address_bus/sid_slots.rb +0 -42
  370. data/lib/badline/address_bus.rb +0 -216
  371. data/lib/badline/c128/bus_state.rb +0 -53
  372. data/lib/badline/c128/saved_state.rb +0 -143
  373. data/lib/badline/cartridge/action_replay.rb +0 -126
  374. data/lib/badline/cartridge/atomic_power.rb +0 -24
  375. data/lib/badline/cartridge/bank.rb +0 -81
  376. data/lib/badline/cartridge/comal80.rb +0 -50
  377. data/lib/badline/cartridge/dinamic.rb +0 -34
  378. data/lib/badline/cartridge/easy_flash.rb +0 -145
  379. data/lib/badline/cartridge/epyx_fastload.rb +0 -79
  380. data/lib/badline/cartridge/final_cartridge3.rb +0 -89
  381. data/lib/badline/cartridge/flash.rb +0 -306
  382. data/lib/badline/cartridge/freezer.rb +0 -33
  383. data/lib/badline/cartridge/fun_play.rb +0 -38
  384. data/lib/badline/cartridge/g_mod2.rb +0 -74
  385. data/lib/badline/cartridge/game_system.rb +0 -40
  386. data/lib/badline/cartridge/geo_ram.rb +0 -79
  387. data/lib/badline/cartridge/kcs_power.rb +0 -75
  388. data/lib/badline/cartridge/mach5.rb +0 -32
  389. data/lib/badline/cartridge/magic_desk.rb +0 -30
  390. data/lib/badline/cartridge/ocean.rb +0 -35
  391. data/lib/badline/cartridge/pagefox.rb +0 -68
  392. data/lib/badline/cartridge/retro_replay.rb +0 -320
  393. data/lib/badline/cartridge/rex_utility.rb +0 -29
  394. data/lib/badline/cartridge/rgcd.rb +0 -58
  395. data/lib/badline/cartridge/simons_basic.rb +0 -35
  396. data/lib/badline/cartridge/standard.rb +0 -15
  397. data/lib/badline/cartridge/super_games.rb +0 -48
  398. data/lib/badline/cartridge/westermann.rb +0 -30
  399. data/lib/badline/cartridge/zaxxon.rb +0 -66
  400. data/lib/badline/cartridge.rb +0 -303
  401. data/lib/badline/checkpoint.rb +0 -98
  402. data/lib/badline/chrout_trap.rb +0 -43
  403. data/lib/badline/cia/fast_forward.rb +0 -60
  404. data/lib/badline/cia/interrupt_register.rb +0 -143
  405. data/lib/badline/cia/serial.rb +0 -275
  406. data/lib/badline/cia/state.rb +0 -47
  407. data/lib/badline/cia/timer.rb +0 -206
  408. data/lib/badline/cia.rb +0 -279
  409. data/lib/badline/color_memory.rb +0 -25
  410. data/lib/badline/computer/attachments.rb +0 -88
  411. data/lib/badline/computer/saved_state.rb +0 -117
  412. data/lib/badline/computer/true_drives.rb +0 -69
  413. data/lib/badline/control_ports.rb +0 -76
  414. data/lib/badline/cpu/addressing.rb +0 -131
  415. data/lib/badline/cpu/boundary.rb +0 -54
  416. data/lib/badline/cpu/core.rb +0 -165
  417. data/lib/badline/cpu/microcode.rb +0 -177
  418. data/lib/badline/cpu/operations.rb +0 -88
  419. data/lib/badline/cpu/saved_state.rb +0 -115
  420. data/lib/badline/cpu/stack_operations.rb +0 -82
  421. data/lib/badline/cpu.rb +0 -10
  422. data/lib/badline/cpu_port.rb +0 -112
  423. data/lib/badline/datasette.rb +0 -161
  424. data/lib/badline/debug_register.rb +0 -28
  425. data/lib/badline/drive/core.rb +0 -147
  426. data/lib/badline/drive/fast_serial.rb +0 -73
  427. data/lib/badline/drive/idle.rb +0 -125
  428. data/lib/badline/drive/idle_cpu.rb +0 -28
  429. data/lib/badline/drive/orbit.rb +0 -79
  430. data/lib/badline/drive/serial_lines.rb +0 -73
  431. data/lib/badline/drive/sleep.rb +0 -112
  432. data/lib/badline/drive/vias.rb +0 -84
  433. data/lib/badline/drive/watch.rb +0 -150
  434. data/lib/badline/drive.rb +0 -11
  435. data/lib/badline/drive1541/bus.rb +0 -86
  436. data/lib/badline/drive1541/byte_ready.rb +0 -48
  437. data/lib/badline/drive1541/cpu.rb +0 -11
  438. data/lib/badline/drive1541/disk.rb +0 -315
  439. data/lib/badline/drive1541/disk_state.rb +0 -86
  440. data/lib/badline/drive1541/disk_via.rb +0 -36
  441. data/lib/badline/drive1541/gcr.rb +0 -57
  442. data/lib/badline/drive1541/mechanism.rb +0 -313
  443. data/lib/badline/drive1541/mechanism_state.rb +0 -68
  444. data/lib/badline/drive1541/rotation.rb +0 -121
  445. data/lib/badline/drive1541/sector_reader.rb +0 -76
  446. data/lib/badline/drive1541/serial_port.rb +0 -18
  447. data/lib/badline/drive1541/track.rb +0 -98
  448. data/lib/badline/drive1541.rb +0 -111
  449. data/lib/badline/drive1571/bus.rb +0 -111
  450. data/lib/badline/drive1571/cpu.rb +0 -11
  451. data/lib/badline/drive1571/serial_port.rb +0 -37
  452. data/lib/badline/drive1571/serial_via.rb +0 -25
  453. data/lib/badline/drive1571/wd1770.rb +0 -120
  454. data/lib/badline/drive1571.rb +0 -175
  455. data/lib/badline/drive1581/bus.rb +0 -137
  456. data/lib/badline/drive1581/cpu.rb +0 -11
  457. data/lib/badline/drive1581/disk.rb +0 -135
  458. data/lib/badline/drive1581/disk_state.rb +0 -87
  459. data/lib/badline/drive1581/mechanism.rb +0 -117
  460. data/lib/badline/drive1581/serial_port.rb +0 -52
  461. data/lib/badline/drive1581/slot.rb +0 -78
  462. data/lib/badline/drive1581/track.rb +0 -100
  463. data/lib/badline/drive1581/track_bytes.rb +0 -75
  464. data/lib/badline/drive1581/wd1772/registers.rb +0 -89
  465. data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
  466. data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
  467. data/lib/badline/drive1581/wd1772/state.rb +0 -66
  468. data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
  469. data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
  470. data/lib/badline/drive1581/wd1772/turn.rb +0 -73
  471. data/lib/badline/drive1581/wd1772.rb +0 -216
  472. data/lib/badline/drive1581.rb +0 -233
  473. data/lib/badline/iec_bus.rb +0 -159
  474. data/lib/badline/instruction.rb +0 -334
  475. data/lib/badline/instruction_set/arithmetic.rb +0 -114
  476. data/lib/badline/instruction_set/bitwise.rb +0 -126
  477. data/lib/badline/instruction_set/branch.rb +0 -79
  478. data/lib/badline/instruction_set/flag.rb +0 -63
  479. data/lib/badline/instruction_set/illegal.rb +0 -270
  480. data/lib/badline/instruction_set/inc_dec.rb +0 -69
  481. data/lib/badline/instruction_set/stack.rb +0 -52
  482. data/lib/badline/instruction_set/transfer.rb +0 -137
  483. data/lib/badline/instruction_set.rb +0 -55
  484. data/lib/badline/interrupts.rb +0 -104
  485. data/lib/badline/joystick.rb +0 -25
  486. data/lib/badline/kernal_trap/channel.rb +0 -181
  487. data/lib/badline/keyboard.rb +0 -112
  488. data/lib/badline/keyboard_buffer.rb +0 -33
  489. data/lib/badline/ram_expansion/banking.rb +0 -30
  490. data/lib/badline/ram_expansion/plus256k.rb +0 -54
  491. data/lib/badline/ram_expansion/plus60k.rb +0 -43
  492. data/lib/badline/ram_expansion/unexpanded.rb +0 -28
  493. data/lib/badline/ram_expansion.rb +0 -21
  494. data/lib/badline/reu/dma/saved_state.rb +0 -50
  495. data/lib/badline/reu/dma.rb +0 -273
  496. data/lib/badline/reu/ram.rb +0 -107
  497. data/lib/badline/reu/saved_state.rb +0 -80
  498. data/lib/badline/reu/trigger.rb +0 -32
  499. data/lib/badline/reu.rb +0 -289
  500. data/lib/badline/sid/catch_up.rb +0 -120
  501. data/lib/badline/sid/decimator.rb +0 -64
  502. data/lib/badline/sid/envelope/state.rb +0 -68
  503. data/lib/badline/sid/envelope.rb +0 -239
  504. data/lib/badline/sid/filter.rb +0 -263
  505. data/lib/badline/sid/voice.rb +0 -77
  506. data/lib/badline/sid/waveform/combined.rb +0 -126
  507. data/lib/badline/sid/waveform/fast_forward.rb +0 -105
  508. data/lib/badline/sid/waveform/noise_writeback.rb +0 -122
  509. data/lib/badline/sid/waveform/state.rb +0 -66
  510. data/lib/badline/sid/waveform.rb +0 -305
  511. data/lib/badline/sid.rb +0 -303
  512. data/lib/badline/snapshot/setup.rb +0 -75
  513. data/lib/badline/snapshot/state.rb +0 -189
  514. data/lib/badline/time_of_day.rb +0 -228
  515. data/lib/badline/traps.rb +0 -19
  516. data/lib/badline/via/control_lines.rb +0 -122
  517. data/lib/badline/via/fast_forward.rb +0 -53
  518. data/lib/badline/via/interrupt_register.rb +0 -67
  519. data/lib/badline/via/shift_register.rb +0 -180
  520. data/lib/badline/via/state.rb +0 -42
  521. data/lib/badline/via/timer1.rb +0 -131
  522. data/lib/badline/via/timer2.rb +0 -133
  523. data/lib/badline/via.rb +0 -266
  524. data/lib/badline/vic/bank.rb +0 -133
  525. data/lib/badline/vic/border_mask.rb +0 -86
  526. data/lib/badline/vic/collisions.rb +0 -115
  527. data/lib/badline/vic/color_patches.rb +0 -47
  528. data/lib/badline/vic/display_state.rb +0 -185
  529. data/lib/badline/vic/graphics_mode.rb +0 -164
  530. data/lib/badline/vic/graphics_shifter.rb +0 -207
  531. data/lib/badline/vic/register_log.rb +0 -81
  532. data/lib/badline/vic/registers.rb +0 -195
  533. data/lib/badline/vic/sequencer.rb +0 -275
  534. data/lib/badline/vic/sequencer_output.rb +0 -116
  535. data/lib/badline/vic/sequencer_state.rb +0 -89
  536. data/lib/badline/vic/sprite/internal_bus.rb +0 -68
  537. data/lib/badline/vic/sprite/saved_state.rb +0 -64
  538. data/lib/badline/vic/sprite/shifter.rb +0 -146
  539. data/lib/badline/vic/sprite/timing.rb +0 -56
  540. data/lib/badline/vic/sprite.rb +0 -337
  541. data/lib/badline/vic/sprites.rb +0 -282
  542. data/lib/badline/vic/sprites_state.rb +0 -57
  543. data/lib/badline/vic.rb +0 -853
  544. data/lib/badline/vic20/saved_state.rb +0 -124
  545. data/lib/badline/vic20/sound/output.rb +0 -83
  546. data/lib/badline/vic20/sound.rb +0 -233
  547. data/lib/badline/vic20/vic/saved_state.rb +0 -55
  548. data/lib/badline/z80/arithmetic.rb +0 -117
  549. data/lib/badline/z80/bit_page.rb +0 -55
  550. data/lib/badline/z80/block_io.rb +0 -58
  551. data/lib/badline/z80/block_transfers.rb +0 -59
  552. data/lib/badline/z80/bus_cycles.rb +0 -111
  553. data/lib/badline/z80/core.rb +0 -113
  554. data/lib/badline/z80/exchanges.rb +0 -50
  555. data/lib/badline/z80/extended_page.rb +0 -89
  556. data/lib/badline/z80/flags.rb +0 -37
  557. data/lib/badline/z80/interrupt_acceptance.rb +0 -46
  558. data/lib/badline/z80/jumps.rb +0 -82
  559. data/lib/badline/z80/loads.rb +0 -98
  560. data/lib/badline/z80/main_page.rb +0 -134
  561. data/lib/badline/z80/registers.rb +0 -120
  562. data/lib/badline/z80/saved_state.rb +0 -69
  563. data/lib/badline/z80/shifts.rb +0 -64
  564. data/lib/badline/z80.rb +0 -11
  565. /data/lib/badline/snapshot/{fields.rb → vice/fields.rb} +0 -0
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Cartridge
5
- # Super Games: four 16K banks. A write to I/O 2 selects the bank from bits
6
- # 0-1, switches the ROM out with bit 2, and with bit 3 locks the register
7
- # until reset.
8
- class SuperGames < Cartridge
9
- def poke(addr, value)
10
- return if addr < 0xdf00 || @locked
11
-
12
- select(value)
13
- changed!
14
- end
15
-
16
- def reset
17
- select(0)
18
- changed!
19
- end
20
-
21
- private
22
-
23
- def save_mapper(out)
24
- super
25
- out.boolean(@locked)
26
- end
27
-
28
- def load_mapper(input)
29
- super
30
- @locked = input.boolean?
31
- end
32
-
33
- def windows = [*@roml_banks, *@romh_banks, EMPTY_BANK]
34
-
35
- def select(value)
36
- @roml = bank(@roml_banks, value & 0x03)
37
- @romh = bank(@romh_banks, value & 0x03)
38
- self.mode = value.anybits?(0x04) ? :off : :rom16k
39
- @locked = value.anybits?(0x08)
40
- end
41
-
42
- def install_chips(chips)
43
- @roml_banks, @romh_banks = banks_from(chips)
44
- reset
45
- end
46
- end
47
- end
48
- end
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Cartridge
5
- # 16K. Reading I/O 2 switches ROMH out (8K mode) until reset.
6
- class Westermann < Cartridge
7
- def readable_io_pages
8
- [0xdf]
9
- end
10
-
11
- def peek(addr)
12
- select_mode(:rom8k) if addr >= 0xdf00
13
- open_bus(addr)
14
- end
15
-
16
- def reset
17
- select_mode(:rom16k)
18
- end
19
-
20
- private
21
-
22
- def install_chips(chips)
23
- roml, romh = banks_from(chips)
24
- @roml = bank(roml, 0)
25
- @romh = bank(romh, 0)
26
- reset
27
- end
28
- end
29
- end
30
- end
@@ -1,66 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Cartridge
5
- # Zaxxon / Super Zaxxon: 16K mode with a 4K ROML mirrored across
6
- # $8000-$9FFF and two 8K ROMH banks. A read through ROML selects the
7
- # ROMH bank: $8000-$8FFF the first, $9000-$9FFF the second.
8
- class Zaxxon < Cartridge
9
- class Low
10
- def initialize(rom, high)
11
- @rom = rom
12
- @high = high
13
- end
14
-
15
- def peek(addr)
16
- @high.select(addr[12])
17
- @rom.peek(addr)
18
- end
19
- end
20
-
21
- class High
22
- def initialize(banks)
23
- @banks = banks
24
- select(0)
25
- end
26
-
27
- def select(number)
28
- @bank = @banks[number] || EMPTY_BANK
29
- end
30
-
31
- def peek(addr)
32
- @bank.peek(addr)
33
- end
34
-
35
- def save_state(out)
36
- out.int([*@banks, EMPTY_BANK].index { |bank| bank.equal?(@bank) })
37
- end
38
-
39
- def load_state(input)
40
- @bank = [*@banks, EMPTY_BANK].fetch(input.int)
41
- end
42
- end
43
-
44
- def reset
45
- @romh.select(0)
46
- end
47
-
48
- private
49
-
50
- def save_mapper(out)
51
- @romh.save_state(out)
52
- end
53
-
54
- def load_mapper(input)
55
- @romh.load_state(input)
56
- end
57
-
58
- def install_chips(chips)
59
- roml, romh = banks_from(chips)
60
- @romh = High.new(romh)
61
- @roml = Low.new(roml.first || EMPTY_BANK, @romh)
62
- self.mode = :rom16k
63
- end
64
- end
65
- end
66
- end
@@ -1,303 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "badline/cartridge/bank"
4
- require "badline/cartridge/flash"
5
- require "badline/cartridge/standard"
6
- require "badline/cartridge/simons_basic"
7
- require "badline/cartridge/ocean"
8
- require "badline/cartridge/fun_play"
9
- require "badline/cartridge/super_games"
10
- require "badline/cartridge/epyx_fastload"
11
- require "badline/cartridge/westermann"
12
- require "badline/cartridge/rex_utility"
13
- require "badline/cartridge/game_system"
14
- require "badline/cartridge/dinamic"
15
- require "badline/cartridge/zaxxon"
16
- require "badline/cartridge/magic_desk"
17
- require "badline/cartridge/comal80"
18
- require "badline/cartridge/easy_flash"
19
- require "badline/cartridge/mach5"
20
- require "badline/cartridge/pagefox"
21
- require "badline/cartridge/rgcd"
22
- require "badline/cartridge/g_mod2"
23
- require "badline/cartridge/freezer"
24
- require "badline/cartridge/action_replay"
25
- require "badline/cartridge/atomic_power"
26
- require "badline/cartridge/final_cartridge3"
27
- require "badline/cartridge/retro_replay"
28
- require "badline/cartridge/kcs_power"
29
- require "badline/cartridge/geo_ram"
30
-
31
- module Badline
32
- class Cartridge
33
- class UnsupportedTypeError < StandardError; end
34
-
35
- ROMH_START = 0xa000
36
- BANK_SIZE = 0x2000
37
-
38
- HARDWARE_TYPES = {
39
- 0 => Standard, 1 => ActionReplay, 2 => KCSPower, 3 => FinalCartridge3,
40
- 4 => SimonsBasic, 5 => Ocean, 7 => FunPlay, 8 => SuperGames,
41
- 9 => AtomicPower, 10 => EpyxFastload, 11 => Westermann,
42
- 12 => RexUtility, 15 => GameSystem, 17 => Dinamic, 18 => Zaxxon,
43
- 19 => MagicDesk, 21 => Comal80, 32 => EasyFlash, 36 => RetroReplay,
44
- 51 => Mach5, 53 => Pagefox, 57 => RGCD, 60 => GMod2
45
- }.freeze
46
-
47
- # The EXROM and GAME line levels of each memory configuration. The lines
48
- # are active low.
49
- MODES = {
50
- rom8k: [0, 1].freeze, rom16k: [0, 0].freeze,
51
- ultimax: [1, 0].freeze, off: [1, 1].freeze
52
- }.freeze
53
-
54
- attr_reader :name, :exrom, :game, :roml, :romh
55
-
56
- # A callable returning the current cycle, for mappers with timed state.
57
- attr_writer :clock
58
-
59
- class << self
60
- # Options set the cartridge's jumpers, for the mappers that have them.
61
- def from_file(path, **)
62
- from_crt(Storage::CRTFile.new(path), **)
63
- end
64
-
65
- def from_crt(crt, **)
66
- mapper_for(crt).new(crt, **)
67
- end
68
-
69
- # A cartridge built afresh from what save_setup wrote, before
70
- # load_state puts its state in.
71
- def from_setup(input)
72
- return GeoRAM.new(size: input.int) if input.int == GEO_RAM_SETUP
73
-
74
- crt = Storage::CRTFile.new(bytes: input.string)
75
- mapper_for(crt).from_jumpers(crt, input)
76
- end
77
-
78
- # A cartridge from its image and what save_jumpers wrote: whether
79
- # there are jumpers, then their settings on a mapper that has them.
80
- def from_jumpers(crt, input)
81
- input.boolean?
82
- new(crt)
83
- end
84
-
85
- def mapper_for(crt)
86
- HARDWARE_TYPES.fetch(crt.hardware_type) do
87
- raise UnsupportedTypeError,
88
- "Unsupported cartridge hardware type #{crt.hardware_type}"
89
- end
90
- end
91
- end
92
-
93
- # What save_setup writes first: a cartridge from a CRT image, or a
94
- # GEO-RAM.
95
- CRT_SETUP = 0
96
- GEO_RAM_SETUP = 1
97
-
98
- # Keeps the image it was built from, so a snapshot's machine can build
99
- # the same cartridge before the snapshot's state goes into it.
100
- def initialize(crt)
101
- @crt = crt
102
- @name = crt.name
103
- @exrom = crt.exrom
104
- @game = crt.game
105
- @roml = @romh = nil
106
- @banks = nil
107
- @on_change = nil
108
- @on_nmi_change = nil
109
- @nmi = false
110
- @open_bus = nil
111
- @clock = nil
112
- install_chips(crt.chips)
113
- end
114
-
115
- def on_change(&block)
116
- @on_change = block
117
- end
118
-
119
- # What builds the same cartridge afresh (Cartridge.from_setup): the CRT
120
- # image it was built from, and the jumpers of a mapper that has them.
121
- def save_setup(out)
122
- out.int(CRT_SETUP).string(Storage::CRTFile.encode(@crt))
123
- save_jumpers(out)
124
- end
125
-
126
- # The lines, the pull on NMI, the button and the mapper's own state.
127
- # Loading sets them without calling back into the machine, which maps
128
- # the cartridge again afterwards.
129
- def save_state(out)
130
- out.marker("CARTRIDGE")
131
- out.int(@exrom).int(@game).boolean(@nmi).boolean(@button == true)
132
- save_mapper(out)
133
- end
134
-
135
- def load_state(input)
136
- input.marker("CARTRIDGE")
137
- @exrom = input.int
138
- @game = input.int
139
- @nmi = input.boolean?
140
- @button = input.boolean?
141
- load_mapper(input)
142
- end
143
-
144
- # Called with the level of the cartridge's pull on the NMI line when it
145
- # changes. The line is wired-OR with CIA 2's.
146
- def on_nmi_change(&block)
147
- @on_nmi_change = block
148
- end
149
-
150
- def nmi?
151
- @nmi
152
- end
153
-
154
- # The address bus hands over the C64's RAM, for mappers that write
155
- # through to it, and the open bus, for I/O reads the cartridge doesn't
156
- # drive.
157
- def connect(ram:, open_bus:)
158
- @ram = ram
159
- @open_bus = open_bus
160
- end
161
-
162
- def ultimax?
163
- @game.zero? && @exrom == 1
164
- end
165
-
166
- # Whether the first half of the cycle, where the VIC does most of its
167
- # fetching, sees Ultimax mode. Some cartridges drive GAME and EXROM
168
- # differently in the two halves; #ultimax? is the second, the CPU's.
169
- def phi1_ultimax?
170
- ultimax?
171
- end
172
-
173
- # The I/O pages ($de, $df) whose reads the mapper drives. Reads of the
174
- # others are open bus.
175
- def readable_io_pages
176
- []
177
- end
178
-
179
- def poke(_addr, _value); end
180
-
181
- # A window taking writes to $E000-$FFFF while reads there see the C64's
182
- # memory, for a cartridge that asserts Ultimax on write cycles only.
183
- def romh_writes; end
184
-
185
- # A window at $A000-$BFFF in Ultimax mode, where the C64 maps nothing.
186
- def ultimax_a000; end
187
-
188
- # The RES line on the expansion port.
189
- def reset; end
190
-
191
- # Whether the cartridge has a freeze button.
192
- def freezer? = false
193
-
194
- # The freeze button, which cartridges without one ignore.
195
- def press_button; end
196
-
197
- def release_button; end
198
-
199
- private
200
-
201
- def save_jumpers(out)
202
- out.boolean(false)
203
- end
204
-
205
- # The mapper's own state: where its windows point, for a mapper that
206
- # moves them, and whatever a mapper adds after calling super.
207
- def save_mapper(out)
208
- save_windows(out, windows) if windows
209
- end
210
-
211
- def load_mapper(input)
212
- load_windows(input, windows) if windows
213
- end
214
-
215
- # The banks and views ROML and ROMH can point at, which a snapshot
216
- # names them by: the mapper's banks, or nothing for a mapper whose
217
- # windows stay where install_chips put them.
218
- def windows
219
- [*@banks, EMPTY_BANK] if @banks
220
- end
221
-
222
- # Where the ROML and ROMH windows point, as their places in `windows`,
223
- # the banks and views the mapper picks them from, or -1 for none.
224
- def save_windows(out, windows)
225
- out.int(window_index(@roml, windows)).int(window_index(@romh, windows))
226
- end
227
-
228
- def load_windows(input, windows)
229
- @roml = window_at(input.int, windows)
230
- @romh = window_at(input.int, windows)
231
- end
232
-
233
- def window_index(window, windows)
234
- return -1 if window.nil?
235
-
236
- windows.index { |candidate| candidate.equal?(window) } ||
237
- raise(ArgumentError, "#{self.class.name}: a window that isn't among its banks")
238
- end
239
-
240
- def window_at(index, windows) = index.negative? ? nil : windows.fetch(index)
241
-
242
- def nmi=(level)
243
- return if @nmi == level
244
-
245
- @nmi = level
246
- @on_nmi_change&.call(level)
247
- end
248
-
249
- def changed!
250
- @on_change&.call
251
- end
252
-
253
- def mode=(mode)
254
- @exrom, @game = MODES.fetch(mode)
255
- end
256
-
257
- # Sets the lines and tells the machine to map the cartridge again.
258
- def select_mode(mode)
259
- self.mode = mode
260
- changed!
261
- end
262
-
263
- def open_bus(addr)
264
- @open_bus ? @open_bus.peek(addr) : 0xff
265
- end
266
-
267
- def install_chips(_chips)
268
- raise NotImplementedError
269
- end
270
-
271
- def rom_bank(data)
272
- Bank.new(data)
273
- end
274
-
275
- # A bank the image leaves out reads as erased ROM.
276
- def bank(banks, number)
277
- banks[number] || EMPTY_BANK
278
- end
279
-
280
- # The bank register bits a ROM decodes. The ROM holds the highest bank
281
- # in the image, and has address lines for the power of two that covers
282
- # it; the register bits above those lines are ignored.
283
- def bank_mask(banks)
284
- (1 << (banks.length - 1).bit_length) - 1
285
- end
286
-
287
- # Sorts the CHIP packets into ROML and ROMH banks by load address. A 16K
288
- # chip at $8000 spans both.
289
- def banks_from(chips)
290
- roml = []
291
- romh = []
292
- chips.each do |chip|
293
- if chip.address >= ROMH_START
294
- romh[chip.bank] = rom_bank(chip.data)
295
- else
296
- roml[chip.bank] = rom_bank(chip.data[0, BANK_SIZE])
297
- romh[chip.bank] = rom_bank(chip.data[BANK_SIZE, BANK_SIZE]) if chip.data.length > BANK_SIZE
298
- end
299
- end
300
- [roml, romh]
301
- end
302
- end
303
- end
@@ -1,98 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- # A digest of the machine's state at one cycle, for comparing two runs of
5
- # the same scenario, on two builds or two revisions. Each component is
6
- # hashed on its own with 32-bit FNV-1a, so a mismatch names the part of the
7
- # machine that went its own way. Nothing is read through a chip's bus
8
- # interface, so taking a checkpoint leaves the machine as it was.
9
- #
10
- # Colour RAM is digested as the four bits each cell stores: the upper
11
- # nibble a CPU read sees comes off the open bus.
12
- class Checkpoint
13
- COMPONENTS = %w[cpu ram color_ram display vic cia1 cia2 sid].freeze
14
-
15
- FNV_OFFSET = 0x811c9dc5
16
- FNV_PRIME = 0x01000193
17
-
18
- attr_reader :cycle, :digests
19
-
20
- class << self
21
- def take(computer)
22
- new(computer.cycles, [
23
- fnv1a(cpu_state(computer.cpu)),
24
- fnv1a(ram(computer.ram)),
25
- fnv1a(color_ram(computer.address_bus.color_ram)),
26
- fnv1a(computer.vic.display),
27
- fnv1a(vic_state(computer.vic)),
28
- fnv1a(cia_state(computer.cia1)),
29
- fnv1a(cia_state(computer.cia2)),
30
- fnv1a(Array.new(0x20) { |reg| computer.sid.register(reg) })
31
- ])
32
- end
33
-
34
- # Reads a line written by #to_s.
35
- def parse(line)
36
- fields = line.split
37
- digests = COMPONENTS.map do |name|
38
- field = fields.find { |f| f.start_with?("#{name}=") }
39
- raise ArgumentError, "no #{name} digest in #{line.inspect}" unless field
40
-
41
- field.split("=").last.to_i(16)
42
- end
43
- new(fields.first.to_i, digests)
44
- end
45
-
46
- def fnv1a(values)
47
- hash = FNV_OFFSET
48
- values.each { |value| hash = ((hash ^ (value & 0xffffffff)) * FNV_PRIME) & 0xffffffff }
49
- hash
50
- end
51
-
52
- private
53
-
54
- def cpu_state(cpu)
55
- [cpu.program_counter, cpu.a, cpu.x, cpu.y, cpu.stack_pointer, cpu.p, cpu.cycles]
56
- end
57
-
58
- def ram(memory)
59
- Array.new(0x10000) { |addr| memory.peek(addr) }
60
- end
61
-
62
- def color_ram(memory)
63
- Array.new(0x400) { |offset| memory.nibble(0xd800 + offset) }
64
- end
65
-
66
- def vic_state(vic)
67
- vic.register_file + [vic.rasterline, vic.column]
68
- end
69
-
70
- def cia_state(cia)
71
- start = cia.start
72
- [cia.peek(start), cia.peek(start + 1), cia.peek(start + 2), cia.peek(start + 3),
73
- cia.timer_a, cia.timer_a_latch, cia.timer_b, cia.timer_b_latch, cia.serial.data,
74
- cia.control_a.value, cia.control_b.value, cia.interrupt_status.value,
75
- cia.interrupt_control.value] + cia.time_of_day.registers
76
- end
77
- end
78
-
79
- def initialize(cycle, digests)
80
- @cycle = cycle
81
- @digests = digests
82
- end
83
-
84
- # The components whose digests differ from `other`'s.
85
- def differences(other)
86
- COMPONENTS.each_index.reject { |i| digests[i] == other.digests[i] }.map { |i| COMPONENTS[i] }
87
- end
88
-
89
- def ==(other)
90
- other.is_a?(Checkpoint) && cycle == other.cycle && digests == other.digests
91
- end
92
-
93
- def to_s
94
- fields = COMPONENTS.each_index.map { |i| "#{COMPONENTS[i]}=#{digests[i].to_s(16).rjust(8, '0')}" }
95
- "#{cycle} #{fields.join(' ')}"
96
- end
97
- end
98
- end
@@ -1,43 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- # Observe-only PC trap on the KERNAL CHROUT routine ($FFD2). Records each
5
- # character written while the layout finds the KERNAL mapped in, then lets execution fall
6
- # through to the ROM, so the screen output is unaffected. Used for headless
7
- # capture of program output.
8
- class ChroutTrap
9
- ADDRESS = 0xffd2
10
-
11
- attr_reader :output
12
-
13
- # The KERNAL layout whose mapping the trap checks.
14
- attr_writer :layout
15
-
16
- def initialize(cpu:, bus:, layout:)
17
- @cpu = cpu
18
- @bus = bus
19
- @layout = layout
20
- @output = +""
21
- end
22
-
23
- def call
24
- @output << ascii(@cpu.a) if @layout.kernal_mapped?(@bus)
25
- end
26
-
27
- def inspect
28
- "#<#{self.class.name} output=#{@output.inspect}>"
29
- end
30
-
31
- private
32
-
33
- def ascii(byte)
34
- case byte
35
- when 0x0d then "\n"
36
- when 0x41..0x5a then (byte + 0x20).chr
37
- when 0xc1..0xda then (byte - 0x80).chr
38
- when 0x20..0x7e then byte.chr
39
- else ""
40
- end
41
- end
42
- end
43
- end
@@ -1,60 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class CIA
5
- # Running a CIA a stretch of cycles at once, for Drive::Idle.
6
- module FastForward
7
- # quiet_cycles for a CIA whose counters will never set a flag.
8
- QUIET = 1 << 40
9
-
10
- # Whether fast_forward can run the CIA: timer B stopped with nothing
11
- # in its pipeline, no interrupt or acknowledge on its way, CNT where it
12
- # was, the TOD clock stopped, and timer A either stopped, or free
13
- # running (Timer#free_running?) with its interrupt masked and the
14
- # serial port an idle input. Drive::Idle sleeps the 1571's CIA through
15
- # such cycles, which its DOS leaves timer A running in.
16
- def quiet?
17
- return false unless @tb.idle? && @icr.quiet && @tod.quiet? && cnt_steady?
18
-
19
- @ta.idle? ? @serial.idle : timer_a_free_running?
20
- end
21
-
22
- # How many cycles the CIA can run with nothing but its counters
23
- # moving: as quiet? allows, but with timer B free running too, up to
24
- # the cycle before it underflows. The 1581's DOS leaves timer B
25
- # interrupting every 10 ms.
26
- def quiet_cycles
27
- return 0 unless @icr.quiet && @tod.quiet? && cnt_steady? && timer_a_quiet?
28
- return QUIET if @tb.idle?
29
- return 0 unless @tb.free_running? && @control_b.value.nobits?(0x60)
30
-
31
- @tb.counter - 1
32
- end
33
-
34
- # Runs +cycles+ cycles at once while quiet? or for quiet_cycles, as
35
- # cycle! would: timer A's underflows flag in the ICR, and reach the
36
- # serial port's underflow line.
37
- def fast_forward(cycles)
38
- @tod.fast_forward(cycles)
39
- @tb.fast_forward(cycles) unless @tb.idle?
40
- return if @ta.idle?
41
-
42
- @icr.flag(:timer_a) if @ta.fast_forward(cycles).positive?
43
- @serial.follow_underflow(@ta.underflowed)
44
- end
45
-
46
- private
47
-
48
- def timer_a_quiet? = @ta.idle? ? @serial.idle : timer_a_free_running?
49
-
50
- # Timer A free running with its interrupt masked, and the serial port
51
- # an idle input it only clocks.
52
- def timer_a_free_running?
53
- @ta.free_running? && !@control_a.serial_mode? && @icr.mask.value.nobits?(0x01) && @serial.drained?
54
- end
55
-
56
- # Whether CNT holds the level the last cycle sampled.
57
- def cnt_steady? = @serial.cnt == @cnt_high && !@cnt_rise
58
- end
59
- end
60
- end