badline 0.13.0 → 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 (254) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +49 -1
  3. data/CLAUDE.md +27 -7
  4. data/CONTRIBUTING.md +4 -3
  5. data/README.md +8 -5
  6. data/doc/media.md +2 -1
  7. data/doc/pinned-behaviour.md +29 -0
  8. data/doc/snapshot-format.md +1047 -0
  9. data/doc/snapshots.md +72 -39
  10. data/lib/badline/audio/bare_player.rb +50 -17
  11. data/lib/badline/audio/machine_player.rb +15 -9
  12. data/lib/badline/audio/renderer.rb +32 -21
  13. data/lib/badline/c128/banks.rb +6 -3
  14. data/lib/badline/c128/bus/keyed_state.rb +45 -0
  15. data/lib/badline/c128/bus.rb +17 -3
  16. data/lib/badline/c128/drives.rb +6 -25
  17. data/lib/badline/c128/keyed_modules.rb +117 -0
  18. data/lib/badline/c128/keyed_state.rb +91 -0
  19. data/lib/badline/c128/keys.rb +9 -0
  20. data/lib/badline/c128/mmu.rb +9 -8
  21. data/lib/badline/c128/mmu_pages.rb +20 -0
  22. data/lib/badline/c128/modes.rb +19 -9
  23. data/lib/badline/c128/z80_turns.rb +1 -1
  24. data/lib/badline/c128.rb +8 -8
  25. data/lib/badline/c64/attachments.rb +0 -44
  26. data/lib/badline/c64/banked_ram/plus256k.rb +18 -10
  27. data/lib/badline/c64/banked_ram/plus60k.rb +8 -6
  28. data/lib/badline/c64/banked_ram/unexpanded.rb +2 -2
  29. data/lib/badline/c64/bus/debug_register.rb +32 -0
  30. data/lib/badline/c64/bus/keyed_state.rb +41 -0
  31. data/lib/badline/c64/bus.rb +2 -1
  32. data/lib/badline/c64/cartridge/action_replay.rb +0 -13
  33. data/lib/badline/c64/cartridge/easy_flash.rb +0 -15
  34. data/lib/badline/c64/cartridge/epyx_fastload.rb +0 -8
  35. data/lib/badline/c64/cartridge/final_cartridge3.rb +0 -12
  36. data/lib/badline/c64/cartridge/flash.rb +3 -3
  37. data/lib/badline/c64/cartridge/g_mod2.rb +0 -12
  38. data/lib/badline/c64/cartridge/geo_ram.rb +0 -16
  39. data/lib/badline/c64/cartridge/kcs_power.rb +0 -8
  40. data/lib/badline/c64/cartridge/keyed_state.rb +393 -0
  41. data/lib/badline/c64/cartridge/pagefox.rb +0 -10
  42. data/lib/badline/c64/cartridge/retro_replay.rb +0 -8
  43. data/lib/badline/c64/cartridge/rgcd.rb +0 -10
  44. data/lib/badline/c64/cartridge/super_games.rb +0 -10
  45. data/lib/badline/c64/cartridge/zaxxon.rb +0 -16
  46. data/lib/badline/c64/cartridge.rb +1 -27
  47. data/lib/badline/c64/kernal_traps.rb +28 -25
  48. data/lib/badline/c64/keyed_modules.rb +111 -0
  49. data/lib/badline/c64/keyed_state.rb +68 -0
  50. data/lib/badline/c64/reu/dma.rb +0 -4
  51. data/lib/badline/c64/reu/keyed_state.rb +140 -0
  52. data/lib/badline/c64/reu/ram.rb +0 -15
  53. data/lib/badline/c64/reu.rb +1 -3
  54. data/lib/badline/c64/true_drives.rb +56 -5
  55. data/lib/badline/c64.rb +7 -3
  56. data/lib/badline/chips/cia/interrupt_register.rb +0 -17
  57. data/lib/badline/chips/cia/keyed_parts.rb +213 -0
  58. data/lib/badline/chips/cia/serial.rb +0 -4
  59. data/lib/badline/chips/cia/time_of_day.rb +0 -22
  60. data/lib/badline/chips/cia/timer.rb +0 -20
  61. data/lib/badline/chips/cia.rb +2 -2
  62. data/lib/badline/chips/cpu/core.rb +18 -2
  63. data/lib/badline/chips/cpu/keyed_state.rb +177 -0
  64. data/lib/badline/chips/cpu/microcode.rb +16 -0
  65. data/lib/badline/chips/cpu/port.rb +20 -3
  66. data/lib/badline/chips/cpu.rb +5 -0
  67. data/lib/badline/chips/sid/decimator.rb +10 -8
  68. data/lib/badline/chips/sid/envelope.rb +1 -6
  69. data/lib/badline/chips/sid/filter.rb +0 -14
  70. data/lib/badline/chips/sid/keyed_parts.rb +286 -0
  71. data/lib/badline/chips/sid/voice.rb +0 -10
  72. data/lib/badline/chips/sid/waveform.rb +0 -2
  73. data/lib/badline/chips/sid.rb +1 -2
  74. data/lib/badline/chips/ted/beam.rb +119 -0
  75. data/lib/badline/chips/ted/timers.rb +66 -0
  76. data/lib/badline/chips/ted.rb +143 -0
  77. data/lib/badline/chips/tia.rb +49 -0
  78. data/lib/badline/chips/vdc/keyed_parts.rb +105 -0
  79. data/lib/badline/chips/vdc/painter.rb +0 -12
  80. data/lib/badline/chips/vdc/raster.rb +0 -16
  81. data/lib/badline/chips/vdc/window.rb +0 -9
  82. data/lib/badline/chips/vdc.rb +1 -2
  83. data/lib/badline/chips/via/control_lines.rb +0 -15
  84. data/lib/badline/chips/via/interrupt_register.rb +0 -9
  85. data/lib/badline/chips/via/keyed_parts.rb +163 -0
  86. data/lib/badline/chips/via/shift_register.rb +0 -14
  87. data/lib/badline/chips/via/timer1.rb +0 -13
  88. data/lib/badline/chips/via/timer2.rb +0 -18
  89. data/lib/badline/chips/via.rb +1 -2
  90. data/lib/badline/chips/vic/border_mask.rb +0 -10
  91. data/lib/badline/chips/vic/collisions.rb +0 -11
  92. data/lib/badline/chips/vic/color_patches.rb +0 -11
  93. data/lib/badline/chips/vic/display_state.rb +0 -19
  94. data/lib/badline/chips/vic/graphics_shifter.rb +0 -4
  95. data/lib/badline/chips/vic/keyed_parts.rb +228 -0
  96. data/lib/badline/chips/vic/keyed_sprites.rb +225 -0
  97. data/lib/badline/chips/vic/keyed_state.rb +102 -0
  98. data/lib/badline/chips/vic/register_log.rb +0 -18
  99. data/lib/badline/chips/vic/registers.rb +0 -9
  100. data/lib/badline/chips/vic/sequencer.rb +0 -2
  101. data/lib/badline/chips/vic/sprite/internal_bus.rb +0 -11
  102. data/lib/badline/chips/vic/sprite.rb +0 -2
  103. data/lib/badline/chips/vic/sprites.rb +0 -3
  104. data/lib/badline/chips/vic.rb +6 -2
  105. data/lib/badline/chips/vic_i/keyed_parts.rb +142 -0
  106. data/lib/badline/chips/vic_i/painter.rb +0 -4
  107. data/lib/badline/chips/vic_i/sound.rb +38 -46
  108. data/lib/badline/chips/vic_i.rb +2 -2
  109. data/lib/badline/chips/z80/core.rb +2 -2
  110. data/lib/badline/chips/z80/keyed_state.rb +73 -0
  111. data/lib/badline/chips.rb +10 -0
  112. data/lib/badline/core.rb +4 -21
  113. data/lib/badline/drives/datasette/keyed_state.rb +38 -0
  114. data/lib/badline/drives/datasette.rb +40 -7
  115. data/lib/badline/drives/engine/core.rb +3 -0
  116. data/lib/badline/drives/engine/serial_lines.rb +4 -7
  117. data/lib/badline/drives/model1541/bus.rb +0 -13
  118. data/lib/badline/drives/model1541/disk.rb +9 -8
  119. data/lib/badline/drives/model1541/keyed_state.rb +251 -0
  120. data/lib/badline/drives/model1541/mechanism.rb +0 -2
  121. data/lib/badline/drives/model1541.rb +1 -2
  122. data/lib/badline/drives/model1571/bus.rb +0 -13
  123. data/lib/badline/drives/model1571/keyed_state.rb +108 -0
  124. data/lib/badline/drives/model1571/wd1770.rb +0 -14
  125. data/lib/badline/drives/model1571.rb +1 -2
  126. data/lib/badline/drives/model1581/bus.rb +0 -13
  127. data/lib/badline/drives/model1581/disk.rb +0 -4
  128. data/lib/badline/drives/model1581/keyed_state.rb +280 -0
  129. data/lib/badline/drives/model1581/mechanism.rb +0 -21
  130. data/lib/badline/drives/model1581/slot.rb +0 -18
  131. data/lib/badline/drives/model1581/wd1772.rb +0 -2
  132. data/lib/badline/drives/model1581.rb +2 -2
  133. data/lib/badline/drives.rb +8 -0
  134. data/lib/badline/frontend/app.rb +3 -3
  135. data/lib/badline/frontend/boot.rb +1 -1
  136. data/lib/badline/frontend/controls.rb +19 -3
  137. data/lib/badline/frontend/drive_led.rb +44 -21
  138. data/lib/badline/frontend/menu/menu_dialogs.rb +2 -2
  139. data/lib/badline/frontend/snapshots.rb +12 -1
  140. data/lib/badline/frontend/timeline.rb +28 -10
  141. data/lib/badline/input/matrix_typist.rb +98 -0
  142. data/lib/badline/input.rb +1 -0
  143. data/lib/badline/kernal_trap/chrout.rb +45 -0
  144. data/lib/badline/kernal_trap/dos/channel.rb +0 -27
  145. data/lib/badline/kernal_trap/dos/channels.rb +0 -25
  146. data/lib/badline/kernal_trap/dos/memory.rb +0 -9
  147. data/lib/badline/kernal_trap/dos/status.rb +0 -8
  148. data/lib/badline/kernal_trap/dos/write_file.rb +0 -18
  149. data/lib/badline/kernal_trap/dos.rb +0 -19
  150. data/lib/badline/kernal_trap/file_routine.rb +4 -4
  151. data/lib/badline/kernal_trap/keyed_state.rb +150 -0
  152. data/lib/badline/kernal_trap/layout.rb +75 -11
  153. data/lib/badline/kernal_trap/load.rb +14 -16
  154. data/lib/badline/kernal_trap/routine.rb +12 -0
  155. data/lib/badline/kernal_trap/save.rb +8 -18
  156. data/lib/badline/kernal_trap/serial.rb +1 -17
  157. data/lib/badline/kernal_trap.rb +2 -0
  158. data/lib/badline/machine/keyboard_buffer.rb +49 -0
  159. data/lib/badline/machine/settling.rb +29 -0
  160. data/lib/badline/machine.rb +5 -2
  161. data/lib/badline/media/boot_disk.rb +14 -2
  162. data/lib/badline/media/extensions.rb +10 -0
  163. data/lib/badline/memory.rb +3 -6
  164. data/lib/badline/options/family.rb +5 -2
  165. data/lib/badline/options/help.rb +42 -16
  166. data/lib/badline/options/table.rb +2 -0
  167. data/lib/badline/options/validation.rb +2 -0
  168. data/lib/badline/options.rb +6 -1
  169. data/lib/badline/plus4/acia.rb +45 -0
  170. data/lib/badline/plus4/bus.rb +312 -0
  171. data/lib/badline/plus4/cpu.rb +10 -0
  172. data/lib/badline/plus4/cpu_port.rb +93 -0
  173. data/lib/badline/plus4/keyboard_port.rb +51 -0
  174. data/lib/badline/plus4/model.rb +38 -0
  175. data/lib/badline/plus4/user_port.rb +31 -0
  176. data/lib/badline/plus4.rb +164 -0
  177. data/lib/badline/roms/README +38 -0
  178. data/lib/badline/roms/plus4/basic.rom +0 -0
  179. data/lib/badline/roms/plus4/function-high.rom +0 -0
  180. data/lib/badline/roms/plus4/function-low.rom +0 -0
  181. data/lib/badline/roms/plus4/kernal-ntsc.rom +0 -0
  182. data/lib/badline/roms/plus4/kernal-pal.rom +0 -0
  183. data/lib/badline/snapshot/c128_setup.rb +9 -20
  184. data/lib/badline/snapshot/c64_setup.rb +28 -24
  185. data/lib/badline/snapshot/container.rb +4 -0
  186. data/lib/badline/snapshot/field_doc/markdown.rb +112 -0
  187. data/lib/badline/snapshot/field_doc.rb +109 -0
  188. data/lib/badline/snapshot/image.rb +134 -28
  189. data/lib/badline/snapshot/keyed/cursor.rb +40 -0
  190. data/lib/badline/snapshot/keyed/modules.rb +66 -0
  191. data/lib/badline/snapshot/keyed/reader.rb +188 -0
  192. data/lib/badline/snapshot/keyed/recorder.rb +88 -0
  193. data/lib/badline/snapshot/keyed/report.rb +26 -0
  194. data/lib/badline/snapshot/keyed/writer.rb +55 -0
  195. data/lib/badline/snapshot/keyed.rb +64 -0
  196. data/lib/badline/snapshot/machine_state.rb +17 -64
  197. data/lib/badline/snapshot/storage_setup.rb +29 -34
  198. data/lib/badline/snapshot/vic20_setup.rb +6 -15
  199. data/lib/badline/snapshot/vice/reu1764.rb +2 -2
  200. data/lib/badline/snapshot/vice.rb +7 -31
  201. data/lib/badline/snapshot.rb +43 -20
  202. data/lib/badline/storage/crt_file.rb +3 -1
  203. data/lib/badline/storage/g64_image.rb +8 -3
  204. data/lib/badline/storage/tap.rb +43 -15
  205. data/lib/badline/version.rb +1 -1
  206. data/lib/badline/vic20/attachments.rb +3 -0
  207. data/lib/badline/vic20/bus/keyed_state.rb +52 -0
  208. data/lib/badline/vic20/bus.rb +1 -2
  209. data/lib/badline/vic20/keyed_modules.rb +73 -0
  210. data/lib/badline/vic20/keyed_state.rb +45 -0
  211. data/lib/badline/vic20.rb +5 -5
  212. data/lib/badline.rb +1 -0
  213. metadata +61 -42
  214. data/lib/badline/c128/bus/saved_state.rb +0 -53
  215. data/lib/badline/c128/saved_state.rb +0 -117
  216. data/lib/badline/c64/bus/saved_state.rb +0 -68
  217. data/lib/badline/c64/cartridge/flash/saved_state.rb +0 -40
  218. data/lib/badline/c64/cartridge/retro_replay/saved_state.rb +0 -47
  219. data/lib/badline/c64/cartridge/saved_state.rb +0 -63
  220. data/lib/badline/c64/reu/dma/saved_state.rb +0 -52
  221. data/lib/badline/c64/reu/saved_state.rb +0 -55
  222. data/lib/badline/c64/saved_state.rb +0 -112
  223. data/lib/badline/chips/cia/saved_state.rb +0 -49
  224. data/lib/badline/chips/cia/serial/saved_state.rb +0 -45
  225. data/lib/badline/chips/cpu/saved_state.rb +0 -117
  226. data/lib/badline/chips/sid/envelope/saved_state.rb +0 -70
  227. data/lib/badline/chips/sid/filter/saved_state.rb +0 -42
  228. data/lib/badline/chips/sid/saved_state.rb +0 -52
  229. data/lib/badline/chips/sid/waveform/saved_state.rb +0 -68
  230. data/lib/badline/chips/vdc/saved_state.rb +0 -36
  231. data/lib/badline/chips/via/saved_state.rb +0 -44
  232. data/lib/badline/chips/vic/graphics_shifter/saved_state.rb +0 -40
  233. data/lib/badline/chips/vic/saved_state.rb +0 -82
  234. data/lib/badline/chips/vic/sequencer/saved_state.rb +0 -91
  235. data/lib/badline/chips/vic/sprite/saved_state.rb +0 -66
  236. data/lib/badline/chips/vic/sprites/saved_state.rb +0 -59
  237. data/lib/badline/chips/vic_i/painter/saved_state.rb +0 -40
  238. data/lib/badline/chips/vic_i/saved_state.rb +0 -55
  239. data/lib/badline/chips/z80/saved_state.rb +0 -71
  240. data/lib/badline/chrout_trap.rb +0 -43
  241. data/lib/badline/debug_register.rb +0 -28
  242. data/lib/badline/drives/datasette/saved_state.rb +0 -37
  243. data/lib/badline/drives/model1541/disk/saved_state.rb +0 -88
  244. data/lib/badline/drives/model1541/mechanism/saved_state.rb +0 -72
  245. data/lib/badline/drives/model1541/saved_state.rb +0 -44
  246. data/lib/badline/drives/model1571/saved_state.rb +0 -47
  247. data/lib/badline/drives/model1581/disk/saved_state.rb +0 -89
  248. data/lib/badline/drives/model1581/saved_state.rb +0 -42
  249. data/lib/badline/drives/model1581/wd1772/saved_state.rb +0 -68
  250. data/lib/badline/keyboard_buffer.rb +0 -33
  251. data/lib/badline/snapshot/setup.rb +0 -31
  252. data/lib/badline/snapshot/state.rb +0 -179
  253. data/lib/badline/vic20/bus/saved_state.rb +0 -35
  254. data/lib/badline/vic20/saved_state.rb +0 -110
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2a074ca0626351bec4132e06bc5e4ab951f7a4b18cf9e78ddc3c16adfd4194b8
4
- data.tar.gz: 878629423f450e6c6440649b00d87646c1ff59d5ccb99801d5909fedc14f9108
3
+ metadata.gz: 320b4659e6c9945509741f928989b2378d38ae18a51c1dd5bbca706e3b3ada54
4
+ data.tar.gz: 9a6ce80ab26e74e325c8fb660f4ed1fabc64a6e3c1859b723b3816aebe3f4b55
5
5
  SHA512:
