badline 0.14.0 → 0.15.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.
Files changed (116) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +86 -0
  3. data/CLAUDE.md +22 -5
  4. data/README.md +101 -11
  5. data/doc/media.md +19 -0
  6. data/doc/pinned-behaviour.md +145 -0
  7. data/doc/snapshot-format.md +244 -46
  8. data/doc/snapshots.md +18 -1
  9. data/exe/badline-ruby +1 -1
  10. data/lib/badline/audio/bare_player.rb +4 -8
  11. data/lib/badline/audio/machine_player.rb +4 -26
  12. data/lib/badline/c128/banks.rb +1 -3
  13. data/lib/badline/c128/bus.rb +19 -1
  14. data/lib/badline/c128/mmu_pages.rb +7 -0
  15. data/lib/badline/c64/bus/extra_sids.rb +80 -0
  16. data/lib/badline/c64/bus.rb +1 -0
  17. data/lib/badline/c64/cartridge/action_replay.rb +6 -2
  18. data/lib/badline/c64/cartridge/comal80.rb +1 -0
  19. data/lib/badline/c64/cartridge/dinamic.rb +3 -1
  20. data/lib/badline/c64/cartridge/final_cartridge3.rb +1 -0
  21. data/lib/badline/c64/cartridge/fun_play.rb +2 -1
  22. data/lib/badline/c64/cartridge/game_system.rb +2 -1
  23. data/lib/badline/c64/cartridge/keyed_state.rb +155 -34
  24. data/lib/badline/c64/cartridge/magic_desk.rb +2 -1
  25. data/lib/badline/c64/cartridge/ocean.rb +1 -0
  26. data/lib/badline/c64/cartridge/pagefox.rb +1 -0
  27. data/lib/badline/c64/cartridge/rgcd.rb +2 -1
  28. data/lib/badline/c64/cartridge/super_games.rb +3 -2
  29. data/lib/badline/c64/cartridge/zaxxon.rb +1 -0
  30. data/lib/badline/c64/cartridge.rb +3 -3
  31. data/lib/badline/c64/keyed_modules.rb +6 -2
  32. data/lib/badline/c64/true_drives.rb +13 -1
  33. data/lib/badline/c64.rb +6 -0
  34. data/lib/badline/chips/ted/beam.rb +13 -14
  35. data/lib/badline/chips/ted/fetches.rb +199 -0
  36. data/lib/badline/chips/ted/keyed_state.rb +156 -0
  37. data/lib/badline/chips/ted/modes.rb +134 -0
  38. data/lib/badline/chips/ted/palette.rb +43 -0
  39. data/lib/badline/chips/ted/picture.rb +182 -0
  40. data/lib/badline/chips/ted/sound/output.rb +86 -0
  41. data/lib/badline/chips/ted/sound.rb +284 -0
  42. data/lib/badline/chips/ted.rb +53 -6
  43. data/lib/badline/chips/tia.rb +28 -0
  44. data/lib/badline/chips/vic/register_log.rb +4 -1
  45. data/lib/badline/drives/datasette/keyed_state.rb +14 -4
  46. data/lib/badline/drives/datasette.rb +22 -5
  47. data/lib/badline/drives/engine/core.rb +6 -14
  48. data/lib/badline/drives/engine/idle.rb +42 -4
  49. data/lib/badline/drives/engine/idle_cpu.rb +18 -0
  50. data/lib/badline/drives/engine/serial_connection.rb +25 -0
  51. data/lib/badline/drives/engine/sleep.rb +1 -0
  52. data/lib/badline/drives/engine.rb +1 -0
  53. data/lib/badline/drives/model1541/byte_ready.rb +19 -3
  54. data/lib/badline/drives/model1541/mechanism.rb +10 -1
  55. data/lib/badline/drives/model1541.rb +1 -0
  56. data/lib/badline/drives/model1551/bus.rb +138 -0
  57. data/lib/badline/drives/model1551/cable.rb +104 -0
  58. data/lib/badline/drives/model1551/cpu.rb +14 -0
  59. data/lib/badline/drives/model1551/keyed_state.rb +65 -0
  60. data/lib/badline/drives/model1551/port.rb +74 -0
  61. data/lib/badline/drives/model1551/tia.rb +92 -0
  62. data/lib/badline/drives/model1551.rb +170 -0
  63. data/lib/badline/drives/model1571.rb +1 -0
  64. data/lib/badline/drives/model1581.rb +1 -0
  65. data/lib/badline/frontend/boot.rb +23 -2
  66. data/lib/badline/frontend/controls.rb +7 -3
  67. data/lib/badline/frontend/keys.rb +14 -2
  68. data/lib/badline/frontend/media_slots.rb +11 -1
  69. data/lib/badline/frontend/menu/menu_dialogs.rb +14 -5
  70. data/lib/badline/frontend/menu/menu_media.rb +102 -14
  71. data/lib/badline/frontend/menu/menu_pages.rb +16 -11
  72. data/lib/badline/frontend/menu/menu_ports.rb +13 -1
  73. data/lib/badline/frontend/player/player_controller.rb +11 -4
  74. data/lib/badline/frontend/screen.rb +33 -12
  75. data/lib/badline/frontend/screens.rb +2 -1
  76. data/lib/badline/frontend/sound.rb +4 -4
  77. data/lib/badline/frontend/timeline.rb +19 -6
  78. data/lib/badline/machine/settling.rb +1 -1
  79. data/lib/badline/machine.rb +30 -6
  80. data/lib/badline/media/plus4_media.rb +68 -0
  81. data/lib/badline/media/program.rb +20 -6
  82. data/lib/badline/media/true_drive.rb +7 -5
  83. data/lib/badline/media.rb +33 -12
  84. data/lib/badline/options/family.rb +1 -0
  85. data/lib/badline/options/help.rb +32 -6
  86. data/lib/badline/options/option.rb +2 -1
  87. data/lib/badline/options/table.rb +29 -4
  88. data/lib/badline/options/validation.rb +66 -4
  89. data/lib/badline/options.rb +71 -11
  90. data/lib/badline/plus4/acia/frames.rb +55 -0
  91. data/lib/badline/plus4/acia.rb +276 -16
  92. data/lib/badline/plus4/bus.rb +245 -46
  93. data/lib/badline/plus4/cassette_sense.rb +21 -0
  94. data/lib/badline/plus4/keyboard_port.rb +35 -10
  95. data/lib/badline/plus4/keyed_modules.rb +116 -0
  96. data/lib/badline/plus4/keyed_parts.rb +172 -0
  97. data/lib/badline/plus4/keyed_state.rb +44 -0
  98. data/lib/badline/plus4/ram_expansion.rb +145 -0
  99. data/lib/badline/plus4/sid_card.rb +95 -0
  100. data/lib/badline/plus4/sound_mix.rb +51 -0
  101. data/lib/badline/plus4/tcbm_drive.rb +120 -0
  102. data/lib/badline/plus4/user_port.rb +11 -2
  103. data/lib/badline/plus4.rb +184 -26
  104. data/lib/badline/roms/README +9 -0
  105. data/lib/badline/roms/dos1551.rom +0 -0
  106. data/lib/badline/snapshot/container.rb +2 -0
  107. data/lib/badline/snapshot/field_doc/markdown.rb +7 -6
  108. data/lib/badline/snapshot/field_doc.rb +48 -7
  109. data/lib/badline/snapshot/image.rb +12 -3
  110. data/lib/badline/snapshot/plus4_setup.rb +81 -0
  111. data/lib/badline/snapshot.rb +9 -4
  112. data/lib/badline/storage/tap.rb +21 -12
  113. data/lib/badline/support/checkpoint.rb +3 -2
  114. data/lib/badline/support/plus4_checkpoint.rb +42 -0
  115. data/lib/badline/version.rb +1 -1
  116. metadata +29 -1
