badline 0.15.1 → 0.16.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +55 -0
- data/CLAUDE.md +8 -7
- data/README.md +128 -9
- data/doc/media.md +9 -0
- data/doc/pinned-behaviour.md +67 -0
- data/doc/snapshot-format.md +215 -18
- data/doc/snapshots.md +55 -0
- data/lib/badline/c64/common.rb +1 -1
- data/lib/badline/chips/crtc/keyed_state.rb +46 -0
- data/lib/badline/chips/crtc.rb +163 -0
- data/lib/badline/chips/pia/control_lines.rb +138 -0
- data/lib/badline/chips/pia/keyed_parts.rb +56 -0
- data/lib/badline/chips/pia.rb +138 -0
- data/lib/badline/chips/vic/register_log.rb +1 -4
- data/lib/badline/core.rb +3 -0
- data/lib/badline/drives/ieee_bus.rb +74 -0
- data/lib/badline/drives/model1551/cable.rb +5 -2
- data/lib/badline/drives/model1551/tia.rb +13 -34
- data/lib/badline/drives/model1551.rb +26 -4
- data/lib/badline/drives/model2031/ieee_port.rb +133 -0
- data/lib/badline/drives/model2031/keyed_state.rb +66 -0
- data/lib/badline/drives/model2031/parts.rb +25 -0
- data/lib/badline/drives/model2031.rb +92 -0
- data/lib/badline/drives.rb +1 -0
- data/lib/badline/frontend/app.rb +1 -1
- data/lib/badline/frontend/controls.rb +23 -3
- data/lib/badline/frontend/gamepads.rb +10 -3
- data/lib/badline/frontend/keys.rb +88 -0
- data/lib/badline/frontend/media_slots.rb +1 -0
- data/lib/badline/frontend/menu/menu_dialogs.rb +2 -1
- data/lib/badline/frontend/menu/menu_media.rb +27 -28
- data/lib/badline/frontend/menu/menu_pages.rb +24 -2
- data/lib/badline/frontend/menu/menu_ports.rb +22 -1
- data/lib/badline/frontend/menu/pause_menu.rb +1 -0
- data/lib/badline/frontend/pet_keyboard.rb +124 -0
- data/lib/badline/frontend/screens.rb +2 -1
- data/lib/badline/frontend/timeline.rb +16 -9
- data/lib/badline/frontend.rb +1 -0
- data/lib/badline/kernal_trap/dos/writes.rb +3 -1
- data/lib/badline/kernal_trap/dos.rb +6 -1
- data/lib/badline/kernal_trap/frames.rb +117 -0
- data/lib/badline/kernal_trap/ieee.rb +151 -0
- data/lib/badline/kernal_trap/ieee_layout.rb +113 -0
- data/lib/badline/kernal_trap/keyed_state.rb +4 -4
- data/lib/badline/kernal_trap/routine.rb +3 -53
- data/lib/badline/kernal_trap/serial.rb +4 -102
- data/lib/badline/kernal_trap/steps.rb +64 -0
- data/lib/badline/kernal_trap.rb +4 -0
- data/lib/badline/machine/keyboard_buffer.rb +8 -0
- data/lib/badline/machine/settling.rb +1 -1
- data/lib/badline/machine.rb +29 -6
- data/lib/badline/media/extensions.rb +5 -2
- data/lib/badline/media/pet_media.rb +40 -0
- data/lib/badline/media/program.rb +14 -2
- data/lib/badline/media/true_drive.rb +19 -6
- data/lib/badline/media/vic20_media.rb +2 -2
- data/lib/badline/media.rb +41 -17
- data/lib/badline/options/family.rb +17 -6
- data/lib/badline/options/help.rb +23 -3
- data/lib/badline/options/table.rb +22 -4
- data/lib/badline/options/validation.rb +84 -5
- data/lib/badline/options.rb +47 -16
- data/lib/badline/pet/bus/expansion.rb +200 -0
- data/lib/badline/pet/bus.rb +222 -0
- data/lib/badline/pet/canvas.rb +97 -0
- data/lib/badline/pet/cassettes.rb +63 -0
- data/lib/badline/pet/characters.rb +32 -0
- data/lib/badline/pet/cpu.rb +10 -0
- data/lib/badline/pet/crtc_video.rb +155 -0
- data/lib/badline/pet/discrete_video.rb +83 -0
- data/lib/badline/pet/ieee_drive.rb +76 -0
- data/lib/badline/pet/ieee_ports.rb +77 -0
- data/lib/badline/pet/ieee_traps.rb +80 -0
- data/lib/badline/pet/keyboard_ports.rb +74 -0
- data/lib/badline/pet/keyed_modules.rb +88 -0
- data/lib/badline/pet/keyed_parts.rb +127 -0
- data/lib/badline/pet/keyed_state.rb +42 -0
- data/lib/badline/pet/model.rb +163 -0
- data/lib/badline/pet/rom_sets.rb +89 -0
- data/lib/badline/pet/sound.rb +128 -0
- data/lib/badline/pet/via.rb +10 -0
- data/lib/badline/pet/via_ports.rb +19 -0
- data/lib/badline/pet.rb +244 -0
- data/lib/badline/plus4/keyed_state.rb +5 -3
- data/lib/badline/plus4/tcbm_drive.rb +14 -0
- data/lib/badline/plus4.rb +1 -1
- data/lib/badline/roms/README +169 -0
- data/lib/badline/roms/dos2031.rom +0 -0
- data/lib/badline/roms/pet/basic1.rom +0 -0
- data/lib/badline/roms/pet/basic2.rom +0 -0
- data/lib/badline/roms/pet/basic4.rom +0 -0
- data/lib/badline/roms/pet/characters-din.rom +0 -0
- data/lib/badline/roms/pet/characters1.rom +0 -0
- data/lib/badline/roms/pet/characters2.rom +0 -0
- data/lib/badline/roms/pet/editor1.rom +0 -0
- data/lib/badline/roms/pet/editor2-b.rom +0 -0
- data/lib/badline/roms/pet/editor2-n.rom +0 -0
- data/lib/badline/roms/pet/editor4-40-n-50hz.rom +0 -0
- data/lib/badline/roms/pet/editor4-40-n-60hz.rom +0 -0
- data/lib/badline/roms/pet/editor4-80-b-50hz-0283.rom +0 -0
- data/lib/badline/roms/pet/editor4-80-b-50hz-8296.rom +0 -0
- data/lib/badline/roms/pet/editor4-80-b-50hz.rom +0 -0
- data/lib/badline/roms/pet/editor4-80-b-60hz.rom +0 -0
- data/lib/badline/roms/pet/editor4-b.rom +0 -0
- data/lib/badline/roms/pet/editor4-n.rom +0 -0
- data/lib/badline/roms/pet/kernal1.rom +0 -0
- data/lib/badline/roms/pet/kernal2.rom +0 -0
- data/lib/badline/roms/pet/kernal4.rom +0 -0
- data/lib/badline/snapshot/container.rb +6 -1
- data/lib/badline/snapshot/field_doc/markdown.rb +1 -1
- data/lib/badline/snapshot/field_doc.rb +17 -3
- data/lib/badline/snapshot/image.rb +28 -10
- data/lib/badline/snapshot/pet_setup.rb +88 -0
- data/lib/badline/snapshot/storage_setup.rb +7 -1
- data/lib/badline/snapshot/vice/pet.rb +117 -0
- data/lib/badline/snapshot/vice/pet_cpu.rb +67 -0
- data/lib/badline/snapshot/vice/pet_crtc.rb +246 -0
- data/lib/badline/snapshot/vice/pet_mem.rb +93 -0
- data/lib/badline/snapshot/vice/pet_pias.rb +56 -0
- data/lib/badline/snapshot/vice/pet_restore.rb +150 -0
- data/lib/badline/snapshot/vice/pet_via.rb +164 -0
- data/lib/badline/snapshot/vice.rb +1 -0
- data/lib/badline/snapshot.rb +9 -5
- data/lib/badline/storage/d80_image.rb +48 -0
- data/lib/badline/storage/d82_image.rb +21 -0
- data/lib/badline/storage/tap.rb +16 -3
- data/lib/badline/storage.rb +2 -0
- data/lib/badline/support/pet_checkpoint.rb +38 -0
- data/lib/badline/timing.rb +5 -4
- data/lib/badline/version.rb +1 -1
- data/lib/badline/vic20/attachments.rb +7 -2
- data/lib/badline/vic20/bus/keyed_state.rb +5 -4
- data/lib/badline/vic20/bus.rb +5 -0
- data/lib/badline/vic20.rb +1 -1
- metadata +70 -1
data/doc/snapshot-format.md
CHANGED
|
@@ -22,11 +22,11 @@ key only some of them have names them.
|
|
|
22
22
|
|
|
23
23
|
## BL-MACHINE
|
|
24
24
|
|
|
25
|
-
Written by the C64, VIC-20, C128, Plus/4.
|
|
25
|
+
Written by the C64, VIC-20, C128, Plus/4, PET.
|
|
26
26
|
|
|
27
27
|
| Key | Type | Default |
|
|
28
28
|
| --- | --- | --- |
|
|
29
|
-
| `family` | text: c64 vic20 c128 plus4 | "c64" |
|
|
29
|
+
| `family` | text: c64 vic20 c128 plus4 pet | "c64" |
|
|
30
30
|
| `region` | text: pal ntsc ntscold drean | C64: "pal" |
|
|
31
31
|
| `vic_model` | text: mos6569 mos8565 mos8566 mos8564 | C64: "mos6569" |
|
|
32
32
|
| `cia_model` | text: mos6526 mos6526a | C64: "mos6526" |
|
|
@@ -49,7 +49,7 @@ Written by the C64, VIC-20, C128, Plus/4.
|
|
|
49
49
|
| `ram` | text: unexpanded 3k 8k 16k 24k 32k all | VIC-20: "unexpanded" |
|
|
50
50
|
| `bus.data` | byte | VIC-20: 253; C128: 255 |
|
|
51
51
|
| `bus.video_data` | byte | VIC-20: 0 |
|
|
52
|
-
| `model` | text: c128 c128ntsc c128dcr c128dcrntsc | C128: "c128"; Plus/4: "plus4" |
|
|
52
|
+
| `model` | text: c128 c128ntsc c128dcr c128dcrntsc | C128: "c128"; Plus/4: "plus4"; PET: "8032" |
|
|
53
53
|
| `mode` | text: c64 c128 | C128: "c64" |
|
|
54
54
|
| `bus.address` | word | C128: 65533 |
|
|
55
55
|
| `clock_bits` | int | C128: 0 |
|
|
@@ -61,22 +61,34 @@ Written by the C64, VIC-20, C128, Plus/4.
|
|
|
61
61
|
| `host.typist.code` | int, optional | C128: absent |
|
|
62
62
|
| `host.typist.wait` | int | C128: 0 |
|
|
63
63
|
| `host.typist.typing` | bool | C128: false |
|
|
64
|
-
| `ram_kb` | int | Plus/4: 64 or 16 |
|
|
64
|
+
| `ram_kb` | int | Plus/4: 64 or 16; PET: 32 or 8 |
|
|
65
65
|
| `sid_card` | text: none mos6581 mos8580 | Plus/4: "none" |
|
|
66
66
|
| `tcbm` | bool | Plus/4: false |
|
|
67
67
|
| `sid_card_address` | int | Plus/4: 64832 |
|
|
68
|
+
| `host.true_drive_model` | text: 1541 1551 | Plus/4: "1551" |
|
|
69
|
+
| `refresh_hz` | int | PET: 50 or 60 |
|
|
70
|
+
| `rom.basic` | text | PET: "pet/basic4.rom" or "pet/basic1.rom" |
|
|
71
|
+
| `rom.editor` | text | PET: "pet/editor4-80-b-50hz.rom" or "pet/editor1.rom" or "pet/editor4-80-b-50hz-8296.rom" |
|
|
72
|
+
| `rom.kernal` | text | PET: "pet/kernal4.rom" or "pet/kernal1.rom" |
|
|
73
|
+
| `rom.characters` | text | PET: "pet/characters2.rom" or "pet/characters1.rom" |
|
|
74
|
+
| `jumpers` | text | PET: "" |
|
|
75
|
+
| `vertical_drive` | bool | PET: true |
|
|
68
76
|
|
|
69
77
|
## BL-RAM
|
|
70
78
|
|
|
71
|
-
Written by the C64, VIC-20, C128, Plus/4.
|
|
79
|
+
Written by the C64, VIC-20, C128, Plus/4, PET.
|
|
72
80
|
|
|
73
81
|
| Key | Type | Default |
|
|
74
82
|
| --- | --- | --- |
|
|
75
|
-
| `ram` | bytes | C64: 65536 values; VIC-20: 49152 values; C128: 131072 values; Plus/4: 65536 × 0 or 16384 × 0 |
|
|
83
|
+
| `ram` | bytes | C64: 65536 values; VIC-20: 49152 values; C128: 131072 values; Plus/4: 65536 × 0 or 16384 × 0; PET: 32768 × 0 or 8192 × 0 |
|
|
76
84
|
| `bus.low_bank` | int & 0x3 | Plus/4: 0 |
|
|
77
85
|
| `bus.high_bank` | int & 0x3 | Plus/4: 0 |
|
|
78
86
|
| `bus.rom_selected` | bool | Plus/4: true |
|
|
79
|
-
| `bus.data` | byte | Plus/4: 255 |
|
|
87
|
+
| `bus.data` | byte | Plus/4: 255; PET: 253 |
|
|
88
|
+
| `screen` | bytes | PET: 2048 × 0 or 1024 × 0 or 32768 × 0 |
|
|
89
|
+
| `expansion.control` | byte | PET: 0 |
|
|
90
|
+
| `expansion.ram` | bytes | PET: 65536 × 0 |
|
|
91
|
+
| `expansion.user_port` | int | PET: 7 |
|
|
80
92
|
|
|
81
93
|
## BL-COLORRAM
|
|
82
94
|
|
|
@@ -89,14 +101,14 @@ Written by the C64, VIC-20, C128.
|
|
|
89
101
|
|
|
90
102
|
## BL-CPU
|
|
91
103
|
|
|
92
|
-
Written by the C64, C128, Plus/4, VIC-20.
|
|
104
|
+
Written by the C64, C128, Plus/4, VIC-20, PET.
|
|
93
105
|
|
|
94
106
|
| Key | Type | Default |
|
|
95
107
|
| --- | --- | --- |
|
|
96
108
|
| `port.ddr` | byte | C64: 0; C128: 0; Plus/4: 0 |
|
|
97
109
|
| `port.data` | byte | C64: 0; C128: 0; Plus/4: 0 |
|
|
98
110
|
| `port.floating` | byte | C64: 0; C128: 0 |
|
|
99
|
-
| `pc` | word | C64: 64738; VIC-20: 64802; C128: 65341; Plus/4: 65526 |
|
|
111
|
+
| `pc` | word | C64: 64738; VIC-20: 64802; C128: 65341; Plus/4: 65526; PET: 64790 or 64824 |
|
|
100
112
|
| `sp` | byte | 255 |
|
|
101
113
|
| `a` | byte | 0 |
|
|
102
114
|
| `x` | byte | 0 |
|
|
@@ -532,6 +544,7 @@ Written by the C64, VIC-20, Plus/4.
|
|
|
532
544
|
| `active` | bool | C64: true |
|
|
533
545
|
| `ram` | bytes | C64: 8192 × 0 |
|
|
534
546
|
| `ram<N>.data` | bytes | C64: 8192 × 0 |
|
|
547
|
+
| `name` | text | VIC-20: "" |
|
|
535
548
|
| `roms` | int | VIC-20: 0 |
|
|
536
549
|
| `rom0.bytes` | bytes | VIC-20: [] |
|
|
537
550
|
| `rom0.start` | word | VIC-20: 0 |
|
|
@@ -542,11 +555,11 @@ Written by the C64, VIC-20, Plus/4.
|
|
|
542
555
|
|
|
543
556
|
## BL-TRAPDOS
|
|
544
557
|
|
|
545
|
-
Written by the C64.
|
|
558
|
+
Written by the C64, PET.
|
|
546
559
|
|
|
547
560
|
| Key | Type | Default |
|
|
548
561
|
| --- | --- | --- |
|
|
549
|
-
| `storage.kind` | text: directory d64 d71 d81 t64 | "directory" |
|
|
562
|
+
| `storage.kind` | text: directory d64 d71 d81 t64 d80 d82 | "directory" |
|
|
550
563
|
| `storage.path` | text | "" |
|
|
551
564
|
| `storage.bytes` | bytes | [] |
|
|
552
565
|
| `storage.read_only` | bool | false |
|
|
@@ -562,13 +575,19 @@ Written by the C64.
|
|
|
562
575
|
| `status.error` | ints | [] |
|
|
563
576
|
| `status.bytes` | bytes | [] |
|
|
564
577
|
| `channels` | ints | [] |
|
|
565
|
-
| `serial.listening` | bool | false |
|
|
566
|
-
| `serial.talking` | bool | false |
|
|
567
|
-
| `serial.listen_channel` | int, optional | absent |
|
|
568
|
-
| `serial.talk_channel` | int, optional | absent |
|
|
569
|
-
| `serial.frame` | int | 240 |
|
|
570
|
-
| `serial.buffer` | bytes | [] |
|
|
571
|
-
| `save.saving` | bool | false |
|
|
578
|
+
| `serial.listening` | bool | C64: false |
|
|
579
|
+
| `serial.talking` | bool | C64: false |
|
|
580
|
+
| `serial.listen_channel` | int, optional | C64: absent |
|
|
581
|
+
| `serial.talk_channel` | int, optional | C64: absent |
|
|
582
|
+
| `serial.frame` | int | C64: 240 |
|
|
583
|
+
| `serial.buffer` | bytes | C64: [] |
|
|
584
|
+
| `save.saving` | bool | C64: false |
|
|
585
|
+
| `ieee.listening` | bool | PET: false |
|
|
586
|
+
| `ieee.talking` | bool | PET: false |
|
|
587
|
+
| `ieee.listen_channel` | int, optional | PET: absent |
|
|
588
|
+
| `ieee.talk_channel` | int, optional | PET: absent |
|
|
589
|
+
| `ieee.frame` | int | PET: 240 |
|
|
590
|
+
| `ieee.buffer` | bytes | PET: [] |
|
|
572
591
|
|
|
573
592
|
## BL-D8
|
|
574
593
|
|
|
@@ -1243,3 +1262,181 @@ Written by the Plus/4.
|
|
|
1243
1262
|
| `ports` | ints | [0, 0, 0] |
|
|
1244
1263
|
| `directions` | ints | [0, 0, 0] |
|
|
1245
1264
|
| `inputs` | ints | [255, 3, 192] |
|
|
1265
|
+
|
|
1266
|
+
## BL-PIA1
|
|
1267
|
+
|
|
1268
|
+
Written by the PET.
|
|
1269
|
+
|
|
1270
|
+
| Key | Type | Default |
|
|
1271
|
+
| --- | --- | --- |
|
|
1272
|
+
| `ora` | byte | 0 |
|
|
1273
|
+
| `orb` | byte | 0 |
|
|
1274
|
+
| `ddra` | byte | 0 |
|
|
1275
|
+
| `ddrb` | byte | 0 |
|
|
1276
|
+
| `ca.control` | int & 0x3f | 0 |
|
|
1277
|
+
| `ca.c1_high` | bool | true |
|
|
1278
|
+
| `ca.c2_high` | bool | true |
|
|
1279
|
+
| `ca.c1_flag` | bool | false |
|
|
1280
|
+
| `ca.c2_flag` | bool | false |
|
|
1281
|
+
| `ca.handshake_low` | bool | false |
|
|
1282
|
+
| `ca.pulse` | int & 0x3 | 0 |
|
|
1283
|
+
| `cb.control` | int & 0x3f | 0 |
|
|
1284
|
+
| `cb.c1_high` | bool | true |
|
|
1285
|
+
| `cb.c2_high` | bool | true |
|
|
1286
|
+
| `cb.c1_flag` | bool | false |
|
|
1287
|
+
| `cb.c2_flag` | bool | false |
|
|
1288
|
+
| `cb.handshake_low` | bool | false |
|
|
1289
|
+
| `cb.pulse` | int & 0x3 | 0 |
|
|
1290
|
+
|
|
1291
|
+
## BL-PIA2
|
|
1292
|
+
|
|
1293
|
+
Written by the PET.
|
|
1294
|
+
|
|
1295
|
+
| Key | Type | Default |
|
|
1296
|
+
| --- | --- | --- |
|
|
1297
|
+
| `ora` | byte | 0 |
|
|
1298
|
+
| `orb` | byte | 0 |
|
|
1299
|
+
| `ddra` | byte | 0 |
|
|
1300
|
+
| `ddrb` | byte | 0 |
|
|
1301
|
+
| `ca.control` | int & 0x3f | 0 |
|
|
1302
|
+
| `ca.c1_high` | bool | true |
|
|
1303
|
+
| `ca.c2_high` | bool | true |
|
|
1304
|
+
| `ca.c1_flag` | bool | false |
|
|
1305
|
+
| `ca.c2_flag` | bool | false |
|
|
1306
|
+
| `ca.handshake_low` | bool | false |
|
|
1307
|
+
| `ca.pulse` | int & 0x3 | 0 |
|
|
1308
|
+
| `cb.control` | int & 0x3f | 0 |
|
|
1309
|
+
| `cb.c1_high` | bool | true |
|
|
1310
|
+
| `cb.c2_high` | bool | true |
|
|
1311
|
+
| `cb.c1_flag` | bool | false |
|
|
1312
|
+
| `cb.c2_flag` | bool | false |
|
|
1313
|
+
| `cb.handshake_low` | bool | false |
|
|
1314
|
+
| `cb.pulse` | int & 0x3 | 0 |
|
|
1315
|
+
|
|
1316
|
+
## BL-VIA
|
|
1317
|
+
|
|
1318
|
+
Written by the PET.
|
|
1319
|
+
|
|
1320
|
+
| Key | Type | Default |
|
|
1321
|
+
| --- | --- | --- |
|
|
1322
|
+
| `ora` | byte | 0 |
|
|
1323
|
+
| `orb` | byte | 0 |
|
|
1324
|
+
| `ddra` | byte | 0 |
|
|
1325
|
+
| `ddrb` | byte | 0 |
|
|
1326
|
+
| `latch_a` | byte | 255 |
|
|
1327
|
+
| `latch_b` | byte | 255 |
|
|
1328
|
+
| `acr` | byte | 0 |
|
|
1329
|
+
| `pcr` | byte | 0 |
|
|
1330
|
+
| `pb6_high` | bool | true |
|
|
1331
|
+
| `t<N>.counter` | word | 65535 |
|
|
1332
|
+
| `t1.latch` | word | 65535 |
|
|
1333
|
+
| `t<N>.hold` | bool | false |
|
|
1334
|
+
| `t1.reload` | bool | false |
|
|
1335
|
+
| `t<N>.armed` | bool | false |
|
|
1336
|
+
| `t1.pb7` | bool | true |
|
|
1337
|
+
| `t2.latch_low` | byte | 255 |
|
|
1338
|
+
| `t2.low_reload` | bool | false |
|
|
1339
|
+
| `t2.low_underflowed` | bool | false |
|
|
1340
|
+
| `t2.count_pulses` | bool | false |
|
|
1341
|
+
| `t2.counting_pulses` | bool | false |
|
|
1342
|
+
| `sr.mode` | int & 0x7 | 0 |
|
|
1343
|
+
| `sr.data` | byte | 0 |
|
|
1344
|
+
| `sr.bits` | int | 0 |
|
|
1345
|
+
| `sr.delay` | int | 0 |
|
|
1346
|
+
| `sr.clock` | bool | true |
|
|
1347
|
+
| `sr.cb2` | bool | true |
|
|
1348
|
+
| `sr.cb2_input` | bool | true |
|
|
1349
|
+
| `ifr.flags` | int & 0x7f | 0 |
|
|
1350
|
+
| `ifr.enable` | int & 0x7f | 0 |
|
|
1351
|
+
| `ca.control` | int & 0xf | 0 |
|
|
1352
|
+
| `ca.c1_high` | bool | true |
|
|
1353
|
+
| `ca.c2_high` | bool | true |
|
|
1354
|
+
| `ca.handshake_low` | bool | false |
|
|
1355
|
+
| `ca.pulse` | int | 0 |
|
|
1356
|
+
| `ca.c2_output` | bool | true |
|
|
1357
|
+
| `cb.control` | int & 0xf | 0 |
|
|
1358
|
+
| `cb.c1_high` | bool | true |
|
|
1359
|
+
| `cb.c2_high` | bool | true |
|
|
1360
|
+
| `cb.handshake_low` | bool | false |
|
|
1361
|
+
| `cb.pulse` | int | 0 |
|
|
1362
|
+
| `cb.c2_output` | bool | true |
|
|
1363
|
+
|
|
1364
|
+
## BL-CRTC
|
|
1365
|
+
|
|
1366
|
+
Written by the PET.
|
|
1367
|
+
|
|
1368
|
+
| Key | Type | Default |
|
|
1369
|
+
| --- | --- | --- |
|
|
1370
|
+
| `registers` | bytes | 18 × 0 |
|
|
1371
|
+
| `selected` | int & 0x1f | 0 |
|
|
1372
|
+
| `column` | byte | 0 |
|
|
1373
|
+
| `since_hsync` | int | 0 |
|
|
1374
|
+
| `line` | int & 0x1f | 0 |
|
|
1375
|
+
| `row` | int & 0x7f | 0 |
|
|
1376
|
+
| `vsync_lines` | int | 16 |
|
|
1377
|
+
| `adjusting` | bool | false |
|
|
1378
|
+
| `row_display` | bool | false |
|
|
1379
|
+
| `column_display` | bool | true |
|
|
1380
|
+
| `row_start` | int & 0x3fff | 0 |
|
|
1381
|
+
| `address` | int & 0x3fff | 0 |
|
|
1382
|
+
|
|
1383
|
+
## BL-VIDEO
|
|
1384
|
+
|
|
1385
|
+
Written by the PET.
|
|
1386
|
+
|
|
1387
|
+
| Key | Type | Default |
|
|
1388
|
+
| --- | --- | --- |
|
|
1389
|
+
| `displayed` | int | 0 |
|
|
1390
|
+
| `frame_displayed` | int | 0 |
|
|
1391
|
+
| `line_shown` | bool | false |
|
|
1392
|
+
| `y` | int | 136 |
|
|
1393
|
+
| `from_y` | int | 136 |
|
|
1394
|
+
| `to_y` | int | 136 |
|
|
1395
|
+
| `shown_from` | int | 36 |
|
|
1396
|
+
| `shown_to` | int | 37 |
|
|
1397
|
+
| `on_canvas` | bool | true |
|
|
1398
|
+
| `origin` | int | 336 |
|
|
1399
|
+
| `from` | int | 704 |
|
|
1400
|
+
| `to` | int | -704 |
|
|
1401
|
+
| `canvas.dots` | bytes | 192192 × 0 or 83328 × 0 |
|
|
1402
|
+
| `canvas.painted` | ints | 48048 × 0 or 20832 × 0 |
|
|
1403
|
+
| `canvas.span_from` | ints | 273 × 0 or 217 × 0 |
|
|
1404
|
+
| `canvas.span_to` | ints | 273 × 0 or 217 × 0 |
|
|
1405
|
+
| `column` | int | 0 |
|
|
1406
|
+
| `line` | int | 0 |
|
|
1407
|
+
|
|
1408
|
+
## BL-TAPE1
|
|
1409
|
+
|
|
1410
|
+
Written by the PET.
|
|
1411
|
+
|
|
1412
|
+
| Key | Type | Default |
|
|
1413
|
+
| --- | --- | --- |
|
|
1414
|
+
| `playing` | bool | false |
|
|
1415
|
+
| `motor` | bool | false |
|
|
1416
|
+
| `countdown` | int | 0 |
|
|
1417
|
+
| `recording` | bool | false |
|
|
1418
|
+
| `since` | int | 0 |
|
|
1419
|
+
| `write_high` | bool | true |
|
|
1420
|
+
| `rise_at` | int | 0 |
|
|
1421
|
+
| `low_recorded` | bool | false |
|
|
1422
|
+
| `tape.bytes` | bytes | [] |
|
|
1423
|
+
| `tape.path` | text | "" |
|
|
1424
|
+
| `tape.position` | int | 0 |
|
|
1425
|
+
|
|
1426
|
+
## BL-TAPE2
|
|
1427
|
+
|
|
1428
|
+
Written by the PET.
|
|
1429
|
+
|
|
1430
|
+
| Key | Type | Default |
|
|
1431
|
+
| --- | --- | --- |
|
|
1432
|
+
| `playing` | bool | false |
|
|
1433
|
+
| `motor` | bool | false |
|
|
1434
|
+
| `countdown` | int | 0 |
|
|
1435
|
+
| `recording` | bool | false |
|
|
1436
|
+
| `since` | int | 0 |
|
|
1437
|
+
| `write_high` | bool | true |
|
|
1438
|
+
| `rise_at` | int | 0 |
|
|
1439
|
+
| `low_recorded` | bool | false |
|
|
1440
|
+
| `tape.bytes` | bytes | [] |
|
|
1441
|
+
| `tape.path` | text | "" |
|
|
1442
|
+
| `tape.position` | int | 0 |
|
data/doc/snapshots.md
CHANGED
|
@@ -140,6 +140,61 @@ KERNAL and function ROMs come with the model. Its file names its machine
|
|
|
140
140
|
doesn't open it, and badline doesn't open xplus4's. `--vice` and
|
|
141
141
|
`computer.export_snapshot(path)` refuse a Plus/4.
|
|
142
142
|
|
|
143
|
+
## The PET
|
|
144
|
+
|
|
145
|
+
Every PET and CBM model saves and restores the same way. A snapshot of
|
|
146
|
+
one holds its RAM, the screen RAM, or on an 8296 all 32K from `$8000`,
|
|
147
|
+
an 8096's or 8296's 64K board with its control register and the user
|
|
148
|
+
port lines the 8296's RAM follows, both PIAs, the VIA, the CPU, the
|
|
149
|
+
CRTC on the boards that have one, the picture with where the video is
|
|
150
|
+
in its frame, the tapes in both datasettes with their places on them,
|
|
151
|
+
and the disk or directory device 8 serves through the IEEE-488 traps.
|
|
152
|
+
It restores into a machine of the same model with the same RAM, the
|
|
153
|
+
same editor frame rate, the same ROMs, which come with the model, and
|
|
154
|
+
an 8296's same jumpers. Its file names its machine `PET`, as xpet's do,
|
|
155
|
+
and holds only badline's modules, so xpet doesn't open it unless it is
|
|
156
|
+
saved with `--vice` (see [xpet](#xpet)).
|
|
157
|
+
|
|
158
|
+
### xpet
|
|
159
|
+
|
|
160
|
+
A PET snapshot saved with `--vice`, or `computer.export_snapshot(path)`,
|
|
161
|
+
also holds xpet's modules for the CPU, the RAM with the screen RAM, or
|
|
162
|
+
an 8296's 32K from `$8000`, an 8096's or 8296's board and its control
|
|
163
|
+
register, the CRTC, both PIAs and the VIA, and the ones xpet 3.10 needs
|
|
164
|
+
to open the file, with nothing open on the file system drive and
|
|
165
|
+
nothing on the user port. The CRTC module carries the discrete boards'
|
|
166
|
+
video too, in xpet's terms. The file says it is in VICE's snapshot
|
|
167
|
+
format 1.0, the only one xpet reads.
|
|
168
|
+
|
|
169
|
+
xpet 3.10 opens those snapshots as long as its model and editor match:
|
|
170
|
+
`-model 2001`, `3032`, `3032B`, `4032`, `8032`, `8096` or `8296`, and
|
|
171
|
+
for a badline editor other than xpet's own, `-editor` naming badline's
|
|
172
|
+
ROM. xpet's 8296 runs the 8032's editor, 901474-04 dated 0283, so an
|
|
173
|
+
8296 saved for it has to run that editor (`--editor 4-80-b-50hz-0283`),
|
|
174
|
+
and xpet takes the 8296's jumpers from its own settings. It keeps its
|
|
175
|
+
own drives and datasettes and leaves out badline's tapes and disk. Its
|
|
176
|
+
CRTC loses a few lines on opening any snapshot, its own too, so a
|
|
177
|
+
program it runs on from one finds the vertical sync a few hundred
|
|
178
|
+
cycles later than one it ran without stopping.
|
|
179
|
+
|
|
180
|
+
Snapshots xpet saves open in badline through the same modules: the CPU
|
|
181
|
+
at its instruction boundary, the RAM, the screen RAM, an 8096's or
|
|
182
|
+
8296's board, the CRTC's registers and beam, both PIAs' registers and
|
|
183
|
+
flags, and the VIA's registers, timers and shift register. A program
|
|
184
|
+
badline runs on from xpet's snapshot finds the vertical sync on the
|
|
185
|
+
cycle xpet does, so the two run on alike, cycle for cycle. The picture
|
|
186
|
+
starts again with the next frame. xpet doesn't save its ROMs, which
|
|
187
|
+
keyboard it has or an 8296's jumpers, so the board, the RAM and the
|
|
188
|
+
CRTC's frame build the machine: a 2001, a 3032 for any other discrete
|
|
189
|
+
board, a 4032, an 8032, an 8096 or an 8296 with none of its jumpers
|
|
190
|
+
fitted, at 50 or 60 Hz, and an 8032, 8096 or 8296 whose CRTC lines are
|
|
191
|
+
64 cycles long runs xpet's own 50 Hz editor, 901474-04 dated 0283. A
|
|
192
|
+
SuperPET's snapshot fails. It reports the modules it leaves out, such
|
|
193
|
+
as the drives, the datasettes and the keyboard, and carries on without
|
|
194
|
+
them. Restored into a running PET, an xpet snapshot fails for a PET
|
|
195
|
+
built another way, such as a 3032B, and otherwise switches the machine
|
|
196
|
+
off and on, keeping its tapes and the disk device 8 serves.
|
|
197
|
+
|
|
143
198
|
## VICE
|
|
144
199
|
|
|
145
200
|
Snapshots use VICE's `.vsf` format, and badline's own modules are named
|
data/lib/badline/c64/common.rb
CHANGED
|
@@ -10,7 +10,7 @@ module Badline
|
|
|
10
10
|
def timing
|
|
11
11
|
region = address_bus.region
|
|
12
12
|
Timing.new(clock_hz: region.clock_hz, cycles_per_line: region.cycles_per_line,
|
|
13
|
-
lines_per_frame: region.lines_per_frame, crop: region.crop, pixel_width: 1)
|
|
13
|
+
lines_per_frame: region.lines_per_frame, crop: region.crop, pixel_width: 1, dots: 1)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def load_prg(data)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class CRTC
|
|
6
|
+
# The CRTC's fields in a keyed snapshot module (Snapshot::Keyed): the
|
|
7
|
+
# registers, the one selected, and the counters: the character, the
|
|
8
|
+
# characters since horizontal sync, the line, the row, the lines of
|
|
9
|
+
# vertical sync left, whether the frame is in its vertical adjust,
|
|
10
|
+
# whether the row and the character show, and the memory address with
|
|
11
|
+
# the row's start. The output restores its own state.
|
|
12
|
+
module KeyedState
|
|
13
|
+
def save_fields(out)
|
|
14
|
+
out.bytes("registers", @registers).int("selected", @selected).int("column", @column)
|
|
15
|
+
out.int("since_hsync", @since_hsync).int("line", @line).int("row", @row).int("vsync_lines", @vsync_lines)
|
|
16
|
+
out.bool("adjusting", @adjusting).bool("row_display", @row_display).bool("column_display", @column_display)
|
|
17
|
+
out.int("row_start", @row_start).int("address", @address)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def load_fields(input)
|
|
21
|
+
input.bytes_into("registers", @registers)
|
|
22
|
+
MASKS.each_with_index { |mask, index| @registers[index] &= mask }
|
|
23
|
+
@selected = input.masked("selected", @selected, 0x1f)
|
|
24
|
+
@column = input.byte("column", @column)
|
|
25
|
+
@since_hsync = input.int("since_hsync", @since_hsync)
|
|
26
|
+
@line = input.masked("line", @line, 0x1f)
|
|
27
|
+
@row = input.masked("row", @row, 0x7f)
|
|
28
|
+
@vsync_lines = input.int("vsync_lines", @vsync_lines)
|
|
29
|
+
load_flag_fields(input)
|
|
30
|
+
@row_start = input.masked("row_start", @row_start, 0x3fff)
|
|
31
|
+
@address = input.masked("address", @address, 0x3fff)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def load_flag_fields(input)
|
|
37
|
+
@adjusting = input.bool("adjusting", @adjusting)
|
|
38
|
+
@row_display = input.bool("row_display", @row_display)
|
|
39
|
+
@column_display = input.bool("column_display", @column_display)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
include KeyedState
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "badline/chips/crtc/keyed_state"
|
|
4
|
+
|
|
5
|
+
module Badline
|
|
6
|
+
module Chips
|
|
7
|
+
# The MOS 6545 CRTC, as the later PETs drive their screens with: an
|
|
8
|
+
# address register at even addresses selects one of eighteen registers,
|
|
9
|
+
# which the odd addresses write. Of them only the light pen's, R16 and
|
|
10
|
+
# R17, and the cursor address, R14 and R15, read back; every other read
|
|
11
|
+
# finds 0.
|
|
12
|
+
#
|
|
13
|
+
# Its counters run one character a cycle, and compare with the
|
|
14
|
+
# registers as they stand that cycle, so a write lands from the next
|
|
15
|
+
# character on:
|
|
16
|
+
#
|
|
17
|
+
# - The character counter runs from 0 to R0, then a line ends. The
|
|
18
|
+
# display shows from character 0 until the counter equals R1, and
|
|
19
|
+
# horizontal sync starts where it equals R2. A compare the counter has
|
|
20
|
+
# already passed doesn't happen that line: the display then runs on
|
|
21
|
+
# to the line's end.
|
|
22
|
+
# - The line counter (RA, five bits) counts a character row's lines. A
|
|
23
|
+
# row ends after the line where it equals R9; past R9 it runs on to
|
|
24
|
+
# 31 and wraps.
|
|
25
|
+
# - The row counter (seven bits) counts rows to R4. R5 more lines of
|
|
26
|
+
# vertical adjust follow, then the frame starts again. The display
|
|
27
|
+
# stops at the start of the row the counter equals R6, and comes back
|
|
28
|
+
# at the next frame; vertical sync starts with row R7 and lasts
|
|
29
|
+
# VSYNC_LINES lines.
|
|
30
|
+
# - The memory address (MA, fourteen bits) starts each frame at
|
|
31
|
+
# R12:R13 and counts one a character. Each line starts again from its
|
|
32
|
+
# row's start, which the last line of a row moves on to the address
|
|
33
|
+
# where the counter equals R1.
|
|
34
|
+
#
|
|
35
|
+
# Each displayed character goes to the output's #character with MA, RA
|
|
36
|
+
# and the characters since horizontal sync last started; the output
|
|
37
|
+
# also hears of each #hsync as it starts, each #line_end, the
|
|
38
|
+
# #rows_end where the display stops for the rest of the frame, and each
|
|
39
|
+
# #frame_start.
|
|
40
|
+
class CRTC
|
|
41
|
+
# The bits each register keeps.
|
|
42
|
+
MASKS = [0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xff, 0x1f, 0x7f, 0x1f,
|
|
43
|
+
0x3f, 0xff, 0x3f, 0xff, 0x3f, 0xff].freeze
|
|
44
|
+
|
|
45
|
+
VSYNC_LINES = 16
|
|
46
|
+
|
|
47
|
+
attr_reader :registers, :column, :line, :row, :address
|
|
48
|
+
|
|
49
|
+
# The characters since horizontal sync last started.
|
|
50
|
+
attr_reader :since_hsync
|
|
51
|
+
|
|
52
|
+
# +registers+ is the register file, which the output may read too.
|
|
53
|
+
def initialize(output, registers: Array.new(MASKS.length, 0))
|
|
54
|
+
@output = output
|
|
55
|
+
@registers = registers
|
|
56
|
+
reset!
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# The RES pin stops the counters at the start of a frame. The
|
|
60
|
+
# registers keep their values.
|
|
61
|
+
def reset!
|
|
62
|
+
@selected = 0
|
|
63
|
+
@column = 0
|
|
64
|
+
@since_hsync = 0
|
|
65
|
+
@vsync_lines = 0
|
|
66
|
+
start_frame
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Whether vertical sync is on.
|
|
70
|
+
def vsync? = @vsync_lines.positive?
|
|
71
|
+
|
|
72
|
+
# Whether the display shows the character the counters are at.
|
|
73
|
+
def display? = @row_display && @column_display
|
|
74
|
+
|
|
75
|
+
def peek(addr)
|
|
76
|
+
return 0 if addr.nobits?(0x01) || @selected < 14 || @selected >= MASKS.length
|
|
77
|
+
|
|
78
|
+
@registers[@selected]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def poke(addr, value)
|
|
82
|
+
if addr.nobits?(0x01)
|
|
83
|
+
@selected = value & 0x1f
|
|
84
|
+
elsif @selected < MASKS.length
|
|
85
|
+
@registers[@selected] = value & MASKS[@selected]
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def cycle!
|
|
90
|
+
regs = @registers
|
|
91
|
+
column = @column
|
|
92
|
+
if column == regs[1]
|
|
93
|
+
@column_display = false
|
|
94
|
+
@row_start = @address if @line == regs[9]
|
|
95
|
+
end
|
|
96
|
+
@output.character(@address, @line, @since_hsync) if @column_display && @row_display
|
|
97
|
+
if column == regs[2]
|
|
98
|
+
@since_hsync = 1
|
|
99
|
+
@output.hsync
|
|
100
|
+
else
|
|
101
|
+
@since_hsync += 1
|
|
102
|
+
end
|
|
103
|
+
@address = (@address + 1) & 0x3fff
|
|
104
|
+
if column == regs[0]
|
|
105
|
+
@column = 0
|
|
106
|
+
end_line
|
|
107
|
+
else
|
|
108
|
+
@column = (column + 1) & 0xff
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
private
|
|
113
|
+
|
|
114
|
+
def end_line
|
|
115
|
+
@output.line_end
|
|
116
|
+
@vsync_lines -= 1 if @vsync_lines.positive?
|
|
117
|
+
@column_display = true
|
|
118
|
+
if @adjusting
|
|
119
|
+
@line += 1
|
|
120
|
+
@line >= @registers[5] ? start_frame : @address = @row_start
|
|
121
|
+
elsif @line == @registers[9]
|
|
122
|
+
end_row
|
|
123
|
+
else
|
|
124
|
+
@line = (@line + 1) & 0x1f
|
|
125
|
+
@address = @row_start
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def end_row
|
|
130
|
+
@line = 0
|
|
131
|
+
if @row == @registers[4]
|
|
132
|
+
return start_frame if @registers[5].zero?
|
|
133
|
+
|
|
134
|
+
@adjusting = true
|
|
135
|
+
else
|
|
136
|
+
@row = (@row + 1) & 0x7f
|
|
137
|
+
start_row
|
|
138
|
+
end
|
|
139
|
+
@address = @row_start
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def start_frame
|
|
143
|
+
@line = 0
|
|
144
|
+
@row = 0
|
|
145
|
+
@adjusting = false
|
|
146
|
+
@row_display = true
|
|
147
|
+
@column_display = true
|
|
148
|
+
@row_start = ((@registers[12] << 8) | @registers[13]) & 0x3fff
|
|
149
|
+
@address = @row_start
|
|
150
|
+
start_row
|
|
151
|
+
@output.frame_start
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def start_row
|
|
155
|
+
if @row == @registers[6] && @row_display
|
|
156
|
+
@row_display = false
|
|
157
|
+
@output.rows_end
|
|
158
|
+
end
|
|
159
|
+
@vsync_lines = VSYNC_LINES if @row == @registers[7]
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|