badline 0.15.1 → 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 (118) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +39 -0
  3. data/CLAUDE.md +8 -7
  4. data/README.md +102 -6
  5. data/doc/pinned-behaviour.md +67 -0
  6. data/doc/snapshot-format.md +213 -18
  7. data/doc/snapshots.md +14 -0
  8. data/lib/badline/c64/common.rb +1 -1
  9. data/lib/badline/chips/crtc/keyed_state.rb +46 -0
  10. data/lib/badline/chips/crtc.rb +163 -0
  11. data/lib/badline/chips/pia/control_lines.rb +138 -0
  12. data/lib/badline/chips/pia/keyed_parts.rb +56 -0
  13. data/lib/badline/chips/pia.rb +138 -0
  14. data/lib/badline/chips/vic/register_log.rb +1 -4
  15. data/lib/badline/core.rb +3 -0
  16. data/lib/badline/drives/ieee_bus.rb +28 -0
  17. data/lib/badline/drives/model1551/cable.rb +5 -2
  18. data/lib/badline/drives/model1551/tia.rb +13 -34
  19. data/lib/badline/drives/model1551.rb +26 -4
  20. data/lib/badline/drives.rb +1 -0
  21. data/lib/badline/frontend/app.rb +1 -1
  22. data/lib/badline/frontend/controls.rb +23 -3
  23. data/lib/badline/frontend/gamepads.rb +10 -3
  24. data/lib/badline/frontend/keys.rb +88 -0
  25. data/lib/badline/frontend/media_slots.rb +1 -0
  26. data/lib/badline/frontend/menu/menu_dialogs.rb +2 -1
  27. data/lib/badline/frontend/menu/menu_media.rb +27 -28
  28. data/lib/badline/frontend/menu/menu_pages.rb +15 -2
  29. data/lib/badline/frontend/menu/menu_ports.rb +22 -1
  30. data/lib/badline/frontend/menu/pause_menu.rb +1 -0
  31. data/lib/badline/frontend/pet_keyboard.rb +124 -0
  32. data/lib/badline/frontend/screens.rb +2 -1
  33. data/lib/badline/frontend/timeline.rb +16 -9
  34. data/lib/badline/frontend.rb +1 -0
  35. data/lib/badline/kernal_trap/dos/writes.rb +3 -1
  36. data/lib/badline/kernal_trap/dos.rb +6 -1
  37. data/lib/badline/kernal_trap/frames.rb +117 -0
  38. data/lib/badline/kernal_trap/ieee.rb +148 -0
  39. data/lib/badline/kernal_trap/ieee_layout.rb +113 -0
  40. data/lib/badline/kernal_trap/keyed_state.rb +4 -4
  41. data/lib/badline/kernal_trap/routine.rb +3 -53
  42. data/lib/badline/kernal_trap/serial.rb +4 -102
  43. data/lib/badline/kernal_trap/steps.rb +64 -0
  44. data/lib/badline/kernal_trap.rb +4 -0
  45. data/lib/badline/machine/keyboard_buffer.rb +8 -0
  46. data/lib/badline/machine/settling.rb +1 -1
  47. data/lib/badline/machine.rb +28 -6
  48. data/lib/badline/media/extensions.rb +5 -2
  49. data/lib/badline/media/pet_media.rb +40 -0
  50. data/lib/badline/media/program.rb +14 -2
  51. data/lib/badline/media/vic20_media.rb +2 -2
  52. data/lib/badline/media.rb +36 -16
  53. data/lib/badline/options/family.rb +17 -6
  54. data/lib/badline/options/help.rb +19 -3
  55. data/lib/badline/options/table.rb +14 -2
  56. data/lib/badline/options/validation.rb +68 -5
  57. data/lib/badline/options.rb +31 -19
  58. data/lib/badline/pet/bus/expansion.rb +106 -0
  59. data/lib/badline/pet/bus.rb +204 -0
  60. data/lib/badline/pet/canvas.rb +97 -0
  61. data/lib/badline/pet/cassettes.rb +63 -0
  62. data/lib/badline/pet/characters.rb +26 -0
  63. data/lib/badline/pet/cpu.rb +10 -0
  64. data/lib/badline/pet/crtc_video.rb +142 -0
  65. data/lib/badline/pet/discrete_video.rb +83 -0
  66. data/lib/badline/pet/ieee_ports.rb +66 -0
  67. data/lib/badline/pet/ieee_traps.rb +75 -0
  68. data/lib/badline/pet/keyboard_ports.rb +74 -0
  69. data/lib/badline/pet/keyed_modules.rb +85 -0
  70. data/lib/badline/pet/keyed_parts.rb +123 -0
  71. data/lib/badline/pet/keyed_state.rb +42 -0
  72. data/lib/badline/pet/model.rb +113 -0
  73. data/lib/badline/pet/rom_sets.rb +65 -0
  74. data/lib/badline/pet/sound.rb +128 -0
  75. data/lib/badline/pet/via.rb +10 -0
  76. data/lib/badline/pet/via_ports.rb +19 -0
  77. data/lib/badline/pet.rb +226 -0
  78. data/lib/badline/plus4/keyed_state.rb +5 -3
  79. data/lib/badline/plus4/tcbm_drive.rb +14 -0
  80. data/lib/badline/plus4.rb +1 -1
  81. data/lib/badline/roms/README +137 -0
  82. data/lib/badline/roms/pet/basic1.rom +0 -0
  83. data/lib/badline/roms/pet/basic2.rom +0 -0
  84. data/lib/badline/roms/pet/basic4.rom +0 -0
  85. data/lib/badline/roms/pet/characters1.rom +0 -0
  86. data/lib/badline/roms/pet/characters2.rom +0 -0
  87. data/lib/badline/roms/pet/editor1.rom +0 -0
  88. data/lib/badline/roms/pet/editor2-b.rom +0 -0
  89. data/lib/badline/roms/pet/editor2-n.rom +0 -0
  90. data/lib/badline/roms/pet/editor4-40-n-50hz.rom +0 -0
  91. data/lib/badline/roms/pet/editor4-40-n-60hz.rom +0 -0
  92. data/lib/badline/roms/pet/editor4-80-b-50hz-0283.rom +0 -0
  93. data/lib/badline/roms/pet/editor4-80-b-50hz.rom +0 -0
  94. data/lib/badline/roms/pet/editor4-80-b-60hz.rom +0 -0
  95. data/lib/badline/roms/pet/editor4-b.rom +0 -0
  96. data/lib/badline/roms/pet/editor4-n.rom +0 -0
  97. data/lib/badline/roms/pet/kernal1.rom +0 -0
  98. data/lib/badline/roms/pet/kernal2.rom +0 -0
  99. data/lib/badline/roms/pet/kernal4.rom +0 -0
  100. data/lib/badline/snapshot/container.rb +2 -0
  101. data/lib/badline/snapshot/field_doc/markdown.rb +1 -1
  102. data/lib/badline/snapshot/field_doc.rb +16 -3
  103. data/lib/badline/snapshot/image.rb +14 -7
  104. data/lib/badline/snapshot/pet_setup.rb +71 -0
  105. data/lib/badline/snapshot/storage_setup.rb +7 -1
  106. data/lib/badline/snapshot.rb +9 -5
  107. data/lib/badline/storage/d80_image.rb +48 -0
  108. data/lib/badline/storage/d82_image.rb +21 -0
  109. data/lib/badline/storage/tap.rb +16 -3
  110. data/lib/badline/storage.rb +2 -0
  111. data/lib/badline/support/pet_checkpoint.rb +38 -0
  112. data/lib/badline/timing.rb +5 -4
  113. data/lib/badline/version.rb +1 -1
  114. data/lib/badline/vic20/attachments.rb +7 -2
  115. data/lib/badline/vic20/bus/keyed_state.rb +5 -4
  116. data/lib/badline/vic20/bus.rb +5 -0
  117. data/lib/badline/vic20.rb +1 -1
  118. metadata +55 -1
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Snapshot
5
+ # How a PET was built: its model's name, one of PET::Model::ALL, its
6
+ # RAM below $8000 in K and its editor's frame rate, the arguments
7
+ # PET.new takes, and the ROMs it runs by file: BASIC, the editor, the
8
+ # KERNAL and the characters.
9
+ PETSetup = Data.define(:model, :ram_kb, :refresh_hz, :basic, :editor, :kernal, :characters)
10
+
11
+ class PETSetup
12
+ MODELS = PET::Model::ALL.map(&:name).freeze
13
+
14
+ REFRESH_RATES = [50, 60].freeze
15
+
16
+ # The setup of `machine`.
17
+ def self.of(machine)
18
+ model = machine.model
19
+ refresh_hz = machine.refresh_hz
20
+ new(model: model.name, ram_kb: machine.ram.length >> 10, refresh_hz:, basic: model.basic,
21
+ editor: model.editor(refresh_hz), kernal: model.kernal, characters: model.characters)
22
+ end
23
+
24
+ # The model by name, the RAM, the frame rate and the ROMs, in a keyed
25
+ # snapshot module.
26
+ def write_fields(out)
27
+ out.text("model", model).int("ram_kb", ram_kb).int("refresh_hz", refresh_hz)
28
+ out.text("rom.basic", basic).text("rom.editor", editor).text("rom.kernal", kernal)
29
+ out.text("rom.characters", characters)
30
+ end
31
+
32
+ # A ROM the snapshot doesn't name is the model's own.
33
+ def self.read_fields(input)
34
+ profile = PET::Model.named(input.choice("model", MODELS, PET::Model::DEFAULT))
35
+ ram_kb = input.int("ram_kb", profile.ram_kb)
36
+ unless PET::Model::RAM_SIZES.include?(ram_kb)
37
+ raise FormatError, "the snapshot is of a PET with #{ram_kb}K of RAM, which badline doesn't build"
38
+ end
39
+
40
+ refresh_hz = input.int("refresh_hz", profile.crtc? ? 50 : 60)
41
+ unless REFRESH_RATES.include?(refresh_hz)
42
+ raise FormatError, "the snapshot is of a PET at #{refresh_hz} Hz, which badline doesn't build"
43
+ end
44
+
45
+ refresh_hz = 60 unless profile.crtc?
46
+ new(model: profile.name, ram_kb:, refresh_hz:, basic: input.text("rom.basic", profile.basic),
47
+ editor: input.text("rom.editor", profile.editor(refresh_hz)),
48
+ kernal: input.text("rom.kernal", profile.kernal),
49
+ characters: input.text("rom.characters", profile.characters))
50
+ end
51
+
52
+ # A machine built this way, at power-on, with the BASIC and editor
53
+ # PET::ROMSets names for its ROMs.
54
+ def build
55
+ version = PET::ROMSets::BASICS.find { |_, roms| roms.first == basic }&.first
56
+ PET.new(model:, ram_kb:, refresh_hz:, basic: version, editor: PET::ROMSets::EDITORS.key(editor))
57
+ rescue ArgumentError => e
58
+ raise FormatError, "the snapshot is of a #{self}, which badline doesn't build: #{e.message}"
59
+ end
60
+
61
+ # The ROMs are named where they aren't the model's own.
62
+ def to_s
63
+ text = "#{model} with #{ram_kb}K at #{refresh_hz} Hz"
64
+ roms = [basic, editor, kernal, characters]
65
+ profile = PET::Model.named(model)
66
+ stock = [profile.basic, profile.editor(refresh_hz), profile.kernal, profile.characters]
67
+ roms == stock ? text : "#{text} running #{roms.join(', ')}"
68
+ end
69
+ end
70
+ end
71
+ end
@@ -11,6 +11,8 @@ module Badline
11
11
  D71 = 2
