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,89 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Cartridge
5
- # The Final Cartridge III: four 16K banks, or sixteen on the III+. I/O 1
6
- # and I/O 2 show the last two pages of the selected ROML bank. A write
7
- # to $DFFF sets the register:
8
- #
9
- # bits 0-1 bank (0-3 on the III+)
10
- # bit 4 EXROM level
11
- # bit 5 GAME level
12
- # bit 6 NMI line, active low
13
- # bit 7 hides the register until the next freeze
14
- #
15
- # Clearing bit 6 pulls NMI without freezing, and setting it lets go of
16
- # NMI after a freeze. A freeze keeps the bank and switches to Ultimax,
17
- # which the VIC doesn't see until the register sets it again.
18
- class FinalCartridge3 < Cartridge
19
- include Freezer
20
-
21
- REGISTER = 0xdfff
22
-
23
- def readable_io_pages
24
- [0xde, 0xdf]
25
- end
26
-
27
- def peek(addr)
28
- @io_bank.peek(addr)
29
- end
30
-
31
- def poke(addr, value)
32
- return unless addr == REGISTER && @register_visible
33
-
34
- @register_visible = value.nobits?(0x80)
35
- self.nmi = value.nobits?(0x40)
36
- select(value & @bank_mask)
37
- @exrom = (value >> 4) & 0x01
38
- @game = (value >> 5) & 0x01
39
- @phi1_ultimax = ultimax?
40
- changed!
41
- end
42
-
43
- def phi1_ultimax?
44
- @phi1_ultimax
45
- end
46
-
47
- def reset
48
- @register_visible = true
49
- @phi1_ultimax = false
50
- self.nmi = false
51
- select(0)
52
- select_mode(:rom16k)
53
- end
54
-
55
- def freeze!
56
- @register_visible = true
57
- @phi1_ultimax = false
58
- select_mode(:ultimax)
59
- end
60
-
61
- private
62
-
63
- def save_mapper(out)
64
- super
65
- out.boolean(@register_visible).boolean(@phi1_ultimax)
66
- end
67
-
68
- def load_mapper(input)
69
- super
70
- @io_bank = @roml
71
- @register_visible = input.boolean?
72
- @phi1_ultimax = input.boolean?
73
- end
74
-
75
- def windows = [*@roml_banks, *@romh_banks, EMPTY_BANK]
76
-
77
- def select(number)
78
- @io_bank = @roml = bank(@roml_banks, number)
79
- @romh = bank(@romh_banks, number)
80
- end
81
-
82
- def install_chips(chips)
83
- @roml_banks, @romh_banks = banks_from(chips)
84
- @bank_mask = @roml_banks.length > 4 ? 0x0f : 0x03
85
- reset
86
- end
87
- end
88
- end
89
- end
@@ -1,306 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Cartridge
5
- # A Flash chip's state, for a snapshot.
6
- module FlashState
7
- STATES = %i[read program_setup autoselect programming erase_window erasing suspended chip_erase
8
- program_error].freeze
9
-
10
- # The array, the command state, a timed operation's end on the
11
- # machine's clock, and the windows handed out so far, which load_state
12
- # builds anew.
13
- def save_state(out)
14
- out.blob(@data).int(STATES.index(@state)).int(STATES.index(@base_state)).int(@cycle).int(@toggle)
15
- out.optional_int(@done_at).optional_int(@programmed).optional_int(@remaining)
16
- out.boolean(!@erasing_sectors.nil?)
17
- out.ints(@erasing_sectors) if @erasing_sectors
18
- out.ints(@windows.keys).ints(@status_windows.keys)
19
- end
20
-
21
- def load_state(input)
22
- input.blob_into(@data)
23
- @state = STATES.fetch(input.int).to_sym
24
- @base_state = STATES.fetch(input.int).to_sym
25
- @cycle = input.int
26
- @toggle = input.int
27
- @done_at = input.optional_int
28
- @programmed = input.optional_int
29
- @remaining = input.optional_int
30
- @erasing_sectors = nil
31
- @erasing_sectors = input.ints if input.boolean?
32
- rebuild_windows(input.ints, input.ints)
33
- end
34
- end
35
-
36
- # An AMD 29F0x0 flash chip, driven through the JEDEC command set in the
37
- # AMD datasheets. Each command opens with two unlock cycles, $AA to the
38
- # first unlock address and $55 to the second, and a third write picks
39
- # the command:
40
- #
41
- # $90 autoselect: offset 0 reads the manufacturer, 1 the device and 2
42
- # the sector protection, until a reset
43
- # $F0 reset to reading the array, which a lone $F0 also does
44
- # $A0 byte program: the next write clears bits of the array, which
45
- # only an erase sets again
46
- # $80 erase, after two more unlock cycles: $10 to the first unlock
47
- # address erases the chip, and $30 to a sector erases the sector.
48
- # Further sectors can follow within the 50 us window.
49
- #
50
- # While a program or erase runs, a read returns status: DQ7 the
51
- # complement of the programmed bit (0 while erasing), DQ6 toggling on
52
- # every read, DQ5 set when a program failed and DQ3 set once an erase
53
- # has left its window. $B0 suspends a sector erase and $30 resumes it.
54
- #
55
- # The cartridge reads the array through windows, and the chip swaps
56
- # them for status windows while it is busy or in autoselect.
57
- class Flash
58
- Model = Data.define(:size, :sector_size, :unlock1, :unlock2, :unlock_mask, :manufacturer, :device)
59
-
60
- AM29F040 = Model.new(size: 0x80000, sector_size: 0x10000, unlock1: 0x5555, unlock2: 0x2aaa,
61
- unlock_mask: 0x7fff, manufacturer: 0x01, device: 0xa4)
62
- AM29F040B = Model.new(size: 0x80000, sector_size: 0x10000, unlock1: 0x555, unlock2: 0x2aa,
63
- unlock_mask: 0x7ff, manufacturer: 0x01, device: 0xa4)
64
- AM29F010 = Model.new(size: 0x20000, sector_size: 0x4000, unlock1: 0x5555, unlock2: 0x2aaa,
65
- unlock_mask: 0x7fff, manufacturer: 0x01, device: 0x20)
66
-
67
- # The datasheet's typical times, in cycles at 1 MHz.
68
- PROGRAM_CYCLES = 7
69
- ERASE_WINDOW_CYCLES = 50
70
- SECTOR_ERASE_CYCLES = 1_000_000
71
- CHIP_ERASE_CYCLES = 8_000_000
72
-
73
- # The array, read directly while the chip reads it.
74
- class Window
75
- def initialize(flash, base)
76
- @flash = flash
77
- @data = flash.data
78
- @base = base
79
- end
80
-
81
- def peek(addr)
82
- @data[@base | (addr & 0x1fff)]
83
- end
84
- alias [] peek
85
-
86
- def poke(addr, value)
87
- @flash.write(@base | (addr & 0x1fff), value)
88
- end
89
- alias []= poke
90
- end
91
-
92
- # Reads through the chip, for its status and autoselect codes.
93
- class StatusWindow < Window
94
- def peek(addr)
95
- @flash.read(@base | (addr & 0x1fff))
96
- end
97
- alias [] peek
98
- end
99
-
100
- include FlashState
101
-
102
- attr_reader :data, :state
103
- attr_writer :clock
104
-
105
- def initialize(data, model: AM29F040B, clock: -> { 0 })
106
- @model = model
107
- @data = data + ([0xff] * (model.size - data.length))
108
- @clock = clock
109
- @windows = {}
110
- @status_windows = {}
111
- @on_change = nil
112
- @state = :read
113
- @base_state = :read
114
- @cycle = 0
115
- @toggle = 0
116
- end
117
-
118
- # Called when the chip starts or stops answering reads from the array.
119
- def on_change(&block)
120
- @on_change = block
121
- end
122
-
123
- def window(base)
124
- if array_mode?
125
- @windows[base] ||= Window.new(self, base)
126
- else
127
- @status_windows[base] ||= StatusWindow.new(self, base)
128
- end
129
- end
130
-
131
- # Hands out new windows at the bases given, as #window would have.
132
- def rebuild_windows(bases, status_bases)
133
- @windows = {}
134
- @status_windows = {}
135
- bases.each { |base| @windows[base] = Window.new(self, base) }
136
- status_bases.each { |base| @status_windows[base] = StatusWindow.new(self, base) }
137
- end
138
-
139
- def array_mode?
140
- @state == :read || @state == :program_setup
141
- end
142
-
143
- def read(offset)
144
- settle
145
- case @state
146
- when :read then @data[offset]
147
- when :autoselect then autoselect_code(offset)
148
- when :suspended then suspended_read(offset)
149
- else status
150
- end
151
- end
152
-
153
- def write(offset, value)
154
- settle
155
- case @state
156
- when :program_setup then program(offset, value)
157
- when :erase_window then extend_erase(offset, value)
158
- when :erasing then suspend if value == 0xb0
159
- when :suspended then resume if value == 0x30
160
- when :program_error then enter(:read, base: :read) if value == 0xf0
161
- when :programming, :chip_erase then nil
162
- else command(offset, value)
163
- end
164
- end
165
-
166
- private
167
-
168
- def command(offset, value)
169
- if value == 0xf0
170
- @cycle = 0
171
- return enter(:read, base: :read)
172
- end
173
-
174
- address = offset & @model.unlock_mask
175
- @cycle = case @cycle
176
- when 0, 3 then address == @model.unlock1 && value == 0xaa ? @cycle + 1 : 0
177
- when 1, 4 then address == @model.unlock2 && value == 0x55 ? @cycle + 1 : 0
178
- when 2 then command_cycle(address, value)
179
- when 5 then erase_command(offset, address, value)
180
- end
181
- end
182
-
183
- def command_cycle(address, value)
184
- return 0 unless address == @model.unlock1
185
-
186
- case value
187
- when 0x90 then enter(:autoselect, base: :autoselect)
188
- when 0xa0 then @state = :program_setup
189
- when 0x80 then return 3
190
- end
191
- 0
192
- end
193
-
194
- def erase_command(offset, address, value)
195
- if value == 0x10 && address == @model.unlock1
196
- start_busy(:chip_erase, CHIP_ERASE_CYCLES)
197
- elsif value == 0x30
198
- @erasing_sectors = [sector(offset)]
199
- start_busy(:erase_window, ERASE_WINDOW_CYCLES)
200
- end
201
- 0
202
- end
203
-
204
- def program(offset, value)
205
- @programmed = value
206
- @data[offset] &= value
207
- if @data[offset] == value
208
- start_busy(:programming, PROGRAM_CYCLES)
209
- else
210
- enter(:program_error)
211
- end
212
- end
213
-
214
- def extend_erase(offset, value)
215
- case value
216
- when 0x30
217
- @erasing_sectors |= [sector(offset)]
218
- @done_at = now + ERASE_WINDOW_CYCLES
219
- when 0xb0
220
- @remaining = @erasing_sectors.length * SECTOR_ERASE_CYCLES
221
- enter(:suspended)
222
- else
223
- @erasing_sectors = nil
224
- enter(@base_state)
225
- end
226
- end
227
-
228
- def suspend
229
- @remaining = @done_at - now
230
- enter(:suspended)
231
- end
232
-
233
- def resume
234
- start_busy(:erasing, @remaining)
235
- end
236
-
237
- # Moves a timed operation on once the clock has passed its end.
238
- def settle
239
- return unless @done_at && now >= @done_at
240
-
241
- case @state
242
- when :erase_window
243
- start_busy(:erasing, @done_at - now + (@erasing_sectors.length * SECTOR_ERASE_CYCLES))
244
- settle
245
- when :erasing
246
- @erasing_sectors.each { |s| @data.fill(0xff, s * @model.sector_size, @model.sector_size) }
247
- @erasing_sectors = nil
248
- finish
249
- when :chip_erase
250
- @data.fill(0xff)
251
- finish
252
- else
253
- finish
254
- end
255
- end
256
-
257
- def finish
258
- @done_at = nil
259
- enter(@base_state)
260
- end
261
-
262
- def start_busy(state, cycles)
263
- @done_at = now + cycles
264
- @programmed = 0xff unless state == :programming
265
- enter(state)
266
- end
267
-
268
- def enter(state, base: @base_state)
269
- was_array = array_mode?
270
- @state = state
271
- @base_state = base
272
- @done_at = nil unless %i[programming erase_window erasing chip_erase].include?(state)
273
- @on_change&.call if was_array != array_mode?
274
- end
275
-
276
- def status
277
- @toggle ^= 0x40
278
- value = (~@programmed & 0x80) | @toggle
279
- value |= 0x20 if @state == :program_error
280
- value |= 0x08 if @state == :erasing || @state == :chip_erase
281
- value
282
- end
283
-
284
- def suspended_read(offset)
285
- @erasing_sectors.include?(sector(offset)) ? 0x80 : @data[offset]
286
- end
287
-
288
- def autoselect_code(offset)
289
- case offset & 0x43
290
- when 0 then @model.manufacturer
291
- when 1 then @model.device
292
- when 2 then 0x00
293
- else @data[offset]
294
- end
295
- end
296
-
297
- def sector(offset)
298
- offset / @model.sector_size
299
- end
300
-
301
- def now
302
- @clock.call
303
- end
304
- end
305
- end
306
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Cartridge
5
- # The freeze button of a freezer cartridge. A press pulls NMI, and the
6
- # computer calls #freeze! once the CPU has pushed the return address and
7
- # status of the interrupt, so the vector fetch that follows reads the
8
- # cartridge ROM in Ultimax mode. The cartridge lets go of NMI when its
9
- # software acknowledges the freeze.
10
- module Freezer
11
- def freezer? = true
12
-
13
- def press_button
14
- @button = true
15
- self.nmi = true if freeze_allowed?
16
- end
17
-
18
- def release_button
19
- @button = false
20
- end
21
-
22
- private
23
-
24
- def freeze_allowed?
25
- true
26
- end
27
-
28
- def button_pressed?
29
- @button == true
30
- end
31
- end
32
- end
33
- end
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Cartridge
5
- # Fun Play / Power Play: up to 16 8K banks. A write to I/O 1 selects the
6
- # bank from bits 3-5 and 0, and either 8K mode ($00 in bits 7, 6, 2 and 1)
7
- # or no ROM ($86 in those bits).
8
- class FunPlay < Cartridge
9
- def poke(addr, value)
10
- return if addr > 0xdeff
11
-
12
- @roml = bank(@banks, self.class.bank_number(value))
13
- case value & 0xc6
14
- when 0x00 then self.mode = :rom8k
15
- when 0x86 then self.mode = :off
16
- end
17
- changed!
18
- end
19
-
20
- # The CRT file numbers each bank by the register value that selects it.
21
- def reset
22
- poke(0xde00, 0)
23
- end
24
-
25
- def self.bank_number(value)
26
- ((value >> 3) & 0x07) | ((value & 0x01) << 3)
27
- end
28
-
29
- private
30
-
31
- def install_chips(chips)
32
- @banks = []
33
- chips.each { |chip| @banks[self.class.bank_number(chip.bank)] = rom_bank(chip.data) }
34
- reset
35
- end
36
- end
37
- end
38
- end
@@ -1,74 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Cartridge
5
- # GMod2: an Am29F040 flash chip of 64 8K banks at ROML. A write to I/O 1
6
- # selects the bank from bits 0-5. Bit 6 selects the EEPROM, which
7
- # switches the ROM out, and bits 6 and 7 together enable flash writes:
8
- # the cartridge then asserts Ultimax on write cycles only, so reads see
9
- # the C64's memory and writes to $E000-$FFFF reach the flash. The EEPROM
10
- # isn't emulated.
11
- class GMod2 < Cartridge
12
- BANKS = 64
13
-
14
- attr_reader :flash
15
-
16
- def clock=(clock)
17
- super
18
- @flash.clock = clock
19
- end
20
-
21
- def poke(addr, value)
22
- return if addr > 0xdeff
23
-
24
- @bank = value & 0x3f
25
- @flash_writes = value.allbits?(0xc0)
26
- self.mode = value.anybits?(0x40) ? :off : :rom8k
27
- select_bank
28
- end
29
-
30
- def romh_writes
31
- @roml if @flash_writes
32
- end
33
-
34
- # Reset selects the first bank in 8K mode, and leaves the flash as it
35
- # is.
36
- def reset
37
- @bank = 0
38
- @flash_writes = false
39
- self.mode = :rom8k
40
- select_bank
41
- end
42
-
43
- private
44
-
45
- def select_bank
46
- @roml = @flash.window(@bank * BANK_SIZE)
47
- changed!
48
- end
49
-
50
- def save_mapper(out)
51
- out.int(@bank).boolean(@flash_writes)
52
- @flash.save_state(out)
53
- end
54
-
55
- def load_mapper(input)
56
- @bank = input.int
57
- @flash_writes = input.boolean?
58
- @flash.load_state(input)
59
- @roml = @flash.window(@bank * BANK_SIZE)
60
- end
61
-
62
- def install_chips(chips)
63
- data = Array.new(BANKS * BANK_SIZE, 0xff)
64
- chips.each do |chip|
65
- bytes = chip.data.first(BANK_SIZE)
66
- data[(chip.bank & 0x3f) * BANK_SIZE, bytes.length] = bytes
67
- end
68
- @flash = Flash.new(data, model: Flash::AM29F040)
69
- @flash.on_change { select_bank }
70
- reset
71
- end
72
- end
73
- end
74
- end
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Cartridge
5
- # C64 Game System / System 3: up to 64 8K banks. Any access to
6
- # $DE00-$DEFF selects the bank from the low six address bits; the data
7
- # is ignored.
8
- class GameSystem < Cartridge
9
- def readable_io_pages
10
- [0xde]
11
- end
12
-
13
- def peek(addr)
14
- select(addr) if addr < 0xdf00
15
- open_bus(addr)
16
- end
17
-
18
- def poke(addr, _value)
19
- select(addr) if addr < 0xdf00
20
- end
21
-
22
- def reset
23
- select(0)
24
- end
25
-
26
- private
27
-
28
- def select(addr)
29
- @roml = bank(@banks, addr & 0x3f)
30
- changed!
31
- end
32
-
33
- def install_chips(chips)
34
- @banks = banks_from(chips).first
35
- self.mode = :rom8k
36
- reset
37
- end
38
- end
39
- end
40
- end
@@ -1,79 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Cartridge
5
- # GEO-RAM: a RAM expansion on the expansion port, seen through a 256-byte
6
- # window at $DE00-$DEFF. Two write-only registers pick the page the
7
- # window shows: $DFFE selects one of the 64 pages of a 16K block, and
8
- # $DFFF selects the block. As in VICE, the registers answer at every
9
- # address from $DF80 up, even for $DFFE and odd for $DFFF, and the block
10
- # number wraps at the number of blocks the RAM holds. Reads of I/O 2 are
11
- # open bus. It leaves EXROM and GAME high, and RES clears both
12
- # registers.
13
- class GeoRAM < Cartridge
14
- SIZES = [64, 128, 256, 512, 1024, 2048, 4096].freeze
15
- BLOCK_SIZE = 0x4000
16
- PAGE_MASK = 0x3f
17
-
18
- attr_reader :size
19
-
20
- # size is the RAM in kilobytes.
21
- def initialize(size: 512)
22
- raise ArgumentError, "Unsupported GEO-RAM size #{size}K" unless SIZES.include?(size)
23
-
24
- @size = size
25
- @block_mask = ((size * 1024) / BLOCK_SIZE) - 1
26
- super(Storage::CRTFile::Image.new(hardware_type: nil, subtype: 0, exrom: 1, game: 1,
27
- name: "GEO-RAM", chips: []))
28
- end
29
-
30
- def readable_io_pages
31
- [0xde]
32
- end
33
-
34
- def peek(addr)
35
- @ram_data[@window + (addr & 0xff)]
36
- end
37
-
38
- def poke(addr, value)
39
- if addr <= 0xdeff
40
- @ram_data[@window + (addr & 0xff)] = value
41
- elsif addr >= 0xdf80
42
- if addr.odd?
43
- @block = value & @block_mask
44
- else
45
- @page = value & PAGE_MASK
46
- end
47
- @window = (@block * BLOCK_SIZE) + (@page * 0x100)
48
- end
49
- end
50
-
51
- def reset
52
- @block = @page = @window = 0
53
- end
54
-
55
- # A GEO-RAM is built from its size alone.
56
- def save_setup(out)
57
- out.int(GEO_RAM_SETUP).int(@size)
58
- end
59
-
60
- private
61
-
62
- def save_mapper(out)
63
- out.blob(@ram_data).int(@block).int(@page).int(@window)
64
- end
65
-
66
- def load_mapper(input)
67
- input.blob_into(@ram_data)
68
- @block = input.int
69
- @page = input.int
70
- @window = input.int
71
- end
72
-
73
- def install_chips(_chips)
74
- @ram_data = Array.new(@size * 1024, 0)
75
- reset
76
- end
77
- end
78
- end
79
- end