badline 0.15.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +102 -0
- data/CLAUDE.md +15 -7
- data/README.md +142 -16
- data/doc/media.md +19 -0
- data/doc/pinned-behaviour.md +67 -0
- data/doc/snapshot-format.md +274 -31
- data/doc/snapshots.md +14 -0
- data/exe/badline-ruby +1 -1
- data/lib/badline/audio/machine_player.rb +2 -14
- data/lib/badline/c64/common.rb +1 -1
- data/lib/badline/c64/true_drives.rb +13 -1
- data/lib/badline/c64.rb +6 -0
- 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/tia.rb +16 -0
- data/lib/badline/core.rb +3 -0
- data/lib/badline/drives/datasette/keyed_state.rb +8 -3
- data/lib/badline/drives/engine/core.rb +6 -14
- data/lib/badline/drives/engine/idle.rb +42 -4
- data/lib/badline/drives/engine/idle_cpu.rb +18 -0
- data/lib/badline/drives/engine/serial_connection.rb +25 -0
- data/lib/badline/drives/engine/sleep.rb +1 -0
- data/lib/badline/drives/engine.rb +1 -0
- data/lib/badline/drives/ieee_bus.rb +28 -0
- data/lib/badline/drives/model1541/byte_ready.rb +19 -3
- data/lib/badline/drives/model1541/mechanism.rb +10 -1
- data/lib/badline/drives/model1541.rb +1 -0
- data/lib/badline/drives/model1551/bus.rb +138 -0
- data/lib/badline/drives/model1551/cable.rb +107 -0
- data/lib/badline/drives/model1551/cpu.rb +14 -0
- data/lib/badline/drives/model1551/keyed_state.rb +65 -0
- data/lib/badline/drives/model1551/port.rb +74 -0
- data/lib/badline/drives/model1551/tia.rb +71 -0
- data/lib/badline/drives/model1551.rb +192 -0
- data/lib/badline/drives/model1571.rb +1 -0
- data/lib/badline/drives/model1581.rb +1 -0
- data/lib/badline/drives.rb +1 -0
- data/lib/badline/frontend/app.rb +1 -1
- data/lib/badline/frontend/boot.rb +20 -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 +15 -6
- data/lib/badline/frontend/menu/menu_media.rb +96 -19
- data/lib/badline/frontend/menu/menu_pages.rb +25 -7
- 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/player/player_controller.rb +11 -4
- 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 +148 -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 +37 -11
- 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 +7 -5
- data/lib/badline/media/vic20_media.rb +2 -2
- data/lib/badline/media.rb +36 -16
- data/lib/badline/options/family.rb +17 -6
- data/lib/badline/options/help.rb +23 -5
- data/lib/badline/options/option.rb +2 -1
- data/lib/badline/options/table.rb +28 -4
- data/lib/badline/options/validation.rb +117 -14
- data/lib/badline/options.rb +65 -21
- data/lib/badline/pet/bus/expansion.rb +106 -0
- data/lib/badline/pet/bus.rb +204 -0
- data/lib/badline/pet/canvas.rb +97 -0
- data/lib/badline/pet/cassettes.rb +63 -0
- data/lib/badline/pet/characters.rb +26 -0
- data/lib/badline/pet/cpu.rb +10 -0
- data/lib/badline/pet/crtc_video.rb +142 -0
- data/lib/badline/pet/discrete_video.rb +83 -0
- data/lib/badline/pet/ieee_ports.rb +66 -0
- data/lib/badline/pet/ieee_traps.rb +75 -0
- data/lib/badline/pet/keyboard_ports.rb +74 -0
- data/lib/badline/pet/keyed_modules.rb +85 -0
- data/lib/badline/pet/keyed_parts.rb +123 -0
- data/lib/badline/pet/keyed_state.rb +42 -0
- data/lib/badline/pet/model.rb +113 -0
- data/lib/badline/pet/rom_sets.rb +65 -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 +226 -0
- data/lib/badline/plus4/acia/frames.rb +55 -0
- data/lib/badline/plus4/acia.rb +276 -16
- data/lib/badline/plus4/bus.rb +181 -45
- data/lib/badline/plus4/keyed_modules.rb +22 -5
- data/lib/badline/plus4/keyed_parts.rb +33 -4
- data/lib/badline/plus4/keyed_state.rb +10 -5
- data/lib/badline/plus4/ram_expansion.rb +145 -0
- data/lib/badline/plus4/sid_card.rb +95 -0
- data/lib/badline/plus4/sound_mix.rb +51 -0
- data/lib/badline/plus4/tcbm_drive.rb +134 -0
- data/lib/badline/plus4/user_port.rb +11 -2
- data/lib/badline/plus4.rb +104 -22
- data/lib/badline/roms/README +146 -0
- data/lib/badline/roms/dos1551.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/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.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 +2 -0
- data/lib/badline/snapshot/field_doc/markdown.rb +1 -1
- data/lib/badline/snapshot/field_doc.rb +21 -6
- data/lib/badline/snapshot/image.rb +14 -7
- data/lib/badline/snapshot/pet_setup.rb +71 -0
- data/lib/badline/snapshot/plus4_setup.rb +52 -10
- data/lib/badline/snapshot/storage_setup.rb +7 -1
- 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/g64_image.rb +1 -1
- 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 +69 -1
data/lib/badline/plus4.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require "badline/chips/ted"
|
|
4
4
|
require "badline/chips/tia"
|
|
5
|
+
require "badline/drives/model1551"
|
|
5
6
|
require "badline/plus4/model"
|
|
6
7
|
require "badline/plus4/cpu"
|
|
7
8
|
require "badline/plus4/cpu_port"
|
|
@@ -9,7 +10,11 @@ require "badline/plus4/keyboard_port"
|
|
|
9
10
|
require "badline/plus4/user_port"
|
|
10
11
|
require "badline/plus4/cassette_sense"
|
|
11
12
|
require "badline/plus4/acia"
|
|
13
|
+
require "badline/plus4/sid_card"
|
|
14
|
+
require "badline/plus4/sound_mix"
|
|
15
|
+
require "badline/plus4/ram_expansion"
|
|
12
16
|
require "badline/plus4/bus"
|
|
17
|
+
require "badline/plus4/tcbm_drive"
|
|
13
18
|
require "badline/snapshot/plus4_setup"
|
|
14
19
|
require "badline/plus4/keyed_parts"
|
|
15
20
|
require "badline/plus4/keyed_state"
|
|
@@ -19,20 +24,31 @@ module Badline
|
|
|
19
24
|
# The Commodore 264 series: the Plus/4, the C16 and the C116. A 7501 on
|
|
20
25
|
# the TED's clock, which runs it once or twice a TED cycle (Chips::TED's
|
|
21
26
|
# Beam), the TED and, on the Plus/4, a 6551 ACIA and the user port's
|
|
22
|
-
# 6529.
|
|
23
|
-
# doesn't have.
|
|
27
|
+
# 6529. The TED and the ACIA pull IRQ, and nothing pulls NMI, which the
|
|
28
|
+
# 7501 doesn't have.
|
|
24
29
|
#
|
|
25
30
|
# The TED paints the picture a front end shows (#video, #timing). Device 8
|
|
26
31
|
# serves disks through the KERNAL traps (C64::KernalTraps), or a true
|
|
27
|
-
# 1541 or 1581 on the serial bus does (
|
|
32
|
+
# 1541 or 1581 on the serial bus or a 1551 on TCBM does (TCBMDrive),
|
|
33
|
+
# cartridges go
|
|
28
34
|
# in the two cartridges' slots, and tapes play on the datasette, whose read
|
|
29
35
|
# line's level the KERNAL times with the TED's timers.
|
|
36
|
+
#
|
|
37
|
+
# A SID card, as third parties built for the 264s, puts a SID at
|
|
38
|
+
# $FD40-$FD5F, or at $FE80-$FE9F as Csory's does. The cards clock it from the TED's single clock, one SID
|
|
39
|
+
# cycle a TED cycle, 886,724 Hz on PAL, below the C64's 985,248 Hz, so a
|
|
40
|
+
# C64 tune plays about a semitone flat (plus4world forum threads 38287
|
|
41
|
+
# and 20130).
|
|
42
|
+
#
|
|
43
|
+
# A RAM expansion, Hannes's 256K or 1M or Csory's 256K, banks more RAM
|
|
44
|
+
# in through a register at $FD16 (RAMExpansion).
|
|
30
45
|
class Plus4
|
|
31
46
|
include IntegerHelper
|
|
32
47
|
include Machine::KeyboardBuffer
|
|
33
48
|
include Machine::Clocking
|
|
34
49
|
include Machine::Settling
|
|
35
50
|
include C64::TrueDrives
|
|
51
|
+
include TCBMDrive
|
|
36
52
|
include C64::KernalTraps
|
|
37
53
|
|
|
38
54
|
# The cycle by which the KERNAL has booted and BASIC printed READY,
|
|
@@ -46,7 +62,7 @@ module Badline
|
|
|
46
62
|
DRIVE_BOOT_CYCLES = 1_200_000
|
|
47
63
|
|
|
48
64
|
attr_reader :model, :bus, :cpu, :ted, :sound, :port, :keyboard, :keyboard_port, :joystick1, :joystick2, :acia,
|
|
49
|
-
:user_port, :datasette, :tias, :iec_bus, :cycles, :ram_kb, :drive1541, :init_threshold
|
|
65
|
+
:user_port, :datasette, :tias, :iec_bus, :cycles, :ram_kb, :drive1541, :init_threshold, :sid_card
|
|
50
66
|
|
|
51
67
|
def family = :plus4
|
|
52
68
|
|
|
@@ -57,8 +73,8 @@ module Badline
|
|
|
57
73
|
def ram = @bus.ram
|
|
58
74
|
|
|
59
75
|
# What a front end plays: the TED's sound, which answers #record and
|
|
60
|
-
# #drain_samples.
|
|
61
|
-
def sound_source = @sound
|
|
76
|
+
# #drain_samples, mixed with the SID card's where one is fitted.
|
|
77
|
+
def sound_source = @sound_mix || @sound
|
|
62
78
|
|
|
63
79
|
# The chip whose #display a front end shows.
|
|
64
80
|
def video = @ted
|
|
@@ -73,7 +89,7 @@ module Badline
|
|
|
73
89
|
ntsc = profile == Chips::TED::NTSC
|
|
74
90
|
Timing.new(clock_hz: profile.clock_hz, cycles_per_line: Chips::TED::Beam::CYCLES_PER_LINE,
|
|
75
91
|
lines_per_frame: ntsc ? 262 : 312, crop: ntsc ? [0, 248, 384, 242] : [0, 276, 384, 288],
|
|
76
|
-
pixel_width: 1)
|
|
92
|
+
pixel_width: 1, dots: 1)
|
|
77
93
|
end
|
|
78
94
|
|
|
79
95
|
# Reads and writes memory as the CPU sees it, through the bus.
|
|
@@ -84,11 +100,16 @@ module Badline
|
|
|
84
100
|
# +model+ names one of Model::ALL, or c116 for the C16, and +ram+ the
|
|
85
101
|
# RAM in K, one of Model::RAM_SIZES, when not the model's own. +tcbm+
|
|
86
102
|
# plugs in a 1551's TCBM interface, the TIAs at $FEC0-$FEFF, with no
|
|
87
|
-
# drive answering on the other side.
|
|
88
|
-
|
|
103
|
+
# drive answering on the other side. +true_drive_model+ names the drive
|
|
104
|
+
# plug_true_drive plugs in, "1541" or "1551". +sid_card+ fits a SID
|
|
105
|
+
# card with a SID of that model, :mos6581 or :mos8580, at
|
|
106
|
+
# +sid_card_address+, $FD40 or $FE80. +ram_expansion+
|
|
107
|
+
# fits a RAMExpansion of that kind, :hannes256, :hannes1m or
|
|
108
|
+
# :csory256, over 64K of the machine's own.
|
|
109
|
+
def initialize(model: "plus4", ram: nil, tcbm: false, true_drive_model: "1551", sid_card: nil,
|
|
110
|
+
sid_card_address: SIDCard::ADDRESSES.first, ram_expansion: nil, debug: false)
|
|
89
111
|
@model = Model.named(model)
|
|
90
|
-
@ram_kb = ram
|
|
91
|
-
raise ArgumentError, "no Plus/4 RAM size of #{@ram_kb}K" unless Model::RAM_SIZES.include?(@ram_kb)
|
|
112
|
+
@ram_kb = fitted_ram(ram, ram_expansion)
|
|
92
113
|
|
|
93
114
|
@ted = Chips::TED.new(@model.ted)
|
|
94
115
|
@keyboard = Input::Keyboard.new(matrix: KeyboardPort::MATRIX)
|
|
@@ -100,39 +121,45 @@ module Badline
|
|
|
100
121
|
@datasette = Drives::Datasette.new(level: true)
|
|
101
122
|
@port = CPUPort.new(serial_bus: @iec_bus, datasette: @datasette)
|
|
102
123
|
plus4_parts = @model.plus4_parts
|
|
103
|
-
@
|
|
124
|
+
@cycles = 0
|
|
125
|
+
@init_threshold = INIT_THRESHOLD
|
|
126
|
+
@acia_irq = false
|
|
127
|
+
@acia_due = ACIA::NEVER
|
|
128
|
+
@due = INIT_THRESHOLD
|
|
129
|
+
@sid_card = sid_card ? SIDCard.new(self, sid_card, sid_card_address) : nil
|
|
130
|
+
@acia = plus4_parts ? ACIA.new(self, @model.ted.clock_hz) : nil
|
|
104
131
|
@user_port = plus4_parts ? UserPort.new(@datasette) : nil
|
|
105
132
|
io = Bus::IOPage.new(keyboard_port: @keyboard_port, acia: @acia, user_port: @user_port,
|
|
106
|
-
cassette_sense: plus4_parts ? nil : CassetteSense.new(@datasette)
|
|
107
|
-
|
|
133
|
+
cassette_sense: plus4_parts ? nil : CassetteSense.new(@datasette),
|
|
134
|
+
sid_card: sid_card_at(0xfd40))
|
|
135
|
+
@bus = Bus.new(ted: @ted, port: @port, io:, model: @model, ram_kb: @ram_kb, ram_expansion:)
|
|
108
136
|
@ted.connect(@bus)
|
|
137
|
+
@bus.plug_sid_card(sid_card_at(0xfe80))
|
|
109
138
|
@tias = tcbm ? [Chips::TIA.new, Chips::TIA.new] : []
|
|
110
139
|
@bus.plug_tcbm(drive8: @tias[0], drive9: @tias[1]) if tcbm
|
|
111
140
|
@cpu = CPU.new(@bus, debug:)
|
|
112
|
-
@cycles = 0
|
|
113
141
|
@sound = Chips::TED::Sound.new(self, @model.ted.clock_hz)
|
|
114
142
|
@ted.sound = @sound
|
|
143
|
+
@sound_mix = @sid_card ? SoundMix.new(@sound, @sid_card) : nil
|
|
115
144
|
@init_handlers = []
|
|
116
145
|
@pending_keys = nil
|
|
117
146
|
@dos = nil
|
|
118
147
|
@serial_trap = nil
|
|
119
148
|
@save_trap = nil
|
|
120
149
|
@capture_output = nil
|
|
121
|
-
|
|
122
|
-
@drive1581 = nil
|
|
123
|
-
@init_threshold = INIT_THRESHOLD
|
|
150
|
+
init_drives(true_drive_model)
|
|
124
151
|
end
|
|
125
152
|
|
|
126
153
|
# One TED cycle: the TED moves on and decides the CPU's clock, then the
|
|
127
154
|
# CPU runs its cycles in it, none while the TED holds the bus.
|
|
128
155
|
def cycle!
|
|
129
|
-
|
|
156
|
+
handle_due if @cycles >= @due
|
|
130
157
|
feed_keyboard if @pending_keys
|
|
131
158
|
|
|
132
159
|
ted = @ted
|
|
133
160
|
ted.cycle!
|
|
134
161
|
@datasette.cycle!
|
|
135
|
-
@cpu.irq = ted.irq?
|
|
162
|
+
@cpu.irq = ted.irq? || @acia_irq
|
|
136
163
|
slots = ted.cpu_slots
|
|
137
164
|
if slots.zero?
|
|
138
165
|
@cpu.stall!
|
|
@@ -142,13 +169,15 @@ module Badline
|
|
|
142
169
|
end
|
|
143
170
|
@drive1541&.host_cycle!
|
|
144
171
|
@drive1581&.host_cycle!
|
|
172
|
+
@drive1551&.host_cycle!
|
|
145
173
|
|
|
146
174
|
@cycles += 1
|
|
147
175
|
end
|
|
148
176
|
|
|
149
177
|
# The RESET line: the CPU, the port, the 6529s, the ACIA, the bank
|
|
150
|
-
# latch and ROM selection,
|
|
151
|
-
# drives. The TED has no
|
|
178
|
+
# latch and ROM selection, a RAM expansion's register, the SID card,
|
|
179
|
+
# and through the serial bus's RESET line, the drives. The TED has no
|
|
180
|
+
# reset pin.
|
|
152
181
|
def reset!
|
|
153
182
|
@port.reset!
|
|
154
183
|
@keyboard_port.reset!
|
|
@@ -156,7 +185,9 @@ module Badline
|
|
|
156
185
|
@dos&.reset!
|
|
157
186
|
@drive1541&.reset!
|
|
158
187
|
@drive1581&.reset!
|
|
188
|
+
@drive1551&.reset!
|
|
159
189
|
@acia&.reset!
|
|
190
|
+
@sid_card&.reset!
|
|
160
191
|
@tias.each(&:reset!)
|
|
161
192
|
@bus.reset!
|
|
162
193
|
@cpu.reset!
|
|
@@ -171,6 +202,13 @@ module Badline
|
|
|
171
202
|
reset!
|
|
172
203
|
end
|
|
173
204
|
|
|
205
|
+
# The ACIA's IRQ line, and the cycle it next has something to do at.
|
|
206
|
+
def acia_changed(irq, due)
|
|
207
|
+
@acia_irq = irq
|
|
208
|
+
@acia_due = due
|
|
209
|
+
schedule
|
|
210
|
+
end
|
|
211
|
+
|
|
174
212
|
# Calls the block with the exit code a VICE testprog writes to $FDCF.
|
|
175
213
|
def install_debug_register(&) = @bus.install_debug_register(&)
|
|
176
214
|
|
|
@@ -201,6 +239,18 @@ module Badline
|
|
|
201
239
|
"#{name} #{standard}, #{@ram_kb}K RAM"
|
|
202
240
|
end
|
|
203
241
|
|
|
242
|
+
# The RAMExpansion fitted, or nil.
|
|
243
|
+
def ram_expansion = @bus.ram_expansion
|
|
244
|
+
|
|
245
|
+
# The RAM expansion as the pause menu names it, such as "HANNES, 256
|
|
246
|
+
# KB", or nil without one.
|
|
247
|
+
def ram_expansion_label
|
|
248
|
+
expansion = @bus.ram_expansion
|
|
249
|
+
return if expansion.nil?
|
|
250
|
+
|
|
251
|
+
"#{RAMExpansion::NAMES.fetch(expansion.kind)}, #{expansion.size_kb} KB"
|
|
252
|
+
end
|
|
253
|
+
|
|
204
254
|
# Stores a PRG's bytes from its load address on, into RAM, and returns
|
|
205
255
|
# that address.
|
|
206
256
|
def load_prg(data)
|
|
@@ -213,6 +263,22 @@ module Badline
|
|
|
213
263
|
|
|
214
264
|
private
|
|
215
265
|
|
|
266
|
+
# The SID card if it is at +address+, or nil.
|
|
267
|
+
def sid_card_at(address)
|
|
268
|
+
card = @sid_card
|
|
269
|
+
card if card && card.address == address
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
# The RAM in K: +ram+, or the model's own, or 64K under a RAM
|
|
273
|
+
# expansion, which needs that much.
|
|
274
|
+
def fitted_ram(ram, ram_expansion)
|
|
275
|
+
ram_kb = ram || (ram_expansion ? 64 : @model.ram_kb)
|
|
276
|
+
raise ArgumentError, "no Plus/4 RAM size of #{ram_kb}K" unless Model::RAM_SIZES.include?(ram_kb)
|
|
277
|
+
raise ArgumentError, "a RAM expansion needs 64K, not #{ram_kb}K" if ram_expansion && ram_kb != 64
|
|
278
|
+
|
|
279
|
+
ram_kb
|
|
280
|
+
end
|
|
281
|
+
|
|
216
282
|
# The 264 KERNAL's keyboard buffer.
|
|
217
283
|
def keyboard_buffer = Machine::KeyboardBuffer::PLUS4_LAYOUT
|
|
218
284
|
|
|
@@ -232,6 +298,22 @@ module Badline
|
|
|
232
298
|
@init_threshold = [@init_threshold, Drives::Model1581::BOOT_CYCLES].max if @cycles < @init_threshold
|
|
233
299
|
end
|
|
234
300
|
|
|
301
|
+
# What falls due at the start of a cycle: the on_init handlers at the
|
|
302
|
+
# init threshold, and the ACIA's next character.
|
|
303
|
+
def handle_due
|
|
304
|
+
handle_init if @cycles == @init_threshold
|
|
305
|
+
acia = @acia
|
|
306
|
+
acia.run!(@cycles) if acia && @cycles >= @acia_due
|
|
307
|
+
schedule
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# The next cycle anything falls due at. A drive that raises the init
|
|
311
|
+
# threshold leaves it early, and handle_due looks again then.
|
|
312
|
+
def schedule
|
|
313
|
+
init = @cycles < @init_threshold ? @init_threshold : ACIA::NEVER
|
|
314
|
+
@due = [@acia_due, init].min
|
|
315
|
+
end
|
|
316
|
+
|
|
235
317
|
# BA stops the CPU at a read, and a write goes ahead.
|
|
236
318
|
def clock_cpu(ted)
|
|
237
319
|
ted.ba_low? && !@cpu.pending_write? ? @cpu.stall! : @cpu.cycle!
|
data/lib/badline/roms/README
CHANGED
|
@@ -79,6 +79,15 @@ Downloaded from
|
|
|
79
79
|
https://www.zimmers.net/anonftp/pub/cbm/firmware/drives/new/1581/1581-rom.318045-02.bin
|
|
80
80
|
SHA-1 01228eae6f066bd9b7b2b6a7fa3f667e41dad393.
|
|
81
81
|
|
|
82
|
+
dos1551.rom
|
|
83
|
+
-----------
|
|
84
|
+
The 1551 disk drive's DOS 2.6, 318008-01, 16 KB for $C000-$FFFF.
|
|
85
|
+
Drives::Model1551 loads it.
|
|
86
|
+
|
|
87
|
+
Downloaded from
|
|
88
|
+
https://www.zimmers.net/anonftp/pub/cbm/firmware/drives/new/1551/1551.318008-01.bin
|
|
89
|
+
SHA-1 fae3c788ad9a6cc2dbdfbcf6c0264b2ca921d55e.
|
|
90
|
+
|
|
82
91
|
Commodore VIC-20 ROMs
|
|
83
92
|
=====================
|
|
84
93
|
|
|
@@ -170,3 +179,140 @@ plus4/function-high.rom
|
|
|
170
179
|
The Plus/4's 3-plus-1 function ROM, high half, 317054-01
|
|
171
180
|
(3-plus-1.317054-01.bin), for $C000-$FFFF in ROM bank 1.
|
|
172
181
|
SHA-1 0ad7ac2db7da692d972e586ca0dfd747d82c7693.
|
|
182
|
+
|
|
183
|
+
Commodore PET/CBM ROMs
|
|
184
|
+
======================
|
|
185
|
+
|
|
186
|
+
Downloaded from
|
|
187
|
+
https://www.zimmers.net/anonftp/pub/cbm/firmware/computers/pet/
|
|
188
|
+
Each BASIC and KERNAL pair is one ROM set, and the editors and the
|
|
189
|
+
character sets are files of their own, so a model's stock set and the
|
|
190
|
+
upgrade ROMs Commodore sold can be picked apart. PET::ROMSets
|
|
191
|
+
(pet/rom_sets.rb) names them for --basic and --editor and says which
|
|
192
|
+
fit each model, and PET::Bus maps the ones fitted.
|
|
193
|
+
|
|
194
|
+
pet/basic1.rom
|
|
195
|
+
--------------
|
|
196
|
+
BASIC 1 for $C000-$DFFF, four 2K chips concatenated:
|
|
197
|
+
901447-09 (rom-2-c000.901447-09.bin, the revision that replaced
|
|
198
|
+
901447-01), 901447-02, 901447-03 and 901447-04 (rom-1-c800, rom-1-d000,
|
|
199
|
+
rom-1-d800).
|
|
200
|
+
SHA-1 3be9cd41b646fefa00d80f1c3433a06146e97c59.
|
|
201
|
+
|
|
202
|
+
pet/editor1.rom
|
|
203
|
+
---------------
|
|
204
|
+
The BASIC 1 screen editor, 901447-05 (rom-1-e000.901447-05.bin), for
|
|
205
|
+
$E000-$E7FF.
|
|
206
|
+
SHA-1 f02f5fb492ba93dbbd390f24c10f7a832dec432a.
|
|
207
|
+
|
|
208
|
+
pet/kernal1.rom
|
|
209
|
+
---------------
|
|
210
|
+
The BASIC 1 KERNAL for $F000-$FFFF, 901447-06 and 901447-07
|
|
211
|
+
(rom-1-f000.901447-06.bin, rom-1-f800.901447-07.bin) concatenated.
|
|
212
|
+
SHA-1 32dc08828e88c74d6433156e64d402b564556308.
|
|
213
|
+
|
|
214
|
+
pet/characters1.rom
|
|
215
|
+
-------------------
|
|
216
|
+
The 2001's character generator, 901447-08 (characters-1.901447-08.bin),
|
|
217
|
+
with upper and lower case swapped against 901447-10.
|
|
218
|
+
SHA-1 3e067cc621e4beafca2b90cb8f6dba975df2855b.
|
|
219
|
+
|
|
220
|
+
pet/basic2.rom
|
|
221
|
+
--------------
|
|
222
|
+
BASIC 2 for $C000-$DFFF, 901465-01 and 901465-02
|
|
223
|
+
(basic-2-c000.901465-01.bin, basic-2-d000.901465-02.bin) concatenated.
|
|
224
|
+
The 2K chips of the 6540 boards (rom-3-*) hold the same bytes.
|
|
225
|
+
SHA-1 9322a9f0354b9049847d98d3a045fbec860a6264.
|
|
226
|
+
|
|
227
|
+
pet/kernal2.rom
|
|
228
|
+
---------------
|
|
229
|
+
The BASIC 2 KERNAL, 901465-03 (kernal-2.901465-03.bin), for $F000-$FFFF.
|
|
230
|
+
SHA-1 38742bdf449f629bcba6276ef24d3daeb7da6e84.
|
|
231
|
+
|
|
232
|
+
pet/editor2-n.rom
|
|
233
|
+
-----------------
|
|
234
|
+
The BASIC 2 editor for the graphics keyboard, 901447-24
|
|
235
|
+
(edit-2-n.901447-24.bin), for $E000-$E7FF.
|
|
236
|
+
SHA-1 5e5502ce32f5a7e387d65efe058916282041e54b.
|
|
237
|
+
|
|
238
|
+
pet/editor2-b.rom
|
|
239
|
+
-----------------
|
|
240
|
+
The BASIC 2 editor for the business keyboard, 901474-01
|
|
241
|
+
(edit-2-b.901474-01.bin), for $E000-$E7FF.
|
|
242
|
+
SHA-1 174ace3a8c0348cd21d39cc864e2adc58b0101a9.
|
|
243
|
+
|
|
244
|
+
pet/characters2.rom
|
|
245
|
+
-------------------
|
|
246
|
+
The character generator of BASIC 2 and 4 machines, 901447-10
|
|
247
|
+
(characters-2.901447-10.bin).
|
|
248
|
+
SHA-1 0157a2d55b7ac4eaeb38475889ebeea52e2593db.
|
|
249
|
+
|
|
250
|
+
pet/basic4.rom
|
|
251
|
+
--------------
|
|
252
|
+
BASIC 4 for $B000-$DFFF, 901465-23, 901465-20 and 901465-21
|
|
253
|
+
(basic-4-b000.901465-23.bin, basic-4-c000.901465-20.bin,
|
|
254
|
+
basic-4-d000.901465-21.bin) concatenated. 901465-23 is the patched
|
|
255
|
+
$B000 chip that replaced 901465-19. The 8296's 324746-01 holds the same
|
|
256
|
+
four chips.
|
|
257
|
+
SHA-1 d70bec479e1e3a0d0908a4897066e9959bbc11c8.
|
|
258
|
+
|
|
259
|
+
pet/kernal4.rom
|
|
260
|
+
---------------
|
|
261
|
+
The BASIC 4 KERNAL, 901465-22 (kernal-4.901465-22.bin), for
|
|
262
|
+
$F000-$FFFF.
|
|
263
|
+
SHA-1 96a0fa56e0c937da92971d9c99d504e44e898806.
|
|
264
|
+
|
|
265
|
+
pet/editor4-n.rom
|
|
266
|
+
-----------------
|
|
267
|
+
The BASIC 4 editor for the graphics keyboard without a CRTC, 901447-29
|
|
268
|
+
(edit-4-n.901447-29.bin), for $E000-$E7FF.
|
|
269
|
+
SHA-1 e88f56e5c54b0e8d8d4e8cb39a4647c803c1f51c.
|
|
270
|
+
|
|
271
|
+
pet/editor4-b.rom
|
|
272
|
+
-----------------
|
|
273
|
+
The BASIC 4 editor for the business keyboard without a CRTC, 901474-02
|
|
274
|
+
(edit-4-b.901474-02.bin), for $E000-$E7FF.
|
|
275
|
+
SHA-1 0ca5c4e8f532f914cb0bf86ea9900f20f0a655ce.
|
|
276
|
+
|
|
277
|
+
pet/editor4-40-n-50hz.rom
|
|
278
|
+
-------------------------
|
|
279
|
+
The 4032's 50 Hz editor, 40 columns on a CRTC, graphics keyboard,
|
|
280
|
+
901498-01 (edit-4-40-n-50Hz.901498-01.bin), for $E000-$E7FF.
|
|
281
|
+
SHA-1 05af284c914d53a52987b5f602466de75765f650.
|
|
282
|
+
|
|
283
|
+
pet/editor4-40-n-60hz.rom
|
|
284
|
+
-------------------------
|
|
285
|
+
The 4032's 60 Hz editor, 901499-01 (edit-4-40-n-60Hz.901499-01.bin),
|
|
286
|
+
for $E000-$E7FF.
|
|
287
|
+
SHA-1 8cbf086c1ce4dfb2a2fe24c47476dfb878493dee.
|
|
288
|
+
|
|
289
|
+
pet/editor4-80-b-50hz.rom
|
|
290
|
+
-------------------------
|
|
291
|
+
The 8032's 50 Hz editor, 80 columns on a CRTC, business keyboard,
|
|
292
|
+
901474-04, the chip dated 3681
|
|
293
|
+
(edit-4-80-b-50Hz.901474-04-3681.bin), for $E000-$E7FF.
|
|
294
|
+
SHA-1 7040b283ba39e9630e3d147f7d076b7abc39bc70.
|
|
295
|
+
|
|
296
|
+
zimmers.net has three dumps of 901474-04 that differ. This one is the
|
|
297
|
+
60 Hz 901474-03 below with the 50 Hz jiffy clock patch at $E431-$E441
|
|
298
|
+
and $E455, the CRTC's vertical registers (R4, R5 and R7) changed in both
|
|
299
|
+
of its register tables at $E72A, and the byte at $E787 changed to keep
|
|
300
|
+
the ROM's byte sum at $8A, the same as 901474-03's. The line length (R0)
|
|
301
|
+
stays the 60 Hz editor's. A second chip, dated 0384, reads the same
|
|
302
|
+
(8296/edit-50hz-324243-02b.txt). The -0283 dump changes R0 and sums to
|
|
303
|
+
$AE, and the _alt dump changes R0 and $E787.
|
|
304
|
+
|
|
305
|
+
pet/editor4-80-b-50hz-0283.rom
|
|
306
|
+
------------------------------
|
|
307
|
+
The 8032's other 50 Hz editor, 901474-04, the chip dated 0283
|
|
308
|
+
(edit-4-80-b-50Hz.901474-04-0283.bin), for $E000-$E7FF, which
|
|
309
|
+
--editor 4-80-b-50hz-0283 fits. It differs from the 3681 dump only in
|
|
310
|
+
the CRTC's register tables at $E72A and $E73C: lines of 64 cycles (R0
|
|
311
|
+
63) and frames of 313 lines, with nine scanlines a character row.
|
|
312
|
+
SHA-1 81975eab31a8f4f51ae2a20d099a567c7b3f2dd1.
|
|
313
|
+
|
|
314
|
+
pet/editor4-80-b-60hz.rom
|
|
315
|
+
-------------------------
|
|
316
|
+
The 8032's 60 Hz editor, 901474-03 (edit-4-80-b-60Hz.901474-03.bin),
|
|
317
|
+
for $E000-$E7FF.
|
|
318
|
+
SHA-1 c605fa343fd77c73cbe1e0e9567e2f014f6e7e30.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -36,6 +36,8 @@ module Badline
|
|
|
36
36
|
C128 = "C128"
|
|
37
37
|
# xplus4 names its machine PLUS4, for the C16 too.
|
|
38
38
|
PLUS4 = "PLUS4"
|
|
39
|
+
# xpet names its machine PET, for every model.
|
|
40
|
+
PET = "PET"
|
|
39
41
|
GZIP_MAGIC = "\x1f\x8b".b
|
|
40
42
|
|
|
41
43
|
# The VICE version block, when VICE wrote the file: four version
|
|
@@ -7,7 +7,7 @@ module Badline
|
|
|
7
7
|
# its default, with keys that differ only in a unit's number, such as
|
|
8
8
|
# voice1 to voice3, on one row.
|
|
9
9
|
class Markdown
|
|
10
|
-
NAMES = { "c64" => "C64", "vic20" => "VIC-20", "c128" => "C128", "plus4" => "Plus/4" }.freeze
|
|
10
|
+
NAMES = { "c64" => "C64", "vic20" => "VIC-20", "c128" => "C128", "plus4" => "Plus/4", "pet" => "PET" }.freeze
|
|
11
11
|
TAG_TYPES = { Keyed::INT => "int", Keyed::BOOL => "bool", Keyed::BYTES => "bytes", Keyed::INTS => "ints",
|
|
12
12
|
Keyed::TEXT => "text" }.freeze
|
|
13
13
|
|
|
@@ -36,8 +36,9 @@ module Badline
|
|
|
36
36
|
|
|
37
37
|
# The machines the doc is made from: each family at power-on, the C64
|
|
38
38
|
# with each kind of expansion, cartridge and media, and a second SID,
|
|
39
|
-
#
|
|
40
|
-
# true
|
|
39
|
+
# the 264 series' models, its TCBM interface, cartridge, tape and
|
|
40
|
+
# true drives, the 1541 and the 1551, and a CRTC PET, a 2001, an 8096
|
|
41
|
+
# and a PET with a disk and tapes.
|
|
41
42
|
def self.machines
|
|
42
43
|
{
|
|
43
44
|
"c64" => [C64.new, C64.new(ram_expansion: :plus256k), C64.new(reu: 512),
|
|
@@ -45,11 +46,25 @@ module Badline
|
|
|
45
46
|
with_drive(:d81), with_extra_sids],
|
|
46
47
|
"vic20" => [Vic20.new, with_rom],
|
|
47
48
|
"c128" => [C128.new(mode: :c128), with_drive(:d71)],
|
|
48
|
-
"plus4" => [Plus4.new, Plus4.new(model: "c16"), Plus4.new(tcbm: true),
|
|
49
|
-
|
|
49
|
+
"plus4" => [Plus4.new, Plus4.new(model: "c16"), Plus4.new(tcbm: true), Plus4.new(sid_card: :mos6581),
|
|
50
|
+
Plus4.new(sid_card: :mos8580, sid_card_address: 0xfe80),
|
|
51
|
+
Plus4.new(ram_expansion: :csory256),
|
|
52
|
+
plus4_with_cartridge, plus4_with_tape, plus4_with_drive, plus4_with_drive("1551")],
|
|
53
|
+
"pet" => [PET.new, PET.new(model: "2001"), PET.new(model: "8096"), pet_with_media]
|
|
50
54
|
}
|
|
51
55
|
end
|
|
52
56
|
|
|
57
|
+
# A PET with a disk in device 8 through the traps and a tape in each
|
|
58
|
+
# datasette.
|
|
59
|
+
def self.pet_with_media
|
|
60
|
+
bytes = "C64-TAPE-RAW".bytes + [1, 3, 0, 0, 4, 0, 0, 0, 0x30, 0x30, 0x30, 0x30]
|
|
61
|
+
PET.new.tap do |machine|
|
|
62
|
+
machine.mount(Storage::D64Image.new("", read_only: true, bytes: blank(174_848)))
|
|
63
|
+
machine.cassettes.datasette1.insert(Storage::TAP.new("", bytes:))
|
|
64
|
+
machine.cassettes.datasette2.insert(Storage::TAP.new("", bytes:))
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
53
68
|
def self.blank(length) = Array.new(length, 0)
|
|
54
69
|
|
|
55
70
|
def self.with_cartridge(type)
|
|
@@ -110,8 +125,8 @@ module Badline
|
|
|
110
125
|
Plus4.new(model: "c16").tap { |machine| machine.datasette.insert(Storage::TAP.new("", bytes:)) }
|
|
111
126
|
end
|
|
112
127
|
|
|
113
|
-
def self.plus4_with_drive
|
|
114
|
-
Plus4.new.tap do |machine|
|
|
128
|
+
def self.plus4_with_drive(model = "1541")
|
|
129
|
+
Plus4.new(true_drive_model: model).tap do |machine|
|
|
115
130
|
image = Storage::D64Image.new("", bytes: blank(174_848))
|
|
116
131
|
machine.plug_true_drive.insert(Drives::Model1541::Disk.decode(image))
|
|
117
132
|
end
|
|
@@ -34,7 +34,7 @@ module Badline
|
|
|
34
34
|
# of a machine in memory (.of).
|
|
35
35
|
class Image
|
|
36
36
|
MACHINE = "BL-MACHINE"
|
|
37
|
-
FAMILIES = { "c64" => "C64", "vic20" => "VIC-20", "c128" => "C128", "plus4" => "Plus/4" }.freeze
|
|
37
|
+
FAMILIES = { "c64" => "C64", "vic20" => "VIC-20", "c128" => "C128", "plus4" => "Plus/4", "pet" => "PET" }.freeze
|
|
38
38
|
|
|
39
39
|
attr_reader :container
|
|
40
40
|
|
|
@@ -54,10 +54,11 @@ module Badline
|
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
# The snapshot with VICE's modules ahead of the BL-* ones for a C64,
|
|
57
|
-
# so x64sc opens it too. Raises FormatError for a Plus/4,
|
|
58
|
-
# snapshots badline doesn't write for xplus4.
|
|
57
|
+
# so x64sc opens it too. Raises FormatError for a Plus/4 or a PET,
|
|
58
|
+
# whose snapshots badline doesn't write for xplus4 or xpet.
|
|
59
59
|
def self.exported(computer)
|
|
60
60
|
raise FormatError, "badline doesn't export a Plus/4's snapshot for VICE" if computer.family == :plus4
|
|
61
|
+
raise FormatError, "badline doesn't export a PET's snapshot for VICE" if computer.family == :pet
|
|
61
62
|
|
|
62
63
|
computer.settle_for_snapshot!
|
|
63
64
|
sections = computer.save_modules
|
|
@@ -71,6 +72,7 @@ module Badline
|
|
|
71
72
|
when :vic20 then Container::VIC20
|
|
72
73
|
when :c128 then Container::C128
|
|
73
74
|
when :plus4 then Container::PLUS4
|
|
75
|
+
when :pet then Container::PET
|
|
74
76
|
else Container::MACHINE
|
|
75
77
|
end
|
|
76
78
|
end
|
|
@@ -82,6 +84,7 @@ module Badline
|
|
|
82
84
|
when "vic20" then Vic20Setup.read_fields(machine)
|
|
83
85
|
when "c128" then C128Setup.read_fields(machine)
|
|
84
86
|
when "plus4" then Plus4Setup.read_fields(machine)
|
|
87
|
+
when "pet" then PETSetup.read_fields(machine)
|
|
85
88
|
else C64Setup.read_fields(machine)
|
|
86
89
|
end
|
|
87
90
|
end
|
|
@@ -97,15 +100,16 @@ module Badline
|
|
|
97
100
|
|
|
98
101
|
# A new machine, built as the snapshot's was and restored from it. A
|
|
99
102
|
# badline snapshot restores from its BL-* modules alone, and a VICE
|
|
100
|
-
# one through the modules badline reads. xvic's, x128's
|
|
101
|
-
# modules aren't read. Yields a line for each thing left
|
|
102
|
-
# warns it without a block. `detached` restores it without
|
|
103
|
-
# files (Keyed::Modules).
|
|
103
|
+
# one through the modules badline reads. xvic's, x128's, xplus4's and
|
|
104
|
+
# xpet's own modules aren't read. Yields a line for each thing left
|
|
105
|
+
# out, or warns it without a block. `detached` restores it without
|
|
106
|
+
# the host's files (Keyed::Modules).
|
|
104
107
|
def load(detached: false, &)
|
|
105
108
|
refuse_old_layout
|
|
106
109
|
raise FormatError, "badline reads only its own VIC-20 snapshots, not xvic's" if vic20? && !badline?
|
|
107
110
|
raise FormatError, "badline reads only its own C128 snapshots, not x128's" if c128? && !badline?
|
|
108
111
|
raise FormatError, "badline reads only its own Plus/4 snapshots, not xplus4's" if plus4? && !badline?
|
|
112
|
+
raise FormatError, "badline reads only its own PET snapshots, not xpet's" if pet? && !badline?
|
|
109
113
|
return load_vice(&) unless badline?
|
|
110
114
|
|
|
111
115
|
modules = Keyed::Modules.new(sections, detached:)
|
|
@@ -123,6 +127,9 @@ module Badline
|
|
|
123
127
|
# Whether the machine is of the 264 series, as the container names it.
|
|
124
128
|
def plus4? = @container.machine == Container::PLUS4
|
|
125
129
|
|
|
130
|
+
# Whether the machine is a PET, as the container names it.
|
|
131
|
+
def pet? = @container.machine == Container::PET
|
|
132
|
+
|
|
126
133
|
# Restores `computer` from the snapshot, and returns the Report. The
|
|
127
134
|
# snapshot goes into a new machine first, so one that fails, or is of
|
|
128
135
|
# a machine built another way, leaves `computer` as it was.
|