12
12
  D81 = 3
13
13
  T64_ARCHIVE = 4
14
+ D80 = 5
15
+ D82 = 6
14
16
 
15
17
  module_function
16
18
 
@@ -18,6 +20,8 @@ module Badline
18
20
  return D71 if image.is_a?(Storage::D71Image)
19
21
  return D64 if image.is_a?(Storage::D64Image)
20
22
  return D81 if image.is_a?(Storage::D81Image)
23
+ return D82 if image.is_a?(Storage::D82Image)
24
+ return D80 if image.is_a?(Storage::D80Image)
21
25
 
22
26
  raise ArgumentError, "#{image.class} can't go in a snapshot"
23
27
  end
@@ -37,7 +41,7 @@ module Badline
37
41
  end
38
42
  end
39
43
 
40
- KIND_NAMES = %w[directory d64 d71 d81 t64].freeze
44
+ KIND_NAMES = %w[directory d64 d71 d81 t64 d80 d82].freeze
41
45
 
42
46
  # Opens the storage write_fields wrote: the same directory by its
43
47
  # path, an archive with the bytes it held, or a disk image with the
@@ -55,6 +59,8 @@ module Badline
55
59
  case kind
56
60
  when D64 then Storage::D64Image.new(path, read_only:, bytes:)
57
61
  when D71 then Storage::D71Image.new(path, read_only:, bytes:)
