badline 0.15.0 → 0.16.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 (155) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +102 -0
  3. data/CLAUDE.md +15 -7
  4. data/README.md +142 -16
  5. data/doc/media.md +19 -0
  6. data/doc/pinned-behaviour.md +67 -0
  7. data/doc/snapshot-format.md +274 -31
  8. data/doc/snapshots.md +14 -0
  9. data/exe/badline-ruby +1 -1
  10. data/lib/badline/audio/machine_player.rb +2 -14
  11. data/lib/badline/c64/common.rb +1 -1
  12. data/lib/badline/c64/true_drives.rb +13 -1
  13. data/lib/badline/c64.rb +6 -0
  14. data/lib/badline/chips/crtc/keyed_state.rb +46 -0
  15. data/lib/badline/chips/crtc.rb +163 -0
  16. data/lib/badline/chips/pia/control_lines.rb +138 -0
  17. data/lib/badline/chips/pia/keyed_parts.rb +56 -0
  18. data/lib/badline/chips/pia.rb +138 -0
  19. data/lib/badline/chips/tia.rb +16 -0
  20. data/lib/badline/core.rb +3 -0
  21. data/lib/badline/drives/datasette/keyed_state.rb +8 -3
  22. data/lib/badline/drives/engine/core.rb +6 -14
  23. data/lib/badline/drives/engine/idle.rb +42 -4
  24. data/lib/badline/drives/engine/idle_cpu.rb +18 -0
  25. data/lib/badline/drives/engine/serial_connection.rb +25 -0
  26. data/lib/badline/drives/engine/sleep.rb +1 -0
  27. data/lib/badline/drives/engine.rb +1 -0
  28. data/lib/badline/drives/ieee_bus.rb +28 -0
  29. data/lib/badline/drives/model1541/byte_ready.rb +19 -3
  30. data/lib/badline/drives/model1541/mechanism.rb +10 -1
  31. data/lib/badline/drives/model1541.rb +1 -0
  32. data/lib/badline/drives/model1551/bus.rb +138 -0
  33. data/lib/badline/drives/model1551/cable.rb +107 -0
  34. data/lib/badline/drives/model1551/cpu.rb +14 -0
  35. data/lib/badline/drives/model1551/keyed_state.rb +65 -0
  36. data/lib/badline/drives/model1551/port.rb +74 -0
  37. data/lib/badline/drives/model1551/tia.rb +71 -0
  38. data/lib/badline/drives/model1551.rb +192 -0
  39. data/lib/badline/drives/model1571.rb +1 -0
  40. data/lib/badline/drives/model1581.rb +1 -0
  41. data/lib/badline/drives.rb +1 -0
  42. data/lib/badline/frontend/app.rb +1 -1
  43. data/lib/badline/frontend/boot.rb +20 -1
  44. data/lib/badline/frontend/controls.rb +23 -3
  45. data/lib/badline/frontend/gamepads.rb +10 -3
  46. data/lib/badline/frontend/keys.rb +88 -0
  47. data/lib/badline/frontend/media_slots.rb +1 -0
  48. data/lib/badline/frontend/menu/menu_dialogs.rb +15 -6
  49. data/lib/badline/frontend/menu/menu_media.rb +96 -19
  50. data/lib/badline/frontend/menu/menu_pages.rb +25 -7
  51. data/lib/badline/frontend/menu/menu_ports.rb +22 -1
  52. data/lib/badline/frontend/menu/pause_menu.rb +1 -0
  53. data/lib/badline/frontend/pet_keyboard.rb +124 -0
  54. data/lib/badline/frontend/player/player_controller.rb +11 -4
  55. data/lib/badline/frontend/screens.rb +2 -1
  56. data/lib/badline/frontend/timeline.rb +16 -9
  57. data/lib/badline/frontend.rb +1 -0
  58. data/lib/badline/kernal_trap/dos/writes.rb +3 -1
  59. data/lib/badline/kernal_trap/dos.rb +6 -1
  60. data/lib/badline/kernal_trap/frames.rb +117 -0
  61. data/lib/badline/kernal_trap/ieee.rb +148 -0
  62. data/lib/badline/kernal_trap/ieee_layout.rb +113 -0
  63. data/lib/badline/kernal_trap/keyed_state.rb +4 -4
  64. data/lib/badline/kernal_trap/routine.rb +3 -53
  65. data/lib/badline/kernal_trap/serial.rb +4 -102
  66. data/lib/badline/kernal_trap/steps.rb +64 -0
  67. data/lib/badline/kernal_trap.rb +4 -0
  68. data/lib/badline/machine/keyboard_buffer.rb +8 -0
  69. data/lib/badline/machine/settling.rb +1 -1
  70. data/lib/badline/machine.rb +37 -11
  71. data/lib/badline/media/extensions.rb +5 -2
  72. data/lib/badline/media/pet_media.rb +40 -0
  73. data/lib/badline/media/program.rb +14 -2
  74. data/lib/badline/media/true_drive.rb +7 -5
  75. data/lib/badline/media/vic20_media.rb +2 -2
  76. data/lib/badline/media.rb +36 -16
  77. data/lib/badline/options/family.rb +17 -6
  78. data/lib/badline/options/help.rb +23 -5
  79. data/lib/badline/options/option.rb +2 -1
  80. data/lib/badline/options/table.rb +28 -4
  81. data/lib/badline/options/validation.rb +117 -14
  82. data/lib/badline/options.rb +65 -21
  83. data/lib/badline/pet/bus/expansion.rb +106 -0
  84. data/lib/badline/pet/bus.rb +204 -0
  85. data/lib/badline/pet/canvas.rb +97 -0
  86. data/lib/badline/pet/cassettes.rb +63 -0
  87. data/lib/badline/pet/characters.rb +26 -0
  88. data/lib/badline/pet/cpu.rb +10 -0
  89. data/lib/badline/pet/crtc_video.rb +142 -0
  90. data/lib/badline/pet/discrete_video.rb +83 -0
  91. data/lib/badline/pet/ieee_ports.rb +66 -0
  92. data/lib/badline/pet/ieee_traps.rb +75 -0
  93. data/lib/badline/pet/keyboard_ports.rb +74 -0
  94. data/lib/badline/pet/keyed_modules.rb +85 -0
  95. data/lib/badline/pet/keyed_parts.rb +123 -0
  96. data/lib/badline/pet/keyed_state.rb +42 -0
  97. data/lib/badline/pet/model.rb +113 -0
  98. data/lib/badline/pet/rom_sets.rb +65 -0
  99. data/lib/badline/pet/sound.rb +128 -0
  100. data/lib/badline/pet/via.rb +10 -0
  101. data/lib/badline/pet/via_ports.rb +19 -0
  102. data/lib/badline/pet.rb +226 -0
  103. data/lib/badline/plus4/acia/frames.rb +55 -0
  104. data/lib/badline/plus4/acia.rb +276 -16
  105. data/lib/badline/plus4/bus.rb +181 -45
  106. data/lib/badline/plus4/keyed_modules.rb +22 -5
  107. data/lib/badline/plus4/keyed_parts.rb +33 -4
  108. data/lib/badline/plus4/keyed_state.rb +10 -5
  109. data/lib/badline/plus4/ram_expansion.rb +145 -0
  110. data/lib/badline/plus4/sid_card.rb +95 -0
  111. data/lib/badline/plus4/sound_mix.rb +51 -0
  112. data/lib/badline/plus4/tcbm_drive.rb +134 -0
  113. data/lib/badline/plus4/user_port.rb +11 -2
  114. data/lib/badline/plus4.rb +104 -22
  115. data/lib/badline/roms/README +146 -0
  116. data/lib/badline/roms/dos1551.rom +0 -0
  117. data/lib/badline/roms/pet/basic1.rom +0 -0
  118. data/lib/badline/roms/pet/basic2.rom +0 -0
  119. data/lib/badline/roms/pet/basic4.rom +0 -0
  120. data/lib/badline/roms/pet/characters1.rom +0 -0
  121. data/lib/badline/roms/pet/characters2.rom +0 -0
  122. data/lib/badline/roms/pet/editor1.rom +0 -0
  123. data/lib/badline/roms/pet/editor2-b.rom +0 -0
  124. data/lib/badline/roms/pet/editor2-n.rom +0 -0
  125. data/lib/badline/roms/pet/editor4-40-n-50hz.rom +0 -0
  126. data/lib/badline/roms/pet/editor4-40-n-60hz.rom +0 -0
  127. data/lib/badline/roms/pet/editor4-80-b-50hz-0283.rom +0 -0
  128. data/lib/badline/roms/pet/editor4-80-b-50hz.rom +0 -0
  129. data/lib/badline/roms/pet/editor4-80-b-60hz.rom +0 -0
  130. data/lib/badline/roms/pet/editor4-b.rom +0 -0
  131. data/lib/badline/roms/pet/editor4-n.rom +0 -0
  132. data/lib/badline/roms/pet/kernal1.rom +0 -0
  133. data/lib/badline/roms/pet/kernal2.rom +0 -0
  134. data/lib/badline/roms/pet/kernal4.rom +0 -0
  135. data/lib/badline/snapshot/container.rb +2 -0
  136. data/lib/badline/snapshot/field_doc/markdown.rb +1 -1
  137. data/lib/badline/snapshot/field_doc.rb +21 -6
  138. data/lib/badline/snapshot/image.rb +14 -7
  139. data/lib/badline/snapshot/pet_setup.rb +71 -0
  140. data/lib/badline/snapshot/plus4_setup.rb +52 -10
  141. data/lib/badline/snapshot/storage_setup.rb +7 -1
  142. data/lib/badline/snapshot.rb +9 -5
  143. data/lib/badline/storage/d80_image.rb +48 -0
  144. data/lib/badline/storage/d82_image.rb +21 -0
  145. data/lib/badline/storage/g64_image.rb +1 -1
  146. data/lib/badline/storage/tap.rb +16 -3
  147. data/lib/badline/storage.rb +2 -0
  148. data/lib/badline/support/pet_checkpoint.rb +38 -0
  149. data/lib/badline/timing.rb +5 -4
  150. data/lib/badline/version.rb +1 -1
  151. data/lib/badline/vic20/attachments.rb +7 -2
  152. data/lib/badline/vic20/bus/keyed_state.rb +5 -4
  153. data/lib/badline/vic20/bus.rb +5 -0
  154. data/lib/badline/vic20.rb +1 -1
  155. metadata +69 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dcc4aea1603a5dac88787b701529e7019573fa5bd3b66cdd31a6d4f071fb3ecf
