badline 0.16.1 → 0.17.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +60 -0
- data/CLAUDE.md +1 -1
- data/README.md +102 -12
- data/doc/media.md +5 -2
- data/doc/pinned-behaviour.md +61 -0
- data/doc/snapshot-format.md +376 -69
- data/doc/snapshots.md +148 -14
- data/lib/badline/cbm2/acia.rb +10 -0
- data/lib/badline/cbm2/bus.rb +263 -0
- data/lib/badline/cbm2/cpu.rb +58 -0
- data/lib/badline/cbm2/crtc_video.rb +133 -0
- data/lib/badline/cbm2/ieee_drive.rb +18 -0
- data/lib/badline/cbm2/ieee_layout.rb +69 -0
- data/lib/badline/cbm2/ieee_ports.rb +104 -0
- data/lib/badline/cbm2/ieee_traps.rb +81 -0
- data/lib/badline/cbm2/keyboard_ports.rb +60 -0
- data/lib/badline/cbm2/keyed_modules.rb +67 -0
- data/lib/badline/cbm2/keyed_state.rb +91 -0
- data/lib/badline/cbm2/model.rb +44 -0
- data/lib/badline/cbm2/p500/control_ports.rb +80 -0
- data/lib/badline/cbm2/p500/ieee_layout.rb +41 -0
- data/lib/badline/cbm2/p500/keyed_state.rb +85 -0
- data/lib/badline/cbm2/p500/model.rb +39 -0
- data/lib/badline/cbm2/p500/pages.rb +57 -0
- data/lib/badline/cbm2/p500.rb +262 -0
- data/lib/badline/cbm2/sid_page.rb +19 -0
- data/lib/badline/cbm2.rb +267 -0
- data/lib/badline/{plus4 → chips}/acia/frames.rb +1 -1
- data/lib/badline/chips/acia/keyed_state.rb +47 -0
- data/lib/badline/chips/acia.rb +307 -0
- data/lib/badline/chips/crtc.rb +3 -2
- data/lib/badline/chips/riot/fast_forward.rb +72 -0
- data/lib/badline/chips/riot/keyed_parts.rb +69 -0
- data/lib/badline/chips/riot/timer.rb +80 -0
- data/lib/badline/chips/riot.rb +162 -0
- data/lib/badline/chips/rriot/keyed_state.rb +30 -0
- data/lib/badline/chips/rriot.rb +132 -0
- data/lib/badline/chips/tpi/keyed_state.rb +38 -0
- data/lib/badline/chips/tpi.rb +233 -0
- data/lib/badline/chips/vic/bank.rb +60 -5
- data/lib/badline/chips/vic/sprite.rb +4 -3
- data/lib/badline/drives/datasette/keyed_state.rb +9 -1
- data/lib/badline/drives/datasette.rb +27 -3
- data/lib/badline/drives/model8050/disk.rb +163 -0
- data/lib/badline/drives/model8050/fdc_bus.rb +102 -0
- data/lib/badline/drives/model8050/idle.rb +177 -0
- data/lib/badline/drives/model8050/ieee_port.rb +147 -0
- data/lib/badline/drives/model8050/ip_bus.rb +93 -0
- data/lib/badline/drives/model8050/keyed_state.rb +160 -0
- data/lib/badline/drives/model8050/mechanism.rb +230 -0
- data/lib/badline/drives/model8050/parts.rb +37 -0
- data/lib/badline/drives/model8050.rb +243 -0
- data/lib/badline/frontend/app.rb +10 -3
- data/lib/badline/frontend/boot.rb +1 -1
- data/lib/badline/frontend/controls.rb +51 -15
- data/lib/badline/frontend/gamepads.rb +3 -3
- data/lib/badline/frontend/keys.rb +61 -2
- data/lib/badline/frontend/media_slots.rb +1 -1
- data/lib/badline/frontend/menu/menu_media.rb +14 -11
- data/lib/badline/frontend/menu/menu_pages.rb +18 -4
- data/lib/badline/frontend/menu/menu_ports.rb +40 -4
- data/lib/badline/frontend/menu/pause_menu.rb +1 -1
- data/lib/badline/frontend/pet_keyboard.rb +23 -7
- data/lib/badline/frontend/timeline.rb +19 -10
- data/lib/badline/kernal_trap/dos/disk_commands.rb +80 -0
- data/lib/badline/kernal_trap/dos/status.rb +3 -0
- data/lib/badline/kernal_trap/dos.rb +18 -5
- data/lib/badline/kernal_trap/ieee.rb +4 -2
- data/lib/badline/kernal_trap/ieee_layout.rb +95 -43
- data/lib/badline/machine/ieee_drives.rb +194 -0
- data/lib/badline/machine/settling.rb +4 -0
- data/lib/badline/machine.rb +23 -6
- data/lib/badline/media/cbm2_media.rb +29 -0
- data/lib/badline/media/program.rb +6 -3
- data/lib/badline/media/true_drive.rb +38 -9
- data/lib/badline/media.rb +15 -6
- data/lib/badline/options/family.rb +15 -3
- data/lib/badline/options/help.rb +16 -2
- data/lib/badline/options/table.rb +18 -4
- data/lib/badline/options/validation.rb +27 -3
- data/lib/badline/options.rb +21 -7
- data/lib/badline/pet/cassettes.rb +22 -1
- data/lib/badline/pet/ieee_drive.rb +5 -64
- data/lib/badline/pet/ieee_ports.rb +7 -0
- data/lib/badline/pet.rb +15 -4
- data/lib/badline/plus4/acia.rb +4 -298
- data/lib/badline/plus4/keyed_parts.rb +0 -44
- data/lib/badline/plus4.rb +1 -0
- data/lib/badline/roms/8050/dos-2.7.rom +0 -0
- data/lib/badline/roms/8050/fdc-901869-01.rom +0 -0
- data/lib/badline/roms/8050/fdc-901885-04.rom +0 -0
- data/lib/badline/roms/README +111 -0
- data/lib/badline/roms/cbm2/basic128-02b.rom +0 -0
- data/lib/badline/roms/cbm2/basic128.rom +0 -0
- data/lib/badline/roms/cbm2/basic256.rom +0 -0
- data/lib/badline/roms/cbm2/characters-600.rom +0 -0
- data/lib/badline/roms/cbm2/characters-700.rom +0 -0
- data/lib/badline/roms/cbm2/kernal-03b.rom +0 -0
- data/lib/badline/roms/cbm2/kernal-04a.rom +0 -0
- data/lib/badline/roms/cbm2/p500-basic.rom +0 -0
- data/lib/badline/roms/cbm2/p500-kernal.rom +0 -0
- data/lib/badline/snapshot/cbm2_setup.rb +53 -0
- data/lib/badline/snapshot/container.rb +7 -2
- data/lib/badline/snapshot/field_doc/markdown.rb +4 -2
- data/lib/badline/snapshot/field_doc.rb +38 -3
- data/lib/badline/snapshot/image.rb +62 -9
- data/lib/badline/snapshot/vice/cbm2.rb +93 -0
- data/lib/badline/snapshot/vice/cbm2_acia.rb +75 -0
- data/lib/badline/snapshot/vice/cbm2_crtc.rb +127 -0
- data/lib/badline/snapshot/vice/cbm2_mains.rb +49 -0
- data/lib/badline/snapshot/vice/cbm2_mem.rb +75 -0
- data/lib/badline/snapshot/vice/cbm2_restore.rb +204 -0
- data/lib/badline/snapshot/vice/cbm2_tpi.rb +58 -0
- data/lib/badline/snapshot/vice/cias.rb +13 -9
- data/lib/badline/snapshot/vice/p500.rb +96 -0
- data/lib/badline/snapshot/vice/p500_restore.rb +130 -0
- data/lib/badline/snapshot/vice/p500_vicii.rb +166 -0
- data/lib/badline/snapshot/vice/pet.rb +7 -3
- data/lib/badline/snapshot/vice/pet_cpu.rb +5 -2
- data/lib/badline/snapshot/vice/pet_crtc.rb +10 -15
- data/lib/badline/snapshot/vice/pet_drive.rb +180 -0
- data/lib/badline/snapshot/vice/pet_drive8050.rb +216 -0
- data/lib/badline/snapshot/vice/pet_restore.rb +70 -6
- data/lib/badline/snapshot/vice/pet_via.rb +6 -5
- data/lib/badline/snapshot/vice/sid_registers.rb +2 -1
- data/lib/badline/snapshot/vice/vicii_import.rb +10 -6
- data/lib/badline/snapshot/vice.rb +3 -0
- data/lib/badline/snapshot.rb +11 -3
- data/lib/badline/storage/crt_file.rb +7 -1
- data/lib/badline/storage/d64_image.rb +7 -0
- data/lib/badline/storage/d80_image.rb +17 -1
- data/lib/badline/storage/d81_image.rb +14 -0
- data/lib/badline/storage/disk_image/bam.rb +18 -3
- data/lib/badline/storage/disk_image/formatting.rb +69 -0
- data/lib/badline/storage/disk_image/writing.rb +35 -0
- data/lib/badline/storage/disk_image.rb +2 -0
- data/lib/badline/storage.rb +1 -0
- data/lib/badline/support/cbm2_checkpoint.rb +48 -0
- data/lib/badline/support/p500_checkpoint.rb +35 -0
- data/lib/badline/version.rb +1 -1
- data/lib/badline.rb +1 -0
- metadata +72 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "badline/storage/crt_file"
|
|
3
4
|
require "badline/storage/p00"
|
|
4
5
|
require "badline/storage/tap"
|
|
5
6
|
|
|
@@ -13,7 +14,8 @@ module Badline
|
|
|
13
14
|
|
|
14
15
|
private
|
|
15
16
|
|
|
16
|
-
# Takes `sid`, `c64`, `vic20`, `c128`, `plus4` or `
|
|
17
|
+
# Takes `sid`, `c64`, `vic20`, `c128`, `plus4`, `pet` or `cbm2` when
|
|
18
|
+
# given first.
|
|
17
19
|
def subcommand(args)
|
|
18
20
|
case args.first
|
|
19
21
|
when "sid" then @sid_command = true
|
|
@@ -22,6 +24,7 @@ module Badline
|
|
|
22
24
|
when "c128" then @family = :c128
|
|
23
25
|
when "plus4" then @family = :plus4
|
|
24
26
|
when "pet" then @family = :pet
|
|
27
|
+
when "cbm2" then @family = :cbm2
|
|
25
28
|
else return
|
|
26
29
|
end
|
|
27
30
|
@family_named = !@sid_command
|
|
@@ -34,23 +37,32 @@ module Badline
|
|
|
34
37
|
when :c128 then C128_MODELS
|
|
35
38
|
when :plus4 then PLUS4_MODELS
|
|
36
39
|
when :pet then PET_MODELS
|
|
40
|
+
when :cbm2 then CBM2_MODELS
|
|
37
41
|
else MODELS
|
|
38
42
|
end
|
|
39
43
|
end
|
|
40
44
|
|
|
41
45
|
# Without a family named, a program that loads at C128_BASIC_START is
|
|
42
|
-
# the C128's,
|
|
43
|
-
#
|
|
46
|
+
# the C128's, an 8050's or 8250's disk or a PET tape the PET's, and a
|
|
47
|
+
# cartridge signed as a CBM-II's the CBM-II's. A program that loads
|
|
48
|
+
# where PET BASIC starts could be a VIC-20's too.
|
|
44
49
|
def pick_family
|
|
45
50
|
return if @family_named || @sid_command || @media_path.nil? || !File.file?(@media_path)
|
|
46
51
|
|
|
47
52
|
if pet_media?
|
|
48
53
|
@family = :pet
|
|
54
|
+
elsif cbm2_cartridge?
|
|
55
|
+
@family = :cbm2
|
|
49
56
|
elsif Media::Extensions::PROGRAMS.include?(File.extname(@media_path).downcase)
|
|
50
57
|
@family = :c128 if Storage::P00.load_address(@media_path) == C128_BASIC_START
|
|
51
58
|
end
|
|
52
59
|
end
|
|
53
60
|
|
|
61
|
+
# Whether the media is a cartridge signed as a CBM-II's.
|
|
62
|
+
def cbm2_cartridge?
|
|
63
|
+
Media::Extensions.kind(@media_path) == :cartridge && Storage::CRTFile.cbm2?(@media_path)
|
|
64
|
+
end
|
|
65
|
+
|
|
54
66
|
# Whether the media is an 8050's or 8250's disk or a PET tape.
|
|
55
67
|
def pet_media?
|
|
56
68
|
kind = Media::Extensions.kind(@media_path)
|
data/lib/badline/options/help.rb
CHANGED
|
@@ -86,6 +86,7 @@ module Badline
|
|
|
86
86
|
#{@program} c128 [options] [media]
|
|
87
87
|
#{@program} plus4 [options] [media]
|
|
88
88
|
#{@program} pet [options] [media]
|
|
89
|
+
#{@program} cbm2 [options] [media]
|
|
89
90
|
#{@program} --headless [options] tune.sid
|
|
90
91
|
#{@program} [options] tune.sid --audio-out FILE
|
|
91
92
|
#{@program} sid [options] FILE|DIR...
|
|
@@ -96,6 +97,7 @@ module Badline
|
|
|
96
97
|
c128 Run a C128 in C128 mode, the one --model names
|
|
97
98
|
plus4 Run a Plus/4 or a C16, the one --model names
|
|
98
99
|
pet Run a PET or a CBM, the one --model names
|
|
100
|
+
cbm2 Run a CBM-II, a B series or a P500, the one --model names
|
|
99
101
|
sid Play .sid tunes and directories of them
|
|
100
102
|
|
|
101
103
|
#{media_kinds}
|
|
@@ -135,6 +137,18 @@ module Badline
|
|
|
135
137
|
it with the DIN character ROM, and --jumpers ram9,rama puts RAM at
|
|
136
138
|
$9000 and $A000, as xpet's -petram9 and -petramA do.
|
|
137
139
|
|
|
140
|
+
The CBM-II takes programs, disks, .d80 and .d82 among them, and
|
|
141
|
+
cartridges, and a cartridge made for it starts one without `cbm2`.
|
|
142
|
+
--kernal 03b fits the 1983 KERNAL in place of 04a, and --60hz runs
|
|
143
|
+
it on 60 Hz mains. Its --true-drive makes device 8 an emulated 2031
|
|
144
|
+
on its IEEE-488 bus, which reads .d64 and .g64 images, and a .d80
|
|
145
|
+
or a .d82 then goes in an emulated 8050 or 8250. Its keys type what
|
|
146
|
+
the host's keys type, F12 is RUN/STOP, Alt with F9 or F10 presses
|
|
147
|
+
its F9 or F10, and the pause menu's KEYBOARD page says where the
|
|
148
|
+
rest are. --model 510 or 510ntsc runs the P500, on the VIC-II with
|
|
149
|
+
KERNAL 02, whose keys are the B series' and whose two joysticks Tab
|
|
150
|
+
switches to.
|
|
151
|
+
|
|
138
152
|
--headless plays a .sid tune on the host's audio device without the
|
|
139
153
|
window, and --audio-out renders it to 16-bit PCM instead. The
|
|
140
154
|
container follows the file's extension, .wav or .aiff. Played on a
|
|
@@ -156,8 +170,8 @@ module Badline
|
|
|
156
170
|
in --at 3500:key=space or --at 250,500:screenshot=shot%05d.bmp.
|
|
157
171
|
key=NAME presses a key (space, return, a, f1, run_stop, restore, and
|
|
158
172
|
on the C128 esc, help, keypad1 and the rest, on the Plus/4
|
|
159
|
-
esc, help and f1 to f3,
|
|
160
|
-
joystick's
|
|
173
|
+
esc, help and f1 to f3, on the PET rvs, escape and kp1, and on
|
|
174
|
+
the CBM-II escape, norm_graph and kp00) or a joystick's
|
|
161
175
|
direction or fire (joy1-up, joy2-fire) for #{Event::HOLD} frames, and
|
|
162
176
|
pushes the C128's caps_lock or forty_eighty, which lock. type=TEXT
|
|
163
177
|
types it, with \\n for RETURN. insert=FILE swaps in a disk, a list's
|
|
@@ -22,6 +22,16 @@ module Badline
|
|
|
22
22
|
# default.
|
|
23
23
|
PET_MODELS = %w[8032 8096 8296 4032 3032 3032b 2001].freeze
|
|
24
24
|
|
|
25
|
+
# The CBM-II's B series, as CBM2::Model names them, the 610 first, the
|
|
26
|
+
# default, and the P500, as CBM2::P500::Model names them.
|
|
27
|
+
CBM2_MODELS = %w[610 620 710 720 510 510ntsc].freeze
|
|
28
|
+
|
|
29
|
+
# The B series' KERNALs --kernal names, 901244-04a first, the default.
|
|
30
|
+
CBM2_KERNALS = %w[04a 03b].freeze
|
|
31
|
+
|
|
32
|
+
# The P500's one KERNAL, 901234-02.
|
|
33
|
+
P500_KERNALS = %w[02].freeze
|
|
34
|
+
|
|
25
35
|
# The true drives --drive-type names for the Plus/4.
|
|
26
36
|
PLUS4_DRIVE_TYPES = %w[1541 1551].freeze
|
|
27
37
|
|
|
@@ -47,7 +57,8 @@ module Badline
|
|
|
47
57
|
section: "Window options", needs: :window),
|
|
48
58
|
Option.new("--no-sound", "Don't play the SID", section: "Window options", needs: :window, build: :native),
|
|
49
59
|
Option.new("--true-drive", "Put a true 1541 on device 8 instead of the KERNAL traps, a 1571 on the C128, " \
|
|
50
|
-
"a 1551 on the Plus/4, a 2031 on the PET"
|
|
60
|
+
"a 1551 on the Plus/4, a 2031 on the PET or the CBM-II, or for a .d80 or .d82 " \
|
|
61
|
+
"an 8050 or 8250",
|
|
51
62
|
section: "Window options", needs: :window),
|
|
52
63
|
Option.new("--drive-type MODEL", "The Plus/4's true drive: 1541 or 1551 (default: 1551); implies --true-drive",
|
|
53
64
|
section: "Window options", needs: :window),
|
|
@@ -55,7 +66,7 @@ module Badline
|
|
|
55
66
|
section: "Window options", needs: :window),
|
|
56
67
|
Option.new("--model NAME", "C64 to run: #{MODELS.join(', ')} (default: #{MODELS.first}); VIC-20: pal; " \
|
|
57
68
|
"C128: #{C128_MODELS.join(', ')}; Plus/4: #{PLUS4_MODELS.join(', ')}; " \
|
|
58
|
-
"PET: #{PET_MODELS.join(', ')}",
|
|
69
|
+
"PET: #{PET_MODELS.join(', ')}; CBM-II: #{CBM2_MODELS.join(', ')}",
|
|
59
70
|
section: "Window options", needs: :window),
|
|
60
71
|
Option.new("--ntsc", "Run an NTSC C64, as --model ntsc does", section: "Window options", needs: :window),
|
|
61
72
|
Option.new("--c64", "Start the C128 in C64 mode, holding C= at power-on",
|
|
@@ -63,7 +74,10 @@ module Badline
|
|
|
63
74
|
Option.new("--ram SIZE", "VIC-20 RAM expansion: #{RAM_NAMES.join(', ')} (default: unexpanded); " \
|
|
64
75
|
"Plus/4 RAM: 16k, 32k or 64k; PET RAM: 4k, 8k, 16k or 32k (default: the model's own)",
|
|
65
76
|
section: "Window options", needs: :window),
|
|
66
|
-
Option.new("--60hz", "Run a CRTC PET's 60 Hz editor instead of its 50 Hz one",
|
|
77
|
+
Option.new("--60hz", "Run a CRTC PET's 60 Hz editor instead of its 50 Hz one, or a CBM-II on 60 Hz mains",
|
|
78
|
+
section: "Window options", needs: :window),
|
|
79
|
+
Option.new("--kernal VERSION", "Fit a CBM-II with KERNAL #{CBM2_KERNALS.join(' or ')} " \
|
|
80
|
+
"(default: #{CBM2_KERNALS.first}); the P500 takes #{P500_KERNALS.first}",
|
|
67
81
|
section: "Window options", needs: :window),
|
|
68
82
|
Option.new("--basic VERSION", "Fit a PET with BASIC 1, 2 or 4, as its board takes (default: its own)",
|
|
69
83
|
section: "Window options", needs: :window),
|
|
@@ -118,7 +132,7 @@ module Badline
|
|
|
118
132
|
section: "Testing options", needs: :window),
|
|
119
133
|
Option.new("--save-snapshot FILE", "Save the machine as a .vsf snapshot after the last frame",
|
|
120
134
|
section: "Testing options", needs: :window),
|
|
121
|
-
Option.new("--vice", "Add VICE's modules to --save-snapshot's C64 or
|
|
135
|
+
Option.new("--vice", "Add VICE's modules to --save-snapshot's C64, PET or CBM-II snapshot",
|
|
122
136
|
section: "Testing options", needs: :window),
|
|
123
137
|
Option.new("--at FRAME:EVENT", "Run EVENT once FRAME frames have run (see above)",
|
|
124
138
|
section: "Testing options", needs: :window),
|
|
@@ -57,6 +57,12 @@ module Badline
|
|
|
57
57
|
value
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
+
def kernal_for(value)
|
|
61
|
+
raise Error, "invalid argument: --kernal #{value}" unless (CBM2_KERNALS + P500_KERNALS).include?(value)
|
|
62
|
+
|
|
63
|
+
value
|
|
64
|
+
end
|
|
65
|
+
|
|
60
66
|
def reu_size(value)
|
|
61
67
|
raise Error, "invalid argument: --reu #{value}" unless REU_SIZES.include?(value)
|
|
62
68
|
|
|
@@ -102,6 +108,7 @@ module Badline
|
|
|
102
108
|
validate_vic20 if @family == :vic20
|
|
103
109
|
@family == :plus4 ? validate_plus4 : refuse_plus4_options
|
|
104
110
|
@family == :pet ? validate_pet : refuse_pet_options
|
|
111
|
+
@family == :cbm2 ? validate_cbm2 : refuse_cbm2_options
|
|
105
112
|
if @family == :c128
|
|
106
113
|
validate_c128
|
|
107
114
|
elsif @c64_mode
|
|
@@ -170,10 +177,10 @@ module Badline
|
|
|
170
177
|
raise Error, "--sid-card-address needs --sid-card" unless @sid_card_address.nil? || @sid_card
|
|
171
178
|
end
|
|
172
179
|
|
|
173
|
-
# Only the PET has
|
|
174
|
-
#
|
|
180
|
+
# Only the PET has BASIC and editor ROMs to fit, and only it and the
|
|
181
|
+
# CBM-II a frame rate to pick.
|
|
175
182
|
def refuse_pet_options
|
|
176
|
-
raise Error, "--60hz needs pet" unless @refresh_hz.nil?
|
|
183
|
+
raise Error, "--60hz needs pet or cbm2" unless @refresh_hz.nil? || @family == :cbm2
|
|
177
184
|
raise Error, "--basic needs pet" unless @basic.nil?
|
|
178
185
|
raise Error, "--editor needs pet" unless @editor.nil?
|
|
179
186
|
raise Error, "--characters needs pet" unless @characters.nil?
|
|
@@ -232,6 +239,23 @@ module Badline
|
|
|
232
239
|
@refresh_hz = editor_hz
|
|
233
240
|
end
|
|
234
241
|
|
|
242
|
+
# Only the CBM-II has a KERNAL to pick.
|
|
243
|
+
def refuse_cbm2_options
|
|
244
|
+
raise Error, "--kernal needs cbm2" unless @kernal.nil?
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
# The CBM-II runs in the window, without the C64's SID and REU, and
|
|
248
|
+
# its model takes the KERNAL named.
|
|
249
|
+
def validate_cbm2
|
|
250
|
+
raise Error, "--ntsc needs the C64; a CBM-II on 60 Hz mains is --60hz" if @models.include?("ntsc")
|
|
251
|
+
raise Error, "--sid needs the C64" unless @sid_model.nil?
|
|
252
|
+
raise Error, "--reu needs the C64" unless @reu.nil?
|
|
253
|
+
raise Error, "the CBM-II needs the window" if headless?
|
|
254
|
+
|
|
255
|
+
kernals = p500? ? P500_KERNALS : CBM2_KERNALS
|
|
256
|
+
raise Error, "the #{model} takes KERNAL #{kernals.join(' or ')}" unless kernals.include?(kernal)
|
|
257
|
+
end
|
|
258
|
+
|
|
235
259
|
# `sid` takes directories as well as tunes.
|
|
236
260
|
def validate_tune(path)
|
|
237
261
|
return if !File.exist?(path) || File.extname(path).casecmp?(".sid")
|
data/lib/badline/options.rb
CHANGED
|
@@ -13,10 +13,11 @@ module Badline
|
|
|
13
13
|
# Either opens the window for any media, or with --headless or
|
|
14
14
|
# --audio-out plays or renders a .sid tune without one. `sid`, given
|
|
15
15
|
# first, plays .sid tunes and directories of them in the terminal.
|
|
16
|
-
# `c64`, `vic20`, `c128`, `plus4` or `
|
|
17
|
-
# machine family, and without one the family is the C64, the C128
|
|
18
|
-
# program that loads where C128 BASIC starts,
|
|
19
|
-
# or 8250's disk or a PET tape
|
|
16
|
+
# `c64`, `vic20`, `c128`, `plus4`, `pet` or `cbm2`, given first, names
|
|
17
|
+
# the machine family, and without one the family is the C64, the C128
|
|
18
|
+
# for a program that loads where C128 BASIC starts, the PET for an
|
|
19
|
+
# 8050's or 8250's disk or a PET tape, or the CBM-II for a cartridge
|
|
20
|
+
# signed as its own.
|
|
20
21
|
# The native build adds --no-sound and --version, and badline-ruby adds
|
|
21
22
|
# --disable-jit.
|
|
22
23
|
#
|
|
@@ -77,7 +78,7 @@ module Badline
|
|
|
77
78
|
:audio_out, :seconds, :songlengths, :filter_chunk, :timeline
|
|
78
79
|
|
|
79
80
|
# The machine family to build (Badline::Machine), :c64, :vic20, :c128,
|
|
80
|
-
# :plus4 or :
|
|
81
|
+
# :plus4, :pet or :cbm2.
|
|
81
82
|
attr_reader :family
|
|
82
83
|
|
|
83
84
|
# The ROMs --basic, --editor and --characters fit a PET with, keys of
|
|
@@ -137,6 +138,7 @@ module Badline
|
|
|
137
138
|
@ram_kb = nil
|
|
138
139
|
@ram_name = nil
|
|
139
140
|
initialize_pet
|
|
141
|
+
@kernal = nil
|
|
140
142
|
@cartridges = {}
|
|
141
143
|
@autostart = true
|
|
142
144
|
@writable = false
|
|
@@ -246,9 +248,20 @@ module Badline
|
|
|
246
248
|
def c64_mode? = @c64_mode
|
|
247
249
|
|
|
248
250
|
# The frame rate of a CRTC PET's editor: 60 with --60hz or a 60 Hz
|
|
249
|
-
# --editor, else 50.
|
|
251
|
+
# --editor, else 50. A B series CBM-II's mains, which its editor
|
|
252
|
+
# follows.
|
|
250
253
|
def refresh_hz = @refresh_hz || 50
|
|
251
254
|
|
|
255
|
+
# The CBM-II's mains, 60 with --60hz, or nil for the model's own.
|
|
256
|
+
def mains_hz = @refresh_hz
|
|
257
|
+
|
|
258
|
+
# The CBM-II's KERNAL --kernal names, one of CBM2_KERNALS or, on the
|
|
259
|
+
# P500, P500_KERNALS, the first of them without it.
|
|
260
|
+
def kernal = @kernal || (p500? ? P500_KERNALS : CBM2_KERNALS).first
|
|
261
|
+
|
|
262
|
+
# Whether the CBM-II to run is a P500, a 510 of either region.
|
|
263
|
+
def p500? = @family == :cbm2 && model.start_with?("510")
|
|
264
|
+
|
|
252
265
|
def help? = @help
|
|
253
266
|
|
|
254
267
|
def version? = @version
|
|
@@ -264,7 +277,7 @@ module Badline
|
|
|
264
277
|
# A .sid on its own plays in the SID player, as `sid` would, unless an
|
|
265
278
|
# option of the emulator's window asks for the machine.
|
|
266
279
|
def play_lone_tune
|
|
267
|
-
return if @sid_command || %i[vic20 plus4 pet].include?(@family) || headless? || !@window_only.empty?
|
|
280
|
+
return if @sid_command || %i[vic20 plus4 pet cbm2].include?(@family) || headless? || !@window_only.empty?
|
|
268
281
|
return if @media_path.nil?
|
|
269
282
|
|
|
270
283
|
@sid_command = File.extname(@media_path).casecmp?(".sid")
|
|
@@ -326,6 +339,7 @@ module Badline
|
|
|
326
339
|
when "--ram" then @ram_name = value
|
|
327
340
|
when "--basic", "--editor", "--characters", "--jumpers" then pet_option(name, value)
|
|
328
341
|
when "--drive-type" then @drive_type = drive_type_for(value)
|
|
342
|
+
when "--kernal" then @kernal = kernal_for(value)
|
|
329
343
|
when "--c1lo", "--c1hi", "--c2lo", "--c2hi" then @cartridges[CARTRIDGE_SLOTS.fetch(name)] = value
|
|
330
344
|
when "--frames" then @frames = number(flag, value)
|
|
331
345
|
when "--screenshot" then @screenshot = value
|
|
@@ -11,7 +11,8 @@ module Badline
|
|
|
11
11
|
# Both record from VIA PB3. The KERNAL reads each tape as the falling
|
|
12
12
|
# edges its read line makes, as the C64 and VIC-20 do. The machine
|
|
13
13
|
# passes the motor and write lines on after each write to the I/O
|
|
14
|
-
# chips (#lines_written)
|
|
14
|
+
# chips (#lines_written), and clocks the decks only while a tape runs
|
|
15
|
+
# (#running?).
|
|
15
16
|
class Cassettes
|
|
16
17
|
attr_reader :datasette1, :datasette2
|
|
17
18
|
|
|
@@ -22,6 +23,18 @@ module Badline
|
|
|
22
23
|
@datasette2 = Drives::Datasette.new
|
|
23
24
|
@datasette1.on_flag { pulse1 }
|
|
24
25
|
@datasette2.on_flag { pulse2 }
|
|
26
|
+
@running = false
|
|
27
|
+
@running_handler = nil
|
|
28
|
+
@datasette1.on_running_change { update_running }
|
|
29
|
+
@datasette2.on_running_change { update_running }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Whether either deck's tape runs.
|
|
33
|
+
def running? = @running
|
|
34
|
+
|
|
35
|
+
# Whether either deck's tape runs, each time that changes.
|
|
36
|
+
def on_running_change(&handler)
|
|
37
|
+
@running_handler = handler
|
|
25
38
|
end
|
|
26
39
|
|
|
27
40
|
def cycle!
|
|
@@ -48,6 +61,14 @@ module Badline
|
|
|
48
61
|
|
|
49
62
|
private
|
|
50
63
|
|
|
64
|
+
def update_running
|
|
65
|
+
running = @datasette1.running? || @datasette2.running?
|
|
66
|
+
return if running == @running
|
|
67
|
+
|
|
68
|
+
@running = running
|
|
69
|
+
@running_handler&.call
|
|
70
|
+
end
|
|
71
|
+
|
|
51
72
|
# A falling edge on a read line, and the line back up.
|
|
52
73
|
def pulse1
|
|
53
74
|
@pia1.ca1 = false
|
|
@@ -1,76 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "badline/
|
|
3
|
+
require "badline/machine/ieee_drives"
|
|
4
4
|
|
|
5
5
|
module Badline
|
|
6
6
|
class PET
|
|
7
|
-
# The PET's true drive
|
|
8
|
-
# (IEEEPorts),
|
|
9
|
-
# the PET's RES line reaches IFC. The traps on the KERNAL's primitives
|
|
10
|
-
# (IEEETraps) leave device 8 to the drive while it is device 8.
|
|
7
|
+
# The PET's true drive, a 2031, 8050 or 8250 on its IEEE-488 bus
|
|
8
|
+
# (IEEEPorts), as Machine::IEEEDrives has it, at the PET's 1 MHz.
|
|
11
9
|
module IEEEDrive
|
|
12
|
-
|
|
13
|
-
attr_reader :drive2031
|
|
14
|
-
|
|
15
|
-
# Plugs in a Drives::Model2031, in place of the one there.
|
|
16
|
-
def attach_drive2031(drive)
|
|
17
|
-
detach_drive2031
|
|
18
|
-
drive.host_clock_hz = 1_000_000
|
|
19
|
-
drive.connect(@ieee.bus)
|
|
20
|
-
@drive2031 = drive
|
|
21
|
-
@ieee.lines_written
|
|
22
|
-
@ieee_trap&.device = trap_device
|
|
23
|
-
@init_threshold = [@init_threshold, Badline::Drives::Model2031::BOOT_CYCLES].max if @cycles < @init_threshold
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
# Unplugs the 2031, leaving it on a bus of its own.
|
|
27
|
-
def detach_drive2031
|
|
28
|
-
drive = @drive2031
|
|
29
|
-
return unless drive
|
|
30
|
-
|
|
31
|
-
drive.connect(Badline::Drives::IEEEBus.new)
|
|
32
|
-
@drive2031 = nil
|
|
33
|
-
@ieee_trap&.device = trap_device
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# The true drive on the bus, or nil.
|
|
37
|
-
def true_drive = @drive2031
|
|
38
|
-
|
|
39
|
-
# Plugs in a 2031 as device 8, in place of the drive there, and
|
|
40
|
-
# returns it.
|
|
41
|
-
def plug_true_drive
|
|
42
|
-
Badline::Drives::Model2031.new.tap { |drive| attach_drive2031(drive) }
|
|
43
|
-
end
|
|
10
|
+
include Machine::IEEEDrives
|
|
44
11
|
|
|
45
12
|
private
|
|
46
13
|
|
|
47
|
-
|
|
48
|
-
# BL-D8, BL-D8-CPU and so on for device 8.
|
|
49
|
-
def save_drive_modules(sections)
|
|
50
|
-
drive = @drive2031
|
|
51
|
-
drive&.save_modules(sections, "BL-D#{drive.device}")
|
|
52
|
-
sections
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
# The 2031 a snapshot's modules hold, built afresh unless one is on
|
|
56
|
-
# the bus as the same device, or none when they hold no drive. The
|
|
57
|
-
# bus then carries the PET's lines as its chips left them.
|
|
58
|
-
def load_drive_modules(modules)
|
|
59
|
-
device = 8
|
|
60
|
-
input = modules.optional("BL-D8")
|
|
61
|
-
while input.nil? && device < 11
|
|
62
|
-
device += 1
|
|
63
|
-
input = modules.optional("BL-D#{device}")
|
|
64
|
-
end
|
|
65
|
-
if input
|
|
66
|
-
detach_drive2031 if @drive2031 && @drive2031.device != device
|
|
67
|
-
attach_drive2031(Badline::Drives::Model2031.new(device:)) unless @drive2031
|
|
68
|
-
@drive2031.load_modules(modules, input, "BL-D#{device}")
|
|
69
|
-
else
|
|
70
|
-
detach_drive2031
|
|
71
|
-
end
|
|
72
|
-
@ieee.lines_written
|
|
73
|
-
end
|
|
14
|
+
def ieee_host_clock_hz = 1_000_000
|
|
74
15
|
end
|
|
75
16
|
end
|
|
76
17
|
end
|
|
@@ -57,6 +57,13 @@ module Badline
|
|
|
57
57
|
bus.host_lines = controller_lines unless bus.drives.empty?
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
+
# The drives on the bus see the lines the PET pulls now.
|
|
61
|
+
def push_lines = lines_written
|
|
62
|
+
|
|
63
|
+
# Nothing to push once a cycle: the PET pushes its lines as its chips
|
|
64
|
+
# are written.
|
|
65
|
+
def cycle_lines = nil
|
|
66
|
+
|
|
60
67
|
private
|
|
61
68
|
|
|
62
69
|
def low_lines = @bus.low_lines(controller_lines)
|
data/lib/badline/pet.rb
CHANGED
|
@@ -106,6 +106,7 @@ module Badline
|
|
|
106
106
|
@via = VIA.new(start: 0xe800, peripheral: VIAPorts.new(self))
|
|
107
107
|
@sound = Sound.new(@via)
|
|
108
108
|
@cassettes = Cassettes.new(@pia1, @via)
|
|
109
|
+
watch_tapes
|
|
109
110
|
keyboard_ports.connect(@pia1, @ieee, @cassettes)
|
|
110
111
|
characters = Characters.new(@model.characters)
|
|
111
112
|
@crtc_output = CRTCVideo.new(characters, @via, registers, columns80: @model.video == :crtc80,
|
|
@@ -130,7 +131,7 @@ module Badline
|
|
|
130
131
|
@dos = nil
|
|
131
132
|
@ieee_trap = nil
|
|
132
133
|
@capture_output = nil
|
|
133
|
-
|
|
134
|
+
init_ieee_drives
|
|
134
135
|
@init_threshold = boot_cycles(ram_kb)
|
|
135
136
|
end
|
|
136
137
|
|
|
@@ -177,10 +178,10 @@ module Badline
|
|
|
177
178
|
@pia2.cycle!
|
|
178
179
|
@via.cycle!
|
|
179
180
|
@sound.cycle! if @sound.recording?
|
|
180
|
-
@cassettes.cycle!
|
|
181
|
+
@cassettes.cycle! if @tapes_running
|
|
181
182
|
@cpu.irq = @pia1.irq? || @pia2.irq? || @via.irq?
|
|
182
183
|
@cpu.cycle!
|
|
183
|
-
|
|
184
|
+
clock_ieee_drives
|
|
184
185
|
|
|
185
186
|
@cycles += 1
|
|
186
187
|
end
|
|
@@ -197,7 +198,7 @@ module Badline
|
|
|
197
198
|
@via.reset!
|
|
198
199
|
@crtc.reset!
|
|
199
200
|
@bus.reset!
|
|
200
|
-
|
|
201
|
+
reset_ieee_drives
|
|
201
202
|
@ieee.lines_written
|
|
202
203
|
@cpu.reset!
|
|
203
204
|
end
|
|
@@ -234,6 +235,16 @@ module Badline
|
|
|
234
235
|
# on a 3032 and 1,980,000 on an 8032.
|
|
235
236
|
def boot_cycles(ram_kb) = (@model.basic == "pet/basic4.rom" ? 700_000 : 150_000) + (46_000 * ram_kb)
|
|
236
237
|
|
|
238
|
+
# The decks are clocked only while a tape runs.
|
|
239
|
+
def watch_tapes
|
|
240
|
+
@tapes_running = false
|
|
241
|
+
@cassettes.on_running_change { tapes_changed }
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def tapes_changed
|
|
245
|
+
@tapes_running = @cassettes.running?
|
|
246
|
+
end
|
|
247
|
+
|
|
237
248
|
def drive_retrace(high)
|
|
238
249
|
return if high == @vertical_drive
|
|
239
250
|
|