62
+ when D80 then Storage::D80Image.new(path, read_only:, bytes:)
63
+ when D82 then Storage::D82Image.new(path, read_only:, bytes:)
58
64
  else Storage::D81Image.new(path, read_only:, bytes:)
59
65
  end
60
66
  end
@@ -35,9 +35,9 @@ module Badline
35
35
  # The machine's snapshot file. Saving first runs the machine on to the
36
36
  # end of the instruction its CPU is in, and of an REU transfer under
37
37
  # way (Machine::Settling), so a save advances it by a few cycles, and a
38
- # second save straight after runs none. A VIC-20's, a C128's or a
39
- # Plus/4's snapshot is in a container named as xvic, x128 or xplus4
40
- # names its machine.
38
+ # second save straight after runs none. A VIC-20's, a C128's, a
39
+ # Plus/4's or a PET's snapshot is in a container named as xvic, x128,
40
+ # xplus4 or xpet names its machine.
41
41
  def dump(computer) = Image.of(computer).to_s
42
42
 
43
43
  def read(path) = Image.new(Container.parse(File.binread(path)), name: File.basename(path))
@@ -51,8 +51,8 @@ module Badline
51
51
  # snapshot that fails leaves the machine as it was.
52
52
  def restore(computer, path, &) = read(path).restore(computer, &)