@@ -13,30 +13,31 @@ machine built afresh has: the default below. `word`, `byte` and
13
13
  `int & 0x..` are ints cut to the latch's width. A text that lists
14
14
  its values takes one of them. An optional int is absent when the
15
15
  latch holds nothing. A true drive's modules are named from its
16
- device number, `BL-D8` to `BL-D11`. Keys with `<N>` stand for each
17
- numbered unit. A default of "written only" is a key the load
18
- doesn't read, or reads only when the snapshot has it. Where the
19
- machines differ, the default is given for each, and a key only
20
- some of them have names them.
16
+ device number, `BL-D8` to `BL-D11`, and the SIDs past the first
17
+ are `BL-SID2` onwards, in the order they were fitted. Keys with
18
+ `<N>` stand for each numbered unit. A default of "written only" is
19
+ a key the load doesn't read, or reads only when the snapshot has
20
+ it. Where the machines differ, the default is given for each, and a
21
+ key only some of them have names them.
21
22
 
22
23
  ## BL-MACHINE
23
24
 
24
- Written by the C64, VIC-20, C128.
25
+ Written by the C64, VIC-20, C128, Plus/4.
25
26
 
26
27
  | Key | Type | Default |
27
28
  | --- | --- | --- |
28
- | `family` | text: c64 vic20 c128 | "c64" |
29
+ | `family` | text: c64 vic20 c128 plus4 | "c64" |
29
30
  | `region` | text: pal ntsc ntscold drean | C64: "pal" |
30
31
  | `vic_model` | text: mos6569 mos8565 mos8566 mos8564 | C64: "mos6569" |
31
32
  | `cia_model` | text: mos6526 mos6526a | C64: "mos6526" |
32
33
  | `sid_model` | text: mos6581 mos8580 | C64: "mos6581"; C128: "mos6581" |
33
- | `ram_expansion` | text: none plus60k plus256k | C64: "none" |
34
+ | `ram_expansion` | text: none plus60k plus256k | C64: "none"; Plus/4: "none" |
34
35
  | `reu_kb` | int | C64: 0 |
35
36
  | `kernal` | text: c64 sx64 pet64 gs | C64: "c64" |
36
37
  | `datasette` | bool | C64: true |
37
38
  | `board` | text: c64 pet64 gs max | C64: "c64" |
38
39
  | `cycles` | int | 0 |
39
- | `nmi_asserted` | bool | false |
40
+ | `nmi_asserted` | bool | C64: false; VIC-20: false; C128: false |
40
41
  | `cartridge_nmi` | bool | C64: false; C128: false |
41
42
  | `restore_pulse` | bool | C64: false; C128: false |
42
43
  | `freezing` | bool | C64: false |
