badline 0.17.0 → 0.18.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 +153 -0
- data/CLAUDE.md +11 -7
- data/CONTRIBUTING.md +7 -1
- data/README.md +169 -20
- data/doc/pinned-behaviour.md +128 -0
- data/doc/snapshot-format.md +253 -18
- data/doc/snapshots.md +57 -23
- data/exe/badline-ruby +5 -0
- data/lib/badline/audio/terminal.rb +34 -2
- data/lib/badline/c128/keyed_state.rb +2 -0
- data/lib/badline/c128.rb +1 -0
- data/lib/badline/c64/keyed_state.rb +2 -0
- data/lib/badline/c64.rb +1 -0
- data/lib/badline/cbm2/keyed_state.rb +4 -0
- data/lib/badline/cbm2/p500.rb +5 -3
- data/lib/badline/cbm2.rb +6 -3
- data/lib/badline/chips/cia/timer.rb +2 -2
- data/lib/badline/chips/cpu/instruction_set.rb +1 -1
- data/lib/badline/chips/m6809/arithmetic.rb +140 -0
- data/lib/badline/chips/m6809/bus_steps.rb +223 -0
- data/lib/badline/chips/m6809/core.rb +149 -0
- data/lib/badline/chips/m6809/indexed.rb +82 -0
- data/lib/badline/chips/m6809/interrupts.rb +159 -0
- data/lib/badline/chips/m6809/keyed_state.rb +147 -0
- data/lib/badline/chips/m6809/opcodes.rb +159 -0
- data/lib/badline/chips/m6809/operations.rb +258 -0
- data/lib/badline/chips/m6809/plans.rb +143 -0
- data/lib/badline/chips/m6809/registers.rb +82 -0
- data/lib/badline/chips/m6809/stack.rb +140 -0
- data/lib/badline/chips/m6809.rb +13 -0
- data/lib/badline/chips/riot/timer.rb +14 -3
- data/lib/badline/chips/rriot.rb +4 -2
- data/lib/badline/chips/sid/filter.rb +4 -4
- data/lib/badline/chips/sid/waveform.rb +6 -6
- data/lib/badline/chips/vic_i/keyed_parts.rb +7 -2
- data/lib/badline/chips/vic_i.rb +84 -21
- data/lib/badline/data_path.rb +3 -3
- data/lib/badline/drives/ieee_models.rb +54 -0
- data/lib/badline/drives/model1001.rb +37 -0
- data/lib/badline/drives/model2031.rb +6 -0
- data/lib/badline/drives/model4040/disk.rb +62 -0
- data/lib/badline/drives/model4040/ip_bus.rb +46 -0
- data/lib/badline/drives/model4040/keyed_state.rb +57 -0
- data/lib/badline/drives/model4040/mechanism.rb +192 -0
- data/lib/badline/drives/model4040/parts.rb +20 -0
- data/lib/badline/drives/model4040.rb +179 -0
- data/lib/badline/drives/model8050/board.rb +77 -0
- data/lib/badline/drives/model8050/dos_board.rb +91 -0
- data/lib/badline/drives/model8050/idle.rb +11 -7
- data/lib/badline/drives/model8050/keyed_state.rb +5 -2
- data/lib/badline/drives/model8050.rb +18 -130
- data/lib/badline/drives/model9060/idle.rb +149 -0
- data/lib/badline/drives/model9060/keyed_state.rb +123 -0
- data/lib/badline/drives/model9060/parts.rb +98 -0
- data/lib/badline/drives/model9060/sasi_bus.rb +88 -0
- data/lib/badline/drives/model9060/sasi_commands.rb +168 -0
- data/lib/badline/drives/model9060/sasi_target.rb +161 -0
- data/lib/badline/drives/model9060.rb +195 -0
- data/lib/badline/frontend/app.rb +8 -0
- data/lib/badline/frontend/boot.rb +3 -2
- data/lib/badline/frontend/controls.rb +62 -6
- data/lib/badline/frontend/keys.rb +36 -0
- data/lib/badline/frontend/kim1_panel.rb +208 -0
- data/lib/badline/frontend/media_slots.rb +8 -1
- data/lib/badline/frontend/menu/drive_types.rb +56 -0
- data/lib/badline/frontend/menu/menu_dialogs.rb +61 -14
- data/lib/badline/frontend/menu/menu_media.rb +42 -12
- data/lib/badline/frontend/menu/menu_pages.rb +97 -2
- data/lib/badline/frontend/menu/menu_ports.rb +38 -1
- data/lib/badline/frontend/menu/pause_menu.rb +5 -1
- data/lib/badline/frontend/pet_keyboard.rb +23 -1
- data/lib/badline/frontend/screen.rb +1 -1
- data/lib/badline/frontend/screens.rb +40 -2
- data/lib/badline/frontend/teletype_pane.rb +152 -0
- data/lib/badline/frontend/timeline.rb +31 -2
- data/lib/badline/frontend.rb +3 -0
- data/lib/badline/kim1/bus.rb +117 -0
- data/lib/badline/kim1/cpu.rb +25 -0
- data/lib/badline/kim1/host_terminal.rb +74 -0
- data/lib/badline/kim1/key_entry.rb +74 -0
- data/lib/badline/kim1/keyed_modules.rb +53 -0
- data/lib/badline/kim1/keyed_state.rb +133 -0
- data/lib/badline/kim1/panel.rb +176 -0
- data/lib/badline/kim1/rriots.rb +28 -0
- data/lib/badline/kim1/sound.rb +29 -0
- data/lib/badline/kim1/tape.rb +116 -0
- data/lib/badline/kim1/teletype.rb +193 -0
- data/lib/badline/kim1.rb +190 -0
- data/lib/badline/machine/ieee_drives.rb +94 -117
- data/lib/badline/machine/keyboard_buffer.rb +20 -3
- data/lib/badline/machine/line_sound.rb +122 -0
- data/lib/badline/machine.rb +46 -15
- data/lib/badline/media/extensions.rb +8 -4
- data/lib/badline/media/kim1_media.rb +150 -0
- data/lib/badline/media/pet_media.rb +3 -1
- data/lib/badline/media/true_drive.rb +42 -45
- data/lib/badline/media.rb +12 -6
- data/lib/badline/options/family.rb +98 -8
- data/lib/badline/options/help.rb +44 -12
- data/lib/badline/options/table.rb +43 -11
- data/lib/badline/options/validation.rb +44 -8
- data/lib/badline/options.rb +27 -8
- data/lib/badline/pet/bus.rb +16 -2
- data/lib/badline/pet/keyboard_ports.rb +9 -2
- data/lib/badline/pet/keyed_state.rb +4 -0
- data/lib/badline/pet/model.rb +11 -2
- data/lib/badline/pet/rom_sets.rb +1 -0
- data/lib/badline/pet/sound.rb +5 -105
- data/lib/badline/pet/superpet/acia.rb +12 -0
- data/lib/badline/pet/superpet/board.rb +221 -0
- data/lib/badline/pet/superpet/dongle.rb +81 -0
- data/lib/badline/pet/superpet/keyed_modules.rb +63 -0
- data/lib/badline/pet/superpet/keyed_parts.rb +76 -0
- data/lib/badline/pet/superpet/m6809.rb +32 -0
- data/lib/badline/pet/superpet/waterloo_traps.rb +199 -0
- data/lib/badline/pet/superpet.rb +216 -0
- data/lib/badline/pet.rb +19 -3
- data/lib/badline/plus4/keyed_state.rb +2 -0
- data/lib/badline/plus4.rb +1 -0
- data/lib/badline/roms/1001/fdc-251257-02a.rom +0 -0
- data/lib/badline/roms/4040/dos-1.2.rom +0 -0
- data/lib/badline/roms/4040/dos-2.1-rev.rom +0 -0
- data/lib/badline/roms/4040/dos-2.1.rom +0 -0
- data/lib/badline/roms/4040/fdc-901466-02.rom +0 -0
- data/lib/badline/roms/4040/fdc-901466-04.rom +0 -0
- data/lib/badline/roms/9060/dos-3.0.rom +0 -0
- data/lib/badline/roms/9060/sasi-300515-revb.rom +0 -0
- data/lib/badline/roms/README +166 -0
- data/lib/badline/roms/kim1/6530-002.rom +0 -0
- data/lib/badline/roms/kim1/6530-003.rom +0 -0
- data/lib/badline/roms/pet/characters-superpet.rom +0 -0
- data/lib/badline/roms/pet/superpet-a000.rom +0 -0
- data/lib/badline/roms/pet/superpet-c000.rom +0 -0
- data/lib/badline/roms/pet/superpet-e000-50hz.rom +0 -0
- data/lib/badline/roms/pet/superpet-e000.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 +27 -6
- data/lib/badline/snapshot/image.rb +4 -1
- data/lib/badline/snapshot/kim1_setup.rb +28 -0
- data/lib/badline/snapshot/pet_setup.rb +27 -11
- data/lib/badline/snapshot/storage_setup.rb +4 -1
- data/lib/badline/snapshot/vic20_setup.rb +11 -7
- data/lib/badline/snapshot/vice/pet.rb +13 -7
- data/lib/badline/snapshot/vice/pet_cpu.rb +39 -5
- data/lib/badline/snapshot/vice/pet_crtc.rb +15 -2
- data/lib/badline/snapshot/vice/pet_drive8050.rb +188 -68
- data/lib/badline/snapshot/vice/pet_mem.rb +49 -5
- data/lib/badline/snapshot/vice/pet_restore.rb +40 -11
- data/lib/badline/snapshot.rb +4 -0
- data/lib/badline/status.rb +30 -30
- data/lib/badline/storage/d67_image.rb +55 -0
- data/lib/badline/storage/d90_image.rb +180 -0
- data/lib/badline/storage/disk_image/writing.rb +2 -2
- data/lib/badline/storage/kim_tape.rb +254 -0
- data/lib/badline/storage/papertape.rb +90 -0
- data/lib/badline/storage.rb +4 -0
- data/lib/badline/support/kim1_checkpoint.rb +41 -0
- data/lib/badline/support/superpet_checkpoint.rb +35 -0
- data/lib/badline/version.rb +1 -1
- data/lib/badline/vic20/keyed_modules.rb +6 -3
- data/lib/badline/vic20/keyed_state.rb +6 -4
- data/lib/badline/vic20.rb +26 -12
- data/lib/badline.rb +1 -0
- metadata +77 -1
|
@@ -13,8 +13,20 @@ module Badline
|
|
|
13
13
|
COLUMNS = 25
|
|
14
14
|
ROW_WIDTH = 200
|
|
15
15
|
|
|
16
|
+
# The KIM-1's settings on its PANEL page (MenuPorts).
|
|
17
|
+
KIM1_SETTINGS = %i[sst_off sst_on keypad teletype irq_open irq_wired pb7_out pa0_speaker].freeze
|
|
18
|
+
|
|
19
|
+
# The KIM-1's deck on its TAPE page: the keys down, and the rest.
|
|
20
|
+
KIM1_DECK = [%w[STOP PLAY RECORD], %i[kim1_stop kim1_play kim1_record]].freeze
|
|
21
|
+
KIM1_TAPE = (KIM1_DECK.last + %i[kim1_rewind kim1_eject]).freeze
|
|
22
|
+
|
|
16
23
|
RECENT = %i[recent0 recent1 recent2 recent3 recent4 recent5 recent6 recent7].freeze
|
|
17
24
|
|
|
25
|
+
# The SuperPET's switches: SW2 picks the CPU and SW1 protects the
|
|
26
|
+
# bank RAM, each at PROG left to the system latch.
|
|
27
|
+
CPU_SWITCH = [%w[6502 6809 PROG], %i[cpu6502 cpu6809 cpu_prog]].freeze
|
|
28
|
+
RAM_SWITCH = [%w[R/W READ PROG], %i[bank_rw bank_read bank_prog]].freeze
|
|
29
|
+
|
|
18
30
|
SID_MODELS = %i[mos6581 mos8580].freeze
|
|
19
31
|
RAM_NAMES = {
|
|
20
32
|
unexpanded: "", "3k": "3K", "8k": "8K", "16k": "16K", "24k": "24K", "32k": "32K",
|
|
@@ -76,8 +88,12 @@ module Badline
|
|
|
76
88
|
when :swap then @controls.swap_ports
|
|
77
89
|
when :sound_on, :mute then @sound.toggle_mute unless @sound.muted? == (action == :mute)
|
|
78
90
|
when :sid6581, :sid8580 then @computer.sound_source.model = action == :sid8580 ? :mos8580 : :mos6581
|
|
91
|
+
when :cpu6502, :cpu6809, :cpu_prog then switch_cpu(action)
|
|
92
|
+
when :bank_rw, :bank_read, :bank_prog then switch_bank_ram(action)
|
|
79
93
|
when :reset then @computer.reset!
|
|
80
94
|
when :power_cycle then @computer.power_cycle!
|
|
95
|
+
when *KIM1_SETTINGS then kim1_setting(action)
|
|
96
|
+
when *KIM1_TAPE then kim1_tape(action)
|
|
81
97
|
else pick_port(action)
|
|
82
98
|
end
|
|
83
99
|
end
|
|
@@ -92,10 +108,17 @@ module Badline
|
|
|
92
108
|
# too.
|
|
93
109
|
def cbm2? = @computer.family == :cbm2
|
|
94
110
|
|
|
111
|
+
# The model of the true drive on device 8, or an empty one for the
|
|
112
|
+
# traps.
|
|
113
|
+
def drive_model = MediaSlots.drive_model(@computer)
|
|
114
|
+
|
|
95
115
|
# Whether the machine is the CBM-II's B series, whose ports page is
|
|
96
116
|
# its keyboard's alone.
|
|
97
117
|
def b_series? = cbm2? && !Controls.p500?(@computer)
|
|
98
118
|
|
|
119
|
+
# Whether the machine is a KIM-1, whose ports page is its panel's.
|
|
120
|
+
def kim1? = @computer.family == :kim1
|
|
121
|
+
|
|
99
122
|
private
|
|
100
123
|
|
|
101
124
|
def vic20? = @computer.family == :vic20
|
|
@@ -103,6 +126,8 @@ module Badline
|
|
|
103
126
|
def plus4? = @computer.family == :plus4
|
|
104
127
|
|
|
105
128
|
def draw_drive
|
|
129
|
+
return info("DRIVE", "") if kim1?
|
|
130
|
+
|
|
106
131
|
media = @media
|
|
107
132
|
inserted = media.inserted?
|
|
108
133
|
set = inserted ? media.disk_set : []
|
|
@@ -118,11 +143,13 @@ module Badline
|
|
|
118
143
|
skip
|
|
119
144
|
drive = @computer.true_drive
|
|
120
145
|
info("DEVICE", drive.nil? ? "FAST LOADING" : "#{drive.model_name}, TRUE DRIVE")
|
|
146
|
+
row("DRIVE TYPE...", :drive_type, drive_model) if pet? || cbm2?
|
|
121
147
|
end
|
|
122
148
|
|
|
123
|
-
# The CBM-II has no datasette.
|
|
149
|
+
# The CBM-II has no datasette, and the KIM-1 a deck of its own.
|
|
124
150
|
def draw_datasette
|
|
125
151
|
return info("TAPE", "") if cbm2?
|
|
152
|
+
return draw_kim1_tape if kim1?
|
|
126
153
|
|
|
127
154
|
datasette = @computer.datasette
|
|
128
155
|
tape = datasette.tape
|
|
@@ -135,9 +162,55 @@ module Badline
|
|
|
135
162
|
info("MOTOR", datasette.motor? ? "ON" : "OFF")
|
|
136
163
|
end
|
|
137
164
|
|
|
165
|
+
# The KIM-1's deck, with its tape's name and how far into it the deck
|
|
166
|
+
# is, in minutes and seconds.
|
|
167
|
+
def draw_kim1_tape
|
|
168
|
+
deck = @computer.tape
|
|
169
|
+
tape = deck.tape
|
|
170
|
+
info("TAPE", File.basename(tape.path))
|
|
171
|
+
row("INSERT...", :insert_tape)
|
|
172
|
+
row("EJECT", :kim1_eject)
|
|
173
|
+
down = 0
|
|
174
|
+
down = 1 if deck.playing?
|
|
175
|
+
down = 2 if deck.recording?
|
|
176
|
+
toggle("DECK", :kim1_deck, [KIM1_DECK.first, KIM1_DECK.last, down])
|
|
177
|
+
row("REWIND", :kim1_rewind)
|
|
178
|
+
skip
|
|
179
|
+
info("POSITION", "#{clock(deck.position)} OF #{clock(tape.duration)}")
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def clock(microseconds)
|
|
183
|
+
seconds = microseconds / 1_000_000
|
|
184
|
+
"#{seconds / 60}:#{(seconds % 60).to_s.rjust(2, '0')}"
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Presses the KIM-1 deck's keys. RECORD with no file to record to
|
|
188
|
+
# puts a new tape in first, in the tapes folder (Badline.data_folder).
|
|
189
|
+
def kim1_tape(action)
|
|
190
|
+
deck = @computer.tape
|
|
191
|
+
case action
|
|
192
|
+
when :kim1_stop then deck.stop
|
|
193
|
+
when :kim1_play then deck.play
|
|
194
|
+
when :kim1_record
|
|
195
|
+
deck.insert_tape(Storage::KIMTape.create(new_tape_path)) if deck.tape.path.empty?
|
|
196
|
+
deck.record
|
|
197
|
+
when :kim1_rewind then deck.rewind
|
|
198
|
+
else deck.eject
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# The first of kim1-1.wav, kim1-2.wav and on that isn't taken.
|
|
203
|
+
def new_tape_path
|
|
204
|
+
folder = Badline.data_folder("tapes")
|
|
205
|
+
number = 1
|
|
206
|
+
number += 1 while File.exist?(File.join(folder, "kim1-#{number}.wav"))
|
|
207
|
+
File.join(folder, "kim1-#{number}.wav")
|
|
208
|
+
end
|
|
209
|
+
|
|
138
210
|
def draw_expansion
|
|
139
211
|
return draw_pet_memory if pet?
|
|
140
212
|
return info("RAM", "#{@computer.model.ram_kb}K") if cbm2?
|
|
213
|
+
return info("RAM", "1K") if kim1?
|
|
141
214
|
|
|
142
215
|
info("CARTRIDGE", @media.cartridge_name)
|
|
143
216
|
return info("RAM EXPANSION", RAM_NAMES.fetch(@computer.ram_configuration)) if vic20?
|
|
@@ -175,6 +248,8 @@ module Badline
|
|
|
175
248
|
return draw_8296_memory if model.cbm8296?
|
|
176
249
|
|
|
177
250
|
info("RAM", "#{@computer.ram_kb}K")
|
|
251
|
+
return info("BANK RAM", "64K, BANK #{@computer.board.bank} AT $9000") if model.superpet?
|
|
252
|
+
|
|
178
253
|
info("EXPANSION RAM", model.expansion ? "64K BOARD" : "")
|
|
179
254
|
end
|
|
180
255
|
|
|
@@ -204,8 +279,9 @@ module Badline
|
|
|
204
279
|
# 901244 or the P500's 901234.
|
|
205
280
|
def draw_power
|
|
206
281
|
info("MACHINE", "#{@computer.model.name.upcase}, #{@computer.mode.to_s.upcase} MODE") if c128?
|
|
207
|
-
info("MACHINE", @computer.model_label.upcase) if pet? || cbm2?
|
|
282
|
+
info("MACHINE", @computer.model_label.upcase) if pet? || cbm2? || kim1?
|
|
208
283
|
info("KERNAL", "#{Controls.p500?(@computer) ? 901_234 : 901_244}-#{@computer.kernal.upcase}") if cbm2?
|
|
284
|
+
draw_superpet_switches if pet? && @computer.superpet?
|
|
209
285
|
if plus4?
|
|
210
286
|
info("MACHINE", @computer.model_label)
|
|
211
287
|
expansion = @computer.ram_expansion_label
|
|
@@ -217,6 +293,25 @@ module Badline
|
|
|
217
293
|
row("QUIT", :quit)
|
|
218
294
|
end
|
|
219
295
|
|
|
296
|
+
# The SuperPET's CPU switch, which a move applies with a reset, and its
|
|
297
|
+
# bank RAM switch, which applies at once, with the CPU that has the
|
|
298
|
+
# bus.
|
|
299
|
+
def draw_superpet_switches
|
|
300
|
+
board = @computer.board
|
|
301
|
+
toggle("CPU SWITCH", :cpu_switch, [*CPU_SWITCH, PET::SuperPET::Board::CPU_SWITCH.index(board.cpu_switch)])
|
|
302
|
+
toggle("RAM SWITCH", :ram_switch, [*RAM_SWITCH, PET::SuperPET::Board::RAM_SWITCH.index(board.ram_switch)])
|
|
303
|
+
info("RUNNING", @computer.m6809_running? ? "6809, WATERLOO" : "6502, BASIC 4")
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
def switch_cpu(action)
|
|
307
|
+
position = PET::SuperPET::Board::CPU_SWITCH[CPU_SWITCH[1].index(action)]
|
|
308
|
+
@computer.switch_cpu(position) unless position == @computer.board.cpu_switch
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
def switch_bank_ram(action)
|
|
312
|
+
@computer.switch_bank_ram(PET::SuperPET::Board::RAM_SWITCH[RAM_SWITCH[1].index(action)])
|
|
313
|
+
end
|
|
314
|
+
|
|
220
315
|
# A label, and its value under it, or NONE in the dim colour when the
|
|
221
316
|
# value is empty.
|
|
222
317
|
def info(label, value)
|
|
@@ -8,7 +8,11 @@ module Badline
|
|
|
8
8
|
# joystick's, and the Plus/4 two joysticks and no pot devices. The PET
|
|
9
9
|
# and the CBM-II's B series have no ports, and the page, KEYBOARD
|
|
10
10
|
# there, says where their keys are instead. The P500 has two joysticks,
|
|
11
|
-
# and the page says where its keys are while they type.
|
|
11
|
+
# and the page says where its keys are while they type. The KIM-1's,
|
|
12
|
+
# PANEL there, sets its SST switch and TTY/KB jumper, which presses RS
|
|
13
|
+
# for the monitor to start again on the keypad or the teletype, and what its
|
|
14
|
+
# application connector wires: U3's PB7 to IRQ, and a speaker on U3's
|
|
15
|
+
# PA0 in place of the audio output on U2's PB7.
|
|
12
16
|
module MenuPorts
|
|
13
17
|
PORT_DEVICES = %i[joystick mouse paddles].freeze
|
|
14
18
|
PORT_NAMES = %w[JOY MOUSE PADDLES].freeze
|
|
@@ -35,6 +39,7 @@ module Badline
|
|
|
35
39
|
return draw_pet_keys if @computer.family == :pet
|
|
36
40
|
return draw_p500_ports if Controls.p500?(@computer)
|
|
37
41
|
return draw_cbm2_keys if @computer.family == :cbm2
|
|
42
|
+
return draw_kim1_panel if @computer.family == :kim1
|
|
38
43
|
|
|
39
44
|
draw_pot_ports
|
|
40
45
|
return unless draw_keys(@computer.family == :c128 ? "C128" : "C64")
|
|
@@ -68,15 +73,47 @@ module Badline
|
|
|
68
73
|
|
|
69
74
|
# The PET's keyboard, whose keys type the characters on the host's
|
|
70
75
|
# (PETKeyboard), and the keys that stand for the rest of its keys.
|
|
76
|
+
# The SuperPET's 6809 shows whether its keys type ASCII, or go by
|
|
77
|
+
# position for the APL symbols on its keycaps.
|
|
71
78
|
def draw_pet_keys
|
|
72
79
|
business = @computer.model.keyboard == :business
|
|
73
80
|
info("KEYBOARD", business ? "BUSINESS" : "GRAPHICS")
|
|
81
|
+
draw_superpet_characters if @computer.superpet?
|
|
74
82
|
(PET_KEYS + (business ? PET_BUSINESS_KEYS : PET_GRAPHICS_KEYS)).each do |line|
|
|
75
83
|
@painter.text(@left, @top, line, MenuTheme::TEXT)
|
|
76
84
|
@top += MenuPages::LINE
|
|
77
85
|
end
|
|
78
86
|
end
|
|
79
87
|
|
|
88
|
+
def draw_superpet_characters
|
|
89
|
+
apl = @computer.apl_characters?
|
|
90
|
+
return unless apl || @computer.m6809_running?
|
|
91
|
+
|
|
92
|
+
info("CHARACTERS", apl ? "APL, KEYS BY POSITION" : "ASCII")
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def draw_kim1_panel
|
|
96
|
+
kim = @computer
|
|
97
|
+
toggle("SST", :sst, [%w[OFF ON], %i[sst_off sst_on], kim.sst ? 1 : 0])
|
|
98
|
+
toggle("TTY/KB", :tty, [%w[KEYPAD TTY], %i[keypad teletype], kim.tty? ? 1 : 0])
|
|
99
|
+
skip
|
|
100
|
+
info("RAM", "#{kim.ram_kb}K")
|
|
101
|
+
toggle("U3 PB7", :irq, [%w[OPEN IRQ], %i[irq_open irq_wired], kim.irq_wired ? 1 : 0])
|
|
102
|
+
toggle("SOUND", :speaker, [["U2 PB7", "U3 PA0"], %i[pb7_out pa0_speaker], kim.speaker? ? 1 : 0])
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def kim1_setting(action)
|
|
106
|
+
kim = @computer
|
|
107
|
+
case action
|
|
108
|
+
when :sst_off, :sst_on then kim.sst = action == :sst_on
|
|
109
|
+
when :keypad, :teletype
|
|
110
|
+
kim.tty = action == :teletype
|
|
111
|
+
kim.reset!
|
|
112
|
+
when :irq_open, :irq_wired then kim.irq_wired = action == :irq_wired
|
|
113
|
+
else kim.speaker = action == :pa0_speaker
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
80
117
|
# What each control port has plugged in, a joystick, a mouse or
|
|
81
118
|
# paddles.
|
|
82
119
|
def draw_pot_ports
|
|
@@ -88,7 +88,7 @@ module Badline
|
|
|
88
88
|
# any: :resume, :quit, :freeze or :swap.
|
|
89
89
|
def click(left, top)
|
|
90
90
|
action = @buttons.action_at(left, top)
|
|
91
|
-
return @dialogs.click(action, top) if %i[browse confirm cancel].include?(action)
|
|
91
|
+
return @dialogs.click(action, top) if %i[browse confirm cancel].include?(action) || picks_drive?(action)
|
|
92
92
|
|
|
93
93
|
choose(action)
|
|
94
94
|
end
|
|
@@ -159,6 +159,7 @@ module Badline
|
|
|
159
159
|
when :insert_cartridge then @dialogs.browse(:cartridge)
|
|
160
160
|
when :quick_open then @dialogs.browse(:program)
|
|
161
161
|
when :remove_cartridge then @dialogs.ask_remove
|
|
162
|
+
when :drive_type then @dialogs.pick_drive(@pages.drive_model)
|
|
162
163
|
else @pages.perform(action)
|
|
163
164
|
end
|
|
164
165
|
nil
|
|
@@ -235,10 +236,13 @@ module Badline
|
|
|
235
236
|
repeat.zero? || Keys::DIRECTIONS.key?(scancode) ? key(scancode) : nil
|
|
236
237
|
end
|
|
237
238
|
|
|
239
|
+
def picks_drive?(action) = DriveTypes::ACTIONS.include?(action) && @dialogs.open?
|
|
240
|
+
|
|
238
241
|
def draw_sections
|
|
239
242
|
top = @top + 32
|
|
240
243
|
SECTIONS.each_with_index do |name, index|
|
|
241
244
|
name = "KEYBOARD" if PAGES[index] == :ports && (@pages.pet? || @pages.b_series?)
|
|
245
|
+
name = "PANEL" if PAGES[index] == :ports && @pages.kim1?
|
|
242
246
|
@buttons.plain(@left + 6, top, name.ljust(14), PAGES[index], on: index == @section)
|
|
243
247
|
top += Buttons::HEIGHT + 2
|
|
244
248
|
end
|
|
@@ -13,6 +13,12 @@ module Badline
|
|
|
13
13
|
# key its unshifted character is on with the PET's SHIFT, so the
|
|
14
14
|
# graphics on the graphics keyboard's symbol keys can be typed.
|
|
15
15
|
#
|
|
16
|
+
# While the SuperPET shows its APL characters the keys go by position
|
|
17
|
+
# instead (#positional=): a key that types a character presses the PET
|
|
18
|
+
# key its unshifted character is on, and the PET's SHIFT follows the
|
|
19
|
+
# host's, so a key types the APL symbol on the SuperPET's keycap in the
|
|
20
|
+
# same place, shifted or not.
|
|
21
|
+
#
|
|
16
22
|
# The CBM-II's keyboard goes the same way (Keys.cbm2_key), and there
|
|
17
23
|
# Alt with a key presses one of the keys the host has none for
|
|
18
24
|
# (Keys.cbm2_alt_key).
|
|
@@ -35,8 +41,12 @@ module Badline
|
|
|
35
41
|
@right_alt = false
|
|
36
42
|
@forced = -1
|
|
37
43
|
@forced_shift = false
|
|
44
|
+
@positional = false
|
|
38
45
|
end
|
|
39
46
|
|
|
47
|
+
# Whether the keys go by position, for the SuperPET's APL characters.
|
|
48
|
+
attr_writer :positional
|
|
49
|
+
|
|
40
50
|
def key(scancode, down)
|
|
41
51
|
if [LSHIFT, RSHIFT].include?(scancode)
|
|
42
52
|
shift_key(scancode, down)
|
|
@@ -70,7 +80,10 @@ module Badline
|
|
|
70
80
|
|
|
71
81
|
def key_down(scancode)
|
|
72
82
|
key_up(scancode) if @held.key?(scancode)
|
|
73
|
-
key, shift = alt?
|
|
83
|
+
key, shift = if alt? then shifted_key(scancode)
|
|
84
|
+
elsif @positional then positional_key(scancode)
|
|
85
|
+
else layout_key(scancode, shifted?)
|
|
86
|
+
end
|
|
74
87
|
return if key == :none
|
|
75
88
|
|
|
76
89
|
unless shift == :host
|
|
@@ -128,6 +141,15 @@ module Badline
|
|
|
128
141
|
[key, :on]
|
|
129
142
|
end
|
|
130
143
|
|
|
144
|
+
# The PET key for the scancode by position: the one its unshifted
|
|
145
|
+
# character is on, with the host's SHIFT.
|
|
146
|
+
def positional_key(scancode)
|
|
147
|
+
key, shift = Keys.pet_key(scancode, false, @layout)
|
|
148
|
+
return [key, shift] if key == :none || !Keys::US_CHARACTERS.key?(scancode)
|
|
149
|
+
|
|
150
|
+
[key, :host]
|
|
151
|
+
end
|
|
152
|
+
|
|
131
153
|
def shifted? = @left_shift || @right_shift
|
|
132
154
|
|
|
133
155
|
def sync_shift
|
|
@@ -15,7 +15,7 @@ module Badline
|
|
|
15
15
|
# least MIN_WIDTH window pixels wide, and at least as high as PAL's C64
|
|
16
16
|
# crop, 272 lines, so a C64 shows in the same window whatever its
|
|
17
17
|
# region. A crop with fewer lines or pixels sits in the middle of the
|
|
18
|
-
# texture, between black bands. The VIC-20's 284 by 284 crop and the
|
|
18
|
+
# texture, between black bands. The PAL VIC-20's 284 by 284 crop and the
|
|
19
19
|
# TED's 384 by 288 fill their own.
|
|
20
20
|
#
|
|
21
21
|
# With `frame_lines`, the crop's lines run on past the frame's last
|
|
@@ -10,6 +10,10 @@ module Badline
|
|
|
10
10
|
# On the C128, #follow switches to the screen the machine prints to
|
|
11
11
|
# (C128#active_screen) each time it moves there, and #show_vdc's choice
|
|
12
12
|
# holds until the next move.
|
|
13
|
+
#
|
|
14
|
+
# The KIM-1 has no video chip, and shows its panel (KIM1Panel), or with
|
|
15
|
+
# its TTY/KB jumper fitted its teletype's page (TeletypePane), which
|
|
16
|
+
# #follow brings up to the machine each frame.
|
|
13
17
|
class Screens
|
|
14
18
|
# The frames a move holds before #follow takes it. The C128 KERNAL's
|
|
15
19
|
# reset clears the 80 column screen with the editor on it for over a
|
|
@@ -18,8 +22,17 @@ module Badline
|
|
|
18
22
|
|
|
19
23
|
attr_reader :screen
|
|
20
24
|
|
|
25
|
+
# The KIM-1's panel, the picture a KIM-1 shows.
|
|
26
|
+
attr_reader :kim1_panel
|
|
27
|
+
|
|
28
|
+
# The KIM-1's teletype's page, which it shows with the jumper fitted.
|
|
29
|
+
attr_reader :teletype_pane
|
|
30
|
+
|
|
21
31
|
def initialize(computer)
|
|
22
32
|
@computer = computer
|
|
33
|
+
@kim1_panel = KIM1Panel.new
|
|
34
|
+
@teletype_pane = TeletypePane.new
|
|
35
|
+
@built_tty = false
|
|
23
36
|
@vdc_shown = false
|
|
24
37
|
@vdc_shape = []
|
|
25
38
|
forget_screen
|
|
@@ -31,6 +44,8 @@ module Badline
|
|
|
31
44
|
# Shows another machine's video chip, once #build builds its screen.
|
|
32
45
|
def computer=(computer)
|
|
33
46
|
@computer = computer
|
|
47
|
+
@kim1_panel = KIM1Panel.new
|
|
48
|
+
@teletype_pane = TeletypePane.new
|
|
34
49
|
@vdc_shown = false
|
|
35
50
|
forget_screen
|
|
36
51
|
end
|
|
@@ -38,6 +53,7 @@ module Badline
|
|
|
38
53
|
# Shows the screen a C128 has moved its output to once the move has
|
|
39
54
|
# held for FOLLOW_FRAMES calls, one a frame. #build then builds it.
|
|
40
55
|
def follow
|
|
56
|
+
return follow_kim1 if @computer.family == :kim1
|
|
41
57
|
return unless @computer.family == :c128
|
|
42
58
|
|
|
43
59
|
vdc = @computer.active_screen == :vdc
|
|
@@ -60,11 +76,17 @@ module Badline
|
|
|
60
76
|
|
|
61
77
|
# Whether the screen was built for the other chip, or the VDC's
|
|
62
78
|
# display has changed size or crop since the screen was built for it.
|
|
63
|
-
def stale?
|
|
79
|
+
def stale?
|
|
80
|
+
return @built_tty != @computer.tty? if @computer.family == :kim1
|
|
81
|
+
|
|
82
|
+
@built_vdc != @vdc_shown || (@vdc_shown && vdc_shape(@computer.vdc) != @vdc_shape)
|
|
83
|
+
end
|
|
64
84
|
|
|
65
85
|
def build
|
|
66
86
|
@built_vdc = @vdc_shown
|
|
67
|
-
if @
|
|
87
|
+
if @computer.family == :kim1
|
|
88
|
+
build_kim1
|
|
89
|
+
elsif @vdc_shown
|
|
68
90
|
vdc = @computer.vdc
|
|
69
91
|
@vdc_shape = vdc_shape(vdc)
|
|
70
92
|
@screen = Screen.new(vdc, vdc.crop, dots: 2)
|
|
@@ -78,6 +100,22 @@ module Badline
|
|
|
78
100
|
|
|
79
101
|
private
|
|
80
102
|
|
|
103
|
+
# The panel and the teletype's page both follow the machine, the
|
|
104
|
+
# LEDs' brightness and the page's lines going on behind the other.
|
|
105
|
+
def follow_kim1
|
|
106
|
+
@kim1_panel.follow(@computer)
|
|
107
|
+
@teletype_pane.follow(@computer)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def build_kim1
|
|
111
|
+
@built_tty = @computer.tty?
|
|
112
|
+
@screen = if @built_tty
|
|
113
|
+
Screen.new(@teletype_pane, @teletype_pane.crop)
|
|
114
|
+
else
|
|
115
|
+
Screen.new(@kim1_panel, @kim1_panel.crop)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
81
119
|
# The machine's output counts as on the VIC-IIe's screen, the one
|
|
82
120
|
# shown.
|
|
83
121
|
def forget_screen
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Frontend
|
|
5
|
+
# The KIM-1's teletype as the window shows it with the TTY/KB jumper
|
|
6
|
+
# fitted: a page of COLUMNS by ROWS characters in the character ROM's
|
|
7
|
+
# font, printed as the teletype prints (KIM1::Teletype#output), with a
|
|
8
|
+
# line of the host keys that type what the window's keys don't. RETURN
|
|
9
|
+
# goes back to the line's start, LINE FEED down a line, the page
|
|
10
|
+
# scrolling up from the last, and a line full at COLUMNS goes on to the
|
|
11
|
+
# next. It answers what a Screen reads of a video chip, as KIM1Panel
|
|
12
|
+
# does.
|
|
13
|
+
class TeletypePane
|
|
14
|
+
COLUMNS = 72
|
|
15
|
+
ROWS = 24
|
|
16
|
+
LINE = 10
|
|
17
|
+
MARGIN = 8
|
|
18
|
+
TOP = 22
|
|
19
|
+
|
|
20
|
+
WIDTH = (COLUMNS * 8) + (2 * MARGIN)
|
|
21
|
+
HEIGHT = 272
|
|
22
|
+
|
|
23
|
+
PAPER = 0
|
|
24
|
+
INK = 1
|
|
25
|
+
HINT = 2
|
|
26
|
+
CURSOR = 3
|
|
27
|
+
PALETTE = [0xf2ecd8, 0x202020, 0x6c6858, 0x9c9480].freeze
|
|
28
|
+
|
|
29
|
+
HINTS = "BACKSPACE: RUBOUT DOWN: LINE FEED F9: MENU"
|
|
30
|
+
|
|
31
|
+
attr_reader :display, :dirty_lines
|
|
32
|
+
|
|
33
|
+
def initialize
|
|
34
|
+
@display = Array.new(WIDTH * HEIGHT, PAPER)
|
|
35
|
+
@dirty_lines = Array.new(HEIGHT, true)
|
|
36
|
+
@font = ROM.read("character.rom")
|
|
37
|
+
@page = Array.new(ROWS) { Array.new(COLUMNS, 0x20) }
|
|
38
|
+
@column = 0
|
|
39
|
+
@row = 0
|
|
40
|
+
@printed = 0
|
|
41
|
+
@baud = 0
|
|
42
|
+
draw_cursor(CURSOR)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def width = WIDTH
|
|
46
|
+
|
|
47
|
+
def height = HEIGHT
|
|
48
|
+
|
|
49
|
+
def palette = PALETTE
|
|
50
|
+
|
|
51
|
+
def crop = [0, 0, WIDTH, HEIGHT]
|
|
52
|
+
|
|
53
|
+
def clear_dirty_lines!
|
|
54
|
+
@dirty_lines.map! { false }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# The characters on the page, a line each, without trailing spaces.
|
|
58
|
+
def lines = @page.map { |row| row.map(&:chr).join.rstrip }
|
|
59
|
+
|
|
60
|
+
# Prints what the KIM-1 `computer`'s teletype has printed since the
|
|
61
|
+
# last call.
|
|
62
|
+
def follow(computer)
|
|
63
|
+
teletype = computer.teletype
|
|
64
|
+
title(teletype.baud) if teletype.baud != @baud
|
|
65
|
+
output = teletype.output
|
|
66
|
+
return if output.size == @printed
|
|
67
|
+
|
|
68
|
+
draw_cursor(PAPER)
|
|
69
|
+
output[@printed, output.size - @printed].bytes.each { |byte| print_byte(byte) }
|
|
70
|
+
@printed = output.size
|
|
71
|
+
draw_cursor(CURSOR)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
def title(baud)
|
|
77
|
+
@baud = baud
|
|
78
|
+
box(0, 0, WIDTH, TOP, PAPER)
|
|
79
|
+
text(MARGIN, 6, "KIM-1 TELETYPE, #{baud} BAUD", HINT)
|
|
80
|
+
text(WIDTH - MARGIN - (HINTS.size * 8), 6, HINTS, HINT)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def print_byte(byte)
|
|
84
|
+
case byte
|
|
85
|
+
when 0x0d then @column = 0
|
|
86
|
+
when 0x0a then line_feed
|
|
87
|
+
when 0x20..0x7e then print_character(byte)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def print_character(byte)
|
|
92
|
+
if @column == COLUMNS
|
|
93
|
+
@column = 0
|
|
94
|
+
line_feed
|
|
95
|
+
end
|
|
96
|
+
@page[@row][@column] = byte
|
|
97
|
+
glyph(MARGIN + (@column * 8), TOP + (@row * LINE), byte, INK)
|
|
98
|
+
@column += 1
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def line_feed
|
|
102
|
+
if @row < ROWS - 1
|
|
103
|
+
@row += 1
|
|
104
|
+
return
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
@page.shift
|
|
108
|
+
@page << Array.new(COLUMNS, 0x20)
|
|
109
|
+
redraw_page
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def redraw_page
|
|
113
|
+
box(0, TOP, WIDTH, ROWS * LINE, PAPER)
|
|
114
|
+
@page.each_with_index do |characters, row|
|
|
115
|
+
characters.each_with_index do |byte, column|
|
|
116
|
+
glyph(MARGIN + (column * 8), TOP + (row * LINE), byte, INK) unless byte == 0x20
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def draw_cursor(color)
|
|
122
|
+
column = [@column, COLUMNS - 1].min
|
|
123
|
+
box(MARGIN + (column * 8), TOP + (@row * LINE) + 8, 8, 1, color)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def box(left, top, width, height, color)
|
|
127
|
+
height.times do |row|
|
|
128
|
+
line = top + row
|
|
129
|
+
@display.fill(color, (line * WIDTH) + left, width)
|
|
130
|
+
@dirty_lines[line] = true
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def text(left, top, string, color)
|
|
135
|
+
string.bytes.each_with_index { |byte, index| glyph(left + (index * 8), top, byte, color) }
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Draws the glyph for the ASCII `byte` over a cleared cell.
|
|
139
|
+
def glyph(left, top, byte, color)
|
|
140
|
+
code = Painter::SCREEN_CODES[byte & 0x7f]
|
|
141
|
+
8.times do |row|
|
|
142
|
+
bits = @font[0x800 + (code * 8) + row]
|
|
143
|
+
line = top + row
|
|
144
|
+
8.times do |dot|
|
|
145
|
+
@display[(line * WIDTH) + left + dot] = bits.anybits?(0x80 >> dot) ? color : PAPER
|
|
146
|
+
end
|
|
147
|
+
@dirty_lines[line] = true
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
@@ -44,6 +44,8 @@ module Badline
|
|
|
44
44
|
# either, and the PET and the CBM-II's B series neither that nor
|
|
45
45
|
# joysticks.
|
|
46
46
|
def self.key?(name, family)
|
|
47
|
+
return !kim1_key(name).empty? if family == :kim1
|
|
48
|
+
|
|
47
49
|
pet = %i[pet cbm2].include?(family)
|
|
48
50
|
(name == "restore" && !pet && !%i[plus4 p500].include?(family)) || (family == :c128 && LOCKS.include?(name)) ||
|
|
49
51
|
!keyboard_key(name, family).nil? || (!pet && !joystick_direction(name).nil?)
|
|
@@ -73,6 +75,13 @@ module Badline
|
|
|
73
75
|
end
|
|
74
76
|
end
|
|
75
77
|
|
|
78
|
+
# The KIM-1's key for a name such as go, a or plus, as
|
|
79
|
+
# KIM1::Panel::KEYS names it, with st and rs, or an empty string.
|
|
80
|
+
def self.kim1_key(name)
|
|
81
|
+
key = name == "plus" ? "+" : name.upcase
|
|
82
|
+
KIM1::Panel::KEYS.include?(key) || %w[ST RS].include?(key) ? key : ""
|
|
83
|
+
end
|
|
84
|
+
|
|
76
85
|
# The direction of joy1-NAME or joy2-NAME, such as up or fire.
|
|
77
86
|
def self.joystick_direction(name)
|
|
78
87
|
return nil unless name.start_with?("joy1-") || name.start_with?("joy2-")
|
|
@@ -150,7 +159,7 @@ module Badline
|
|
|
150
159
|
def perform(computer, event)
|
|
151
160
|
case event.action
|
|
152
161
|
when "key" then press(computer, event)
|
|
153
|
-
when "type" then computer
|
|
162
|
+
when "type" then type(computer, event.argument)
|
|
154
163
|
when "insert" then insert(computer, event.argument)
|
|
155
164
|
when "eject" then eject(computer, event.argument)
|
|
156
165
|
when "reset" then computer.reset!
|
|
@@ -158,8 +167,15 @@ module Badline
|
|
|
158
167
|
end
|
|
159
168
|
end
|
|
160
169
|
|
|
170
|
+
# Types the text, which on the KIM-1 goes to its teletype, or with
|
|
171
|
+
# none presses the keys it names (KIM1#type_text).
|
|
172
|
+
def type(computer, text)
|
|
173
|
+
computer.type_text(text.gsub("\\n", "\r").gsub("\\r", "\r"))
|
|
174
|
+
end
|
|
175
|
+
|
|
161
176
|
def press(computer, event)
|
|
162
177
|
name = event.argument
|
|
178
|
+
return press_kim1(computer, event) if computer.family == :kim1
|
|
163
179
|
return lock(computer, name) if LOCKS.include?(name)
|
|
164
180
|
|
|
165
181
|
if name == "restore"
|
|
@@ -176,6 +192,17 @@ module Badline
|
|
|
176
192
|
hold(event)
|
|
177
193
|
end
|
|
178
194
|
|
|
195
|
+
# ST and RS act as they go down, and the KIM-1's other keys are held.
|
|
196
|
+
def press_kim1(computer, event)
|
|
197
|
+
case (key = Timeline.kim1_key(event.argument))
|
|
198
|
+
when "ST" then computer.press_stop
|
|
199
|
+
when "RS" then computer.press_reset
|
|
200
|
+
else
|
|
201
|
+
computer.press_key(key)
|
|
202
|
+
hold(event)
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
179
206
|
# CAPS LOCK and 40/80 DISPLAY lock: a push puts one down if it was up,
|
|
180
207
|
# and up if it was down.
|
|
181
208
|
def lock(computer, name)
|
|
@@ -199,6 +226,8 @@ module Badline
|
|
|
199
226
|
def release(computer, event)
|
|
200
227
|
return computer.release_cartridge_button if event.action == "freeze" && computer.family == :c64
|
|
201
228
|
|
|
229
|
+
return computer.release_key if computer.family == :kim1
|
|
230
|
+
|
|
202
231
|
name = event.argument
|
|
203
232
|
return computer.release_restore if name == "restore"
|
|
204
233
|
|
|
@@ -237,7 +266,7 @@ module Badline
|
|
|
237
266
|
# its cartridge stays in.
|
|
238
267
|
def ejectable?(computer, what)
|
|
239
268
|
family = computer.family
|
|
240
|
-
return false if family == :cbm2 && what != "disk"
|
|
269
|
+
return false if family == :kim1 || (family == :cbm2 && what != "disk")
|
|
241
270
|
|
|
242
271
|
(what != "cartridge" || !%i[vic20 pet].include?(family)) && inserted?(computer, what)
|
|
243
272
|
end
|
data/lib/badline/frontend.rb
CHANGED
|
@@ -4,6 +4,8 @@ require "badline/sdl"
|
|
|
4
4
|
require "badline/frontend/boot"
|
|
5
5
|
require "badline/frontend/frame_rate"
|
|
6
6
|
require "badline/frontend/screen"
|
|
7
|
+
require "badline/frontend/kim1_panel"
|
|
8
|
+
require "badline/frontend/teletype_pane"
|
|
7
9
|
require "badline/frontend/screens"
|
|
8
10
|
require "badline/frontend/drive_led"
|
|
9
11
|
require "badline/frontend/keys"
|
|
@@ -42,6 +44,7 @@ require "badline/frontend/menu/pause_menu"
|
|
|
42
44
|
require "badline/frontend/menu/file_browser"
|
|
43
45
|
require "badline/frontend/menu/confirmation"
|
|
44
46
|
require "badline/frontend/menu/name_field"
|
|
47
|
+
require "badline/frontend/menu/drive_types"
|
|
45
48
|
require "badline/frontend/menu/menu_dialogs"
|
|
46
49
|
require "badline/frontend/menu/menu_media"
|
|
47
50
|
require "badline/frontend/menu/menu_ports"
|