badline 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (516) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/CLAUDE.md +59 -31
  4. data/README.md +1 -1
  5. data/doc/library.md +9 -9
  6. data/doc/pinned-behaviour.md +105 -105
  7. data/doc/snapshots.md +1 -4
  8. data/lib/badline/audio/bare_player.rb +4 -4
  9. data/lib/badline/audio/cli.rb +6 -6
  10. data/lib/badline/audio/jukebox.rb +2 -2
  11. data/lib/badline/audio/machine_player.rb +2 -2
  12. data/lib/badline/{media → audio}/queue.rb +1 -1
  13. data/lib/badline/audio/queued_tune.rb +6 -6
  14. data/lib/badline/audio/renderer.rb +5 -5
  15. data/lib/badline/audio/stereo.rb +1 -1
  16. data/lib/badline/c128/{bus_state.rb → bus/saved_state.rb} +6 -6
  17. data/lib/badline/c128/bus.rb +30 -51
  18. data/lib/badline/c128/color_lines.rb +2 -2
  19. data/lib/badline/c128/cpu.rb +1 -1
  20. data/lib/badline/c128/drives.rb +10 -11
  21. data/lib/badline/c128/fast_serial.rb +5 -5
  22. data/lib/badline/c128/mmu_pages.rb +1 -1
  23. data/lib/badline/c128/modes.rb +2 -2
  24. data/lib/badline/c128/saved_state.rb +21 -47
  25. data/lib/badline/c128/z80.rb +2 -2
  26. data/lib/badline/c128.rb +18 -72
  27. data/lib/badline/{computer → c64}/attachments.rb +16 -47
  28. data/lib/badline/c64/banked_ram/banking.rb +32 -0
  29. data/lib/badline/c64/banked_ram/plus256k.rb +56 -0
  30. data/lib/badline/c64/banked_ram/plus60k.rb +45 -0
  31. data/lib/badline/c64/banked_ram/unexpanded.rb +30 -0
  32. data/lib/badline/c64/banked_ram.rb +23 -0
  33. data/lib/badline/c64/bus/extra_sids.rb +32 -0
  34. data/lib/badline/c64/bus/fittings.rb +40 -0
  35. data/lib/badline/c64/bus/pla.rb +149 -0
  36. data/lib/badline/c64/bus/roms.rb +41 -0
  37. data/lib/badline/c64/bus/saved_state.rb +68 -0
  38. data/lib/badline/c64/bus/sid_slots.rb +44 -0
  39. data/lib/badline/c64/bus.rb +218 -0
  40. data/lib/badline/c64/cartridge/action_replay.rb +128 -0
  41. data/lib/badline/c64/cartridge/atomic_power.rb +26 -0
  42. data/lib/badline/c64/cartridge/bank.rb +83 -0
  43. data/lib/badline/c64/cartridge/comal80.rb +52 -0
  44. data/lib/badline/c64/cartridge/dinamic.rb +36 -0
  45. data/lib/badline/c64/cartridge/easy_flash.rb +147 -0
  46. data/lib/badline/c64/cartridge/epyx_fastload.rb +81 -0
  47. data/lib/badline/c64/cartridge/final_cartridge3.rb +91 -0
  48. data/lib/badline/c64/cartridge/flash/saved_state.rb +40 -0
  49. data/lib/badline/c64/cartridge/flash.rb +279 -0
  50. data/lib/badline/c64/cartridge/freezer.rb +35 -0
  51. data/lib/badline/c64/cartridge/fun_play.rb +40 -0
  52. data/lib/badline/c64/cartridge/g_mod2.rb +76 -0
  53. data/lib/badline/c64/cartridge/game_system.rb +42 -0
  54. data/lib/badline/c64/cartridge/geo_ram.rb +81 -0
  55. data/lib/badline/c64/cartridge/kcs_power.rb +77 -0
  56. data/lib/badline/c64/cartridge/mach5.rb +34 -0
  57. data/lib/badline/c64/cartridge/magic_desk.rb +32 -0
  58. data/lib/badline/c64/cartridge/ocean.rb +37 -0
  59. data/lib/badline/c64/cartridge/pagefox.rb +70 -0
  60. data/lib/badline/c64/cartridge/retro_replay/saved_state.rb +47 -0
  61. data/lib/badline/c64/cartridge/retro_replay.rb +286 -0
  62. data/lib/badline/c64/cartridge/rex_utility.rb +31 -0
  63. data/lib/badline/c64/cartridge/rgcd.rb +60 -0
  64. data/lib/badline/c64/cartridge/saved_state.rb +63 -0
  65. data/lib/badline/c64/cartridge/simons_basic.rb +37 -0
  66. data/lib/badline/c64/cartridge/standard.rb +17 -0
  67. data/lib/badline/c64/cartridge/super_games.rb +50 -0
  68. data/lib/badline/c64/cartridge/westermann.rb +32 -0
  69. data/lib/badline/c64/cartridge/zaxxon.rb +68 -0
  70. data/lib/badline/c64/cartridge.rb +258 -0
  71. data/lib/badline/c64/color_memory.rb +27 -0
  72. data/lib/badline/c64/common.rb +34 -0
  73. data/lib/badline/c64/kernal_traps.rb +89 -0
  74. data/lib/badline/c64/reu/dma/saved_state.rb +52 -0
  75. data/lib/badline/c64/reu/dma.rb +275 -0
  76. data/lib/badline/c64/reu/ram.rb +109 -0
  77. data/lib/badline/c64/reu/saved_state.rb +55 -0
  78. data/lib/badline/c64/reu/trigger.rb +34 -0
  79. data/lib/badline/c64/reu.rb +291 -0
  80. data/lib/badline/{computer → c64}/saved_state.rb +13 -18
  81. data/lib/badline/{computer → c64}/true_drives.rb +20 -31
  82. data/lib/badline/{computer.rb → c64.rb} +22 -80
  83. data/lib/badline/chips/cia/fast_forward.rb +62 -0
  84. data/lib/badline/chips/cia/interrupt_register.rb +145 -0
  85. data/lib/badline/chips/cia/saved_state.rb +49 -0
  86. data/lib/badline/chips/cia/serial/saved_state.rb +45 -0
  87. data/lib/badline/chips/cia/serial.rb +250 -0
  88. data/lib/badline/chips/cia/time_of_day.rb +232 -0
  89. data/lib/badline/chips/cia/timer.rb +208 -0
  90. data/lib/badline/chips/cia.rb +281 -0
  91. data/lib/badline/chips/cpu/addressing.rb +133 -0
  92. data/lib/badline/chips/cpu/boundary.rb +56 -0
  93. data/lib/badline/chips/cpu/core.rb +167 -0
  94. data/lib/badline/chips/cpu/instruction.rb +338 -0
  95. data/lib/badline/chips/cpu/instruction_set/arithmetic.rb +118 -0
  96. data/lib/badline/chips/cpu/instruction_set/bitwise.rb +130 -0
  97. data/lib/badline/chips/cpu/instruction_set/branch.rb +83 -0
  98. data/lib/badline/chips/cpu/instruction_set/flag.rb +67 -0
  99. data/lib/badline/chips/cpu/instruction_set/illegal.rb +274 -0
  100. data/lib/badline/chips/cpu/instruction_set/inc_dec.rb +73 -0
  101. data/lib/badline/chips/cpu/instruction_set/stack.rb +56 -0
  102. data/lib/badline/chips/cpu/instruction_set/transfer.rb +141 -0
  103. data/lib/badline/chips/cpu/instruction_set.rb +59 -0
  104. data/lib/badline/chips/cpu/interrupts.rb +108 -0
  105. data/lib/badline/chips/cpu/microcode.rb +179 -0
  106. data/lib/badline/chips/cpu/operations.rb +90 -0
  107. data/lib/badline/chips/cpu/port.rb +116 -0
  108. data/lib/badline/chips/cpu/saved_state.rb +117 -0
  109. data/lib/badline/chips/cpu/stack_operations.rb +84 -0
  110. data/lib/badline/chips/cpu/traps.rb +23 -0
  111. data/lib/badline/chips/cpu.rb +12 -0
  112. data/lib/badline/chips/sid/catch_up.rb +122 -0
  113. data/lib/badline/chips/sid/decimator.rb +66 -0
  114. data/lib/badline/chips/sid/envelope/saved_state.rb +70 -0
  115. data/lib/badline/chips/sid/envelope.rb +241 -0
  116. data/lib/badline/chips/sid/filter/saved_state.rb +42 -0
  117. data/lib/badline/chips/sid/filter.rb +241 -0
  118. data/lib/badline/chips/sid/saved_state.rb +52 -0
  119. data/lib/badline/chips/sid/voice.rb +79 -0
  120. data/lib/badline/chips/sid/waveform/combined.rb +128 -0
  121. data/lib/badline/chips/sid/waveform/fast_forward.rb +107 -0
  122. data/lib/badline/chips/sid/waveform/noise_writeback.rb +124 -0
  123. data/lib/badline/chips/sid/waveform/saved_state.rb +68 -0
  124. data/lib/badline/chips/sid/waveform.rb +307 -0
  125. data/lib/badline/chips/sid.rb +265 -0
  126. data/lib/badline/{c128 → chips}/vdc/memory.rb +1 -1
  127. data/lib/badline/{c128 → chips}/vdc/painter.rb +1 -1
  128. data/lib/badline/{c128 → chips}/vdc/raster.rb +1 -1
  129. data/lib/badline/chips/vdc/saved_state.rb +36 -0
  130. data/lib/badline/{c128 → chips}/vdc/window.rb +1 -1
  131. data/lib/badline/{c128 → chips}/vdc.rb +7 -31
  132. data/lib/badline/chips/via/control_lines.rb +124 -0
  133. data/lib/badline/chips/via/fast_forward.rb +55 -0
  134. data/lib/badline/chips/via/interrupt_register.rb +69 -0
  135. data/lib/badline/chips/via/saved_state.rb +44 -0
  136. data/lib/badline/chips/via/shift_register.rb +182 -0
  137. data/lib/badline/chips/via/timer1.rb +133 -0
  138. data/lib/badline/chips/via/timer2.rb +135 -0
  139. data/lib/badline/chips/via.rb +268 -0
  140. data/lib/badline/chips/vic/bank.rb +135 -0
  141. data/lib/badline/chips/vic/border_mask.rb +88 -0
  142. data/lib/badline/chips/vic/collisions.rb +117 -0
  143. data/lib/badline/chips/vic/color_patches.rb +49 -0
  144. data/lib/badline/chips/vic/display_state.rb +187 -0
  145. data/lib/badline/chips/vic/graphics_mode.rb +166 -0
  146. data/lib/badline/chips/vic/graphics_shifter/saved_state.rb +40 -0
  147. data/lib/badline/chips/vic/graphics_shifter.rb +187 -0
  148. data/lib/badline/chips/vic/register_log.rb +83 -0
  149. data/lib/badline/chips/vic/registers.rb +197 -0
  150. data/lib/badline/chips/vic/saved_state.rb +82 -0
  151. data/lib/badline/chips/vic/sequencer/saved_state.rb +91 -0
  152. data/lib/badline/chips/vic/sequencer.rb +277 -0
  153. data/lib/badline/chips/vic/sequencer_output.rb +118 -0
  154. data/lib/badline/chips/vic/sprite/internal_bus.rb +70 -0
  155. data/lib/badline/chips/vic/sprite/saved_state.rb +66 -0
  156. data/lib/badline/chips/vic/sprite/shifter.rb +148 -0
  157. data/lib/badline/chips/vic/sprite/timing.rb +58 -0
  158. data/lib/badline/chips/vic/sprite.rb +339 -0
  159. data/lib/badline/chips/vic/sprites/saved_state.rb +59 -0
  160. data/lib/badline/chips/vic/sprites.rb +284 -0
  161. data/lib/badline/chips/vic.rb +783 -0
  162. data/lib/badline/chips/vic_i/painter/saved_state.rb +40 -0
  163. data/lib/badline/{vic20/vic → chips/vic_i}/painter.rb +6 -30
  164. data/lib/badline/{vic20/vic → chips/vic_i}/saved_state.rb +2 -2
  165. data/lib/badline/chips/vic_i/sound/output.rb +85 -0
  166. data/lib/badline/chips/vic_i/sound.rb +235 -0
  167. data/lib/badline/{vic20/vic → chips/vic_i}/text_window.rb +2 -2
  168. data/lib/badline/{vic20/vic.rb → chips/vic_i.rb} +5 -5
  169. data/lib/badline/chips/z80/arithmetic.rb +119 -0
  170. data/lib/badline/chips/z80/bit_page.rb +57 -0
  171. data/lib/badline/chips/z80/block_io.rb +60 -0
  172. data/lib/badline/chips/z80/block_transfers.rb +61 -0
  173. data/lib/badline/chips/z80/bus_cycles.rb +113 -0
  174. data/lib/badline/chips/z80/core.rb +115 -0
  175. data/lib/badline/chips/z80/exchanges.rb +52 -0
  176. data/lib/badline/chips/z80/extended_page.rb +91 -0
  177. data/lib/badline/chips/z80/flags.rb +39 -0
  178. data/lib/badline/chips/z80/interrupt_acceptance.rb +48 -0
  179. data/lib/badline/chips/z80/jumps.rb +84 -0
  180. data/lib/badline/chips/z80/loads.rb +100 -0
  181. data/lib/badline/chips/z80/main_page.rb +136 -0
  182. data/lib/badline/chips/z80/registers.rb +122 -0
  183. data/lib/badline/chips/z80/saved_state.rb +71 -0
  184. data/lib/badline/chips/z80/shifts.rb +66 -0
  185. data/lib/badline/chips/z80.rb +13 -0
  186. data/lib/badline/core.rb +27 -29
  187. data/lib/badline/drives/datasette/saved_state.rb +37 -0
  188. data/lib/badline/drives/datasette.rb +140 -0
  189. data/lib/badline/drives/engine/core.rb +149 -0
  190. data/lib/badline/drives/engine/fast_serial.rb +75 -0
  191. data/lib/badline/drives/engine/idle.rb +127 -0
  192. data/lib/badline/drives/engine/idle_cpu.rb +30 -0
  193. data/lib/badline/drives/engine/orbit.rb +81 -0
  194. data/lib/badline/drives/engine/serial_lines.rb +75 -0
  195. data/lib/badline/drives/engine/sleep.rb +114 -0
  196. data/lib/badline/drives/engine/vias.rb +86 -0
  197. data/lib/badline/drives/engine/watch.rb +152 -0
  198. data/lib/badline/drives/engine.rb +11 -0
  199. data/lib/badline/drives/model1541/bus.rb +88 -0
  200. data/lib/badline/drives/model1541/byte_ready.rb +50 -0
  201. data/lib/badline/drives/model1541/cpu.rb +13 -0
  202. data/lib/badline/drives/model1541/disk/saved_state.rb +88 -0
  203. data/lib/badline/drives/model1541/disk.rb +317 -0
  204. data/lib/badline/drives/model1541/disk_via.rb +38 -0
  205. data/lib/badline/drives/model1541/gcr.rb +59 -0
  206. data/lib/badline/drives/model1541/mechanism/saved_state.rb +72 -0
  207. data/lib/badline/drives/model1541/mechanism.rb +315 -0
  208. data/lib/badline/drives/model1541/rotation.rb +123 -0
  209. data/lib/badline/drives/model1541/saved_state.rb +44 -0
  210. data/lib/badline/drives/model1541/sector_reader.rb +78 -0
  211. data/lib/badline/drives/model1541/serial_port.rb +20 -0
  212. data/lib/badline/drives/model1541/track.rb +100 -0
  213. data/lib/badline/drives/model1541.rb +81 -0
  214. data/lib/badline/drives/model1571/bus.rb +113 -0
  215. data/lib/badline/drives/model1571/cpu.rb +13 -0
  216. data/lib/badline/drives/model1571/saved_state.rb +47 -0
  217. data/lib/badline/drives/model1571/serial_port.rb +39 -0
  218. data/lib/badline/drives/model1571/serial_via.rb +27 -0
  219. data/lib/badline/drives/model1571/wd1770.rb +122 -0
  220. data/lib/badline/drives/model1571.rb +142 -0
  221. data/lib/badline/drives/model1581/bus.rb +139 -0
  222. data/lib/badline/drives/model1581/cpu.rb +13 -0
  223. data/lib/badline/drives/model1581/disk/saved_state.rb +89 -0
  224. data/lib/badline/drives/model1581/disk.rb +137 -0
  225. data/lib/badline/drives/model1581/mechanism.rb +119 -0
  226. data/lib/badline/drives/model1581/saved_state.rb +42 -0
  227. data/lib/badline/drives/model1581/serial_port.rb +54 -0
  228. data/lib/badline/drives/model1581/slot.rb +79 -0
  229. data/lib/badline/drives/model1581/track.rb +102 -0
  230. data/lib/badline/drives/model1581/track_bytes.rb +77 -0
  231. data/lib/badline/drives/model1581/wd1772/registers.rb +91 -0
  232. data/lib/badline/drives/model1581/wd1772/saved_state.rb +68 -0
  233. data/lib/badline/drives/model1581/wd1772/sector_writes.rb +75 -0
  234. data/lib/badline/drives/model1581/wd1772/sectors.rb +152 -0
  235. data/lib/badline/drives/model1581/wd1772/stepping.rb +111 -0
  236. data/lib/badline/drives/model1581/wd1772/tracks.rb +127 -0
  237. data/lib/badline/drives/model1581/wd1772/turn.rb +75 -0
  238. data/lib/badline/drives/model1581/wd1772.rb +218 -0
  239. data/lib/badline/drives/model1581.rb +206 -0
  240. data/lib/badline/drives/serial_bus.rb +161 -0
  241. data/lib/badline/frontend/boot.rb +10 -61
  242. data/lib/badline/frontend/machine_window.rb +3 -1
  243. data/lib/badline/frontend/player/filter_view.rb +1 -1
  244. data/lib/badline/frontend/player/player_controller.rb +2 -2
  245. data/lib/badline/frontend/player/player_screen.rb +1 -0
  246. data/lib/badline/frontend/player/theme.rb +7 -7
  247. data/lib/badline/frontend/timeline.rb +3 -3
  248. data/lib/badline/input/control_ports.rb +78 -0
  249. data/lib/badline/input/joystick.rb +27 -0
  250. data/lib/badline/input/keyboard.rb +114 -0
  251. data/lib/badline/input.rb +3 -0
  252. data/lib/badline/kernal_trap/{drive → dos}/block_commands.rb +1 -1
  253. data/lib/badline/kernal_trap/dos/channel.rb +183 -0
  254. data/lib/badline/kernal_trap/{drive → dos}/channels.rb +1 -1
  255. data/lib/badline/kernal_trap/{drive → dos}/memory.rb +1 -1
  256. data/lib/badline/kernal_trap/{drive → dos}/parameters.rb +1 -1
  257. data/lib/badline/kernal_trap/{drive → dos}/status.rb +1 -1
  258. data/lib/badline/kernal_trap/{drive → dos}/write_file.rb +1 -1
  259. data/lib/badline/kernal_trap/{drive → dos}/writes.rb +1 -1
  260. data/lib/badline/kernal_trap/{drive.rb → dos.rb} +11 -10
  261. data/lib/badline/kernal_trap/{file.rb → file_routine.rb} +1 -1
  262. data/lib/badline/kernal_trap/load.rb +6 -6
  263. data/lib/badline/kernal_trap/save.rb +5 -5
  264. data/lib/badline/kernal_trap/serial.rb +7 -7
  265. data/lib/badline/kernal_trap.rb +2 -3
  266. data/lib/badline/machine/clocking.rb +50 -0
  267. data/lib/badline/machine.rb +63 -7
  268. data/lib/badline/media/boot_disk.rb +2 -2
  269. data/lib/badline/media/disk_list.rb +3 -3
  270. data/lib/badline/media/disk_set.rb +1 -1
  271. data/lib/badline/media/extensions.rb +33 -0
  272. data/lib/badline/media/program.rb +28 -0
  273. data/lib/badline/media/true_drive.rb +4 -3
  274. data/lib/badline/media/tune.rb +35 -0
  275. data/lib/badline/media/vic20_cartridge.rb +1 -7
  276. data/lib/badline/media/vic20_media.rb +38 -80
  277. data/lib/badline/media.rb +84 -81
  278. data/lib/badline/model.rb +1 -1
  279. data/lib/badline/options/event.rb +3 -1
  280. data/lib/badline/roms/README +6 -6
  281. data/lib/badline/sdl.rb +1 -0
  282. data/lib/badline/{storage/sid_file.rb → sid_tune/file.rb} +3 -3
  283. data/lib/badline/{storage → sid_tune}/hvsc.rb +7 -7
  284. data/lib/badline/{storage → sid_tune}/song_lengths.rb +2 -2
  285. data/lib/badline/{storage → sid_tune}/stil/credit.rb +1 -1
  286. data/lib/badline/{storage → sid_tune}/stil.rb +3 -3
  287. data/lib/badline/sid_tune.rb +6 -0
  288. data/lib/badline/snapshot/c128_setup.rb +43 -0
  289. data/lib/badline/snapshot/c64_setup.rb +79 -0
  290. data/lib/badline/snapshot/image.rb +5 -25
  291. data/lib/badline/snapshot/machine_state.rb +10 -2
  292. data/lib/badline/snapshot/setup.rb +22 -66
  293. data/lib/badline/snapshot/state.rb +8 -17
  294. data/lib/badline/snapshot/storage_setup.rb +68 -0
  295. data/lib/badline/snapshot/vic20_setup.rb +37 -0
  296. data/lib/badline/snapshot/vice/c64_mem.rb +1 -1
  297. data/lib/badline/snapshot/vice/restore.rb +1 -1
  298. data/lib/badline/snapshot/vice/reu1764.rb +1 -1
  299. data/lib/badline/snapshot/vice/reu_fields.rb +40 -0
  300. data/lib/badline/snapshot/vice.rb +7 -5
  301. data/lib/badline/snapshot.rb +13 -12
  302. data/lib/badline/storage/d64_image.rb +15 -9
  303. data/lib/badline/storage/d71_image.rb +0 -2
  304. data/lib/badline/storage/d81_image.rb +0 -2
  305. data/lib/badline/storage/disk_image/writing.rb +2 -2
  306. data/lib/badline/storage/disk_image.rb +3 -6
  307. data/lib/badline/storage/g64_image.rb +2 -2
  308. data/lib/badline/storage/host_directory.rb +0 -5
  309. data/lib/badline/storage/t64.rb +2 -8
  310. data/lib/badline/storage/unavailable.rb +1 -1
  311. data/lib/badline/storage.rb +0 -37
  312. data/lib/badline/support/c128_checkpoint.rb +39 -0
  313. data/lib/badline/support/checkpoint.rb +108 -0
  314. data/lib/badline/support/vic20_checkpoint.rb +38 -0
  315. data/lib/badline/support.rb +5 -0
  316. data/lib/badline/version.rb +1 -1
  317. data/lib/badline/vic20/attachments.rb +11 -81
  318. data/lib/badline/vic20/bus/saved_state.rb +35 -0
  319. data/lib/badline/vic20/bus.rb +3 -25
  320. data/lib/badline/vic20/cpu.rb +1 -1
  321. data/lib/badline/vic20/port_wiring.rb +4 -4
  322. data/lib/badline/vic20/saved_state.rb +16 -60
  323. data/lib/badline/vic20/user_via_ports.rb +2 -2
  324. data/lib/badline/vic20.rb +20 -51
  325. metadata +250 -221
  326. data/lib/badline/address_bus/extra_sids.rb +0 -30
  327. data/lib/badline/address_bus/fittings.rb +0 -38
  328. data/lib/badline/address_bus/pla.rb +0 -147
  329. data/lib/badline/address_bus/roms.rb +0 -39
  330. data/lib/badline/address_bus/saved_state.rb +0 -72
  331. data/lib/badline/address_bus/sid_slots.rb +0 -42
  332. data/lib/badline/address_bus.rb +0 -235
  333. data/lib/badline/cartridge/action_replay.rb +0 -126
  334. data/lib/badline/cartridge/atomic_power.rb +0 -24
  335. data/lib/badline/cartridge/bank.rb +0 -81
  336. data/lib/badline/cartridge/comal80.rb +0 -50
  337. data/lib/badline/cartridge/dinamic.rb +0 -34
  338. data/lib/badline/cartridge/easy_flash.rb +0 -145
  339. data/lib/badline/cartridge/epyx_fastload.rb +0 -79
  340. data/lib/badline/cartridge/final_cartridge3.rb +0 -89
  341. data/lib/badline/cartridge/flash.rb +0 -306
  342. data/lib/badline/cartridge/freezer.rb +0 -33
  343. data/lib/badline/cartridge/fun_play.rb +0 -38
  344. data/lib/badline/cartridge/g_mod2.rb +0 -74
  345. data/lib/badline/cartridge/game_system.rb +0 -40
  346. data/lib/badline/cartridge/geo_ram.rb +0 -79
  347. data/lib/badline/cartridge/kcs_power.rb +0 -75
  348. data/lib/badline/cartridge/mach5.rb +0 -32
  349. data/lib/badline/cartridge/magic_desk.rb +0 -30
  350. data/lib/badline/cartridge/ocean.rb +0 -35
  351. data/lib/badline/cartridge/pagefox.rb +0 -68
  352. data/lib/badline/cartridge/retro_replay.rb +0 -320
  353. data/lib/badline/cartridge/rex_utility.rb +0 -29
  354. data/lib/badline/cartridge/rgcd.rb +0 -58
  355. data/lib/badline/cartridge/simons_basic.rb +0 -35
  356. data/lib/badline/cartridge/standard.rb +0 -15
  357. data/lib/badline/cartridge/super_games.rb +0 -48
  358. data/lib/badline/cartridge/westermann.rb +0 -30
  359. data/lib/badline/cartridge/zaxxon.rb +0 -66
  360. data/lib/badline/cartridge.rb +0 -303
  361. data/lib/badline/checkpoint.rb +0 -98
  362. data/lib/badline/cia/fast_forward.rb +0 -60
  363. data/lib/badline/cia/interrupt_register.rb +0 -143
  364. data/lib/badline/cia/serial.rb +0 -275
  365. data/lib/badline/cia/state.rb +0 -47
  366. data/lib/badline/cia/timer.rb +0 -206
  367. data/lib/badline/cia.rb +0 -279
  368. data/lib/badline/color_memory.rb +0 -25
  369. data/lib/badline/computer/kernal_traps.rb +0 -29
  370. data/lib/badline/control_ports.rb +0 -76
  371. data/lib/badline/cpu/addressing.rb +0 -131
  372. data/lib/badline/cpu/boundary.rb +0 -54
  373. data/lib/badline/cpu/core.rb +0 -165
  374. data/lib/badline/cpu/microcode.rb +0 -177
  375. data/lib/badline/cpu/operations.rb +0 -88
  376. data/lib/badline/cpu/saved_state.rb +0 -115
  377. data/lib/badline/cpu/stack_operations.rb +0 -82
  378. data/lib/badline/cpu.rb +0 -10
  379. data/lib/badline/cycleable.rb +0 -38
  380. data/lib/badline/datasette.rb +0 -161
  381. data/lib/badline/drive/core.rb +0 -147
  382. data/lib/badline/drive/fast_serial.rb +0 -73
  383. data/lib/badline/drive/idle.rb +0 -125
  384. data/lib/badline/drive/idle_cpu.rb +0 -28
  385. data/lib/badline/drive/orbit.rb +0 -79
  386. data/lib/badline/drive/serial_lines.rb +0 -73
  387. data/lib/badline/drive/sleep.rb +0 -112
  388. data/lib/badline/drive/vias.rb +0 -84
  389. data/lib/badline/drive/watch.rb +0 -150
  390. data/lib/badline/drive.rb +0 -11
  391. data/lib/badline/drive1541/bus.rb +0 -86
  392. data/lib/badline/drive1541/byte_ready.rb +0 -48
  393. data/lib/badline/drive1541/cpu.rb +0 -11
  394. data/lib/badline/drive1541/disk.rb +0 -318
  395. data/lib/badline/drive1541/disk_state.rb +0 -94
  396. data/lib/badline/drive1541/disk_via.rb +0 -36
  397. data/lib/badline/drive1541/gcr.rb +0 -57
  398. data/lib/badline/drive1541/mechanism.rb +0 -313
  399. data/lib/badline/drive1541/mechanism_state.rb +0 -68
  400. data/lib/badline/drive1541/rotation.rb +0 -121
  401. data/lib/badline/drive1541/sector_reader.rb +0 -76
  402. data/lib/badline/drive1541/serial_port.rb +0 -18
  403. data/lib/badline/drive1541/track.rb +0 -98
  404. data/lib/badline/drive1541.rb +0 -111
  405. data/lib/badline/drive1571/bus.rb +0 -111
  406. data/lib/badline/drive1571/cpu.rb +0 -11
  407. data/lib/badline/drive1571/serial_port.rb +0 -37
  408. data/lib/badline/drive1571/serial_via.rb +0 -25
  409. data/lib/badline/drive1571/wd1770.rb +0 -120
  410. data/lib/badline/drive1571.rb +0 -175
  411. data/lib/badline/drive1581/bus.rb +0 -137
  412. data/lib/badline/drive1581/cpu.rb +0 -11
  413. data/lib/badline/drive1581/disk.rb +0 -135
  414. data/lib/badline/drive1581/disk_state.rb +0 -87
  415. data/lib/badline/drive1581/mechanism.rb +0 -117
  416. data/lib/badline/drive1581/serial_port.rb +0 -52
  417. data/lib/badline/drive1581/slot.rb +0 -78
  418. data/lib/badline/drive1581/track.rb +0 -100
  419. data/lib/badline/drive1581/track_bytes.rb +0 -75
  420. data/lib/badline/drive1581/wd1772/registers.rb +0 -89
  421. data/lib/badline/drive1581/wd1772/sector_writes.rb +0 -73
  422. data/lib/badline/drive1581/wd1772/sectors.rb +0 -150
  423. data/lib/badline/drive1581/wd1772/state.rb +0 -66
  424. data/lib/badline/drive1581/wd1772/stepping.rb +0 -109
  425. data/lib/badline/drive1581/wd1772/tracks.rb +0 -125
  426. data/lib/badline/drive1581/wd1772/turn.rb +0 -73
  427. data/lib/badline/drive1581/wd1772.rb +0 -216
  428. data/lib/badline/drive1581.rb +0 -233
  429. data/lib/badline/iec_bus.rb +0 -159
  430. data/lib/badline/instruction.rb +0 -334
  431. data/lib/badline/instruction_set/arithmetic.rb +0 -114
  432. data/lib/badline/instruction_set/bitwise.rb +0 -126
  433. data/lib/badline/instruction_set/branch.rb +0 -79
  434. data/lib/badline/instruction_set/flag.rb +0 -63
  435. data/lib/badline/instruction_set/illegal.rb +0 -270
  436. data/lib/badline/instruction_set/inc_dec.rb +0 -69
  437. data/lib/badline/instruction_set/stack.rb +0 -52
  438. data/lib/badline/instruction_set/transfer.rb +0 -137
  439. data/lib/badline/instruction_set.rb +0 -55
  440. data/lib/badline/interrupts.rb +0 -104
  441. data/lib/badline/joystick.rb +0 -25
  442. data/lib/badline/kernal_trap/channel.rb +0 -181
  443. data/lib/badline/keyboard.rb +0 -112
  444. data/lib/badline/ram_expansion/banking.rb +0 -30
  445. data/lib/badline/ram_expansion/plus256k.rb +0 -54
  446. data/lib/badline/ram_expansion/plus60k.rb +0 -43
  447. data/lib/badline/ram_expansion/unexpanded.rb +0 -28
  448. data/lib/badline/ram_expansion.rb +0 -21
  449. data/lib/badline/reu/dma/saved_state.rb +0 -50
  450. data/lib/badline/reu/dma.rb +0 -273
  451. data/lib/badline/reu/ram.rb +0 -107
  452. data/lib/badline/reu/saved_state.rb +0 -80
  453. data/lib/badline/reu/trigger.rb +0 -32
  454. data/lib/badline/reu.rb +0 -289
  455. data/lib/badline/sid/catch_up.rb +0 -120
  456. data/lib/badline/sid/decimator.rb +0 -64
  457. data/lib/badline/sid/envelope/state.rb +0 -68
  458. data/lib/badline/sid/envelope.rb +0 -239
  459. data/lib/badline/sid/filter.rb +0 -263
  460. data/lib/badline/sid/voice.rb +0 -77
  461. data/lib/badline/sid/waveform/combined.rb +0 -126
  462. data/lib/badline/sid/waveform/fast_forward.rb +0 -105
  463. data/lib/badline/sid/waveform/noise_writeback.rb +0 -122
  464. data/lib/badline/sid/waveform/state.rb +0 -66
  465. data/lib/badline/sid/waveform.rb +0 -305
  466. data/lib/badline/sid.rb +0 -303
  467. data/lib/badline/time_of_day.rb +0 -228
  468. data/lib/badline/traps.rb +0 -19
  469. data/lib/badline/via/control_lines.rb +0 -122
  470. data/lib/badline/via/fast_forward.rb +0 -53
  471. data/lib/badline/via/interrupt_register.rb +0 -67
  472. data/lib/badline/via/shift_register.rb +0 -180
  473. data/lib/badline/via/state.rb +0 -42
  474. data/lib/badline/via/timer1.rb +0 -131
  475. data/lib/badline/via/timer2.rb +0 -133
  476. data/lib/badline/via.rb +0 -266
  477. data/lib/badline/vic/bank.rb +0 -133
  478. data/lib/badline/vic/border_mask.rb +0 -86
  479. data/lib/badline/vic/collisions.rb +0 -115
  480. data/lib/badline/vic/color_patches.rb +0 -47
  481. data/lib/badline/vic/display_state.rb +0 -185
  482. data/lib/badline/vic/graphics_mode.rb +0 -164
  483. data/lib/badline/vic/graphics_shifter.rb +0 -207
  484. data/lib/badline/vic/register_log.rb +0 -81
  485. data/lib/badline/vic/registers.rb +0 -195
  486. data/lib/badline/vic/sequencer.rb +0 -275
  487. data/lib/badline/vic/sequencer_output.rb +0 -116
  488. data/lib/badline/vic/sequencer_state.rb +0 -89
  489. data/lib/badline/vic/sprite/internal_bus.rb +0 -68
  490. data/lib/badline/vic/sprite/saved_state.rb +0 -64
  491. data/lib/badline/vic/sprite/shifter.rb +0 -146
  492. data/lib/badline/vic/sprite/timing.rb +0 -56
  493. data/lib/badline/vic/sprite.rb +0 -337
  494. data/lib/badline/vic/sprites.rb +0 -282
  495. data/lib/badline/vic/sprites_state.rb +0 -57
  496. data/lib/badline/vic.rb +0 -852
  497. data/lib/badline/vic20/sound/output.rb +0 -83
  498. data/lib/badline/vic20/sound.rb +0 -233
  499. data/lib/badline/z80/arithmetic.rb +0 -117
  500. data/lib/badline/z80/bit_page.rb +0 -55
  501. data/lib/badline/z80/block_io.rb +0 -58
  502. data/lib/badline/z80/block_transfers.rb +0 -59
  503. data/lib/badline/z80/bus_cycles.rb +0 -111
  504. data/lib/badline/z80/core.rb +0 -113
  505. data/lib/badline/z80/exchanges.rb +0 -50
  506. data/lib/badline/z80/extended_page.rb +0 -89
  507. data/lib/badline/z80/flags.rb +0 -37
  508. data/lib/badline/z80/interrupt_acceptance.rb +0 -46
  509. data/lib/badline/z80/jumps.rb +0 -82
  510. data/lib/badline/z80/loads.rb +0 -98
  511. data/lib/badline/z80/main_page.rb +0 -134
  512. data/lib/badline/z80/registers.rb +0 -120
  513. data/lib/badline/z80/saved_state.rb +0 -69
  514. data/lib/badline/z80/shifts.rb +0 -64
  515. data/lib/badline/z80.rb +0 -11
  516. /data/lib/badline/snapshot/{fields.rb → vice/fields.rb} +0 -0
