badline 0.16.1 → 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 +213 -0
- data/CLAUDE.md +11 -7
- data/CONTRIBUTING.md +7 -1
- data/README.md +265 -26
- data/doc/media.md +5 -2
- data/doc/pinned-behaviour.md +189 -0
- data/doc/snapshot-format.md +616 -74
- data/doc/snapshots.md +192 -24
- 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/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 +95 -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 +264 -0
- data/lib/badline/cbm2/sid_page.rb +19 -0
- data/lib/badline/cbm2.rb +270 -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/cia/timer.rb +2 -2
- data/lib/badline/chips/cpu/instruction_set.rb +1 -1
- data/lib/badline/chips/crtc.rb +3 -2
- 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/fast_forward.rb +72 -0
- data/lib/badline/chips/riot/keyed_parts.rb +69 -0
- data/lib/badline/chips/riot/timer.rb +91 -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 +134 -0
- data/lib/badline/chips/sid/filter.rb +4 -4
- data/lib/badline/chips/sid/waveform.rb +6 -6
- 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/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/datasette/keyed_state.rb +9 -1
- data/lib/badline/drives/datasette.rb +27 -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/disk.rb +163 -0
- data/lib/badline/drives/model8050/dos_board.rb +91 -0
- data/lib/badline/drives/model8050/fdc_bus.rb +102 -0
- data/lib/badline/drives/model8050/idle.rb +181 -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 +163 -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 +131 -0
- 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 +18 -3
- data/lib/badline/frontend/boot.rb +4 -3
- data/lib/badline/frontend/controls.rb +107 -15
- data/lib/badline/frontend/gamepads.rb +3 -3
- data/lib/badline/frontend/keys.rb +97 -2
- 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 +47 -14
- data/lib/badline/frontend/menu/menu_pages.rb +113 -4
- data/lib/badline/frontend/menu/menu_ports.rb +77 -4
- data/lib/badline/frontend/menu/pause_menu.rb +6 -2
- data/lib/badline/frontend/pet_keyboard.rb +45 -7
- 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 +49 -11
- data/lib/badline/frontend.rb +3 -0
- 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/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 +171 -0
- data/lib/badline/machine/keyboard_buffer.rb +20 -3
- data/lib/badline/machine/line_sound.rb +122 -0
- data/lib/badline/machine/settling.rb +4 -0
- data/lib/badline/machine.rb +62 -14
- data/lib/badline/media/cbm2_media.rb +29 -0
- 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/program.rb +6 -3
- data/lib/badline/media/true_drive.rb +51 -25
- data/lib/badline/media.rb +23 -8
- data/lib/badline/options/family.rb +108 -6
- data/lib/badline/options/help.rb +58 -12
- data/lib/badline/options/table.rb +60 -14
- data/lib/badline/options/validation.rb +71 -11
- data/lib/badline/options.rb +46 -13
- data/lib/badline/pet/bus.rb +16 -2
- 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/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 +33 -6
- data/lib/badline/plus4/acia.rb +4 -298
- data/lib/badline/plus4/keyed_parts.rb +0 -44
- data/lib/badline/plus4/keyed_state.rb +2 -0
- data/lib/badline/plus4.rb +2 -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/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/9060/dos-3.0.rom +0 -0
- data/lib/badline/roms/9060/sasi-300515-revb.rom +0 -0
- data/lib/badline/roms/README +277 -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/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/cbm2_setup.rb +53 -0
- data/lib/badline/snapshot/container.rb +9 -2
- data/lib/badline/snapshot/field_doc/markdown.rb +4 -2
- data/lib/badline/snapshot/field_doc.rb +59 -3
- data/lib/badline/snapshot/image.rb +65 -9
- 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/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 +20 -10
- data/lib/badline/snapshot/vice/pet_cpu.rb +42 -5
- data/lib/badline/snapshot/vice/pet_crtc.rb +25 -17
- data/lib/badline/snapshot/vice/pet_drive.rb +180 -0
- data/lib/badline/snapshot/vice/pet_drive8050.rb +336 -0
- data/lib/badline/snapshot/vice/pet_mem.rb +49 -5
- data/lib/badline/snapshot/vice/pet_restore.rb +100 -7
- 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 +15 -3
- data/lib/badline/status.rb +30 -30
- data/lib/badline/storage/crt_file.rb +7 -1
- data/lib/badline/storage/d64_image.rb +7 -0
- data/lib/badline/storage/d67_image.rb +55 -0
- data/lib/badline/storage/d80_image.rb +17 -1
- data/lib/badline/storage/d81_image.rb +14 -0
- data/lib/badline/storage/d90_image.rb +180 -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 +37 -2
- data/lib/badline/storage/disk_image.rb +2 -0
- data/lib/badline/storage/kim_tape.rb +254 -0
- data/lib/badline/storage/papertape.rb +90 -0
- data/lib/badline/storage.rb +5 -0
- data/lib/badline/support/cbm2_checkpoint.rb +48 -0
- data/lib/badline/support/kim1_checkpoint.rb +41 -0
- data/lib/badline/support/p500_checkpoint.rb +35 -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 +2 -0
- metadata +148 -2
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Frontend
|
|
5
|
+
# The pause menu's list of the true drives a PET or a CBM-II takes on
|
|
6
|
+
# device 8, which the DRIVE 8 page's DRIVE TYPE row brings up: a row
|
|
7
|
+
# for each model, the disks it reads at its right, and the one on the
|
|
8
|
+
# bus said so. Up and Down move along the list, Return or a click picks
|
|
9
|
+
# a model, and Left or Esc goes back to the page.
|
|
10
|
+
class DriveTypes
|
|
11
|
+
MODELS = %w[2031 2040 3040 4040 1001 8050 8250 9060 9090].freeze
|
|
12
|
+
ACTIONS = %i[type2031 type2040 type3040 type4040 type1001 type8050 type8250 type9060 type9090].freeze
|
|
13
|
+
|
|
14
|
+
def initialize(painter, buttons)
|
|
15
|
+
@painter = painter
|
|
16
|
+
@buttons = buttons
|
|
17
|
+
@open = false
|
|
18
|
+
@model = ""
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def open? = @open
|
|
22
|
+
|
|
23
|
+
# Opens the list with the focus on `model`, the drive on the bus, or
|
|
24
|
+
# on the first if there's none.
|
|
25
|
+
def open(model)
|
|
26
|
+
@model = model
|
|
27
|
+
@open = true
|
|
28
|
+
index = MODELS.index(model)
|
|
29
|
+
@buttons.focus = ACTIONS[index.nil? ? 0 : index]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def close
|
|
33
|
+
@open = false
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# The model `action` picks, or nil.
|
|
37
|
+
def model_for(action)
|
|
38
|
+
index = ACTIONS.index(action)
|
|
39
|
+
index.nil? ? nil : MODELS[index]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Draws the list `width` wide.
|
|
43
|
+
def draw(left, top, width)
|
|
44
|
+
@painter.text(left, top, "DRIVE 8 TYPE", MenuTheme::BRIGHT)
|
|
45
|
+
top += 20
|
|
46
|
+
MODELS.each_with_index do |model, index|
|
|
47
|
+
media = Drives::IEEEModels::MEDIA.fetch(model).join(" ").upcase
|
|
48
|
+
label = model == @model ? "#{model}, ON THE BUS" : model
|
|
49
|
+
@buttons.row([left, top, width], label, ACTIONS[index], media)
|
|
50
|
+
top += Buttons::HEIGHT + 2
|
|
51
|
+
end
|
|
52
|
+
@painter.text(left, top + 6, "RETURN: PICK LEFT, ESC: BACK", MenuTheme::DIM)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -4,12 +4,14 @@ module Badline
|
|
|
4
4
|
module Frontend
|
|
5
5
|
# The pause menu's screens that take over its panel: the file browser
|
|
6
6
|
# INSERT, Quick open and LOAD bring up, the question before a cartridge
|
|
7
|
-
# or Quick open power cycles the machine,
|
|
8
|
-
#
|
|
7
|
+
# or Quick open power cycles the machine, the prompt for a save's name,
|
|
8
|
+
# and the list of a PET's or a CBM-II's drive types. A disk or tape
|
|
9
|
+
# picked goes straight in, a save loads, and a drive type picked goes on
|
|
10
|
+
# the bus.
|
|
9
11
|
class MenuDialogs
|
|
10
12
|
EXTENSIONS = {
|
|
11
|
-
disk: Media::Extensions::DEVICE8,
|
|
12
|
-
|
|
13
|
+
disk: Media::Extensions::DEVICE8, cartridge: Media::Extensions.of(%i[cartridge]),
|
|
14
|
+
program: Media::Extensions::ALL, snapshot: %w[.vsf]
|
|
13
15
|
}.freeze
|
|
14
16
|
TITLES = { disk: "INSERT A DISK", tape: "INSERT A TAPE", cartridge: "INSERT A CARTRIDGE",
|
|
15
17
|
program: "QUICK OPEN", snapshot: "LOAD A SAVE" }.freeze
|
|
@@ -25,13 +27,14 @@ module Badline
|
|
|
25
27
|
@browser = FileBrowser.new(painter, buttons)
|
|
26
28
|
@confirmation = Confirmation.new(painter, buttons)
|
|
27
29
|
@name_field = NameField.new(painter)
|
|
30
|
+
@drive_types = DriveTypes.new(painter, buttons)
|
|
28
31
|
@snapshots = snapshots
|
|
29
32
|
@browsing = nil
|
|
30
33
|
@browse_from = media_path.empty? ? Dir.pwd : File.dirname(File.expand_path(media_path))
|
|
31
34
|
@computer = nil
|
|
32
35
|
end
|
|
33
36
|
|
|
34
|
-
def open? = !@browsing.nil? || @confirmation.open? || @name_field.open?
|
|
37
|
+
def open? = !@browsing.nil? || @confirmation.open? || @name_field.open? || @drive_types.open?
|
|
35
38
|
|
|
36
39
|
# Opens the browser on the files for `kind`: :disk, :tape, :cartridge,
|
|
37
40
|
# :program, or :snapshot, which starts in the saves folder.
|
|
@@ -40,12 +43,16 @@ module Badline
|
|
|
40
43
|
extensions = case kind
|
|
41
44
|
when :cartridge then @media.cartridge_extensions
|
|
42
45
|
when :disk then @media.disk_extensions
|
|
46
|
+
when :tape then @media.tape_extensions
|
|
43
47
|
when :program then programs
|
|
44
48
|
else EXTENSIONS.fetch(kind)
|
|
45
49
|
end
|
|
46
50
|
@browser.open(kind == :snapshot ? Badline.data_folder("saves") : @browse_from, extensions)
|
|
47
51
|
end
|
|
48
52
|
|
|
53
|
+
# Lists the drive types, with `model` the one on the bus.
|
|
54
|
+
def pick_drive(model) = @drive_types.open(model)
|
|
55
|
+
|
|
49
56
|
# Asks for a save's name, starting from `name`.
|
|
50
57
|
def ask_name(name) = @name_field.open("SAVE AS", name)
|
|
51
58
|
|
|
@@ -66,7 +73,7 @@ module Badline
|
|
|
66
73
|
def drop(path)
|
|
67
74
|
extension = File.extname(path).downcase
|
|
68
75
|
return @media.insert(:disk, path) && false if @media.disk_extensions.include?(extension)
|
|
69
|
-
return @media.insert(:tape, path) && false if
|
|
76
|
+
return @media.insert(:tape, path) && false if @media.tape_extensions.include?(extension)
|
|
70
77
|
return false unless programs.include?(extension)
|
|
71
78
|
|
|
72
79
|
@confirmation.ask(@media.cartridge_extensions.include?(extension) ? :cartridge : :start, path)
|
|
@@ -77,6 +84,7 @@ module Badline
|
|
|
77
84
|
# answered yes, or nil.
|
|
78
85
|
def key(scancode)
|
|
79
86
|
return browsed(@browser.key(scancode)) unless @browsing.nil?
|
|
87
|
+
return drive_key(scancode) if @drive_types.open?
|
|
80
88
|
if @name_field.open? && !@confirmation.open?
|
|
81
89
|
return named(@name_field.key(scancode, SDL.event_mod(SDL.event).anybits?(SDL::KMOD_SHIFT)))
|
|
82
90
|
end
|
|
@@ -88,15 +96,21 @@ module Badline
|
|
|
88
96
|
nil
|
|
89
97
|
end
|
|
90
98
|
|
|
91
|
-
# Handles a click on the browser's list at `top`,
|
|
92
|
-
# answer, `action
|
|
93
|
-
def click(action, top)
|
|
99
|
+
# Handles a click on the browser's list at `top`, on a question's
|
|
100
|
+
# answer, `action`, or on a drive type.
|
|
101
|
+
def click(action, top)
|
|
102
|
+
return browsed(@browser.click(top)) if action == :browse
|
|
103
|
+
return picked(action) if @drive_types.open?
|
|
104
|
+
|
|
105
|
+
answer(action)
|
|
106
|
+
end
|
|
94
107
|
|
|
95
108
|
def scroll(rows) = @browser.scroll(rows)
|
|
96
109
|
|
|
97
110
|
def draw(left, top, width)
|
|
98
111
|
return @browser.draw(left, top, width, TITLES.fetch(@browsing)) unless @browsing.nil?
|
|
99
112
|
return @confirmation.draw(left, top) if @confirmation.open?
|
|
113
|
+
return @drive_types.draw(left, top, width) if @drive_types.open?
|
|
100
114
|
|
|
101
115
|
@name_field.draw(left, top, width)
|
|
102
116
|
end
|
|
@@ -104,12 +118,16 @@ module Badline
|
|
|
104
118
|
private
|
|
105
119
|
|
|
106
120
|
# What Quick open and a drop start: every medium, and the cartridges
|
|
107
|
-
# the machine takes.
|
|
108
|
-
def programs
|
|
121
|
+
# the machine takes, or on the KIM-1 its programs.
|
|
122
|
+
def programs
|
|
123
|
+
return Media::KIM1Media::EXTENSIONS if @media.kim1?
|
|
124
|
+
|
|
125
|
+
(EXTENSIONS[:program] + @media.cartridge_extensions).uniq
|
|
126
|
+
end
|
|
109
127
|
|
|
110
|
-
# Puts the disk or tape picked in,
|
|
111
|
-
#
|
|
112
|
-
# does.
|
|
128
|
+
# Puts the disk or tape picked in, a tape Quick open picks on the
|
|
129
|
+
# KIM-1 too, or asks before a cartridge or Quick open power cycles the
|
|
130
|
+
# machine, and leaves the browser, as Esc does.
|
|
113
131
|
def browsed(picked)
|
|
114
132
|
return nil if picked.nil?
|
|
115
133
|
|
|
@@ -121,12 +139,41 @@ module Badline
|
|
|
121
139
|
|
|
122
140
|
if %i[disk tape].include?(kind)
|
|
123
141
|
@media.insert(kind, picked)
|
|
142
|
+
elsif @media.kim1? && @media.tape_extensions.include?(File.extname(picked).downcase)
|
|
143
|
+
@media.insert(:tape, picked)
|
|
124
144
|
else
|
|
125
145
|
@confirmation.ask(kind == :cartridge ? :cartridge : :start, picked)
|
|
126
146
|
end
|
|
127
147
|
nil
|
|
128
148
|
end
|
|
129
149
|
|
|
150
|
+
# Up and Down move along the drive types, Return or Space picks one,
|
|
151
|
+
# and Left or Esc goes back to the page.
|
|
152
|
+
def drive_key(scancode)
|
|
153
|
+
return picked(@buttons.focus) if [Keys::RETURN, Keys::SPACE].include?(scancode)
|
|
154
|
+
|
|
155
|
+
direction = Keys::DIRECTIONS[scancode]
|
|
156
|
+
if scancode == Keys::ESCAPE || direction == :left
|
|
157
|
+
@drive_types.close
|
|
158
|
+
@buttons.focus = :drive_type
|
|
159
|
+
elsif %i[up down].include?(direction)
|
|
160
|
+
@buttons.shift(direction == :up ? -1 : 1, 1)
|
|
161
|
+
end
|
|
162
|
+
nil
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Puts the drive type `action` stands for on the bus, and goes back
|
|
166
|
+
# to the page.
|
|
167
|
+
def picked(action)
|
|
168
|
+
model = @drive_types.model_for(action)
|
|
169
|
+
return nil if model.nil?
|
|
170
|
+
|
|
171
|
+
@drive_types.close
|
|
172
|
+
@buttons.focus = :drive_type
|
|
173
|
+
@media.drive_type(model)
|
|
174
|
+
nil
|
|
175
|
+
end
|
|
176
|
+
|
|
130
177
|
# Saves the machine under the name typed once Return takes it, and
|
|
131
178
|
# asks first when a save has that name already.
|
|
132
179
|
def named(result)
|
|
@@ -37,19 +37,28 @@ module Badline
|
|
|
37
37
|
|
|
38
38
|
def writable? = @writable
|
|
39
39
|
|
|
40
|
+
def kim1? = @computer.family == :kim1
|
|
41
|
+
|
|
40
42
|
def disk_path = MediaSlots.disk_path(@computer)
|
|
41
43
|
|
|
42
44
|
def inserted? = MediaSlots.disk?(@computer)
|
|
43
45
|
|
|
44
|
-
# Puts a disk in device 8 or a tape in the datasette
|
|
45
|
-
# :tape, and says whether it went in. A list
|
|
46
|
+
# Puts a disk in device 8 or a tape in the datasette or the KIM-1's
|
|
47
|
+
# deck, `kind` :disk or :tape, and says whether it went in. A list
|
|
48
|
+
# puts its first disk in.
|
|
46
49
|
def insert(kind, path)
|
|
47
50
|
succeeds? do
|
|
48
|
-
if
|
|
51
|
+
if @computer.family == :kim1
|
|
52
|
+
raise Machine::Unsupported, "the KIM-1 takes no disks" if kind == :disk
|
|
53
|
+
|
|
54
|
+
@computer.tape.insert_tape(Storage::KIMTape.read(path))
|
|
55
|
+
elsif kind == :disk
|
|
49
56
|
disk = Media::DiskList.disk(path)
|
|
50
57
|
Media.insert_disk(@computer, disk, read_only: !@writable)
|
|
51
58
|
list(path)
|
|
52
59
|
else
|
|
60
|
+
raise Machine::Unsupported, "the CBM-II has no datasette" if @computer.family == :cbm2
|
|
61
|
+
|
|
53
62
|
@computer.datasette.insert(Storage::TAP.new(path))
|
|
54
63
|
end
|
|
55
64
|
end
|
|
@@ -68,6 +77,21 @@ module Badline
|
|
|
68
77
|
|
|
69
78
|
def eject_disk = MediaSlots.eject_disk(@computer)
|
|
70
79
|
|
|
80
|
+
# Puts a true drive of `model` on the PET's or the CBM-II's bus as
|
|
81
|
+
# device 8, in place of the drive or the traps there, with the disk
|
|
82
|
+
# device 8 had in it if the model reads it, and says whether it went
|
|
83
|
+
# on. The disk comes out first, so what was written reaches its file.
|
|
84
|
+
def drive_type(model)
|
|
85
|
+
return true if MediaSlots.drive_model(@computer) == model
|
|
86
|
+
|
|
87
|
+
succeeds? do
|
|
88
|
+
path = disk_path
|
|
89
|
+
eject_disk
|
|
90
|
+
@computer.plug_ieee_drive(model)
|
|
91
|
+
Media::TrueDrive.insert(@computer, path, read_only: !@writable) if Drives::IEEEModels.reads?(model, path)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
71
95
|
# Sets whether disks are writable, for the disk in the drive too,
|
|
72
96
|
# which goes in again as the notch now says.
|
|
73
97
|
def writable(writable)
|
|
@@ -99,18 +123,25 @@ module Badline
|
|
|
99
123
|
insert(:disk, set[index + step])
|
|
100
124
|
end
|
|
101
125
|
|
|
126
|
+
# The extensions of the tapes the datasette takes, or the KIM-1's
|
|
127
|
+
# deck: .wav recordings.
|
|
128
|
+
def tape_extensions = kim1? ? [Media::KIM1Media::TAPE] : Media::Extensions.of(%i[tape])
|
|
129
|
+
|
|
102
130
|
# The extensions of the cartridges the machine takes: .crt, on the
|
|
103
|
-
# Plus/4 raw .bin ROM images too, and none on the PET
|
|
131
|
+
# Plus/4 raw .bin ROM images too, and none on the PET or the KIM-1,
|
|
132
|
+
# or on the CBM-II, whose cartridge goes in from the command line.
|
|
104
133
|
def cartridge_extensions
|
|
105
|
-
extensions = Media::Extensions.of(@computer.family
|
|
134
|
+
extensions = Media::Extensions.of(%i[pet cbm2 kim1].include?(@computer.family) ? %i[none] : %i[cartridge])
|
|
106
135
|
@computer.family == :plus4 ? extensions + [Media::Plus4Media::ROM_IMAGE] : extensions
|
|
107
136
|
end
|
|
108
137
|
|
|
109
|
-
# The extensions of what goes in device 8: on the PET the
|
|
110
|
-
# 8250's disk images
|
|
111
|
-
# a serial true drive reads.
|
|
138
|
+
# The extensions of what goes in device 8: on the PET and the CBM-II
|
|
139
|
+
# the 8050's and 8250's disk images and the hard disks' besides the
|
|
140
|
+
# others, and no raw GCR, which only a serial true drive reads.
|
|
112
141
|
def disk_extensions
|
|
113
|
-
|
|
142
|
+
if %i[pet cbm2].include?(@computer.family)
|
|
143
|
+
return Media::Extensions.of(%i[disk ieee_disk hard_disk archive disk_list])
|
|
144
|
+
end
|
|
114
145
|
|
|
115
146
|
Media::Extensions::DEVICE8
|
|
116
147
|
end
|
|
@@ -125,17 +156,19 @@ module Badline
|
|
|
125
156
|
|
|
126
157
|
# What a save of the machine is named after: the cartridge, the disk,
|
|
127
158
|
# the tape, or BASIC, without the bracketed parts of a file's name. A
|
|
128
|
-
# VIC-20's are named after its disk, or else the machine,
|
|
129
|
-
#
|
|
159
|
+
# VIC-20's are named after its disk, or else the machine, a Plus/4's
|
|
160
|
+
# or a PET's after its disk or tape, and a CBM-II's after its disk.
|
|
130
161
|
def game_name
|
|
131
162
|
vic20 = @computer.family == :vic20
|
|
132
|
-
name = vic20 || %i[plus4 pet].include?(@computer.family) ? "" : cartridge_name
|
|
163
|
+
name = vic20 || %i[plus4 pet cbm2 kim1].include?(@computer.family) ? "" : cartridge_name
|
|
133
164
|
disk = disk_path
|
|
134
165
|
name = File.basename(disk, File.extname(disk)) if name.empty? && !disk.empty?
|
|
135
|
-
name = tape_name if name.empty? && !vic20
|
|
166
|
+
name = tape_name if name.empty? && !vic20 && !%i[cbm2 kim1].include?(@computer.family)
|
|
136
167
|
name = name.sub(/\s*[(\[].*\z/, "").strip
|
|
137
168
|
return name unless name.empty?
|
|
138
169
|
|
|
170
|
+
return "KIM-1" if @computer.family == :kim1
|
|
171
|
+
|
|
139
172
|
vic20 ? "VIC-20" : "BASIC"
|
|
140
173
|
end
|
|
141
174
|
|
|
@@ -154,7 +187,7 @@ module Badline
|
|
|
154
187
|
case @computer.family
|
|
155
188
|
when :plus4 then @computer.cartridge_slots.map { |slot| slot_name(slot) }.uniq.join(", ")
|
|
156
189
|
when :vic20 then @computer.cartridge_name
|
|
157
|
-
when :pet then ""
|
|
190
|
+
when :pet, :cbm2, :kim1 then ""
|
|
158
191
|
else
|
|
159
192
|
cartridge = @computer.address_bus.cartridge
|
|
160
193
|
cartridge.nil? ? "" : cartridge.name
|
|
@@ -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
|
|
@@ -88,6 +104,21 @@ module Badline
|
|
|
88
104
|
# Whether the machine is a PET, whose ports page shows its keyboard.
|
|
89
105
|
def pet? = @computer.family == :pet
|
|
90
106
|
|
|
107
|
+
# Whether the machine is a CBM-II, whose ports page shows its keyboard
|
|
108
|
+
# too.
|
|
109
|
+
def cbm2? = @computer.family == :cbm2
|
|
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
|
+
|
|
115
|
+
# Whether the machine is the CBM-II's B series, whose ports page is
|
|
116
|
+
# its keyboard's alone.
|
|
117
|
+
def b_series? = cbm2? && !Controls.p500?(@computer)
|
|
118
|
+
|
|
119
|
+
# Whether the machine is a KIM-1, whose ports page is its panel's.
|
|
120
|
+
def kim1? = @computer.family == :kim1
|
|
121
|
+
|
|
91
122
|
private
|
|
92
123
|
|
|
93
124
|
def vic20? = @computer.family == :vic20
|
|
@@ -95,6 +126,8 @@ module Badline
|
|
|
95
126
|
def plus4? = @computer.family == :plus4
|
|
96
127
|
|
|
97
128
|
def draw_drive
|
|
129
|
+
return info("DRIVE", "") if kim1?
|
|
130
|
+
|
|
98
131
|
media = @media
|
|
99
132
|
inserted = media.inserted?
|
|
100
133
|
set = inserted ? media.disk_set : []
|
|
@@ -110,9 +143,14 @@ module Badline
|
|
|
110
143
|
skip
|
|
111
144
|
drive = @computer.true_drive
|
|
112
145
|
info("DEVICE", drive.nil? ? "FAST LOADING" : "#{drive.model_name}, TRUE DRIVE")
|
|
146
|
+
row("DRIVE TYPE...", :drive_type, drive_model) if pet? || cbm2?
|
|
113
147
|
end
|
|
114
148
|
|
|
149
|
+
# The CBM-II has no datasette, and the KIM-1 a deck of its own.
|
|
115
150
|
def draw_datasette
|
|
151
|
+
return info("TAPE", "") if cbm2?
|
|
152
|
+
return draw_kim1_tape if kim1?
|
|
153
|
+
|
|
116
154
|
datasette = @computer.datasette
|
|
117
155
|
tape = datasette.tape
|
|
118
156
|
info("TAPE", tape.nil? ? "" : File.basename(tape.path))
|
|
@@ -124,8 +162,55 @@ module Badline
|
|
|
124
162
|
info("MOTOR", datasette.motor? ? "ON" : "OFF")
|
|
125
163
|
end
|
|
126
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
|
+
|
|
127
210
|
def draw_expansion
|
|
128
211
|
return draw_pet_memory if pet?
|
|
212
|
+
return info("RAM", "#{@computer.model.ram_kb}K") if cbm2?
|
|
213
|
+
return info("RAM", "1K") if kim1?
|
|
129
214
|
|
|
130
215
|
info("CARTRIDGE", @media.cartridge_name)
|
|
131
216
|
return info("RAM EXPANSION", RAM_NAMES.fetch(@computer.ram_configuration)) if vic20?
|
|
@@ -163,6 +248,8 @@ module Badline
|
|
|
163
248
|
return draw_8296_memory if model.cbm8296?
|
|
164
249
|
|
|
165
250
|
info("RAM", "#{@computer.ram_kb}K")
|
|
251
|
+
return info("BANK RAM", "64K, BANK #{@computer.board.bank} AT $9000") if model.superpet?
|
|
252
|
+
|
|
166
253
|
info("EXPANSION RAM", model.expansion ? "64K BOARD" : "")
|
|
167
254
|
end
|
|
168
255
|
|
|
@@ -186,12 +273,15 @@ module Badline
|
|
|
186
273
|
end
|
|
187
274
|
end
|
|
188
275
|
|
|
189
|
-
# The C128 names its model and the mode it runs in first, the Plus/4
|
|
190
|
-
# and the
|
|
191
|
-
# it has one
|
|
276
|
+
# The C128 names its model and the mode it runs in first, the Plus/4,
|
|
277
|
+
# the PET and the CBM-II their model and RAM, the Plus/4 its RAM
|
|
278
|
+
# expansion if it has one, and the CBM-II its KERNAL, the B series'
|
|
279
|
+
# 901244 or the P500's 901234.
|
|
192
280
|
def draw_power
|
|
193
281
|
info("MACHINE", "#{@computer.model.name.upcase}, #{@computer.mode.to_s.upcase} MODE") if c128?
|
|
194
|
-
info("MACHINE", @computer.model_label) if pet?
|
|
282
|
+
info("MACHINE", @computer.model_label.upcase) if pet? || cbm2? || kim1?
|
|
283
|
+
info("KERNAL", "#{Controls.p500?(@computer) ? 901_234 : 901_244}-#{@computer.kernal.upcase}") if cbm2?
|
|
284
|
+
draw_superpet_switches if pet? && @computer.superpet?
|
|
195
285
|
if plus4?
|
|
196
286
|
info("MACHINE", @computer.model_label)
|
|
197
287
|
expansion = @computer.ram_expansion_label
|
|
@@ -203,6 +293,25 @@ module Badline
|
|
|
203
293
|
row("QUIT", :quit)
|
|
204
294
|
end
|
|
205
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
|
+
|
|
206
315
|
# A label, and its value under it, or NONE in the dim colour when the
|
|
207
316
|
# value is empty.
|
|
208
317
|
def info(label, value)
|
|
@@ -6,8 +6,13 @@ module Badline
|
|
|
6
6
|
# control port has plugged in, a joystick or a pot device, and whether
|
|
7
7
|
# the keys type or drive the joysticks. The VIC-20 has one port, a
|
|
8
8
|
# joystick's, and the Plus/4 two joysticks and no pot devices. The PET
|
|
9
|
-
#
|
|
10
|
-
# instead.
|
|
9
|
+
# and the CBM-II's B series have no ports, and the page, KEYBOARD
|
|
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. 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.
|
|
11
16
|
module MenuPorts
|
|
12
17
|
PORT_DEVICES = %i[joystick mouse paddles].freeze
|
|
13
18
|
PORT_NAMES = %w[JOY MOUSE PADDLES].freeze
|
|
@@ -21,15 +26,22 @@ module Badline
|
|
|
21
26
|
PET_GRAPHICS_KEYS = ["ESC: RUN/STOP", "SHIFT+LETTER: GRAPHIC", "ALT+SYMBOL: GRAPHIC"].freeze
|
|
22
27
|
PET_BUSINESS_KEYS = ["ESC: ESC", "TAB: TAB", "PAGE UP: REPEAT", "KEYPAD: KEYPAD", "ALT+KEY: SHIFT+KEY"].freeze
|
|
23
28
|
|
|
29
|
+
# Where the CBM-II's keys without a character of their own are.
|
|
30
|
+
CBM2_KEYS = ["ESC: ESC", "F12: RUN/STOP", "HOME: CLR/HOME", "BACKSPACE: INST/DEL", "F1-F8: F1-F8",
|
|
31
|
+
"ALT+F9, ALT+F10: F9, F10", "KEYPAD: KEYPAD", "ALT+0: KEYPAD 00", "ALT+C: C= ALT+E: CE",
|
|
32
|
+
"ALT+G: NORM/GRAPH", "ALT+R: OFF/RVS ALT+P: PI", "_: LEFT ARROW"].freeze
|
|
33
|
+
|
|
24
34
|
private
|
|
25
35
|
|
|
26
36
|
def draw_ports
|
|
27
37
|
return draw_vic20_port if @computer.family == :vic20
|
|
28
38
|
return draw_plus4_ports if @computer.family == :plus4
|
|
29
39
|
return draw_pet_keys if @computer.family == :pet
|
|
40
|
+
return draw_p500_ports if Controls.p500?(@computer)
|
|
41
|
+
return draw_cbm2_keys if @computer.family == :cbm2
|
|
42
|
+
return draw_kim1_panel if @computer.family == :kim1
|
|
30
43
|
|
|
31
|
-
|
|
32
|
-
toggle("PORT 2", :port2, [PORT_NAMES, PORT_ACTIONS[1], PORT_DEVICES.index(port_device(2))])
|
|
44
|
+
draw_pot_ports
|
|
33
45
|
return unless draw_keys(@computer.family == :c128 ? "C128" : "C64")
|
|
34
46
|
|
|
35
47
|
row("SWAP JOYSTICKS", :swap)
|
|
@@ -61,15 +73,76 @@ module Badline
|
|
|
61
73
|
|
|
62
74
|
# The PET's keyboard, whose keys type the characters on the host's
|
|
63
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.
|
|
64
78
|
def draw_pet_keys
|
|
65
79
|
business = @computer.model.keyboard == :business
|
|
66
80
|
info("KEYBOARD", business ? "BUSINESS" : "GRAPHICS")
|
|
81
|
+
draw_superpet_characters if @computer.superpet?
|
|
67
82
|
(PET_KEYS + (business ? PET_BUSINESS_KEYS : PET_GRAPHICS_KEYS)).each do |line|
|
|
68
83
|
@painter.text(@left, @top, line, MenuTheme::TEXT)
|
|
69
84
|
@top += MenuPages::LINE
|
|
70
85
|
end
|
|
71
86
|
end
|
|
72
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
|
+
|
|
117
|
+
# What each control port has plugged in, a joystick, a mouse or
|
|
118
|
+
# paddles.
|
|
119
|
+
def draw_pot_ports
|
|
120
|
+
toggle("PORT 1", :port1, [PORT_NAMES, PORT_ACTIONS[0], PORT_DEVICES.index(port_device(1))])
|
|
121
|
+
toggle("PORT 2", :port2, [PORT_NAMES, PORT_ACTIONS[1], PORT_DEVICES.index(port_device(2))])
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# The P500's two ports, its joysticks one for each set of keys, and
|
|
125
|
+
# while the keys type, where its keys are.
|
|
126
|
+
def draw_p500_ports
|
|
127
|
+
draw_pot_ports
|
|
128
|
+
return draw_cbm2_keys unless draw_keys("P500")
|
|
129
|
+
|
|
130
|
+
row("SWAP JOYSTICKS", :swap)
|
|
131
|
+
skip
|
|
132
|
+
arrows = @controls.arrows_port
|
|
133
|
+
info("ARROWS, SPACE", "JOYSTICK #{arrows}")
|
|
134
|
+
info("WASD, LEFT SHIFT", "JOYSTICK #{3 - arrows}")
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# The CBM-II's keyboard, which types as the PET's does, and the keys
|
|
138
|
+
# that stand for the rest of its keys.
|
|
139
|
+
def draw_cbm2_keys
|
|
140
|
+
CBM2_KEYS.each do |line|
|
|
141
|
+
@painter.text(@left, @top, line, MenuTheme::TEXT)
|
|
142
|
+
@top += MenuPages::LINE
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
73
146
|
# The toggle between the keyboard named and the joysticks, and
|
|
74
147
|
# whether the keys drive the joysticks.
|
|
75
148
|
def draw_keys(keyboard)
|
|
@@ -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
|
-
name = "KEYBOARD" if PAGES[index] == :ports && @pages.pet?
|
|
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
|