@@ -48,7 +49,7 @@ Written by the C64, VIC-20, C128.
48
49
  | `ram` | text: unexpanded 3k 8k 16k 24k 32k all | VIC-20: "unexpanded" |
49
50
  | `bus.data` | byte | VIC-20: 253; C128: 255 |
50
51
  | `bus.video_data` | byte | VIC-20: 0 |
51
- | `model` | text: c128 c128ntsc c128dcr c128dcrntsc | C128: "c128" |
52
+ | `model` | text: c128 c128ntsc c128dcr c128dcrntsc | C128: "c128"; Plus/4: "plus4" |
52
53
  | `mode` | text: c64 c128 | C128: "c64" |
53
54
  | `bus.address` | word | C128: 65533 |
54
55
  | `clock_bits` | int | C128: 0 |
@@ -60,14 +61,22 @@ Written by the C64, VIC-20, C128.
60
61
  | `host.typist.code` | int, optional | C128: absent |
61
62
  | `host.typist.wait` | int | C128: 0 |
62
63
  | `host.typist.typing` | bool | C128: false |
64
+ | `ram_kb` | int | Plus/4: 64 or 16 |
65
+ | `sid_card` | text: none mos6581 mos8580 | Plus/4: "none" |
66
+ | `tcbm` | bool | Plus/4: false |
67
+ | `sid_card_address` | int | Plus/4: 64832 |
63
68
 
64
69
  ## BL-RAM
65
70
 
66
- Written by the C64, VIC-20, C128.
71
+ Written by the C64, VIC-20, C128, Plus/4.
67
72
 
68
73
  | Key | Type | Default |
69
74
  | --- | --- | --- |
70
- | `ram` | bytes | C64: 65536 values; VIC-20: 49152 values; C128: 131072 values |
75
+ | `ram` | bytes | C64: 65536 values; VIC-20: 49152 values; C128: 131072 values; Plus/4: 65536 × 0 or 16384 × 0 |
76
+ | `bus.low_bank` | int & 0x3 | Plus/4: 0 |
77
+ | `bus.high_bank` | int & 0x3 | Plus/4: 0 |
78
+ | `bus.rom_selected` | bool | Plus/4: true |
79
+ | `bus.data` | byte | Plus/4: 255 |
71
80
 
72
81
  ## BL-COLORRAM
73
82
 
@@ -80,14 +89,14 @@ Written by the C64, VIC-20, C128.
80
89
 
81
90
  ## BL-CPU
82
91
 
83
- Written by the C64, C128, VIC-20.
92
+ Written by the C64, C128, Plus/4, VIC-20.
84
93
 
85
94
  | Key | Type | Default |
86
95
  | --- | --- | --- |
87
- | `port.ddr` | byte | C64: 0; C128: 0 |
88
- | `port.data` | byte | C64: 0; C128: 0 |
96
+ | `port.ddr` | byte | C64: 0; C128: 0; Plus/4: 0 |
97
+ | `port.data` | byte | C64: 0; C128: 0; Plus/4: 0 |
89
98
  | `port.floating` | byte | C64: 0; C128: 0 |
90
- | `pc` | word | C64: 64738; VIC-20: 64802; C128: 65341 |
99
+ | `pc` | word | C64: 64738; VIC-20: 64802; C128: 65341; Plus/4: 65526 |
91
100
  | `sp` | byte | 255 |
92
101
  | `a` | byte | 0 |
93
102
  | `x` | byte | 0 |
@@ -369,7 +378,7 @@ Written by the C64, C128.
369
378
 
370
379
  ## BL-SID
371
380
 
372
- Written by the C64, C128.
381
+ Written by the C64, C128, Plus/4.
373
382
 
374
383
  | Key | Type | Default |
375
384
  | --- | --- | --- |
@@ -410,26 +419,34 @@ Written by the C64, C128.
410
419
 
411
420
  ## BL-TAPE
412
421
 
413
- Written by the C64, VIC-20, C128.
422
+ Written by the C64, VIC-20, C128, Plus/4.
414
423
 
415
424
  | Key | Type | Default |
416
425
  | --- | --- | --- |
417
426
  | `playing` | bool | false |
418
427
  | `motor` | bool | false |
419
428
  | `countdown` | int | 0 |
429
+ | `recording` | bool | false |
430
+ | `since` | int | 0 |
431
+ | `write_high` | bool | C64: false; VIC-20: true; C128: false; Plus/4: true |
432
+ | `rise_at` | int | 0 |
433
+ | `low_recorded` | bool | false |
420
434
  | `tape.bytes` | bytes | [] |
421
- | `tape.path` | text | C64: "" |
422
- | `tape.position` | int | C64: 0 |
435
+ | `tape.path` | text | C64: ""; Plus/4: "" |
436
+ | `tape.position` | int | C64: 0; Plus/4: 0 |
423
437
 
424
438
  ## BL-RAMEXP
425
439
 
426
- Written by the C64.
440
+ Written by the C64, Plus/4.
427
441
 
428
442
  | Key | Type | Default |
429
443
  | --- | --- | --- |