6
- metadata.gz: 8eb5553980d187ccafd1ac4906b8a3d7fb6a80a8219375ef872f208411c362bf3724e721946ed166b91595177ce3adf38632e2b69008d9a4082032239cfcb697
7
- data.tar.gz: dcb3a6ab34cceff4e85b56d09c2e38eaeab8350f57928c07e23ba7c6f5de38b32a88a0735802a2d196bb2ccf89a6a058579a47daf85ca8ac275f5b6bce90a975
6
+ metadata.gz: 0f4e3b6c6bc7c35eec18ea3a81165050183e92eeebab3c04b12472970b5b0a87d8ad860ceac81e411a39836c601239b3e708bcffbcb7f4eb6561599c1cda1522
7
+ data.tar.gz: 61d6698127237a45d99febd816088da06d227519b34455188babc7dafebb977613a61c1472ed348c691433a8c02f4dcbab0346f48083b71fc02035f64f7c8549
data/CHANGELOG.md CHANGED
@@ -1,5 +1,54 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.14.0](https://github.com/elektronaut/badline/compare/v0.13.0...v0.14.0) (2026-10-11)
4
+
5
+
6
+ ### Features
7
+
8
+ * add the keyed snapshot record encoding ([1b87aed](https://github.com/elektronaut/badline/commit/1b87aeddea27f81cb1ccedbbef2bba58c2db0bb3))
9
+ * boot the Plus/4 and the C16 to READY headless ([278020e](https://github.com/elektronaut/badline/commit/278020ee0256fa1d085391fd0e7a6679ac80dbcb))
10
+ * bundle the 264 series ROMs and refuse badline plus4 until it runs ([7072ae7](https://github.com/elektronaut/badline/commit/7072ae7cb6e1ccd96a4e02eb1146b7b1bfaf7125))
11
+ * give each machine its keyboard buffer layout ([0b64648](https://github.com/elektronaut/badline/commit/0b64648fec3cd56bbbee1ac4dc8fe446c84dd4b9))
12
+ * keep the KERNAL's file variables in KernalTrap::Layout ([0ca7488](https://github.com/elektronaut/badline/commit/0ca7488505b2b7af9f358bdf6d3e86a1e1c768e3))
13
+ * keyed snapshot fields for device 8 through the KERNAL traps ([cce36f2](https://github.com/elektronaut/badline/commit/cce36f2f740c5337cd2b0a66fe99394114409c32))
14
+ * keyed snapshot fields for each machine's own state and setup ([ff251a6](https://github.com/elektronaut/badline/commit/ff251a62cbad4502f576628a4f4c5d3d6a22eaf8))
15
+ * keyed snapshot fields for the 1541 ([f3f57b7](https://github.com/elektronaut/badline/commit/f3f57b7e24471e198304bfd90ba16c4abb7c4c16))
16
+ * keyed snapshot fields for the 1571 ([5ceb741](https://github.com/elektronaut/badline/commit/5ceb7416a1902252d97c80aff22658a68e4abfb6))
17
+ * keyed snapshot fields for the 1581 ([1c67e29](https://github.com/elektronaut/badline/commit/1c67e298c24e82e92cc5feddcc0153143d4eda8d))
18
+ * keyed snapshot fields for the 6502 cores and the Z80 ([8ee592e](https://github.com/elektronaut/badline/commit/8ee592e5ee5b658c8f452cf4bdf9df044f8c19ab))
19
+ * keyed snapshot fields for the C128's MMU ([aa861ca](https://github.com/elektronaut/badline/commit/aa861cac0a33d79f777b60310f0cb573024f2d60))
20
+ * keyed snapshot fields for the cartridges ([349ae81](https://github.com/elektronaut/badline/commit/349ae81c7c002f5c1b94fa50cc994a6b7ec16915))
21
+ * keyed snapshot fields for the CIA ([b5a6ff8](https://github.com/elektronaut/badline/commit/b5a6ff8b02026daa3ec6247ab4024d35efedb18e))
22
+ * keyed snapshot fields for the datasette and its tape ([37a52f1](https://github.com/elektronaut/badline/commit/37a52f1018ab226a60395e1c98c6a362c0159f01))
23
+ * keyed snapshot fields for the memories, RAM expansions and buses ([14b1a95](https://github.com/elektronaut/badline/commit/14b1a951a44c2bc23871208b9843489d4ca6963c))
24
+ * keyed snapshot fields for the REU ([8088ac5](https://github.com/elektronaut/badline/commit/8088ac52c68667db7d6acdc6e0f0b629e165b0b3))
25
+ * keyed snapshot fields for the SID ([b58f88d](https://github.com/elektronaut/badline/commit/b58f88d1a98346aba4dbec0dead306b3d36b32f7))
26
+ * keyed snapshot fields for the VDC ([b894c3e](https://github.com/elektronaut/badline/commit/b894c3ef0b83988d17f03027b1831e7be3739be3))
27
+ * keyed snapshot fields for the VIA ([52ab12c](https://github.com/elektronaut/badline/commit/52ab12cb129adedc8a3f0b7df469a1440eb72309))
28
+ * keyed snapshot fields for the VIC-I and its sound ([a47d3e8](https://github.com/elektronaut/badline/commit/a47d3e823891e5d597141423f1675962ac266df7))
29
+ * keyed snapshot fields for the VIC-II ([8fc8b4c](https://github.com/elektronaut/badline/commit/8fc8b4c39f8ae5cac781f51f0bbeab5134c3bc9f))
30
+ * latch the VIC's sprite collisions when a snapshot settles ([a1c9429](https://github.com/elektronaut/badline/commit/a1c9429fefdbbc57407fb68baf057209d7163db1))
31
+ * let a unit report its own adjustments when its snapshot loads ([3b3af19](https://github.com/elektronaut/badline/commit/3b3af19ef0d74b0a45fbea96feef107f26db12a6))
32
+ * read Plus/4 CRT images ([450148d](https://github.com/elektronaut/badline/commit/450148db02c8057cc071f6d867707aa45a87c996))
33
+ * read version 2 C16 tapes and time the datasette's read level ([7e78070](https://github.com/elektronaut/badline/commit/7e78070877394a4657e23699a3098f297469be05))
34
+ * report a VIC-II line restarted from another renderer's snapshot ([6cb0607](https://github.com/elektronaut/badline/commit/6cb06075d410e59a8cd6f7d82d29757819e23e67))
35
+ * run the 264 testbench's exitcode rows as testbench-plus4 and testbench-c16 ([862f14b](https://github.com/elektronaut/badline/commit/862f14bd474bdac92017f25a57a057cf1f42a63f))
36
+ * run the Lorenz suite's plus4 build as lorenz-plus4 ([006efdd](https://github.com/elektronaut/badline/commit/006efddeb3a052714b99ff9b11ec18dd85cb6778))
37
+ * save and load snapshots as BL-* modules ([25db1be](https://github.com/elektronaut/badline/commit/25db1be28817d292c314672c5401251d36d11902))
38
+ * save snapshots at the next instruction boundary ([3f9ae3c](https://github.com/elektronaut/badline/commit/3f9ae3cf5392c194a1915801c9da4739832649e3))
39
+
40
+
41
+ ### Bug Fixes
42
+
43
+ * boot C128 boot sectors on .g64 and .g71 images ([81ad184](https://github.com/elektronaut/badline/commit/81ad1842fdc66b5ddb5d2988eb699409741f376a))
44
+ * draw the true drive's power LED, and the LEDs of a drive plugged in after start ([982c522](https://github.com/elektronaut/badline/commit/982c522c56c46d193ca5d15f49c59f221f04ad8e))
45
+ * drive the datasette's write line from the CPU port's bit 3 ([b90c29d](https://github.com/elektronaut/badline/commit/b90c29dd758eb7867930c5f26dbd0ae510f430af))
46
+ * let a held key go as the key it pressed across a C128 mode switch ([3a8d731](https://github.com/elektronaut/badline/commit/3a8d7313034f0b69057528b58ff247250b7e7168))
47
+ * read the ROMs and I/O a C128 KERNAL bank maps when saving ([3e4db21](https://github.com/elektronaut/badline/commit/3e4db218959237fada950e4b65238203af10e3c6))
48
+ * run the VIC-20's sound voices whether or not the host plays them ([13052c7](https://github.com/elektronaut/badline/commit/13052c7bbb9ca2b4ed678935ec6b88cc84bb2806))
49
+ * take the C128's own keys in --at key= ([428047c](https://github.com/elektronaut/badline/commit/428047cc4eca55b70967048d49579840b90ea946))
50
+ * type --at type= text on the C128's key matrix while the Z80 runs ([39d77ff](https://github.com/elektronaut/badline/commit/39d77ff29989a46c82184cd2dde03e8d470c553b))
51
+
3
52
  ## [0.13.0](https://github.com/elektronaut/badline/compare/v0.12.1...v0.13.0) (2026-10-11)
4
53
 
5
54
 
@@ -81,7 +130,6 @@
81
130
  * bundle the PET 64's KERNAL, 901246-01 ([9a029ec](https://github.com/elektronaut/badline/commit/9a029ecfe25c0d9a806d8858253c4c172e175b7f))
82
131
 
83
132
 
84
- ### Miscellaneous Chores
85
133
 
86
134
  * release 0.10.1 ([9d6f6ba](https://github.com/elektronaut/badline/commit/9d6f6ba71a647f24f00a830fbc772531fbcb4d92))
87
135
 
data/CLAUDE.md CHANGED
@@ -92,6 +92,13 @@ Z80), and names the first component that differs. It builds a C64 unless
92
92
  `--family vic20` or `--family c128` (with `--mode c64|c128`) says
93
93
  otherwise. Use it for refactors and speed work.
94
94
 
95
+ `bin/snapshot_check` checks snapshots. For each scenario (`--list`) it saves
96
+ twice, then saves, loads and saves again, and expects the same bytes each
97
+ time. It then runs the saved and the loaded machine side by side and names
98
+ the first difference. `--carts` does the same for every cartridge mapper,
99
+ and `--diff A B` compares two snapshot files module by module. Run it on any
100
+ change to a unit's saved state.
101
+
95
102
  ## Driving the emulator headlessly
96
103
 
97
104
  `exe/badline-ruby <media>` opens the SDL window, which is no use for checking
@@ -153,7 +160,7 @@ worktree and owns a different set of files.
153
160
 
154
161
  - `rake vendor:checkout` fetches SingleStepTests 65x02, the Z80 sample
155
162
  and VICE-testprogs into `vendor/`
156
- - `bundle exec rspec`: line coverage is about 97%. `spec/spec_helper.rb`
163
+ - `bundle exec rspec`: line coverage is about 95%. `spec/spec_helper.rb`
157
164
  fails a whole-suite run (every spec file, no filters) below 90%, while
158
165
  single-file and filtered runs skip the floor. `:slow` specs are excluded
159
166
  by default: run them with `bundle exec rspec --tag slow`
@@ -200,12 +207,25 @@ the rows your change can't reach tell you nothing about it.
200
207
  `ruby --yjit bin/lorenz [image] [start_test] [max_cycles]` (resumes the
201
208
  chain at a named test, and `--stop-after NAME` ends it once that test is
202
209
  done). These take seconds to minutes
203
- - A pull request's CI is the verdict. It runs every suite on the Spinel
204
- build, compared row by row against
205
- `test/baselines/`, and every job is a required check. A row that moved
206
- fails it. A pull request that changes only docs, or only a release's
207
- version bump, skips the specs and suites; pushes to main always run
208
- them. Re-record only those rows, in the same change:
210
+ - A pull request's CI is the verdict, and a pull request merges on it
211
+ alone. It runs the specs, Rubocop, Minitest, the harness builds, the
212
+ Spinel checks, the native round trip, and the suites its changed files
213
+ can reach, on the Spinel build, compared row by row against
214
+ `test/baselines/`. `test/support/ci_reach.rb` maps paths to suites, and
215
+ a path it doesn't name runs every suite. A row that moved fails it. A
216
+ pull request that changes only docs, or only a release's version bump,
217
+ skips the specs and suites. A row that moves in a pull request's CI is
218
+ re-recorded in that pull request with its reason; nobody waits for
219
+ `suites.yml` to confirm it. A change that reaches a suite the map
220
+ doesn't name adds the path to `test/support/ci_reach.rb` in the same
221
+ pull request, and a change that adds a directory under `lib/badline/`
222
+ gives it a rule
223
+ - The full suites run on main every two hours (`.github/workflows/suites.yml`).
224
+ Nobody waits for it, polls it or dispatches it to check a pull request.
225
+ Its result is a `suites` commit status and, when red, one `suites-red`
226
+ issue the planner owns. A red main never blocks a merge. A release
227
+ publishes only once its tagged commit is green
228
+ - Re-record only the rows that moved, in the same change:
209
229
  `rake "regression:record:<suite>[filter,...]"` (quote it, because zsh
210
230
  globs the brackets). It runs only the matching tests on CRuby and
211
231
  splices their rows into the baseline, and every other row keeps its
data/CONTRIBUTING.md CHANGED
@@ -91,9 +91,10 @@ bundle exec rubocop
91
91
  ## Tests and commits
92
92
 
93
93
  - Add tests for any behavior you change.
94
- - CI runs rubocop, the specs and every regression suite on each pull
95
- request, and fails on any suite row that differs from its baseline in
96
- `test/baselines/`. When a change moves rows on purpose, re-record just
94
+ - CI runs rubocop, the specs and the regression suites a pull request's
95
+ changes can reach on each pull request, and fails on any suite row that
96
+ differs from its baseline in `test/baselines/`. Every suite runs on
97
+ `main` every two hours. When a change moves rows on purpose, re-record just
97
98
  those rows as [test/baselines/README.md](test/baselines/README.md)
98
99
  describes, and say why in the pull request.
99
100
  - Write commit messages using
data/README.md CHANGED
@@ -107,6 +107,7 @@ differences noted in the table. `--help` lists the options for either.
107
107
  | `--script FILE` | Run the events in `FILE`, one `FRAME:EVENT` a line |
108
108
  | `--screenshot FILE` | Save the last frame as a `.bmp` |
109
109
  | `--save-snapshot FILE` | Save the machine as a `.vsf` snapshot after the last frame |
110
+ | `--vice` | Add VICE's modules to `--save-snapshot`'s C64 snapshot, so x64sc opens it too |
110
111
 
111
112
  ```sh
112
113
  badline --unpaced --frames 12000 --true-drive disk1.d64 \
@@ -139,7 +140,8 @@ Without `--true-drive`, device 8 is no drive at all but traps on the
139
140
  KERNAL's disk routines. Loading is instant, but fast loaders and copy
140
141
  protection that run code on the drive need `--true-drive`, which puts
141
142
  an emulated 1541 there, running its own DOS at a real 1541's speed. Its
142
- red LED lights in the bottom right corner of the border. With
143
+ red activity LED and green power LED light in the bottom right corner
144
+ of the border. With
143
145
  `--true-drive`, a `.d81` goes in an emulated 1581 in place of the 1541.
144
146
  [doc/media.md](doc/media.md) has the details, and how to attach media
145
147
  from Ruby.
@@ -225,10 +227,11 @@ snapshots, and x128's `.vsf` files don't load.
225
227
  badline's data folder, replacing the oldest, and `F12` restores the
226
228
  newest, even after badline has quit and started again. badline also
227
229
  autosaves every two minutes of play, and the pause menu's Snapshots page
228
- saves under a name and loads any of them. Snapshots use
229
- VICE's `.vsf` format: badline opens those x64sc saves, and x64sc opens
230
- badline's. See [doc/snapshots.md](doc/snapshots.md) for where they're
231
- kept, what they hold and how far the two agree.
230
+ saves under a name and loads any of them. Snapshots from badline 0.14.0
231
+ on load in every later version. They use VICE's `.vsf` format: badline
232
+ opens those x64sc saves, and x64sc opens badline's saved with `--vice`.
233
+ See [doc/snapshots.md](doc/snapshots.md) for where they're kept, what
234
+ they hold and how far the two agree.
232
235
 
233
236
  ## Playing and rendering SID tunes
234
237
 
data/doc/media.md CHANGED
@@ -31,7 +31,8 @@ own DOS ROM on its own 6502 and talking to the machine over the serial
31
31
  bus. It reads `.d64` and `.g64` images, which it autostarts with the
32
32
  same `LOAD"*",8,1` and `RUN`, but not `.d71`, `.d81` or `.t64` images
33
33
  or directories. Loading runs at the speed of a real 1541, and the
34
- drive's red LED lights in the bottom right corner of the border.
34
+ drive's red activity LED and green power LED light in the bottom right
35
+ corner of the border. A 1581 flashes its power LED after an error.
35
36
 
36
37
  A `.g64` holds the disk's raw GCR, half tracks and all, so copy
37
38
  protection and fast loaders that read it work.
@@ -38,6 +38,7 @@ only catches the rows that happen to move.
38
38
  - [VIC-20 RAM power-on pattern](#vic-20-ram-power-on-pattern)
39
39
  - [VIC-I fetches and the V-bus](#vic-i-fetches-and-the-v-bus)
40
40
  - [VIC-I sound](#vic-i-sound)
41
+ - [TED beam and the 7501 port](#ted-beam-and-the-7501-port)
41
42
  - [1541 serial port](#1541-serial-port)
42
43
  - [1541 disk mechanism](#1541-disk-mechanism)
43
44
  - [REU DMA](#reu-dma)
@@ -1490,6 +1491,34 @@ wasn't read.
1490
1491
  - Spec guard: *a step* in
1491
1492
  [`vic_i/sound/output_spec.rb`](../spec/badline/chips/vic_i/sound/output_spec.rb).
1492
1493
 
1494
+ ## TED beam and the 7501 port
1495
+
1496
+ Two places where badline knowingly differs from xplus4 r45942, which was
1497
+ run as a black box. No hardware capture settles either of them. Whoever
1498
+ finds one should start here.
1499
+
1500
+ - The line count steps, and the raster interrupt fires, at horizontal
1501
+ count 376, column 47 of `Chips::TED::Beam`: the datasheet's "Increment
1502
+ Vertical Line" decode, which fits its "8 cycles before the character
1503
+ window" for the raster interrupt. xplus4 steps the line about 3 single
1504
+ clock cycles later, and its raster interrupt reaches the handler 2-3
1505
+ cycles later, on display and border lines alike.
1506
+ - Pinned by the TED datasheet in the *Plus/4 Hardware Manual*, the
1507
+ scanned decode table on sheet 11 (page 62 of `hw.pdf`), not by a test.
1508
+ The comparison with xplus4 used trace probes that sample `$FF1E` and
1509
+ `$FF1D` through the lines, described with #644. The Lorenz plus4 rows
1510
+ don't move either way.
1511
+ - Spec guard: *the beam* in
1512
+ [`chips/ted_spec.rb`](../spec/badline/chips/ted_spec.rb).
1513
+ - `trap10`, `trap12` and `trap14` of the Lorenz suite's plus4 build, and
1514
+ their `ane` and `lxa` variants, pass on badline and fail (`$ff`) on
1515
+ xplus4. They are the trap tests that put their data on the 7501's port
1516
+ at `$00`-`$01` (`Plus4::CPUPort`: a full 8-bit direction register, P5
1517
+ reading 1 as an input). `readme-plus4.txt` says the trap tests don't
1518
+ work on a real 264, so its results don't decide this either.
1519
+ - Pinned by `lorenz-plus4`'s rows for those tests. The xplus4 verdicts
1520
+ are its exit codes with `-debugcart`, one program at a time.
1521
+
1493
1522
  ## 1541 serial port
1494
1523
 
1495
1524
  - The drive sees the C64's side of the serial bus a host cycle late. The