53
53
 
54
- # A machine's snapshots, as .vsf files and in memory. C64, Vic20, C128
55
- # and Plus4 each include it.
54
+ # A machine's snapshots, as .vsf files and in memory. C64, Vic20, C128,
55
+ # Plus4 and PET each include it.
56
56
  module Files
57
57
  def save_snapshot(path) = Snapshot.save(self, path)
58
58
 
@@ -95,4 +95,8 @@ module Badline
95
95
  class Plus4
96
96
  include Snapshot::Files
97
97
  end
98
+
99
+ class PET
100
+ include Snapshot::Files
101
+ end
98
102
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Storage
5
+ # An 8050 disk: 77 tracks on one side, in four speed zones.
6
+ class D80Image < DiskImage
7
+ ERROR_TABLES = { 535_331 => 2083 }.freeze
8
+
9
+ # The last track of each zone but the innermost, from the outermost
10
+ # in: tracks 1-39, 40-53 and 54-64, and the last zone from 65 on.
11
+ ZONE_LAST_TRACKS = [39, 53, 64].freeze
12
+
13
+ # The sectors a track holds in each zone, from the outermost in.
14
+ ZONE_SECTORS = [29, 27, 25, 23].freeze
15
+
16
+ # The tracks a side holds.
17
+ SIDE_TRACKS = 77
18
+
19
+ def sectors_in(track)
20
+ zone = ZONE_LAST_TRACKS.count { |last| track > last }
21
+ ZONE_SECTORS[zone]
22
+ end
23
+
24
+ private
25
+
26
+ def error_tables = ERROR_TABLES
27
+
28
+ # The header block holds the disk name at $06 and the ID at $18,
29
+ # after the link to the BAM's first block and the format, "C".
30
+ def header_name = 0x06
31
+ def directory_track = 39
32
+ def directory_sector = 1
33
+ def directory_interleave = 3
34
+ def interleave = 6
35
+
36
+ # Only the directory track is kept from files. The BAM's blocks on
37
+ # track 38 are marked in use, and the rest of that track holds files.
38
+ def reserved_tracks = [39]
39
+
40
+ # The BAM takes blocks 0, 3, 6 and 9 of track 38 as it needs them,
41
+ # each covering 50 tracks with a free count and a four-byte bitmap
42
+ # each from offset 6.
43
+ def bam_tracks = 1..SIDE_TRACKS
44
+ def bam_count(track) = [38, 3 * ((track - 1) / 50), 6 + (5 * ((track - 1) % 50))]
45
+ def bam_bitmap(track) = [38, 3 * ((track - 1) / 50), 7 + (5 * ((track - 1) % 50))]
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Storage
5
+ # An 8250 disk: an 8050's 77 tracks on each side, tracks 78-154 on the
6
+ # second, one directory and one BAM for both.
7
+ class D82Image < D80Image
8
+ ERROR_TABLES = { 1_070_662 => 4166 }.freeze
9
+
10
+ def sectors_in(track)
11
+ track > SIDE_TRACKS ? super(track - SIDE_TRACKS) : super
12
+ end
13
+
14
+ private
15
+
16
+ def error_tables = ERROR_TABLES
17
+
18
+ def bam_tracks = 1..(2 * SIDE_TRACKS)
19
+ end
20
+ end
21
+ end
@@ -3,7 +3,7 @@
3
3
  module Badline