430
- | `d100` | byte | 0 |
431
- | `locked` | bool | false |
432
- | `bank<N>` | bytes | 65536 × 0 |
444
+ | `d100` | byte | C64: 0 |
445
+ | `locked` | bool | C64: false |
446
+ | `bank<N>` | bytes | C64: 65536 × 0 |
447
+ | `control` | byte | Plus/4: 255 |
448
+ | `csory_latch` | byte | Plus/4: 0 |
449
+ | `ram` | bytes | Plus/4: 196608 × 0 |
433
450
 
434
451
  ## BL-REU
435
452
 
@@ -476,14 +493,14 @@ Written by the C64.
476
493
 
477
494
  ## BL-CART
478
495
 
479
- Written by the C64, VIC-20.
496
+ Written by the C64, VIC-20, Plus/4.
480
497
 
481
498
  | Key | Type | Default |
482
499
  | --- | --- | --- |
483
500
  | `geo_ram_kb` | int | C64: 0 |
484
501
  | `crt` | bytes | C64: [] |
485
- | `exrom` | int & 0x1 | C64: 1 |
486
- | `game` | int & 0x1 | C64: 0 |
502
+ | `exrom` | int & 0x1 | C64: 1 or 0 |
503
+ | `game` | int & 0x1 | C64: 0 or 1 |
487
504
  | `nmi` | bool | C64: false |
488
505
  | `button` | bool | C64: false |
489
506
  | `bank` | int | C64: 0 |
@@ -511,9 +528,17 @@ Written by the C64, VIC-20.
511
528
  | `flash_high.erasing_sectors` | ints | C64: [] |
512
529
  | `flash_high.windows` | ints | C64: [] |
513
530
  | `flash_high.status_windows` | ints | C64: [] |
531
+ | `high_bank` | int | C64: 0 |
532
+ | `active` | bool | C64: true |
533
+ | `ram` | bytes | C64: 8192 × 0 |
534
+ | `ram<N>.data` | bytes | C64: 8192 × 0 |
514
535
  | `roms` | int | VIC-20: 0 |
515
536
  | `rom0.bytes` | bytes | VIC-20: [] |
516
537
  | `rom0.start` | word | VIC-20: 0 |
538
+ | `c1lo` | bytes | Plus/4: [] |
539
+ | `c2lo` | bytes | Plus/4: [] |
540
+ | `c1hi` | bytes | Plus/4: [] |
541
+ | `c2hi` | bytes | Plus/4: [] |
517
542
 
518
543
  ## BL-TRAPDOS
519
544
 
@@ -547,29 +572,31 @@ Written by the C64.
547
572
 
548
573
  ## BL-D8
549
574
 
550
- Written by the C64, C128.
575
+ Written by the C64, C128, Plus/4.
551
576
 
552
577
  | Key | Type | Default |
553
578
  | --- | --- | --- |
554
- | `model` | text: 1541 1571 1581 | C64: "1541" or "1581"; C128: "1541" or "1571" |
579
+ | `model` | text: 1541 1551 1571 1581 | C64: "1541" or "1581"; C128: "1541" or "1571"; Plus/4: "1541" or "1551" |
555
580
  | `phase` | int | 0 |
556
581
  | `cycles` | int | 0 |
557
582
  | `so_pending` | bool | false |
558
- | `serial.host` | int | 255 |
583
+ | `serial.host` | int | C64: 255; C128: 255; Plus/4: 0 |
559
584
  | `atn` | bool | C64: true |
585
+ | `irq_timer` | int | Plus/4: 16660 |
586
+ | `latched_byte` | byte | Plus/4: 0 |
560
587
 
561
588
  ## BL-D8-RAM
562
589
 
563
- Written by the C64, C128.
590
+ Written by the C64, C128, Plus/4.
564
591
 
565
592
  | Key | Type | Default |
566
593
  | --- | --- | --- |
567
- | `data` | byte | C64: 234 or 175; C128: 234 |
568
- | `ram` | bytes | C64: 2048 × 0 or 8192 × 0; C128: 2048 × 0 |
594
+ | `data` | byte | C64: 234 or 175; C128: 234; Plus/4: 234 or 233 |
595
+ | `ram` | bytes | C64: 2048 × 0 or 8192 × 0; C128: 2048 × 0; Plus/4: 2048 × 0 |
569
596
 
570
597
  ## BL-D8-VIA1
571
598
 
572
- Written by the C64, C128.
599
+ Written by the C64, C128, Plus/4.
573
600
 
574
601
  | Key | Type | Default |
575
602
  | --- | --- | --- |
@@ -603,7 +630,7 @@ Written by the C64, C128.
603
630
  | `ifr.flags` | int & 0x7f | 0 |
604
631
  | `ifr.enable` | int & 0x7f | 0 |
605
632
  | `ca.control` | int & 0xf | 0 |
606
- | `ca.c1_high` | bool | true |
633
+ | `ca.c1_high` | bool | C64: true; C128: true; Plus/4: false |
607
634
  | `ca.c2_high` | bool | true |
608
635
  | `ca.handshake_low` | bool | false |
609
636
  | `ca.pulse` | int | 0 |
@@ -617,7 +644,7 @@ Written by the C64, C128.
617
644
 
618
645
  ## BL-D8-VIA2
619
646
 
620
- Written by the C64, C128.
647
+ Written by the C64, C128, Plus/4.
621
648
 
622
649
  | Key | Type | Default |
623
650
  | --- | --- | --- |
@@ -665,11 +692,11 @@ Written by the C64, C128.
665
692
 