data/lib/badline/cia.rb DELETED
@@ -1,279 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "badline/cia/interrupt_register"
4
- require "badline/cia/serial"
5
- require "badline/cia/timer"
6
- require "badline/cia/state"
7
- require "badline/cia/fast_forward"
8
-
9
- module Badline
10
- # CIA (Complex Interface Adapter) chip
11
- class CIA
12
- include Addressable
13
- include State
14
- include FastForward
15
-
16
- # The original NMOS 6526 of the breadbin C64, and the HMOS 6526A of the
17
- # C64C, which differs from it only in its interrupt control register.
18
- MODELS = %i[mos6526 mos6526a].freeze
19
-
20
- attr_reader :start, :control_a, :control_b, :serial, :model
21
-
22
- # What's on the ports outside the chip. It pulls port lines low through
23
- # read_a and read_b, and on CIA 1 drives PB4 through port_b4_high?.
24
- attr_accessor :peripheral
25
-
26
- # Timer A and timer B.
27
- def timers = [@ta, @tb]
28
-
29
- # Port A and B's data and direction registers.
30
- def port_registers = [@data_port_a, @data_port_b, @data_dir_a, @data_dir_b]
31
-
32
- def interrupt_status = @icr.status
33
-
34
- def interrupt_control = @icr.mask
35
-
36
- def interrupt!(delay = 1) = @icr.assert!(delay)
37
-
38
- def time_of_day = @tod
39
-
40
- def timer_a = @ta.counter
41
-
42
- def timer_a=(value)
43
- @ta.counter = value
44
- end
45
-
46
- def timer_a_latch = @ta.latch
47
-
48
- def timer_a_latch=(value)
49
- @ta.latch = value
50
- end
51
-
52
- def timer_b = @tb.counter
53
-
54
- def timer_b=(value)
55
- @tb.counter = value
56
- end
57
-
58
- def timer_b_latch = @tb.latch
59
-
60
- def timer_b_latch=(value)
61
- @tb.latch = value
62
- end
63
-
64
- # +tod_hz+ is the rate of the pulses on the TOD pin, the region's mains
65
- # unless a machine feeds it otherwise, and 0 for a pin held still.
66
- def initialize(start: 0, peripheral: nil, model: :mos6526, region: Region::PAL, tod_hz: nil)
67
- raise ArgumentError, "unknown CIA model #{model}" unless MODELS.include?(model)
68
-
69
- addressable_at(start, length: 2**8)
70
-
71
- @model = model
72
- @clock_hz = region.clock_hz
73
- @mains_hz = tod_hz || region.mains_hz
74
-
75
- @peripheral = peripheral
76
- @port_b4_handler = nil
77
- @port_a_handler = nil
78
- @port_b4_high = true
79
- reset!
80
- end
81
-
82
- # The RES line: ports back to inputs, timers stopped with their latches
83
- # full, interrupts masked and the TOD clock stopped at 1:00:00.0. The
84
- # PB4 level carries over and is resampled on the next cycle.
85
- def reset!
86
- @data_port_a = 0x00
87
- @data_port_b = 0x00
88
- @data_dir_a = 0x00
89
- @data_dir_b = 0x00
90
- @port_b4_driven_high = true
91
- @cnt_high = true
92
- @cnt_rise = false
93
- @tod = TimeOfDay.new(clock_hz: @clock_hz, mains_hz: @mains_hz)
94
- @icr = InterruptRegister.new(@model)
95
- @icr_status = @icr.status
96
- @control_a = ControlRegister.new(%i[start output out_mode run_mode load
97
- in_mode serial_mode clock_frequency])
98
- @control_b = ControlRegister.new(%i[start output out_mode run_mode load
99
- in_cnt in_timer_a alarm])
100
- @ta = Timer.new(@control_a)
101
- @tb = Timer.new(@control_b)
102
- @serial = Serial.new(@control_a)
103
- @port_a_handler&.call
104
- end
105
-
106
- # Register a change handler on the PB4 line. On CIA 1, this feeds the
107
- # light pen input.
108
- def on_port_b4_change(&handler)
109
- @port_b4_handler = handler
110
- end
111
-
112
- # Register a handler for writes that can move port A's lines: to the
113
- # data register or DDR, and the reset. On CIA 2, this tells the drives
114
- # on the serial bus that the C64 may have moved a line.
115
- def on_port_a_write(&handler)
116
- @port_a_handler = handler
117
- end
118
-
119
- # A falling edge on the FLAG pin. On CIA 1 the datasette's tape read
120
- # line drives it, on CIA 2 the serial bus SRQ.
121
- def flag! = raise_interrupt(:flag)
122
-
123
- def interrupted? = @icr_status.value >= 0x80
124
-
125
- def cycle!
126
- @icr.cycle! unless @icr.quiet
127
- refresh_port_b4 if @port_b4_handler
128
- level = @serial.cnt
129
- level == @cnt_high ? @cnt_rise = false : cnt_edge(level)
130
- underflowed = update_timers
131
- @serial.cycle!(underflowed) { trigger_serial } if underflowed || !@serial.idle
132
- @tod.cycle! { trigger_alarm }
133
- end
134
-
135
- def read_port_a
136
- lines = driven_lines(@data_port_a, @data_dir_a)
137
- return lines unless peripheral
138
-
139
- lines & peripheral.read_a(lines, driven_lines(@data_port_b, @data_dir_b))
140
- end
141
-
142
- # Port A as driven by the data/direction registers alone, without
143
- # peripheral pulldown. Cheap path for the VIC bank lookup.
144
- def port_a_lines = driven_lines(@data_port_a, @data_dir_a)
145
-
146
- # Port B as driven by the data/direction registers alone.
147
- def port_b_lines = driven_lines(@data_port_b, @data_dir_b)
148
-
149
- def read_port_b
150
- lines = driven_lines(@data_port_b, @data_dir_b)
151
- lines &= peripheral.read_b(driven_lines(@data_port_a, @data_dir_a), lines) if peripheral
152
- apply_timer_output(lines)
153
- end
154
-
155
- def peek(addr)
156
- case offset_of(addr) & 0x0f
157
- when 0x00 then read_port_a
158
- when 0x01 then read_port_b
159
- when 0x02 then @data_dir_a
160
- when 0x03 then @data_dir_b
161
- when 0x04 then low_byte(@ta.counter)
162
- when 0x05 then high_byte(@ta.counter)
163
- when 0x06 then low_byte(@tb.counter)
164
- when 0x07 then high_byte(@tb.counter)
165
- when 0x08 then @tod.tenths
166
- when 0x09 then @tod.seconds
167
- when 0x0a then @tod.minutes
168
- when 0x0b then @tod.hours
169
- when 0x0c then @serial.data
170
- when 0x0d then @icr.read
171
- when 0x0e then control_a.value
172
- when 0x0f then control_b.value
173
- end
174
- end
175
-
176
- def poke(addr, value)
177
- case offset_of(addr) & 0x0f
178
- when 0x00 then update_port_a { @data_port_a = value }
179
- when 0x01 then update_port_b { @data_port_b = value }
180
- when 0x02 then update_port_a { @data_dir_a = value }
181
- when 0x03 then update_port_b { @data_dir_b = value }
182
- when 0x04 then @ta.write_latch_low(value)
183
- when 0x05 then @ta.write_latch_high(value)
184
- when 0x06 then @tb.write_latch_low(value)
185
- when 0x07 then @tb.write_latch_high(value)
186
- when 0x08 then @tod.write(:tenths, value, alarm: control_b.alarm?)
187
- when 0x09 then @tod.write(:seconds, value, alarm: control_b.alarm?)
188
- when 0x0a then @tod.write(:minutes, value, alarm: control_b.alarm?)
189
- when 0x0b then @tod.write_hours(value, alarm: control_b.alarm?)
190
- when 0x0c then @serial.write(value)
191
- when 0x0d then @icr.write(value)
192
- when 0x0e then write_control_a(value)
193
- when 0x0f then @tb.write_control(value)
194
- end
195
- end
196
-
197
- private
198
-
199
- def update_port_a
200
- yield
201
- @port_a_handler&.call
202
- end
203
-
204
- def update_port_b
205
- yield
206
- @port_b4_driven_high = driven_lines(@data_port_b, @data_dir_b).anybits?(0x10)
207
- refresh_port_b4 if @port_b4_handler
208
- end
209
-
210
- # PB4 is also control port 1's fire line, and a peripheral pulls it low
211
- # without any register write, so the level is resampled every cycle rather
212
- # than only after a poke.
213
- def refresh_port_b4
214
- high = @port_b4_driven_high && (peripheral.nil? || peripheral.port_b4_high?)
215
- return if high == @port_b4_high
216
-
217
- @port_b4_high = high
218
- @port_b4_handler.call(high)
219
- end
220
-
221
- def driven_lines(register, direction)
222
- # Output bits are driven from the data register; input bits float high.
223
- # External peripherals can still pull any line low (wired-AND).
224
- (register & direction) | (~direction & 0xff)
225
- end
226
-
227
- def apply_timer_output(value)
228
- value = with_bit(value, 6, @ta.output?) if control_a.output?
229
- value = with_bit(value, 7, @tb.output?) if control_b.output?
230
- value
231
- end
232
-
233
- def with_bit(value, bit, set)
234
- set ? value | (1 << bit) : value & ~(1 << bit)
235
- end
236
-
237
- def trigger_alarm = raise_interrupt(:alarm)
238
- def trigger_serial = raise_interrupt(:serial)
239
-
240
- def raise_interrupt(source) = @icr.flag(source)
241
-
242
- # CNT is sampled once a cycle. When the serial port drives it from this
243
- # cycle's timer A underflow, the new level is picked up on the next one.
244
- def cnt_edge(level)
245
- @cnt_high = level
246
- @cnt_rise = level
247
- @serial.rising_edge! { trigger_serial } if level
248
- end
249
-
250
- # Returns whether timer A underflowed, which clocks the serial port.
251
- #
252
- # CRB bits 6-5 pick timer B's source: ø2, CNT edges, timer A
253
- # underflows, or timer A underflows gated by the CNT level. Every source
254
- # drives the same count-enable line, so a cascaded underflow goes through
255
- # the input pipeline exactly as a CNT edge does.
256
- def update_timers
257
- @ta.cycle!(@control_a.value & 0x20 == 0x20 ? @cnt_rise : true)
258
- underflowed = @ta.underflowed
259
- @tb.cycle!(
260
- case @control_b.value & 0x60
261
- when 0x00 then true
262
- when 0x20 then @cnt_rise
263
- when 0x40 then underflowed
264
- else underflowed && @cnt_high
265
- end
266
- )
267
- @icr.flag(:timer_a) if underflowed
268
- @icr.timer_b_underflow! if @tb.underflowed
269
- underflowed
270
- end
271
-
272
- def write_control_a(value)
273
- was_output = control_a.serial_mode?
274
- @ta.write_control(value)
275
- @serial.reset! { trigger_serial } if control_a.serial_mode? != was_output
276
- @tod.fifty_hz = control_a.clock_frequency?
277
- end
278
- end
279
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- # Colour RAM is four bits wide. A CPU read takes the upper nibble off the
5
- # open data bus, which still holds the byte the VIC fetched in phi1.
6
- class ColorMemory < Memory
7
- def initialize(vic, start: 0xd800, length: 2**10)
8
- super(start:, length:)
9
- @vic = vic
10
- end
11
-
12
- def peek(addr)
13
- (@vic.phi1_data & 0xf0) | @storage[offset_of(addr)]
14
- end
15
-
16
- def poke(addr, value)
17
- super(addr, value & 0x0f)
18
- end
19
-
20
- # The four bits the cell stores, as the VIC's c-access sees them.
21
- def nibble(addr)
22
- @storage[offset_of(addr)]
23
- end
24
- end
25
- end
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class Computer
5
- # The LOAD, SAVE and serial traps on the KERNAL a KernalTrap::Layout
6
- # describes, which serve the disk in device 8 (Attachments#mount).
7
- module KernalTraps
8
- private
9
-
10
- def install_kernal_traps(layout)
11
- @trap_layout = layout
12
- load_trap = KernalTrap::Load.new(cpu:, bus: address_bus, layout:, drive: @drive)
13
- cpu.install_trap(layout.load) { load_trap.call }
14
- @serial_trap = KernalTrap::Serial.new(cpu:, bus: address_bus, layout:, drive: @drive,
15
- device: serial_trap_device).install
16
- save_trap = @save_trap = KernalTrap::Save.new(cpu:, bus: address_bus, layout:, drive: @drive)
17
- cpu.install_trap(layout.save) { save_trap.call }
18
- end
19
-
20
- def remove_kernal_traps
21
- cpu.remove_trap(@trap_layout.load)
22
- cpu.remove_trap(@trap_layout.save)
23
- @serial_trap.uninstall
24
- @serial_trap = nil
25
- @save_trap = nil
26
- end
27
- end
28
- end
29
- end
@@ -1,76 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- # CIA 1's control ports and the keyboard matrix that spans them.
5
- #
6
- # Port A carries the matrix rows together with joystick 2, port B the matrix
7
- # columns together with joystick 1. Every switch is active low, so the
8
- # joysticks are wired-AND onto the lines *before* the matrix settles: a stick
9
- # held in a direction selects rows and columns of its own, which is where
10
- # hardware's phantom keypresses come from. Paddles and a 1351 mouse have
11
- # buttons on those same lines.
12
- #
13
- # The ports also carry SID's POTX/POTY lines, which reach them through analog
14
- # switches closed by CIA 1 PA6 (port 1) and PA7 (port 2). Close both and the
15
- # pots sit in parallel, so SID charges through the lower of the two
16
- # resistances; close neither and the lines float high. Reading a pot asks the
17
- # CIA for the current select lines, since a program sets them and then goes
18
- # straight to SID without touching the ports again.
19
- #
20
- # A matrix may have rows beyond port A's eight. Their select lines come from
21
- # outside the CIA and are pushed into +extra_rows+, bit 0 for the ninth row
22
- # upwards, active low like port A; idle, every line is high and none of
23
- # those rows is selected. They settle with port A's lines as rows 8 and up,
24
- # so their keys reach port B, but port A reads only its own eight.
25
- class ControlPorts
26
- PORT1_POTS = 0x40
27
- PORT2_POTS = 0x80
28
- FIRE = 0x10
29
-
30
- attr_reader :keyboard, :joystick1, :joystick2
31
- attr_accessor :device1, :device2, :port_a_source, :extra_rows
32
-
33
- def initialize(keyboard:, joystick1:, joystick2:)
34
- @keyboard = keyboard
35
- @joystick1 = joystick1
36
- @joystick2 = joystick2
37
- @device1 = nil
38
- @device2 = nil
39
- @port_a_source = nil
40
- @extra_rows = 0xff
41
- end
42
-
43
- def read_a(port_a, port_b) = scan(port_a, port_b).first & 0xff
44
-
45
- def read_b(port_a, port_b) = scan(port_a, port_b).last
46
-
47
- # Control port 1 pin 6 is both the port B fire line and the VIC's light
48
- # pen input, so joystick 1's button and a 1351's left button latch
49
- # $D013/$D014. The CIA samples this every cycle, so it skips the matrix and
50
- # asks only what the port's own devices drive.
51
- def port_b4_high? = port_bits(@joystick1, @device1).anybits?(FIRE)
52
-
53
- def pot_x = selected_devices.map(&:pot_x).min || 0xff
54
-
55
- def pot_y = selected_devices.map(&:pot_y).min || 0xff
56
-
57
- private
58
-
59
- def selected_devices
60
- lines = @port_a_source&.port_a_lines || 0x00
61
- devices = []
62
- devices << @device1 if @device1 && lines.anybits?(PORT1_POTS)
63
- devices << @device2 if @device2 && lines.anybits?(PORT2_POTS)
64
- devices
65
- end
66
-
67
- def scan(port_a, port_b)
68
- keyboard.scan((port_a & port_bits(@joystick2, @device2)) | (@extra_rows << 8),
69
- port_b & port_bits(@joystick1, @device1))
70
- end
71
-
72
- def port_bits(joystick, device)
73
- device ? joystick.port_bits & device.port_bits : joystick.port_bits
74
- end
75
- end
76
- end
@@ -1,131 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class CPU
5
- # Steps that read an instruction's operand bytes and work out the
6
- # address it operates on, which they leave in @address. Also the
7
- # single-step implied, accumulator and immediate instructions, and JMP.
8
- module Addressing
9
- private
10
-
11
- def op_implied_dummy
12
- @memory.peek(@program_counter)
13
- end
14
-
15
- def op_implied_exec
16
- @memory.peek(@program_counter)
17
- send(@operation, nil, nil)
18
- end_instruction
19
- end
20
-
21
- def op_accumulator_exec
22
- @memory.peek(@program_counter)
23
- send(@operation, :accumulator, @a)
24
- end_instruction
25
- end
26
-
27
- def op_immediate_read
28
- value = @memory.peek(@program_counter)
29
- @program_counter = (@program_counter + 1) & 0xffff
30
- send(@operation, nil, value)
31
- end_instruction
32
- end
33
-
34
- def op_zp
35
- @address = @memory.peek(@program_counter)
36
- @program_counter = (@program_counter + 1) & 0xffff
37
- end
38
-
39
- def op_zp_x
40
- @memory.peek(@address)
41
- @address = (@address + @x) & 0xff
42
- end
43
-
44
- def op_zp_y
45
- @memory.peek(@address)
46
- @address = (@address + @y) & 0xff
47
- end
48
-
49
- def op_abs_low
50
- @address = @memory.peek(@program_counter)
51
- @program_counter = (@program_counter + 1) & 0xffff
52
- end
53
-
54
- def op_abs_high
55
- @address |= @memory.peek(@program_counter) << 8
56
- @program_counter = (@program_counter + 1) & 0xffff
57
- end
58
-
59
- def op_abs_high_x
60
- high = @memory.peek(@program_counter)
61
- @program_counter = (@program_counter + 1) & 0xffff
62
- index_address(high, @x)
63
- end
64
-
65
- def op_abs_high_y
66
- high = @memory.peek(@program_counter)
67
- @program_counter = (@program_counter + 1) & 0xffff
68
- index_address(high, @y)
69
- end
70
-
71
- def op_idx_dummy
72
- @memory.peek(@dummy_address)
73
- end
74
-
75
- def op_zp_pointer
76
- @pointer = @memory.peek(@program_counter)
77
- @program_counter = (@program_counter + 1) & 0xffff
78
- end
79
-
80
- def op_pointer_x
81
- @memory.peek(@pointer)
82
- @pointer = (@pointer + @x) & 0xff
83
- end
84
-
85
- def op_pointer_low
86
- @address = @memory.peek(@pointer)
87
- end
88
-
89
- def op_pointer_high
90
- @address |= @memory.peek((@pointer + 1) & 0xff) << 8
91
- end
92
-
93
- def op_pointer_high_y
94
- index_address(@memory.peek((@pointer + 1) & 0xff), @y)
95
- end
96
-
97
- def op_jmp_high
98
- @program_counter = @address | (@memory.peek(@program_counter) << 8)
99
- end_instruction
100
- end
101
-
102
- def op_indirect_low
103
- @pointer = @address
104
- @address = @memory.peek(@pointer)
105
- end
106
-
107
- # The pointer's high byte never increments, so JMP ($30FF) reads its
108
- # target's high byte from $3000, not $3100.
109
- def op_indirect_high
110
- high = @memory.peek((@pointer & 0xff00) | ((@pointer + 1) & 0xff))
111
- @program_counter = @address | (high << 8)
112
- end_instruction
113
- end
114
-
115
- # Adds an index register to a base address. The 6502 adds to the low
116
- # byte first and spends the next cycle reading from that address,
117
- # before the carry reaches the high byte. Read instructions skip that
118
- # cycle when there is no carry.
119
- def index_address(high, index)
120
- low = @address
121
- @address = (((high << 8) | low) + index) & 0xffff
122
- @boundary_crossed = (low + index) > 0xff
123
- if @optional_dummy && !@boundary_crossed
124
- @index += 1
125
- else
126
- @dummy_address = (high << 8) | ((low + index) & 0xff)
127
- end
128
- end
129
- end
130
- end
131
- end
@@ -1,54 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- class CPU
5
- # The steps at an instruction boundary: the opcode fetch that starts
6
- # an instruction, and the ends of one.
7
- module Boundary
8
- private
9
-
10
- # The first cycle of every instruction. Starts an interrupt if one was
11
- # pending when the previous instruction ended. Otherwise reads the
12
- # opcode and switches to its plan.
13
- def op_fetch
14
- return start_interrupt if @boundary_nmi || @boundary_irq
15
-
16
- run_traps
17
- opcode = @memory.peek(@program_counter)
18
- log(opcode) if @debug
19
- micro = MICROCODE[opcode]
20
- @operation = micro.operation
21
- @plan = micro.plan
22
- @writes = micro.writes
23
- @optional_dummy = micro.optional_dummy
24
- @index = 1
25
- @boundary_crossed = false
26
- @program_counter = (@program_counter + 1) & 0xffff
27
- end
28
-
29
- def end_instruction
30
- @instructions += 1
31
- end_sequence
32
- end
33
-
34
- # Makes the next cycle an opcode fetch, and saves the pending interrupt
35
- # flags for op_fetch. The next cycle polls before op_fetch runs, which
36
- # updates the live flags.
37
- def end_sequence
38
- @plan = FETCH_PLAN
39
- @writes = FETCH_WRITES
40
- @index = 0
41
- @boundary_irq = @irq_pending
42
- @boundary_nmi = @nmi_pending
43
- end
44
-
45
- def log(opcode)
46
- instruction = Instruction.find(opcode)
47
- puts(
48
- "#{@cycles}: PC: #{format16(@program_counter)} - " \
49
- "#{instruction.name.upcase} #{instruction.addressing_mode}"
50
- )
51
- end
52
- end
53
- end
54
- end