4
4
  module Storage
5
5
  # Raw datasette pulse stream. The header holds the signature, the
6
- # version at $0c, the platform at $0d (0 C64, 1 VIC-20, 2 C16) and the
6
+ # version at $0c, the platform at $0d (0 C64, 1 VIC-20, 2 C16, 3 PET) and the
7
7
  # data size at $10; the data runs from $14, every byte the time to the
8
8
  # next falling edge on the tape read line, in units of 8 cycles. A
9
9
  # version 2 tape, the C16's and the Plus/4's, times half waves instead,
@@ -16,18 +16,31 @@ module Badline
16
16
  HEADER_SIZE = 0x14
17
17
  OVERFLOW = 0x100 * 8
18
18
 
19
+ # The platform byte of a PET tape, a version 1 tape timed in PET
20
+ # cycles.
21
+ PET_PLATFORM = 3
22
+
19
23
  # The file it was read from, expanded, and the file's bytes.
20
24
  attr_reader :version, :platform, :path, :bytes
21
25
 
22
26
  # A blank tape for `platform` at `path`, written to the host file: a
23
- # version 1 tape for the C64 (0) or the VIC-20 (1), and a version 2
24
- # C16 tape for the 264 series (2).
27
+ # version 1 tape for the C64 (0), the VIC-20 (1) or the PET (3), and
28
+ # a version 2 C16 tape for the 264 series (2).
25
29
  def self.create(path, platform:)
26
30
  header = platform == 2 ? C16_SIGNATURE + [2] : SIGNATURE + [1]
27
31
  File.binwrite(path, (header + [platform, 0, 0, 0, 0, 0, 0]).pack("C*"))
28
32
  new(path)
29
33
  end
30
34
 
35
+ # The platform byte of the tape at `path`, or nil when it isn't a
36
+ # TAP file, read from its header alone.
37
+ def self.platform_of(path)
38
+ header = File.binread(path, HEADER_SIZE)&.bytes || []
39
+ return unless [SIGNATURE, C16_SIGNATURE].include?(header[0, SIGNATURE.length]) && header.length > 0x0d
40
+
41
+ header[0x0d]
42
+ end
43
+
31
44
  # `bytes` stands in for the host file's contents, as a snapshot
32
45
  # restores the tape it holds.
33
46
  def initialize(path, bytes: nil)
@@ -7,6 +7,8 @@ require "badline/storage/disk_image"
7
7
  require "badline/storage/d64_image"
8
8
  require "badline/storage/d71_image"
9
9
  require "badline/storage/d81_image"
10
+ require "badline/storage/d80_image"
11
+ require "badline/storage/d82_image"
10
12
  require "badline/storage/g64_image"
11
13
  require "badline/storage/t64"
12
14
  require "badline/storage/tap"
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Support
5
+ # A Checkpoint of a PET: its CPU, the RAM below $8000, the screen RAM,
6
+ # the picture the video paints, both PIAs, the VIA, the CRTC's
7
+ # registers and counters, and the 8096's control register and 64K
8
+ # board, or nothing on another model.
9
+ module PETCheckpoint
10
+ COMPONENTS = %w[cpu ram screen display pia1 pia2 via crtc expansion].freeze
11
+
12
+ def self.take(machine)
13
+ ram = machine.ram
14
+ Checkpoint.new(machine.cycles, [
15
+ Checkpoint.fnv1a(Checkpoint.cpu_state(machine.cpu)),
16
+ Checkpoint.fnv1a(Checkpoint.ram(ram, ram.length)),
17
+ Checkpoint.fnv1a(machine.bus.screen.cells),
18
+ Checkpoint.fnv1a(machine.video.display),
19
+ Checkpoint.fnv1a(pia_state(machine.pia1)),
20
+ Checkpoint.fnv1a(pia_state(machine.pia2)),
21
+ Checkpoint.fnv1a(Vic20Checkpoint.via_state(machine.via)),
22
+ Checkpoint.fnv1a(crtc_state(machine.crtc)),
23
+ Checkpoint.fnv1a(expansion_state(machine.bus.expansion))
24
+ ], COMPONENTS)
25
+ end
26
+
27
+ def self.parse(line) = Checkpoint.parse(line, COMPONENTS)
28
+
29
+ def self.pia_state(pia) = [pia.port_a_output, pia.port_b_output, pia.cra, pia.crb]
30
+
31
+ def self.crtc_state(crtc) = crtc.registers + [crtc.column, crtc.line, crtc.row]
32
+
33
+ def self.expansion_state(expansion)
34
+ expansion ? [expansion.control, *expansion.cells] : []
35
+ end
36
+ end
37
+ end
38
+ end
@@ -5,8 +5,9 @@ module Badline
5
5
  #