666
693
  ## BL-D8-CPU
667
694
 
668
- Written by the C64, C128.
695
+ Written by the C64, C128, Plus/4.
669
696
 
670
697
  | Key | Type | Default |
671
698
  | --- | --- | --- |
672
- | `pc` | word | C64: 60064 or 44836; C128: 60064 |
699
+ | `pc` | word | C64: 60064 or 44836; C128: 60064; Plus/4: 60064 or 59829 |
673
700
  | `sp` | byte | 255 |
674
701
  | `a` | byte | 0 |
675
702
  | `x` | byte | 0 |
@@ -691,7 +718,7 @@ Written by the C64, C128.
691
718
 
692
719
  ## BL-D8-DISK
693
720
 
694
- Written by the C64, C128.
721
+ Written by the C64, C128, Plus/4.
695
722
 
696
723
  | Key | Type | Default |
697
724
  | --- | --- | --- |
@@ -706,14 +733,14 @@ Written by the C64, C128.
706
733
 
707
734
  ## BL-D8-MECH
708
735
 
709
- Written by the C64, C128.
736
+ Written by the C64, C128, Plus/4.
710
737
 
711
738
  | Key | Type | Default |
712
739
  | --- | --- | --- |
713
- | `half_track` | int | C64: 35; C128: 37 |
714
- | `slip` | int & 0x3 | C64: 0; C128: 2 |
715
- | `side` | int | C64: 0 or 1; C128: 85 |
716
- | `zone` | int & 0x3 | 3 |
740
+ | `half_track` | int | C64: 35; C128: 37; Plus/4: 35 or 36 |
741
+ | `slip` | int & 0x3 | C64: 0; C128: 2; Plus/4: 0 |
742
+ | `side` | int | C64: 0 or 1; C128: 85; Plus/4: 0 |
743
+ | `zone` | int & 0x3 | C64: 3; C128: 3; Plus/4: 3 or 0 |
717
744
  | `time` | int | 0 |
718
745
  | `read_clock_in` | int | 2097152 |
719
746
  | `clocks` | int | 0 |
@@ -721,8 +748,8 @@ Written by the C64, C128.
721
748
  | `ones` | int | 0 |
722
749
  | `bits` | int | 0 |
723
750
  | `write_shift` | int | 0 |
724
- | `motor` | bool | C64: true or false; C128: true |
725
- | `led` | bool | true |
751
+ | `motor` | bool | C64: true or false; C128: true; Plus/4: true or false |
752
+ | `led` | bool | C64: true; C128: true; Plus/4: true or false |
726
753
  | `sync` | bool | false |
727
754
  | `byte_ready` | bool | false |
728
755
  | `byte_latched` | bool | false |
@@ -843,6 +870,49 @@ Written by the C64, C128.
843
870
  | `registers` | ints | C128: [0, 0, 0, 0] |
844
871
  | `result` | int | C128: 0 |
845
872
 
873
+ ## BL-SID2
874
+
875
+ Written by the C64.
876
+
877
+ | Key | Type | Default |
878
+ | --- | --- | --- |
879
+ | `address` | word | 54304 |
880
+ | `model` | text: mos6581 mos8580 | "mos6581" |
881
+ | `registers` | bytes | 32 × 0 |
882
+ | `bus_value` | byte | 0 |
883
+ | `bus_ttl` | int | 0 |
884
+ | `voice<N>.wave.accumulator` | int & 0xffffff | 5592405 |
885
+ | `voice<N>.wave.shift_register` | int & 0x7fffff | 8388606 |
886
+ | `voice<N>.wave.shift_register_reset` | int | 0 |
887
+ | `voice<N>.wave.shift_pipeline` | int | 0 |
888
+ | `voice<N>.wave.delayed_triangle` | int & 0xfff | 0 |
889
+ | `voice<N>.wave.delayed_sawtooth` | int & 0xfff | 0 |
890
+ | `voice<N>.wave.msb_rising` | bool | false |
891
+ | `voice<N>.wave.floating` | int & 0xfff | 0 |
892
+ | `voice<N>.wave.floating_ttl` | int | 0 |
893
+ | `voice<N>.wave.pulse` | int & 0xfff | 4095 |
894
+ | `voice<N>.env.state` | text: attack decay_sustain release | "release" |
895
+ | `voice<N>.env.next_state` | text: attack decay_sustain release | "release" |
896
+ | `voice<N>.env.counter` | byte | 0 |
897
+ | `voice<N>.env.env<N>` | byte | 0 |
898
+ | `voice<N>.env.rate_counter` | int & 0x7fff | 0 |
899
+ | `voice<N>.env.rate_period` | int | 8 |
900
+ | `voice<N>.env.reset_rate_counter` | bool | false |
901
+ | `voice<N>.env.exponential_counter` | int | 0 |
902
+ | `voice<N>.env.exponential_period` | int | 1 |
903
+ | `voice<N>.env.state_pipeline` | int | 0 |
904
+ | `voice<N>.env.envelope_pipeline` | int | 0 |
905
+ | `voice<N>.env.exponential_pipeline` | int | 0 |
906
+ | `voice<N>.env.hold_zero` | bool | true |
907
+ | `filter.highpass` | int | 0 |
908
+ | `filter.bandpass` | int | 0 |
909
+ | `filter.lowpass` | int | 0 |
910
+ | `filter.unfiltered` | int | 0 |
911
+ | `filter.input` | int | 0 |
912
+ | `ext.lowpass` | int | 0 |
913
+ | `ext.highpass` | int | 0 |
914
+ | `ext.output` | int | 0 |
915
+
846
916
  ## BL-VICI