4
- data.tar.gz: bc8de62e989822edd15ff2d59002a034c361c176e50a0e064a3482ff820b150a
3
+ metadata.gz: e262717ff30b8634c869b951cbb627fead4c6d4270cb0f9251cfadb567c0edef
4
+ data.tar.gz: 6c35c8a8313fe7de6de0d7df4a8436bebc160e1267e11132bd84c0be0abc50b0
5
5
  SHA512:
6
- metadata.gz: 88c53ecfb3d2322c4f2ed6cc99c58e3e5cdb9b135b9afaae85a183f95d23d1546c0c7d245547dfe968574849689508e0669dda8648c3a0cb123251672895d442
7
- data.tar.gz: 2d2d289ef46a002ff548fb7a219805a8c6fcbd555f469f4f8bb8eb87bc6895df48e83d8694ec262251d87997a2f2d325120f608f491df76ef9c47f83be1cc0e2
6
+ metadata.gz: b9de5e45e9ab8b0d8a18c98815599c6055f0fc1a44a2324f34f60753a3096d5c254edad42852e7bf0bf1507b1fb845512cca41117fb6f5f51988fa3a41be0204
7
+ data.tar.gz: 5102663a8eee7f811f9e88b81ff79948ad4f1011d790551a8d8bbba53de29c676f4055db0fe15a2e1085b0bbe3efee805e2db421ba5161b77c9abbaefb181623
data/CHANGELOG.md CHANGED
@@ -1,5 +1,107 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.16.0](https://github.com/elektronaut/badline/compare/v0.15.1...v0.16.0) (2026-10-17)
4
+
5
+
6
+ ### Features
7
+
8
+ * add the 6520 PIA ([329bf8c](https://github.com/elektronaut/badline/commit/329bf8c04a6f8cc666ea1dfded4ec1a8431e07cc))
9
+ * add the PET's IEEE trap layouts and keyboard buffer layouts ([f628ba2](https://github.com/elektronaut/badline/commit/f628ba26c661d1c539c28506e48a95504afd7fd3))
10
+ * answer the debug register at $8BFF on every PET ([76f47ab](https://github.com/elektronaut/badline/commit/76f47ab67f834eb89451fb95134fae2abcadde36))
11
+ * attach programs, disks and archives to the PET, .d80 and .d82 among them ([2094ee5](https://github.com/elektronaut/badline/commit/2094ee53ec3e94a1a7571d38b598212476cf738b))
12
+ * boot the PET to READY headless ([b86044a](https://github.com/elektronaut/badline/commit/b86044a149cde620b41eac3c5a77db252e68c10c))
13
+ * bundle the PET ROMs and refuse badline pet until it runs ([76591ff](https://github.com/elektronaut/badline/commit/76591ffc72c615f0c78649e4b29f0dc8e4a3775f))
14
+ * count the PET's CRTC to the cycle and paint its picture ([59a010f](https://github.com/elektronaut/badline/commit/59a010fc1e5250f543c796ab0de464241b28dcae))
15
+ * fit the 8032's other 50 Hz editor, 901474-04 dated 0283, with --editor 4-80-b-50hz-0283 ([b7b230f](https://github.com/elektronaut/badline/commit/b7b230f4032ba7145358cb60f1be1e370997c0e0))
16
+ * let any machine's timing share a window pixel between its dots ([55f04e8](https://github.com/elektronaut/badline/commit/55f04e86871423f1b0121a4570763f501cb08db1))
17
+ * paint the PET's discrete 40-column video ([2d4f5e6](https://github.com/elektronaut/badline/commit/2d4f5e6caac7c2a3d4e3abe5e8ef37185962dbc9))
18
+ * play and record tapes on the PET's two cassette ports ([aea1a9d](https://github.com/elektronaut/badline/commit/aea1a9de8008ceb576e006520234fa7dc6b4a5e3))
19
+ * play the PET's VIA CB2 as its sound ([cd24520](https://github.com/elektronaut/badline/commit/cd24520a8e87bce7938cae12d153e332f9be1f99))
20
+ * read and write 8050 and 8250 disk images ([2196736](https://github.com/elektronaut/badline/commit/2196736d0e9c84146ce259e322c991a14e1fe69d))
21
+ * run the PET and the CBM in the window with badline pet ([0ee8585](https://github.com/elektronaut/badline/commit/0ee8585ef6a2d789dbbbbf06af3a54a9f33fbbff))
22
+ * save and restore the PET in keyed snapshots ([1dcbb75](https://github.com/elektronaut/badline/commit/1dcbb75785ce70ca6de7b6596970ce06a2275a30))
23
+ * serve device 8 to the PET through traps on its IEEE-488 primitives ([7f72c7d](https://github.com/elektronaut/badline/commit/7f72c7d3d58e5520f32c62120a4ce0270f02893a))
24
+ * show the PET in the window, with its keys, memory and model in the pause menu ([7e90498](https://github.com/elektronaut/badline/commit/7e9049864015e511c3db8455b2d5d6749ffc6ea3))
25
+ * type on the PET's graphics and business keyboards by character from the window ([0797790](https://github.com/elektronaut/badline/commit/079779011880ffca5ecc7c67e6bcef9620147ca5))
26
+ * type the PET's shifted keys with Alt, and name its pause-menu page KEYBOARD ([22b3059](https://github.com/elektronaut/badline/commit/22b305966dd44bdd813af71c3bb5e0a4e2202761))
27
+ * wire the PET's key matrices and type into its keyboard buffer ([1f22475](https://github.com/elektronaut/badline/commit/1f22475b581ac95776a86c1dd27f2671afcfb90c))
28
+ * write PET tapes and read a tape's platform from its header ([29ccd99](https://github.com/elektronaut/badline/commit/29ccd99629bb98c311842628be39c298aab12eb9))
29
+
30
+
31
+ ### Bug Fixes
32
+
33
+ * keep the VIC-20's cartridge name in the machine and its snapshots ([4837ab1](https://github.com/elektronaut/badline/commit/4837ab10049309f39d1b5d3b2170e55ab9d21c76))
34
+ * move a 1551's TCBM interface with its DEV line ([f934bcf](https://github.com/elektronaut/badline/commit/f934bcf6cd2058a4528521fb1e14f75b7d15021c))
35
+ * record the Plus/4's true drive model in its snapshots ([9c8ddb1](https://github.com/elektronaut/badline/commit/9c8ddb1b355145382df4a2813a3e55769839f0c9))
36
+
37
+
38
+ ### Performance Improvements
39
+
40
+ * sweep only the lines the last PET CRTC frame showed ([026b26a](https://github.com/elektronaut/badline/commit/026b26afc97ed72f32b2e6517a8df18de5d863d1))
41
+
42
+ ## [0.15.1](https://github.com/elektronaut/badline/compare/v0.15.0...v0.15.1) (2026-10-12)
43
+
44
+
45
+ ### Features
46
+
47
+ * add the 1551 disk drive, booting its DOS headless ([db03667](https://github.com/elektronaut/badline/commit/db036672799acae2ea13a1b16780875547d74eb6))
48
+ * add the 1551 disk drive, booting its DOS headless ([1f4db55](https://github.com/elektronaut/badline/commit/1f4db555eeb86da755241870a40c75e5441f5894))
49
+ * emulate the Plus/4's 6551 ACIA ([8b1cc23](https://github.com/elektronaut/badline/commit/8b1cc236d7dc5c7e48c772c9256416c1011d2526))
50
+ * emulate the Plus/4's 6551 ACIA ([06bf40f](https://github.com/elektronaut/badline/commit/06bf40f1f618db8decb25fe4d95577a035e9e903))
51
+ * fit a Plus/4 or C16 with a Hannes or Csory RAM expansion ([14bc152](https://github.com/elektronaut/badline/commit/14bc15249914f4ecdb42212ab39d28dc4f2ee557))
52
+ * fit a Plus/4 or C16 with a Hannes or Csory RAM expansion ([85baeba](https://github.com/elektronaut/badline/commit/85baeba267ef6f8e0243444ecd849260a22588de))
53
+ * fit a Plus/4 or C16 with a SID card ([0ed886d](https://github.com/elektronaut/badline/commit/0ed886d5fe10e40223d9de330e38df8501bbbbfc))
54
+ * fit a Plus/4 or C16 with a SID card ([2ae2e19](https://github.com/elektronaut/badline/commit/2ae2e197f783465a8b85c74ca6c78afdc071a66c))
55
+ * machine_diff --family plus4 ([c479566](https://github.com/elektronaut/badline/commit/c479566180254a841d1b6e998089b8ca64ac6a48))
56
+ * machine_diff --family plus4 ([55702f1](https://github.com/elektronaut/badline/commit/55702f10deb8e4f3775d7387a531ef7dbf4a6834))
57
+ * make the 1551 the Plus/4's default true drive ([e3d3120](https://github.com/elektronaut/badline/commit/e3d312099478c71b59088ca4070cd839aabaac46))
58
+ * make the 1551 the Plus/4's default true drive ([e275808](https://github.com/elektronaut/badline/commit/e27580834142351c3bfb4a088b2128bc52885036))
59
+ * name the cartridge on the Expansion port page of every machine ([beab6e5](https://github.com/elektronaut/badline/commit/beab6e58a0aa9a374789645bb18e5c82d50fc0c8))
60
+ * name the cartridge on the Expansion port page of every machine ([6e08889](https://github.com/elektronaut/badline/commit/6e08889edc1de913289ddfd03b75d79b6c42d994))
61
+ * put a true 1551 on the Plus/4's TCBM with --drive-type 1551 ([1d0f9f4](https://github.com/elektronaut/badline/commit/1d0f9f42f622e5e00db1c63dd8413fb7484dd65a))
62
+ * put a true 1551 on the Plus/4's TCBM with --drive-type 1551 ([ba8b9a3](https://github.com/elektronaut/badline/commit/ba8b9a3816300840f6b6fe8138427b81814f3957))
63
+ * put the Plus/4's SID card at $FE80 with --sid-card-address ([da597a2](https://github.com/elektronaut/badline/commit/da597a240f77a870e610f3c186d1afd4f234695a))
64
+ * put the Plus/4's SID card at $FE80 with --sid-card-address ([893c5eb](https://github.com/elektronaut/badline/commit/893c5eb08ca1617c5bced97501e9b8bcae443bb5))
65
+ * save a 1551 in the Plus/4's snapshots ([8c2edad](https://github.com/elektronaut/badline/commit/8c2edadd246985d294b68ae5f46f572691d7045c))
66
+ * save a 1551 in the Plus/4's snapshots ([06313fe](https://github.com/elektronaut/badline/commit/06313fe5de493ff8d92047ea4b2adc815d84d7b7))
67
+
68
+
69
+ ### Bug Fixes
70
+
71
+ * clock the extra SIDs in C64#cycle! ([7fc8b71](https://github.com/elektronaut/badline/commit/7fc8b719702b90b43df822162c7fde48d1205409))
72
+ * clock the extra SIDs in C64#cycle! ([016a9c4](https://github.com/elektronaut/badline/commit/016a9c4517be052db809bfc42345eedf296f3fbc))
73
+ * read the register log's seed by index for Spinel ([d9b3c43](https://github.com/elektronaut/badline/commit/d9b3c43ef51c81faf471018a85721753450949e0))
74
+ * refuse a .crt with a chip in an unmapped bank on the command line ([15b4060](https://github.com/elektronaut/badline/commit/15b4060afe320df465da5f767c21d69ccf93d3bc))
75
+ * refuse a .crt with a chip in an unmapped bank on the command line ([c8c51fc](https://github.com/elektronaut/badline/commit/c8c51fc2f98deae8eaad1c671987c5b726cb4ba5))
76
+ * refuse a cartridge with a chip in a bank the machine doesn't map ([c2bee2a](https://github.com/elektronaut/badline/commit/c2bee2a4ee01b5959a465b7d72034a9be7ec3bf3))
77
+ * refuse a cartridge with a chip in a bank the machine doesn't map ([d08f37e](https://github.com/elektronaut/badline/commit/d08f37e2b2ff0207b1173aee2f467e4f9e71f685))
78
+ * save the datasette's recording state in snapshots ([ba8e5e8](https://github.com/elektronaut/badline/commit/ba8e5e8dbcf088449324d66f30f8bbfe15e80210))
79
+ * save the datasette's recording state in snapshots ([b155546](https://github.com/elektronaut/badline/commit/b1555467f70a1d2db4117ab43e623f8a060a4a3f))
80
+ * take --frames in the SID player ([b9a54f3](https://github.com/elektronaut/badline/commit/b9a54f3c7bb84edd67c69ee38efb4f5f79347760))
81
+ * take --frames in the SID player ([3483684](https://github.com/elektronaut/badline/commit/3483684fe8efdf2b828d85db98c9e4c1667293a4))
82
+ * take a Plus/4 .bin cartridge from Quick open and drag and drop ([214dcd6](https://github.com/elektronaut/badline/commit/214dcd63bc48956d0f2139d89bab63613dde78d7))
83
+ * take a Plus/4 .bin cartridge from Quick open and drag and drop ([32ec8d0](https://github.com/elektronaut/badline/commit/32ec8d0deb54000a1c2b956a02ad26b53ef2cf6d))
84
+ * type ACIA#feed's bytes for Spinel ([32b9f72](https://github.com/elektronaut/badline/commit/32b9f72a7ad24cd862531d19e545e117c7e8e340))
85
+
86
+
87
+ ### Performance Improvements
88
+
89
+ * check the init threshold and the ACIA with one compare ([b0050a7](https://github.com/elektronaut/badline/commit/b0050a7a4716e21551882f10c0811a6f0284686a))
90
+ * count the SID card's cycles when it is touched ([d0cec9c](https://github.com/elektronaut/badline/commit/d0cec9c9d9144bb2303d0cba0b182dcf705d1b32))
91
+ * look in on the ACIA's IRQ only when it is due ([d099091](https://github.com/elektronaut/badline/commit/d09909138087a305ce59384dafbece7ef08f340a))
92
+ * sleep the 1551 through its idle loop ([3fabf2a](https://github.com/elektronaut/badline/commit/3fabf2ab6f866bf088682b14e5f04e4dd9054d29))
93
+ * sleep the 1551 through its idle loop ([8d99fa3](https://github.com/elektronaut/badline/commit/8d99fa3ac22f862a51e967dc5a69471dece782da))
94
+
95
+
96
+ ### Reverts
97
+
98
+ * find the longest G64 track with a splat again ([31a3df2](https://github.com/elektronaut/badline/commit/31a3df2d35ab79a072a46213d5996068eaa2d793))
99
+
100
+
101
+ ### Miscellaneous Chores
102
+
103
+ * release 0.15.1 ([23586fb](https://github.com/elektronaut/badline/commit/23586fbc26b2132c4a8afe04d44cbeaed6b0eb12))
104
+
3
105
  ## [0.15.0](https://github.com/elektronaut/badline/compare/v0.14.0...v0.15.0) (2026-10-12)
4
106
 
5
107
 
data/CLAUDE.md CHANGED
@@ -14,8 +14,8 @@ directory: `chips/vic.rb` is `Badline::Chips::VIC`.
14
14
  the VIC holds BA low). `c64/` holds the rest of the C64's board:
15
15
  `c64/bus.rb` handles banking and page-table dispatch, and
16
16
  `c64/banked_ram.rb` and `c64/banked_ram/` the +60K and +256K boards
17
- that bank in extra RAM through `$D100`. `vic20.rb` and `vic20/`, and
18
- `c128.rb` and `c128/`, are the other two families, and `machine.rb`
17
+ that bank in extra RAM through `$D100`. `vic20.rb` and `vic20/`, `c128.rb` and `c128/`,
18
+ `plus4.rb` and `plus4/`, and `pet.rb` and `pet/` are the other families, and `machine.rb`
19
19
  builds each by name. Every family reads and writes memory as its CPU
20
20
  sees it with `peek` and `poke`
21
21
  - **CPU**: `chips/cpu.rb` and `chips/cpu/`: the 6502 core
@@ -25,10 +25,11 @@ directory: `chips/vic.rb` is `Badline::Chips::VIC`.
25
25
  C128's Z80
26
26
  - **VIC-II**: `chips/vic.rb` and `chips/vic/`, covering the sequencer,
27
27
  sprites, graphics modes, border and register timing. `chips/vic_i.rb`
28
- is the VIC-20's VIC-I and its sound, and `chips/vdc.rb` the C128's VDC
28
+ is the VIC-20's VIC-I and its sound, `chips/vdc.rb` the C128's VDC,
29
+ and `chips/crtc.rb` the PET's 6545 CRTC
29
30
  - **CIA**: `chips/cia.rb` and `chips/cia/` (timers, serial and the TOD
30
- clock, `time_of_day.rb`). `chips/via.rb` is the 6522 of the VIC-20 and
31
- the drives
31
+ clock, `time_of_day.rb`). `chips/via.rb` is the 6522 of the VIC-20, the
32
+ drives and the PET, and `chips/pia.rb` the PET's 6520 PIA
32
33
  - **REU**: `c64/reu.rb` and `c64/reu/`, the RAM Expansion Unit's
33
34
  registers and its DMA, which `C64#cycle!` clocks in place of the CPU
34
35
  while it holds the bus
@@ -70,7 +71,7 @@ file: `core.rb` requires their members one by one.
70
71
  | SingleStepTests 65x02 | `rake test` (100 sampled cases per opcode) | CPU, per-cycle bus traces |
71
72
  | SingleStepTests z80 | `rake test` (the first 100 cases per opcode, `Z80_SAMPLE=all` for all 1,604,000) | `Z80`: registers, flags, ports and the bus pins on every T-state |
72
73
  | Wolfgang Lorenz suite | `bin/lorenz` | CPU, CIA, interrupts; its plus4 build with `--plus4`: the CPU on the 264's bus, the TED's clock, DMA, timers and interrupt |
73
- | VICE testbench | `bin/testbench <subtree>` | `VICII/`, `CIA/`, `interrupts/`, `CPU/`, cartridges with `--carts`, the true 1541 drive with `--drive`, the VIC-20 with `--vic20`, the C128 in C64 mode with `--c128c64`, in C128 mode with `--c128`, and its Z80 with `--c128-z80`, the Plus/4 with `--plus4` and the C16 with `--c16` |
74
+ | VICE testbench | `bin/testbench <subtree>` | `VICII/`, `CIA/`, `interrupts/`, `CPU/`, cartridges with `--carts`, the true 1541 drive with `--drive`, the VIC-20 with `--vic20`, the C128 in C64 mode with `--c128c64`, in C128 mode with `--c128`, and its Z80 with `--c128-z80`, the Plus/4 with `--plus4`, the C16 with `--c16`, and the PET with `--pet` (8096) and `--pet-discrete` (2001, 3032) |
74
75
  | VICE SID testprogs | `bin/sidtests` | SID |
75
76
  | Drive scenarios | `bin/drive_scenarios` | The true 1541 running the DOS ROM: save, format, the error channel, idle, write protect and autostart; the `plus4-*` rows on the Plus/4 and C16, with the 1541 and 1581 on their serial bus and a tape saved and loaded back on the datasette |
76
77
  | CIA offline grids | `bundle exec rspec --tag slow spec/badline/chips/cia` | CIA timers and shift register, against a bare CIA in about 2 min |
@@ -239,6 +240,13 @@ the rows your change can't reach tell you nothing about it.
239
240
  - For a change whose reach you can't bound to a set of filters, such as
240
241
  reordering `C64#cycle!` or changing the LOAD trap every suite loads
241
242
  through, push and let CI run the suites
243
+ - Each Spinel harness compiles only the code its own entry point reaches.
244
+ A method nothing in a harness calls, such as a host-side API only the
245
+ window uses, is compiled only by `native/badline.rb`, with untyped
246
+ arguments, and can fail there alone. A change that adds such a method
247
+ builds the native binary locally (`rake native:build`; on macOS with
248
+ `SPINEL_CC="cc -Wno-nullability-completeness"`) before it's pushed, or
249
+ types its arguments in `spinel/sig`
242
250
  - The Regression workflow runs the suites on CRuby, started by hand from
243
251
  the Actions tab, for a person checking that CRuby and Spinel agree.
244
252
  Agents don't start it
@@ -267,7 +275,7 @@ serial bus, its media, the CPU port or the datasette.
267
275
  Its tests run one at a time as the C64's do, with
268
276
  `ruby --yjit bin/lorenz --plus4 --resume <test> --stop-after <test>`; the C128 (`c128.rb`, `c128/`), or
269
277
  the VIC-IIe, CPU or PLA code it shares with the C64 → `testbench-c128c64`
270
- (`bin/testbench --c128c64`); the C128's Z80, MMU or hand-over → `testbench-c128-z80` (`bin/testbench --c128-z80`) and `testbench-c128`; SID → `sid`, plus `sid-8580` for anything the 8580
278
+ (`bin/testbench --c128c64`); the PET (`pet.rb`, `pet/`), its 6520 PIA (`chips/pia.rb`) or its CRTC (`chips/crtc.rb`) → `testbench-pet` (`bin/testbench --pet`) and `testbench-pet-discrete` (`bin/testbench --pet-discrete`); the C128's Z80, MMU or hand-over → `testbench-c128-z80` (`bin/testbench --c128-z80`) and `testbench-c128`; SID → `sid`, plus `sid-8580` for anything the 8580
271
279
  model reaches (`bin/sidtests --sid 8580`). Leave the Lorenz chain to CI,
272
280
  unless your code has a rule in `doc/pinned-behaviour.md` that names Lorenz
273
281
  tests: the interrupt polling, CPU port and CIA timer rules. Run just the
data/README.md CHANGED
@@ -13,7 +13,7 @@ are modelled at the cycle level.
13
13
  It runs programs, disk and tape images, cartridges and SID tunes, and
14
14
  the SDL2 front end supports the keyboard, joysticks, game controllers,
15
15
  paddles and a 1351 mouse. It also runs a PAL VIC-20, as
16
- `badline vic20`, the C128, in C128 mode on 40 or 80 columns and in C64 mode, as `badline c128`, and the Plus/4, the C16 and the C116, as `badline plus4`. See [What's emulated](#whats-emulated) for the details.
16
+ `badline vic20`, the C128, in C128 mode on 40 or 80 columns and in C64 mode, as `badline c128`, the Plus/4, the C16 and the C116, as `badline plus4`, and the PET and CBM, as `badline pet`. See [What's emulated](#whats-emulated) for the details.
17
17
 
18
18
  It comes in two builds of the same emulator:
19
19
 
@@ -70,7 +70,8 @@ from it.
70
70
  The first argument can name the machine, as in `badline c64 game.prg`.
71
71
  The C64 is the default, and `--model` picks which C64. See
72
72
  [The VIC-20](#the-vic-20) for `badline vic20`, [The C128](#the-c128)
73
- for `badline c128` and [The Plus/4](#the-plus4) for `badline plus4`.
73
+ for `badline c128`, [The Plus/4](#the-plus4) for `badline plus4` and
74
+ [The PET](#the-pet) for `badline pet`.
74
75
 
75
76
  `badline-ruby` takes the same media and the same options, with the
76
77
  differences noted in the table. `--help` lists the options for either.
@@ -81,13 +82,19 @@ differences noted in the table. `--help` lists the options for either.
81
82
  | --- | --- |
82
83
  | `--no-autostart` | Attach the media and stop at `READY.`, so you can type the `LOAD` yourself |
83
84
  | `--writable` | Let the machine write to disk images. Without it, a disk goes in write-protected: the drive reports `26,WRITE PROTECT ON` for any write and the image file stays as it was |
84
- | `--true-drive` | Put an emulated 1541 on device 8 instead of the KERNAL traps. See [Media](#media) |
85
+ | `--true-drive` | Put an emulated 1541 on device 8 instead of the KERNAL traps, or a 1551 on the Plus/4. See [Media](#media) |
86
+ | `--drive-type 1541` | On the Plus/4, make the true drive on device 8 an emulated 1541 on the serial bus in place of the 1551. It implies `--true-drive`. See [The Plus/4](#the-plus4) |
85
87
  | `-s`, `--subtune N` | Pick a subtune of a `.sid` file, counting from 1 |
86
88
  | `--sid 6581`, `--sid 8580` | Fit the older or newer SID. `--sid auto`, the default, takes a `.sid` tune's own |
87
- | `--ram SIZE` | Give a VIC-20 the RAM expansion `SIZE`: `unexpanded`, `3k`, `8k`, `16k`, `24k`, `32k` or `all`. Without it, the VIC-20 gets the expansion its media needs. See [The VIC-20](#the-vic-20). On the Plus/4, `16k`, `32k` or `64k` of RAM in place of the model's own |
89
+ | `--ram SIZE` | Give a VIC-20 the RAM expansion `SIZE`: `unexpanded`, `3k`, `8k`, `16k`, `24k`, `32k` or `all`. Without it, the VIC-20 gets the expansion its media needs. See [The VIC-20](#the-vic-20). On the Plus/4, `16k`, `32k` or `64k` of RAM in place of the model's own, and on the PET `4k`, `8k`, `16k` or `32k` |
90
+ | `--60hz` | Run a CRTC PET's 60 Hz editor in place of its 50 Hz one. See [The PET](#the-pet) |
91
+ | `--basic VERSION`, `--editor NAME` | Fit a PET with an upgrade ROM its board takes: BASIC `1`, `2` or `4`, or an editor. See [The PET](#the-pet) |
88
92
  | `--c1lo FILE`, `--c1hi FILE`, `--c2lo FILE`, `--c2hi FILE` | Put a raw `.bin` ROM image in one of the Plus/4's cartridge slots: cartridge 1 or 2, low (`$8000`) or high (`$C000`). See [The Plus/4](#the-plus4) |
93
+ | `--sid-card 6581`, `--sid-card 8580` | Fit a Plus/4 or C16 with a SID card at `$FD40`. See [The Plus/4](#the-plus4) |
94
+ | `--sid-card-address fd40`, `--sid-card-address fe80` | Put the SID card at `$FD40` (the default) or at `$FE80` |
95
+ | `--ram-expansion NAME` | Fit a Plus/4 or C16 with a RAM expansion: `hannes256`, `hannes1m` or `csory256`. See [The Plus/4](#the-plus4) |
89
96
  | `--reu SIZE` | Plug in a RAM Expansion Unit of `SIZE` K: 128, 256, 512 (a 1750) or up to 16384 |
90
- | `--model NAME` | Run another model of the machine, named as in VICE. For the C64: `c64` (the default, a PAL C64 with the 6569 VIC-II, 6526 CIAs and the 6581 SID), `c64c` (the PAL C64C, with the 8565, 6526As and the 8580), `ntsc` (the 6567R8), `newntsc` (the NTSC C64C, with the 8562, 6526As and the 8580), `oldntsc` (the first NTSC C64s' 6567R56A), `drean` (the Drean C64 of Argentina, PAL-N with the 6572), `sx64` (the portable SX-64, with its own KERNAL and no datasette), `pet64` (the PET 64 or Educator 64, a PAL C64 in a PET's case with its own KERNAL and a green monochrome monitor) `c64gs` (the C64GS games console, a PAL C64C with its own BASIC and KERNAL, and no keyboard or datasette) or `ultimax` (the MAX Machine of Japan, NTSC with 2K of RAM, one CIA and no ROMs, which runs only a cartridge). `--sid` or a `.sid` tune's own SID takes the model's place. The VIC-20, the C128 and the Plus/4 have models of their own: see their sections |
97
+ | `--model NAME` | Run another model of the machine, named as in VICE. For the C64: `c64` (the default, a PAL C64 with the 6569 VIC-II, 6526 CIAs and the 6581 SID), `c64c` (the PAL C64C, with the 8565, 6526As and the 8580), `ntsc` (the 6567R8), `newntsc` (the NTSC C64C, with the 8562, 6526As and the 8580), `oldntsc` (the first NTSC C64s' 6567R56A), `drean` (the Drean C64 of Argentina, PAL-N with the 6572), `sx64` (the portable SX-64, with its own KERNAL and no datasette), `pet64` (the PET 64 or Educator 64, a PAL C64 in a PET's case with its own KERNAL and a green monochrome monitor) `c64gs` (the C64GS games console, a PAL C64C with its own BASIC and KERNAL, and no keyboard or datasette) or `ultimax` (the MAX Machine of Japan, NTSC with 2K of RAM, one CIA and no ROMs, which runs only a cartridge). `--sid` or a `.sid` tune's own SID takes the model's place. The VIC-20, the C128, the Plus/4 and the PET have models of their own: see their sections |
91
98
  | `--ntsc` | Run an NTSC C64, as `--model ntsc` does |
92
99
  | `--c64` | Start a C128 in C64 mode, holding `C=` at power-on. See [The C128](#the-c128) |
93
100
  | `--no-sound` | Don't play the SID (`badline` only, where sound is on by default) |
@@ -102,7 +109,7 @@ differences noted in the table. `--help` lists the options for either.
102
109
 
103
110
  | Option | Effect |
104
111
  | --- | --- |
105
- | `--frames N` | Quit after N frames |
112
+ | `--frames N` | Quit after N frames, in the SID player as in the machine's window |
106
113
  | `--unpaced` | Run as fast as it can, without vsync or pacing |
107
114
  | `--at FRAME:EVENT` | Press keys, type, swap media, open the pause menu or take a screenshot once `FRAME` frames have run |
108
115
  | `--script FILE` | Run the events in `FILE`, one `FRAME:EVENT` a line |
@@ -253,13 +260,95 @@ as xplus4's options do:
253
260
  badline plus4 --c1lo game-low.bin --c1hi game-high.bin
254
261
  ```
255
262
 
256
- Disks go through the KERNAL traps or, with `--true-drive`, a 1541 or a
257
- 1581 on the serial bus. There is no 1551 yet. The pause menu's Power
258
- page names the model and its RAM, and its Expansion port page shows the
259
- slots that hold a cartridge and takes them all out. `F11` and the
263
+ `--sid-card 6581` or `--sid-card 8580` fits a SID card, as third
264
+ parties built for the 264s, with its SID at `$FD40`-`$FD5F`. The card
265
+ clocks the SID at the TED's single clock, 886,724 Hz on PAL, so a C64
266
+ tune plays about a semitone flat, as it did on those cards. Its sound
267
+ plays with the TED's, and the Sound page swaps its SID's model.
268
+ `--sid-card-address fe80` puts the SID at `$FE80`-`$FE9F` instead, as
269
+ Csory's card does, beside a 1551's TCBM interface at `$FEC0`.
270
+
271
+ `--ram-expansion hannes256` or `hannes1m` fits Hannes's 256K or 1M RAM
272
+ expansion, which banks 64K at a time through its register at `$FD16`,
273
+ above `$1000` or `$4000`, with the TED fetching from the CPU's bank or
274
+ the standard one. `csory256` fits the 256K board with Csory's mapping
275
+ as well, which puts one of 16 blocks of 16K in a window that `$FD15`
276
+ picks. Each needs 64K of the machine's own, and a C16 gets that much.
277
+
278
+ Disks go through the KERNAL traps or, with `--true-drive`, a 1551 on
279
+ device 8, on TCBM, the parallel cable to its interface in the expansion
280
+ port, on the C16 as on the Plus/4. `--drive-type 1541` puts a 1541 on
281
+ the serial bus there instead, and a `.d81` goes in a 1581 on the serial
282
+ bus. The pause menu's Power
283
+ page names the model, its RAM and a RAM expansion, and its Expansion port page names the
284
+ cartridges in, or the slot of one a snapshot put in, and takes them all
285
+ out. `F11` and the
260
286
  Snapshots page save it as they do the others, but not for VICE.
261
287
  [Input](#input) lists its keys.
262
288
 
289
+ ## The PET
290
+
291
+ `badline pet` runs a CBM 8032, with BASIC 4 and 80 columns on a green
292
+ screen, and takes programs, disks and tapes:
293
+
294
+ ```sh
295
+ badline pet # READY., in BASIC 4
296
+ badline pet game.prg # Load and run a program
297
+ badline pet game.d64 # Mount a disk image as device 8 and load it
298
+ badline pet game.d82 # The same with an 8250's disk
299
+ badline pet game.tap # Insert a tape and load it
300
+ badline pet --model 2001 # The first PET, with BASIC 1
301
+ ```
302
+
303
+ `--model` picks the machine: `8032` (the default, 32K, 80 columns and
304
+ the business keyboard), `8096` (an 8032 with the 64K board at `$FFF0`),
305
+ `4032` (40 columns on a CRTC and the graphics keyboard), `3032` (the
306
+ discrete 40-column board with BASIC 2), `3032b` (the same with the
307
+ business keyboard) and `2001` (8K, BASIC 1 and the chiclet keyboard).
308
+ `--ram 4k`, `8k` or `16k` fits less RAM in place of the model's own, as
309
+ the 3008, 3016 and 4016 had.
310
+
311
+ The 4032, 8032 and 8096 run their 50 Hz editor, and `--60hz` their
312
+ 60 Hz one. The others always run at 60 Hz. `--basic` fits the upgrade
313
+ ROMs Commodore sold, with the editor that goes with them: BASIC 2 for the
314
+ 2001, and BASIC 4 for the 3032 and the 3032b. `--editor` names the editor
315
+ instead, among those the board and its BASIC take. Each name is the
316
+ BASIC, the keyboard, `n` for graphics or `b` for business, and on a CRTC
317
+ board the columns and the frame rate: `1`, `2-n`, `2-b`, `4-n`, `4-b`,
318
+ `4-40-n-50hz`, `4-40-n-60hz`, `4-80-b-50hz`, `4-80-b-50hz-0283` and
319
+ `4-80-b-60hz`.
320
+
321
+ The 8032 and the 8096 take two 50 Hz editors, both 901474-04 and read
322
+ from different chips. `4-80-b-50hz`, the default, runs lines of 50
323
+ cycles, 400 to a frame. `4-80-b-50hz-0283`, the chip dated 0283, runs
324
+ lines of 64 cycles, 313 to a frame, with the screen's rows a scanline
325
+ closer together and lower down. Both boot to the same READY.
326
+
327
+ ```sh
328
+ badline pet --model 2001 --basic 2 # A 2001 with BASIC 2
329
+ badline pet --model 3032 --basic 4 # A 3032 with BASIC 4, without a CRTC
330
+ badline pet --editor 4-80-b-60hz # An 8032 at 60 Hz, as --60hz runs it
331
+ badline pet --editor 4-80-b-50hz-0283 # An 8032 with the other 50 Hz editor
332
+ ```
333
+
334
+ BASIC 1, on the 2001, can't LOAD from a disk drive: its own ROM breaks
335
+ the transfer, so `LOAD"NAME",8` finds the file and loads nothing. A
336
+ disk given to `badline` still starts its first program on a 2001, which
337
+ goes into memory as a program file does. `--basic 2`, the upgrade
338
+ Commodore sold, loads from disk.
339
+
340
+ A program loads at the start of BASIC, `$0401`, and runs. A `.d80`, a
341
+ `.d82` or a tape made for the PET starts a PET without `pet`, but a
342
+ program that loads at `$0401` starts a C64, since a VIC-20 with 3K loads
343
+ there too. Disks go through the KERNAL traps on the IEEE-488 bus as
344
+ device 8, and tapes play on cassette port 1. The keys type what the host's
345
+ keys type, on either keyboard, and `Alt` adds the PET's `SHIFT`:
346
+ [Input](#input) lists the rest. The pause
347
+ menu's Power page names the model, its RAM and its frame rate, and its
348
+ Expansion port page its RAM and the 8096's 64K board. The PET has no
349
+ joysticks. `F11` and the Snapshots page save it as they do the others,
350
+ but not for VICE.
351
+
263
352
  ## Snapshots
264
353
 
265
354
  `F11` quicksaves the whole machine to the next of five slots in
@@ -326,6 +415,30 @@ and put their own here:
326
415
  They have no `RESTORE`, `←` or `↑` key, so `Page Up`, `` ` `` and `]`
327
416
  press nothing.
328
417
 
418
+ The PET types the characters on the host's keys, so Shift and `'` type
419
+ `"` on the graphics keyboard, where `"` has a key of its own, and on the
420
+ business keyboard, where it's `SHIFT` and `2`. Shift with a letter types
421
+ the graphics character on its key. Either `Alt` with a key presses the
422
+ PET's `SHIFT` and the key its unshifted character is on, so `Alt` and
423
+ `'` type the graphics character on the graphics keyboard's `'` key, and
424
+ on the business keyboard the character `SHIFT` gives that key. The keys
425
+ without a character are here, with the pause menu's Keyboard page
426
+ listing them too:
427
+
428
+ | PET | Host |
429
+ |-----|------|
430
+ | `RUN/STOP` | `Page Down`, or `Escape` on the graphics keyboard |
431
+ | `ESC` | `Escape`, on the business keyboard |
432
+ | `CLR/HOME` | `Home` |
433
+ | `INST/DEL` | `Backspace` |
434
+ | `RVS` | `Ctrl` |
435
+ | `CRSR ⇔` / `CRSR ⇕` | `Left`, `Right` / `Up`, `Down`, with `SHIFT` where they go left or up |
436
+ | `↑` / `←` | `^` / `_` or `` ` `` |
437
+ | `TAB`, `REPEAT` | `Tab`, `Page Up`, on the business keyboard |
438
+ | Keypad | The keypad |
439
+
440
+ On the PET `Tab` is a key, since there are no joysticks to switch to.
441
+
329
442
  `Tab` switches the keys between the C64 keyboard and the joysticks. The
330
443
  window title shows where they go, and any device plugged into a control
331
444
  port:
@@ -368,10 +481,10 @@ too.
368
481
  | Snapshots | Quicksave, save under a name, load a named save, and the latest quicksaves and autosaves |
369
482
  | Drive 8 | The disk: insert, eject, the previous or next disk of its set, and whether it's writable |
370
483
  | Datasette | The tape: insert, eject, PLAY and REWIND |
371
- | Expansion port | The cartridge: insert, remove, and its freeze button if it has one. On the Plus/4, the slots that hold one |
372
- | Ports | The device in each control port, and where the keys go |
484
+ | Expansion port | The cartridge's name: a `.crt`'s own, or a raw image's file name. Insert, remove, and its freeze button if it has one. On the VIC-20, the cartridge and the RAM expansion |
485
+ | Ports | The device in each control port, and where the keys go. On the PET, Keyboard: where its keys are |
373
486
  | Sound | Mute, and the SID's model |
374
- | Power | Reset, power cycle and quit, on a C128 its model and mode, and on a Plus/4 its model and RAM |
487
+ | Power | Reset, power cycle and quit, on a C128 its model and mode, and on a Plus/4 or a PET its model and RAM |
375
488
 
376
489
  INSERT opens a file browser. A disk's set is the `.m3u` or `.vfl` list it
377
490
  was opened from, or one in its folder that lists it. Without one, it comes
@@ -384,7 +497,9 @@ inserting or removing a cartridge does, since each power cycles the
384
497
  machine.
385
498
 
386
499
  A disk, list of disks or tape dropped on the window goes into its drive. A cartridge,
387
- program or `.sid` dropped on it opens the menu to ask first.
500
+ program or `.sid` dropped on it opens the menu to ask first. On the Plus/4, a
501
+ `.bin` ROM image dropped or opened with Quick open is a cartridge, and goes
502
+ in cartridge 1 as it does from the command line.
388
503
 
389
504
  ## What's emulated
390
505
 
@@ -415,8 +530,16 @@ program or `.sid` dropped on it opens the menu to ask first.
415
530
  timers and the CPU's single and double clock, 16K to 64K of RAM, ROM
416
531
  banking with the 3-plus-1 function ROMs, the keyboard and both
417
532
  joysticks, cartridges in both slots, the datasette and the serial bus
418
- to device 8, PAL and NTSC (`badline plus4`). The ACIA's registers are
419
- there but send and receive nothing.
533
+ to device 8, PAL and NTSC (`badline plus4`). The 6551 ACIA sends and
534
+ receives at its baud rates, with nothing on the user port; Ruby code
535
+ driving the machine can plug in a terminal, whose bytes it feeds and
536
+ drains, or a loopback plug (`Plus4::ACIA#plug`).
537
+ - **PET and CBM**: the 2001, 3032, 3032b, 4032, 8032 and 8096, with
538
+ BASIC 1, 2 or 4, the discrete video and the 6545 CRTC on 40 and 80
539
+ columns, both 6520 PIAs and the 6522 VIA, the graphics and business
540
+ keyboards, the sound on the VIA's CB2, the 8096's 64K board, both
541
+ cassette ports and device 8 on the IEEE-488 bus through the KERNAL
542
+ traps, `.d80` and `.d82` among its disks (`badline pet`).
420
543
  - **1541**: an emulated drive running its own DOS (`--true-drive`).
421
544
  - **1571**: the C128D's drive running DOS 3.0, in 1541 mode and in 1571
422
545
  mode at 2 MHz with both sides of a `.d71` or `.g71`, and fast serial
@@ -424,6 +547,9 @@ program or `.sid` dropped on it opens the menu to ask first.
424
547
  - **1581**: the 3.5" drive running its own DOS on its WD1772 and 8520,
425
548
  reading and writing `.d81` images, on the C64, the VIC-20, the C128 and the Plus/4
426
549
  (`--true-drive` with a `.d81`).
550
+ - **1551**: the 264 series' parallel drive, its 6510T running its own DOS
551
+ at 2 MHz with the 1541's mechanism, on TCBM to a Plus/4 or a C16
552
+ (`badline plus4 --true-drive`).
427
553
  - **Cartridges**: standard 8K, 16K and Ultimax, Simons' BASIC, Ocean,
428
554
  Fun Play / Power Play, Super Games, Epyx FastLoad, Westermann
429
555
  Learning, Rex Utility, C64 Game System / System 3, Dinamic, Zaxxon /
data/doc/media.md CHANGED
@@ -34,6 +34,10 @@ or directories. Loading runs at the speed of a real 1541, and the
34
34
  drive's red activity LED and green power LED light in the bottom right
35
35
  corner of the border. A 1581 flashes its power LED after an error.
36
36
 
37
+ On the Plus/4 and the C16, `--true-drive` puts an emulated 1551 there
38
+ instead, on TCBM, the parallel cable to its interface in the expansion
39
+ port, and `--drive-type 1541` a 1541 on the serial bus.
40
+
37
41
  A `.g64` holds the disk's raw GCR, half tracks and all, so copy
38
42
  protection and fast loaders that read it work.
39
43
 
@@ -99,6 +103,21 @@ the entries after a `UNIT 8` line, or before any `UNIT` line, count.
99
103
  `Media.attach` and the command line take a list as media and attach its
100
104
  first disk.
101
105
 
106
+ ## Recording to tape
107
+
108
+ From Ruby, a blank tape made with
109
+ `Badline::Storage::TAP.create(path, platform:)` (0 for the C64, 1 for
110
+ the VIC-20, 2 for the Plus/4 and the C16) goes in the datasette with
111
+ `computer.datasette.insert`, `record!` presses RECORD and PLAY, and
112
+ `stop!` lets them up and writes the tape to its file. The C64 and the
113
+ VIC-20 record version 1 TAPs, and the Plus/4 and the C16 version 2 TAPs
114
+ of half waves.
115
+
116
+ A program SAVEd that way on the C64 loads and runs in VICE's x64sc, on
117
+ the VIC-20 in xvic, and on the Plus/4 or the C16 in xplus4 as a Plus/4.
118
+ Neither the Plus/4's tape nor the C16's ran on xplus4's C16 model.
119
+ Checked with VICE 3.10.
120
+
102
121
  ## The light pen
103
122
 
104
123
  Control port 1's fire line is also the VIC-II's light pen input, so
@@ -48,6 +48,8 @@ only catches the rows that happen to move.
48
48
  - [SID data bus](#sid-data-bus)
49
49
  - [SID envelope](#sid-envelope)
50
50
  - [`.sid` tune banking](#sid-tune-banking)
51
+ - [PET discrete video](#pet-discrete-video)
52
+ - [PET CRTC](#pet-crtc)
51
53
 
52
54
  ## CPU interrupt recognition
53
55
 
@@ -2162,3 +2164,68 @@ testprogs named.
2162
2164
  in `$19` and goes silent when BASIC writes `$0a` there.
2163
2165
  - Spec guard:
2164
2166
  [`sid_tune/file/driver_spec.rb`](../spec/badline/sid_tune/file/driver_spec.rb).
2167
+
2168
+ ## PET discrete video
2169
+
2170
+ - The 2001's and 3000 series' frame is 260 lines of 64 cycles, 16,640
2171
+ cycles, and the vertical drive line is low for 3,840 of them, 60 lines.
2172
+ - Pinned by xpet's 2001 and 3032 as a black box: the falling edges of
2173
+ VIA PB5, timed with VIA T1 over 64 frames, come 16,640 cycles apart,
2174
+ each low for 3,840. Nothing checks the 64-cycle line itself.
2175
+ - Spec guard: *the vertical drive line* in
2176
+ [`pet/discrete_video_spec.rb`](../spec/badline/pet/discrete_video_spec.rb).
2177
+ - A line's 40 characters come in its last 40 cycles, 24 cycles after the
2178
+ line starts, and the vertical drive line falls right after line 199's
2179
+ last character. Each character reads the screen RAM as it stands before
2180
+ the CPU's access in the same cycle.
2181
+ - Pinned by `PET/hi-res`, which rewrites the screen RAM as the beam
2182
+ reads it: its picture matches `hi-res.bitmap` (all but the bitmap's
2183
+ tenth column, which `hi-res.py` makes from an immediate that isn't a
2184
+ screen write) with the characters anywhere from 6 to 32 cycles after
2185
+ the line starts. 24 puts them at the end of the line, so the vertical
2186
+ drive line falls as the display ends.
2187
+ - Spec guard: *shows a line's characters in its last 40 cycles* in
2188
+ [`pet/discrete_video_spec.rb`](../spec/badline/pet/discrete_video_spec.rb).
2189
+
2190
+ ## PET CRTC
2191
+
2192
+ - The 6545's counters step once a cycle, ahead of the CPU, and compare
2193
+ with the registers as they stand that cycle, so a write lands from the
2194
+ next character. Vertical sync starts at the first character of row R7
2195
+ and lasts 16 lines, and its start is PIA 1 CB1's falling edge, the
2196
+ editor's IRQ. Every editor leaves R3's upper four bits 0, and nothing
2197
+ has checked another value.
2198
+ - Pinned by `CRTC/crtc0`, `crtc4`-`crtc9`, `crtc11` and `crtc12`
2199
+ (`testbench-pet`), which time their register writes from that IRQ
2200
+ with VIA T1 and loops: all eight match their references dot for dot.
2201
+ The 16 lines match xpet's frame probe on every editor (vertical drive
2202
+ low for 800 cycles of 50-cycle lines, 1,024 of 64).
2203
+ - Spec guard:
2204
+ [`chips/crtc_spec.rb`](../spec/badline/chips/crtc_spec.rb).
2205
+ - A compare the counter has already passed doesn't happen: R1 written
2206
+ below the character counter leaves the display on to the line's end,
2207
+ MA counting on, and on a row's last line leaves the next row's start
2208
+ where it was, so the row repeats. R9 written below the line counter
2209
+ runs the row on to 32 lines, and R6 written below the row counter
2210
+ leaves the display on to the frame's end.
2211
+ - Pinned by `CRTC/crtc6` and `crtc7` (R1), `crtc10` (R9, which matches
2212
+ today's xpet dot for dot; its reference is an older xpet's) and
2213
+ `crtc13` (R6).
2214
+ - Spec guard: *past an R1 it missed*, *repeats a row*, *past an R9 it
2215
+ missed* and *past an R6 it missed* in
2216
+ [`chips/crtc_spec.rb`](../spec/badline/chips/crtc_spec.rb).
2217
+ - The picture is framed as xpet frames its screenshots: R1's characters
2218
+ in the middle of 704 dots (80 columns) or 384 (40); each character as
2219
+ far right as it comes after its line's horizontal sync, so lines whose
2220
+ sync moves mid-frame move against the rest; the frame's first line
2221
+ where the last frame's lines up to the R6 stop would sit in the middle
2222
+ of 273, unchanged after a frame where the display never stopped; each
2223
+ horizontal sync starting the next line of the picture; nothing within
2224
+ 8 dots of either side.
2225
+ - Pinned by `CRTC/crtc4` and `crtc5` (sync moved for some lines),
2226
+ `crtc6` and `crtc7` (display through horizontal sync), `crtc10`
2227
+ (a frame of 232 displayed lines framed from line 20) and the boot
2228
+ screens of the 4032 and the 8032, which match xpet's at the same
2229
+ cycle dot for dot.
2230
+ - Spec guard:
2231
+ [`pet/crtc_video_spec.rb`](../spec/badline/pet/crtc_video_spec.rb).