6
6
  # What a front end needs to run a machine's frames and show them: the CPU
7
7
  # clock, the raster's cycles per line and lines per frame, and the
8
- # [left, top, width, height] of the raster it shows, and how many of the
9
- # window's square pixels wide each of its pixels shows. Each machine
10
- # derives it from its region.
11
- Timing = Data.define(:clock_hz, :cycles_per_line, :lines_per_frame, :crop, :pixel_width)
8
+ # [left, top, width, height] of the raster it shows, how many of the
9
+ # window's square pixels wide each of its pixels shows, and how many of
10
+ # its pixels share one window pixel, as an 80-column screen's dots do.
11
+ # Each machine derives it from its region.
12
+ Timing = Data.define(:clock_hz, :cycles_per_line, :lines_per_frame, :crop, :pixel_width, :dots)
12
13
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Badline
4
- VERSION = "0.15.1"
4
+ VERSION = "0.16.0"
5
5
  end
@@ -23,12 +23,17 @@ module Badline
23
23
  # Puts a cartridge's ROM chips, each a CRTFile::Chip with its address
24
24
  # and bytes, into their blocks, and switches the machine off and on,
25
25
  # as a cartridge goes in with the power off. The KERNAL then starts
26
- # the cartridge in BLK5 that signs itself with A0CBM.
27
- def attach_cartridge(chips)
26
+ # the cartridge in BLK5 that signs itself with A0CBM. +name+ is the
27
+ # name it goes by (#cartridge_name).
28
+ def attach_cartridge(chips, name = "")
28
29
  chips.each { |chip| @bus.map_rom(chip.address, chip.data) }
30
+ @bus.cartridge_name = name
29
31
  power_cycle!
30
32
  end
31
33
 
34
+ # The name of the cartridge in the expansion blocks, or an empty one.
35
+ def cartridge_name = @bus.cartridge_name
36
+
32
37
  private
33
38
 
34
39
  # The VIC-20's KERNAL, which the traps stand in for.
@@ -11,9 +11,9 @@ module Badline
11
11
  end
12
12
 
13
13
  # The bytes each side's data lines hold, under `prefix`, and a
14
- # cartridge's ROM chips as rom<N>.start and rom<N>.bytes, in a keyed
15
- # snapshot module (Snapshot::Keyed). The pages are mapped again once
16
- # they are loaded.
14
+ # cartridge's name and its ROM chips as rom<N>.start and rom<N>.bytes,
15
+ # in a keyed snapshot module (Snapshot::Keyed). The pages are mapped
16
+ # again once they are loaded.
17
17
  module KeyedState
18
18
  def save_fields(out, prefix)
19
19
  out.int("#{prefix}data", @data).int("#{prefix}video_data", @video_data)
@@ -28,7 +28,7 @@ module Badline
28
28
  def cartridge? = !@roms.empty?
29
29
 
30
30
  def save_rom_fields(out)
31
- out.int("roms", @roms.length)
31
+ out.text("name", @cartridge_name).int("roms", @roms.length)
32
32
  @roms.each_with_index do |rom, number|
33
33
  out.int("rom#{number}.start", rom.start)
34
34
  rom.save_fields(out, "rom#{number}.bytes")
@@ -37,6 +37,7 @@ module Badline
37
37
 
38
38
  def load_rom_fields(input)
39
39
  @roms = []
40
+ @cartridge_name = input.text("name", "")
40
41
  input.int("roms", 0).times do |number|
41
42
  bytes = input.bytes("rom#{number}.bytes", "".b).bytes
42
43
  @roms << ROM.new(bytes, length: bytes.length, start: input.word("rom#{number}.start", 0))
@@ -160,6 +160,10 @@ module Badline
160
160
  # The last byte on the V-bus.
161
161
  attr_reader :video_data
162
162
 
163
+ # The name of the cartridge whose ROM chips are in the expansion
164
+ # blocks, or an empty one.
165
+ attr_accessor :cartridge_name
166
+
163
167
  # +vic+, +via1+ and +via2+ are the chips in I/O 0, each answering
164
168
  # peek and poke with the CPU's address. +blocks+ names the expansion
165
169
  # blocks that hold RAM (BLOCKS), and +kernal+ the KERNAL ROM's file.