847
917
 
848
918
  Written by the VIC-20.
@@ -1045,3 +1115,131 @@ Written by the C128.
1045
1115
  | `int` | bool | false |
1046
1116
  | `nmi` | bool | false |
1047
1117
  | `nmi_pending` | bool | false |
1118
+
1119
+ ## BL-TED
1120
+
1121
+ Written by the Plus/4.
1122
+
1123
+ | Key | Type | Default |
1124
+ | --- | --- | --- |
1125
+ | `registers` | bytes | 32 × 0 |
1126
+ | `interrupt_flags` | byte | 0 |
1127
+ | `key_latch` | byte | 255 |
1128
+ | `blink` | int & 0xf | 0 |
1129
+ | `blink_on` | bool | false |
1130
+ | `timer<N>.count` | word | 0 |
1131
+ | `timer<N>.running` | bool | false |
1132
+ | `timer1.reload` | word | 0 |
1133
+ | `column` | int | 0 |
1134
+ | `line` | int & 0x1ff | 0 |
1135
+ | `ba` | bool | false |
1136
+ | `cpu_slots` | int | 1 |
1137
+ | `fetch.patterns` | bytes | 40 × 0 |
1138
+ | `fetch.pointers` | bytes | 40 × 0 |
1139
+ | `fetch.attributes` | bytes | 40 × 0 |
1140
+ | `fetch.next_attributes` | bytes | 40 × 0 |
1141
+ | `fetch.char_position` | int & 0x3ff | 0 |
1142
+ | `fetch.line_position` | int & 0x3ff | 0 |
1143
+ | `fetch.row_line` | int & 0x7 | 0 |
1144
+ | `fetch.row_active` | bool | false |
1145
+ | `fetch.dma` | text: none attributes pointers | "none" |
1146
+ | `fetch.patterns_on` | bool | false |
1147
+ | `scanline` | int | 0 |
1148
+ | `window_open` | bool | false |
1149
+ | `line.layout` | int | 0 |
1150
+ | `line.painted` | int | 0 |
1151
+ | `display` | bytes | 119808 × 0 |
1152
+
1153
+ ## BL-TEDSOUND
1154
+
1155
+ Written by the Plus/4.
1156
+
1157
+ | Key | Type | Default |
1158
+ | --- | --- | --- |
1159
+ | `voice<N>.phase` | int & 0x1 | 1 |
1160
+ | `voice<N>.toggle_in` | int, optional | absent |
1161
+ | `noise` | byte | 255 |
1162
+ | `ran_ago` | int | 0 |
1163
+
1164
+ ## BL-KEYPORT
1165
+
1166
+ Written by the Plus/4.
1167
+
1168
+ | Key | Type | Default |
1169
+ | --- | --- | --- |
1170
+ | `output` | byte | 255 |
1171
+
1172
+ ## BL-USERPORT
1173
+
1174
+ Written by the Plus/4.
1175
+
1176
+ | Key | Type | Default |
1177
+ | --- | --- | --- |
1178
+ | `output` | byte | 255 |
1179
+
1180
+ ## BL-ACIA
1181
+
1182
+ Written by the Plus/4.
1183
+
1184
+ | Key | Type | Default |
1185
+ | --- | --- | --- |
1186
+ | `command` | byte | 0 |
1187
+ | `control` | byte | 0 |
1188
+ | `errors` | int & 0x7 | 0 |
1189
+ | `receiver_full` | bool | false |
1190
+ | `transmitter_empty` | bool | true |
1191
+ | `irq` | bool | false |
1192
+ | `receive_data` | byte | 0 |
1193
+ | `transmit_data` | byte | 0 |
1194
+ | `shifting` | int | -1 |
1195
+ | `transmit_remainder` | int | 0 |
1196
+ | `transmit_at` | int, optional | absent |
1197
+
1198
+ ## BL-TIA1
1199
+
1200
+ Written by the Plus/4.
1201
+
1202
+ | Key | Type | Default |
1203
+ | --- | --- | --- |
1204
+ | `ports` | ints | [0, 0, 0] |
1205
+ | `directions` | ints | [0, 0, 0] |
1206
+ | `inputs` | ints | [0, 0, 0] |
1207
+
1208
+ ## BL-TIA2
1209
+
1210
+ Written by the Plus/4.
1211
+
1212
+ | Key | Type | Default |
1213
+ | --- | --- | --- |
1214
+ | `ports` | ints | [0, 0, 0] |
1215
+ | `directions` | ints | [0, 0, 0] |
1216
+ | `inputs` | ints | [0, 0, 0] |
1217
+
1218
+ ## BL-D8-PORT
1219
+
1220
+ Written by the Plus/4.
1221
+
1222
+ | Key | Type | Default |
1223
+ | --- | --- | --- |
1224
+ | `ddr` | byte | 0 |
1225
+ | `data` | byte | 0 |
1226
+
1227
+ ## BL-D8-TIA
1228
+
1229
+ Written by the Plus/4.
1230
+
1231
+ | Key | Type | Default |
1232
+ | --- | --- | --- |
1233
+ | `ports` | ints | [0, 0, 0] |
1234
+ | `directions` | ints | [0, 0, 0] |
1235
+ | `inputs` | ints | [255, 255, 255] |
1236
+
1237
+ ## BL-D8-HOSTTIA
1238
+
1239
+ Written by the Plus/4.
1240
+
1241
+ | Key | Type | Default |
1242
+ | --- | --- | --- |
1243
+ | `ports` | ints | [0, 0, 0] |
1244
+ | `directions` | ints | [0, 0, 0] |
1245
+ | `inputs` | ints | [255, 3, 192] |
data/doc/snapshots.md CHANGED
@@ -87,7 +87,9 @@ blocks given to `on_init` that hadn't run yet, which a restore reports.
87
87
  Every model saves this way, PAL, NTSC, old NTSC and Drean alike, and so
88
88
  does a machine with an REU, with its RAM and its registers. A snapshot
89
89
  restores into a machine with the same chip models, region, RAM
90
- expansion, REU, KERNAL, datasette and board.
90
+ expansion, REU, KERNAL, datasette and board. The second and third SIDs
91
+ the SID player fits for a stereo tune are saved too, each with its
92
+ address and model, and a restore fits them.
91
93
 
92
94
  Text typed with `type_text` that the machine hasn't taken yet, such as
93
95
  autostart's `RUN`, carries over, and so do the keys a C128 is typing on
@@ -123,6 +125,21 @@ do, and holds only badline's modules, so x128 doesn't open it, and
123
125
  badline doesn't open x128's. Restoring a C128 snapshot while another machine runs swaps the
124
126
  machine in the window, as for the VIC-20.
125
127
 
128
+ ## The Plus/4
129
+
130
+ The Plus/4, the C16 and the C116 save and restore the same way. A
131
+ snapshot of one holds its RAM with the ROM bank latch and whether ROM or
132
+ RAM is selected, the cartridges' ROMs in each slot, the CPU with its
133
+ port, the TED with its timers, its counters and its picture, the TED's
134
+ sound, the keyboard's 6529, the Plus/4's user port 6529 and ACIA, a TCBM
135
+ interface's TIAs, the tape with its place on it, the disk or directory
136
+ device 8 serves through the traps and a true 1541 or 1581. It restores
137
+ into a machine of the same model with the same RAM, and the BASIC,
138
+ KERNAL and function ROMs come with the model. Its file names its machine
139
+ `PLUS4`, as xplus4's do, and holds only badline's modules, so xplus4
140
+ doesn't open it, and badline doesn't open xplus4's. `--vice` and
141
+ `computer.export_snapshot(path)` refuse a Plus/4.
142
+
126
143
  ## VICE
127
144
 
128
145
  Snapshots use VICE's `.vsf` format, and badline's own modules are named
data/exe/badline-ruby CHANGED
@@ -39,7 +39,7 @@ if options.headless?
39
39
  console = if options.player_window?
40
40
  lambda do |input:, output:|
41
41
  load_sdl
42
- Badline::Frontend::PlayerController.new(input:, output:)
42
+ Badline::Frontend::PlayerController.new(input:, output:, frames: options.frames)
43
43
  end
44
44
  else
45
45
  Badline::Audio::Console.method(:new)
@@ -93,10 +93,7 @@ module Badline
93
93
  sections << Snapshot::Keyed.section("BL-CIA1") { |out| bus.cia1.save_fields(out) }
94
94
  sections << Snapshot::Keyed.section("BL-CIA2") { |out| bus.cia2.save_fields(out) }
95
95
  sections << Snapshot::Keyed.section("BL-SID") { |out| bus.sid.save_fields(out) }
96
- @extras.each_with_index do |sid, index|
97
- sections << Snapshot::Keyed.section("BL-SID#{index + 2}") { |out| sid.save_fields(out) }
98
- end
99
- sections
96
+ bus.save_extra_sid_modules(sections)
100
97
  end
101
98
 
102
99
  # Takes a rig that hasn't started to where #save_modules found one, in
@@ -152,10 +149,9 @@ module Badline
152
149
  bus.vic.load_fields(modules.required("BL-VIC"))
153
150
  bus.cia1.load_fields(modules.required("BL-CIA1"))
154
151
  bus.cia2.load_fields(modules.required("BL-CIA2"))
155
- @stereo.sids.each_with_index do |sid, index|
156
- sid.load_fields(modules.required(index.zero? ? "BL-SID" : "BL-SID#{index + 1}"))
157
- sid.restored!
158
- end
152
+ bus.sid.load_fields(modules.required("BL-SID"))
153
+ bus.load_extra_sid_modules(modules)
154
+ @stereo.sids.each(&:restored!)
159
155
  bus.vic.restored!
160
156
  bus.cia1.restored!
161
157
  bus.cia2.restored!
@@ -19,8 +19,6 @@ module Badline
19
19
  @subtune = subtune || tune.start_subtune
20
20
  @computer = C64.new(sid_model: sid_models[0])
21
21
  @stereo = Stereo.new(@computer.address_bus, tune, sid_models)
22
- @extras = @stereo.extras
23
- @multi = !@extras.empty?
24
22
  region = @computer.region