@@ -177,6 +181,7 @@ module Badline
177
181
  @read_pages = Array.new(256, @open_bus)
178
182
  @write_pages = Array.new(256, @open_bus)
179
183
  @roms = []
184
+ @cartridge_name = ""
180
185
  @debug_register = nil
181
186
  @via_write_handler = nil
182
187
  self.blocks = blocks
data/lib/badline/vic20.rb CHANGED
@@ -120,7 +120,7 @@ module Badline
120
120
  blanked = profile.blanked_lines
121
121
  Timing.new(clock_hz: profile.clock_hz, cycles_per_line: profile.cycles_per_line,
122
122
  lines_per_frame: profile.lines_per_frame,
123
- crop: [0, blanked, width, profile.lines_per_frame - blanked], pixel_width: 2)
123
+ crop: [0, blanked, width, profile.lines_per_frame - blanked], pixel_width: 2, dots: 1)
124
124
  end
125
125
 
126
126
  # The RESTORE key pulls VIA 1's CA1 low while it is held. The KERNAL
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: badline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.1
4
+ version: 0.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Inge Jørgensen
@@ -169,6 +169,11 @@ files:
169
169
  - lib/badline/chips/cpu/port.rb
170
170
  - lib/badline/chips/cpu/stack_operations.rb
171
171
  - lib/badline/chips/cpu/traps.rb
172
+ - lib/badline/chips/crtc.rb
173
+ - lib/badline/chips/crtc/keyed_state.rb
174
+ - lib/badline/chips/pia.rb
175
+ - lib/badline/chips/pia/control_lines.rb
176
+ - lib/badline/chips/pia/keyed_parts.rb
172
177
  - lib/badline/chips/sid.rb
173
178
  - lib/badline/chips/sid/catch_up.rb
174
179
  - lib/badline/chips/sid/decimator.rb
@@ -264,6 +269,7 @@ files:
264
269
  - lib/badline/drives/engine/sleep.rb
265
270
  - lib/badline/drives/engine/vias.rb
266
271
  - lib/badline/drives/engine/watch.rb
272
+ - lib/badline/drives/ieee_bus.rb
267
273
  - lib/badline/drives/model1541.rb
268
274
  - lib/badline/drives/model1541/bus.rb
269
275
  - lib/badline/drives/model1541/byte_ready.rb
@@ -336,6 +342,7 @@ files:
336
342
  - lib/badline/frontend/pacer.rb
337
343
  - lib/badline/frontend/pad_port.rb
338
344
  - lib/badline/frontend/painter.rb
345
+ - lib/badline/frontend/pet_keyboard.rb
339
346
  - lib/badline/frontend/player/filter_view.rb
340
347
  - lib/badline/frontend/player/info_view.rb
341
348
  - lib/badline/frontend/player/player_commands.rb
@@ -375,12 +382,16 @@ files:
375
382
  - lib/badline/kernal_trap/dos/write_file.rb
376
383
  - lib/badline/kernal_trap/dos/writes.rb
377
384
  - lib/badline/kernal_trap/file_routine.rb
385
+ - lib/badline/kernal_trap/frames.rb
386
+ - lib/badline/kernal_trap/ieee.rb
387
+ - lib/badline/kernal_trap/ieee_layout.rb
378
388
  - lib/badline/kernal_trap/keyed_state.rb
379
389
  - lib/badline/kernal_trap/layout.rb
380
390
  - lib/badline/kernal_trap/load.rb
381
391
  - lib/badline/kernal_trap/routine.rb
382
392
  - lib/badline/kernal_trap/save.rb
383
393
  - lib/badline/kernal_trap/serial.rb
394
+ - lib/badline/kernal_trap/steps.rb
384
395
  - lib/badline/machine.rb
385
396
  - lib/badline/machine/clocking.rb
386
397
  - lib/badline/machine/keyboard_buffer.rb
@@ -391,6 +402,7 @@ files:
391
402
  - lib/badline/media/disk_set.rb
392
403
  - lib/badline/media/extensions.rb
393
404
  - lib/badline/media/not_disk.rb
405
+ - lib/badline/media/pet_media.rb
394
406
  - lib/badline/media/plus4_media.rb
395
407
  - lib/badline/media/program.rb
396
408
  - lib/badline/media/true_drive.rb
@@ -407,6 +419,26 @@ files:
407
419
  - lib/badline/options/option.rb
408
420
  - lib/badline/options/table.rb
409
421
  - lib/badline/options/validation.rb