25
23
  @frame_cycles = region.cycles_per_line * region.lines_per_frame
26
24
  @injected = false
@@ -30,7 +28,7 @@ module Badline
30
28
  def start
31
29
  @computer.on_init { inject }
32
30
  @computer.cpu.install_trap(@tune.entry_address) { begin_playing }
33
- step until @started || @computer.cycles > START_LIMIT
31
+ @computer.cycle! until @started || @computer.cycles > START_LIMIT
34
32
  end
35
33
 
36
34
  attr_reader :stereo
@@ -40,23 +38,13 @@ module Badline
40
38
  def clock_hz = @computer.region.clock_hz
41
39
 
42
40
  # The whole machine as its keyed snapshot modules, as it stands between
43
- # frames, and the extra SIDs as BL-SID2 and BL-SID3, once it plays.
44
- def save_modules
45
- sections = @computer.save_modules
46
- @extras.each_with_index do |sid, index|
47
- sections << Snapshot::Keyed.section("BL-SID#{index + 2}") { |out| sid.save_fields(out) }
48
- end
49
- sections
50
- end
41
+ # frames, with the extra SIDs as BL-SID2 and BL-SID3, once it plays.
42
+ def save_modules = @computer.save_modules
51
43
 
52
44
  # Takes a machine that hasn't started to where #save_modules found one,
53
45
  # in place of #start.
54
46
  def load_modules(modules)
55
47
  @computer.load_modules(modules)
56
- @extras.each_with_index do |sid, index|
57
- sid.load_fields(modules.required("BL-SID#{index + 2}"))
58
- sid.restored!
59
- end
60
48
  @stereo.synthesize!
61
49
  @started = true
62
50
  end
@@ -66,23 +54,13 @@ module Badline
66
54
  # Returns the cycles advanced.
67
55
  def frame(budget, &)
68
56
  cycles = [budget, @frame_cycles].min
69
- if @multi
70
- cycles.times { step }
71
- else
72
- cycles.times { @computer.cycle! }
73
- end
57
+ cycles.times { @computer.cycle! }
74
58
  @stereo.mix(&)
75
59
  cycles
76
60
  end
77
61
 
78
62
  private
79
63
 
80
- # The extra SIDs clock ahead of the CPU, as the machine's own does.
81
- def step
82
- @extras.each(&:cycle!) if @multi
83
- @computer.cycle!
84
- end
85
-
86
64
  def inject
87
65
  @computer.ram.write(@tune.load_address, @tune.data)
88
66
  @tune.boot_memory(subtune: @subtune).each { |address, bytes| @computer.ram.write(address, bytes) }
@@ -21,9 +21,7 @@ module Badline
21
21
  # The CR value the KERNAL's table holds for the bank.
22
22
  def configuration(bank) = @kernal_rom.peek(CONFIGURATIONS + (bank & 0x0f))
23
23
 
24
- def write(bank, addr, bytes)
25
- bytes.each_with_index { |byte, i| @ram.poke(physical(bank, (addr + i) & 0xffff), byte) }
26
- end
24
+ def poke(bank, addr, value) = @ram.poke(physical(bank, addr), value)
27
25
 
28
26
  private
29
27
 
@@ -228,7 +228,25 @@ module Badline
228
228
  system_rom_peek(addr)
229
229
  end
230
230
 
231
- def write_bank(bank, addr, bytes) = @banks.write(bank, addr, bytes)
231
+ # Stores +bytes+ from +addr+ on in the C128 KERNAL's bank number
232
+ # +bank+, as its INDSTA does, with CR set to the bank's CR value for
233
+ # each byte and put back after it: into the chips where that value
234
+ # maps I/O, the MMU's at $D500 among them, into nothing at $FF00-$FF04,
235
+ # where the configuration registers take the byte, and otherwise into
236
+ # the RAM the bank reaches (Banks).
237
+ def write_bank(bank, addr, bytes)
238
+ cr = @mmu.cr
239
+ io = @banks.configuration(bank).nobits?(0x01)
240
+ bytes.each_with_index do |byte, i|
241
+ address = (addr + i) & 0xffff
242
+ if io && (address & 0xf000) == 0xd000
243
+ bank_io_poke(address, byte)
244
+ elsif !address.between?(0xff00, 0xff04)
245
+ @banks.poke(bank, address, byte)
246
+ end
247
+ end
248
+ @mmu.poke_configuration(0xff00, cr) unless @mmu.cr == cr
249
+ end
232
250
 
233
251
  def install_debug_register(&)
234
252
  @debug_page = DebugPage.new(@open_bus, &)
@@ -66,6 +66,13 @@ module Badline
66
66
  @bank_io_reads[addr >> 8].peek(addr)
67
67
  end
68
68
 
69
+ # Writes the chip at +addr+, in $D000-$DFFF, as C128 mode's I/O maps it.
70
+ def bank_io_poke(addr, value)
71
+ lay_out_io(@bank_io_reads, @bank_io_writes)
72
+ @bank_io_writes[0xd5] = @mmu
73
+ @bank_io_writes[addr >> 8].poke(addr, value)
74
+ end
75
+
69
76
  # The bank CR picks, with common RAM in bank 0, then the pages page 0
70
77
  # and page 1 move to.
71
78
  def map_ram_pages