422
+ - lib/badline/pet.rb
423
+ - lib/badline/pet/bus.rb
424
+ - lib/badline/pet/bus/expansion.rb
425
+ - lib/badline/pet/canvas.rb
426
+ - lib/badline/pet/cassettes.rb
427
+ - lib/badline/pet/characters.rb
428
+ - lib/badline/pet/cpu.rb
429
+ - lib/badline/pet/crtc_video.rb
430
+ - lib/badline/pet/discrete_video.rb
431
+ - lib/badline/pet/ieee_ports.rb
432
+ - lib/badline/pet/ieee_traps.rb
433
+ - lib/badline/pet/keyboard_ports.rb
434
+ - lib/badline/pet/keyed_modules.rb
435
+ - lib/badline/pet/keyed_parts.rb
436
+ - lib/badline/pet/keyed_state.rb
437
+ - lib/badline/pet/model.rb
438
+ - lib/badline/pet/rom_sets.rb
439
+ - lib/badline/pet/sound.rb
440
+ - lib/badline/pet/via.rb
441
+ - lib/badline/pet/via_ports.rb
410
442
  - lib/badline/plus4.rb
411
443
  - lib/badline/plus4/acia.rb
412
444
  - lib/badline/plus4/acia/frames.rb
@@ -443,6 +475,24 @@ files:
443
475
  - lib/badline/roms/kernal-pet64.rom
444
476
  - lib/badline/roms/kernal-sx64.rom
445
477
  - lib/badline/roms/kernal.rom
478
+ - lib/badline/roms/pet/basic1.rom
479
+ - lib/badline/roms/pet/basic2.rom
480
+ - lib/badline/roms/pet/basic4.rom
481
+ - lib/badline/roms/pet/characters1.rom
482
+ - lib/badline/roms/pet/characters2.rom
483
+ - lib/badline/roms/pet/editor1.rom
484
+ - lib/badline/roms/pet/editor2-b.rom
485
+ - lib/badline/roms/pet/editor2-n.rom
486
+ - lib/badline/roms/pet/editor4-40-n-50hz.rom
487
+ - lib/badline/roms/pet/editor4-40-n-60hz.rom
488
+ - lib/badline/roms/pet/editor4-80-b-50hz-0283.rom
489
+ - lib/badline/roms/pet/editor4-80-b-50hz.rom
490
+ - lib/badline/roms/pet/editor4-80-b-60hz.rom
491
+ - lib/badline/roms/pet/editor4-b.rom
492
+ - lib/badline/roms/pet/editor4-n.rom
493
+ - lib/badline/roms/pet/kernal1.rom
494
+ - lib/badline/roms/pet/kernal2.rom
495
+ - lib/badline/roms/pet/kernal4.rom
446
496
  - lib/badline/roms/plus4/basic.rom
447
497
  - lib/badline/roms/plus4/function-high.rom
448
498
  - lib/badline/roms/plus4/function-low.rom
@@ -474,6 +524,7 @@ files:
474
524
  - lib/badline/snapshot/keyed/report.rb
475
525
  - lib/badline/snapshot/keyed/writer.rb
476
526
  - lib/badline/snapshot/machine_state.rb
527
+ - lib/badline/snapshot/pet_setup.rb
477
528
  - lib/badline/snapshot/plus4_setup.rb
478
529
  - lib/badline/snapshot/storage_setup.rb
479
530
  - lib/badline/snapshot/vic20_setup.rb
@@ -496,7 +547,9 @@ files:
496
547
  - lib/badline/storage/crt_file.rb
497
548
  - lib/badline/storage/d64_image.rb
498
549
  - lib/badline/storage/d71_image.rb
550
+ - lib/badline/storage/d80_image.rb
499
551
  - lib/badline/storage/d81_image.rb
552
+ - lib/badline/storage/d82_image.rb
500
553
  - lib/badline/storage/disk_image.rb
501
554
  - lib/badline/storage/disk_image/bam.rb
502
555
  - lib/badline/storage/disk_image/catalog.rb
@@ -512,6 +565,7 @@ files:
512
565
  - lib/badline/support.rb
513
566
  - lib/badline/support/c128_checkpoint.rb
514
567
  - lib/badline/support/checkpoint.rb
568
+ - lib/badline/support/pet_checkpoint.rb
515
569
  - lib/badline/support/plus4_checkpoint.rb
516
570
  - lib/badline/support/vic20_checkpoint.rb
517
571
  - lib/badline/timing.rb