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
|
@@ -7,17 +7,21 @@ module Badline
|
|
|
7
7
|
# It loads on its own, for Options.
|
|
8
8
|
#
|
|
9
9
|
# - :disk, a disk image that the traps mount and a true drive reads
|
|
10
|
-
# - :ieee_disk, an 8050's or
|
|
11
|
-
# drive
|
|
10
|
+
# - :ieee_disk, an 8050's, 8250's or 2040's disk image, for a PET's
|
|
11
|
+
# IEEE-488 drive
|
|
12
|
+
# - :hard_disk, a D9060's or D9090's hard disk, which only a PET's or a
|
|
13
|
+
# CBM-II's true drive reads
|
|
12
14
|
# - :gcr, a disk's raw GCR, which only a true drive reads
|
|
13
15
|
# - :archive, a .t64, which the traps mount read-only
|
|
14
16
|
# - :tape, :cartridge and :tune
|
|
17
|
+
# - :papertape, a MOS papertape, which only the KIM-1 loads
|
|
15
18
|
# - :disk_list, a list of the disks of a set (DiskList)
|
|
16
19
|
module Extensions
|
|
17
20
|
KINDS = {
|
|
18
21
|
".d64" => :disk, ".d71" => :disk, ".d81" => :disk, ".g64" => :gcr, ".g71" => :gcr, ".t64" => :archive,
|
|
19
|
-
".d80" => :ieee_disk, ".d82" => :ieee_disk, ".
|
|
20
|
-
".m3u" => :disk_list, ".vfl" => :disk_list
|
|
22
|
+
".d80" => :ieee_disk, ".d82" => :ieee_disk, ".d67" => :ieee_disk, ".d90" => :hard_disk, ".tap" => :tape,
|
|
23
|
+
".crt" => :cartridge, ".sid" => :tune, ".m3u" => :disk_list, ".vfl" => :disk_list, ".ptp" => :papertape,
|
|
24
|
+
".pap" => :papertape
|
|
21
25
|
}.freeze
|
|
22
26
|
|
|
23
27
|
# The kind of the medium at `path`, by its extension.
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Media
|
|
5
|
+
# What a KIM-1 loads (Media.attach): a MOS papertape, a .ptp or .pap
|
|
6
|
+
# (Storage::Papertape), at the addresses its records give, or a .bin
|
|
7
|
+
# of bare bytes, which says nothing of where it goes, at its Loading's
|
|
8
|
+
# load address.
|
|
9
|
+
#
|
|
10
|
+
# Once the monitor runs, the bytes go straight into memory, after
|
|
11
|
+
# the NMI and IRQ vectors at $17FA and $17FE, which nothing sets at
|
|
12
|
+
# power-on, are pointed at the monitor's $1C00, so ST and BRK stop
|
|
13
|
+
# the program and show where (User Manual, section 4.1). A papertape
|
|
14
|
+
# can go in through the teletype instead, as the monitor's L command
|
|
15
|
+
# reads it, in real time. The program then starts at its Loading's
|
|
16
|
+
# start address, or else where it loads, as the user would start it:
|
|
17
|
+
# AD, the address and GO on the keypad, or the address, a space and G
|
|
18
|
+
# on the teletype. Without autostart the monitor stops at the
|
|
19
|
+
# address.
|
|
20
|
+
#
|
|
21
|
+
# A .wav, a recording of a KIM tape (Storage::KIMTape), goes in the
|
|
22
|
+
# cassette deck, for the monitor's LOADT to read once PLAY is down.
|
|
23
|
+
module KIM1Media
|
|
24
|
+
PAPERTAPES = Extensions.of(%i[papertape])
|
|
25
|
+
|
|
26
|
+
# A .bin, bare bytes.
|
|
27
|
+
BINARY = ".bin"
|
|
28
|
+
|
|
29
|
+
# A recording of a tape.
|
|
30
|
+
TAPE = ".wav"
|
|
31
|
+
|
|
32
|
+
# What a KIM-1 takes.
|
|
33
|
+
EXTENSIONS = (PAPERTAPES + [BINARY, TAPE]).freeze
|
|
34
|
+
|
|
35
|
+
# Where a .bin loads without a load address, as most of the First
|
|
36
|
+
# Book of KIM's programs do.
|
|
37
|
+
DEFAULT_LOAD_ADDRESS = 0x0200
|
|
38
|
+
|
|
39
|
+
# Where the monitor saves the registers and shows the PC, for the
|
|
40
|
+
# NMI and IRQ vectors.
|
|
41
|
+
MONITOR = 0x1c00
|
|
42
|
+
|
|
43
|
+
NMI_VECTOR = 0x17fa
|
|
44
|
+
IRQ_VECTOR = 0x17fe
|
|
45
|
+
|
|
46
|
+
# How a KIM-1 loads and starts a program: at `load_address`, a .bin's,
|
|
47
|
+
# or -1 for DEFAULT_LOAD_ADDRESS, from `start_address`, or -1 for
|
|
48
|
+
# where it loads, and through the teletype's L command if
|
|
49
|
+
# `teletype`.
|
|
50
|
+
class Loading
|
|
51
|
+
attr_reader :load_address, :start_address
|
|
52
|
+
|
|
53
|
+
def initialize(load_address: -1, start_address: -1, teletype: false)
|
|
54
|
+
@load_address = load_address
|
|
55
|
+
@start_address = start_address
|
|
56
|
+
@teletype = teletype
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def teletype? = @teletype
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Loads straight into memory, from where it loads.
|
|
63
|
+
DIRECT = Loading.new
|
|
64
|
+
|
|
65
|
+
class << self
|
|
66
|
+
# The Loading the command line's `options` ask for, with
|
|
67
|
+
# --load-address, --start-address and --tty-load.
|
|
68
|
+
def loading(options)
|
|
69
|
+
load_address = options.load_address
|
|
70
|
+
start_address = options.start_address
|
|
71
|
+
Loading.new(load_address: load_address.nil? ? -1 : load_address,
|
|
72
|
+
start_address: start_address.nil? ? -1 : start_address, teletype: options.tty_load?)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Whether a KIM-1 takes the file at `path`.
|
|
76
|
+
def takes?(path) = EXTENSIONS.include?(File.extname(path).downcase)
|
|
77
|
+
|
|
78
|
+
# Loads the program at `path` into the KIM-1 `machine` as
|
|
79
|
+
# `loading` says, and starts it if `autostart`. Raises
|
|
80
|
+
# Machine::Unsupported when it loads outside the RAM.
|
|
81
|
+
def attach(machine, path, loading, autostart:)
|
|
82
|
+
raise Machine::Unsupported, "doesn't go in a KIM-1" unless takes?(path)
|
|
83
|
+
return insert_tape(machine, path) if File.extname(path).downcase == TAPE
|
|
84
|
+
|
|
85
|
+
papertape = PAPERTAPES.include?(File.extname(path).downcase)
|
|
86
|
+
tape = papertape ? Storage::Papertape.read(path) : nil
|
|
87
|
+
records = tape.nil? ? [binary(path, loading.load_address)] : tape.records
|
|
88
|
+
refuse_outside_ram(machine, records)
|
|
89
|
+
start = loading.start_address.negative? ? records.first.address : loading.start_address
|
|
90
|
+
if !tape.nil? && loading.teletype? && machine.tty?
|
|
91
|
+
machine.teletype.type("L#{tape.text}")
|
|
92
|
+
else
|
|
93
|
+
machine.on_init { deposit(machine, records) }
|
|
94
|
+
end
|
|
95
|
+
machine.on_init { machine.type_text(start_keys(machine, start, autostart)) }
|
|
96
|
+
"Loading #{path} at $#{hex(records.first.address)}"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
private
|
|
100
|
+
|
|
101
|
+
def insert_tape(machine, path)
|
|
102
|
+
machine.tape.insert_tape(Storage::KIMTape.read(path))
|
|
103
|
+
"Inserted #{path} in the tape deck"
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def binary(path, load_address)
|
|
107
|
+
Storage::Papertape::Record.new(load_address.negative? ? DEFAULT_LOAD_ADDRESS : load_address,
|
|
108
|
+
File.binread(path).bytes)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def refuse_outside_ram(machine, records)
|
|
112
|
+
records.each do |record|
|
|
113
|
+
address = record.address
|
|
114
|
+
last = address + record.bytes.size - 1
|
|
115
|
+
raise Machine::Unsupported, "has no bytes to load" if last < address
|
|
116
|
+
next if last <= 0xffff && (address..last).all? { |byte_address| machine.bus.ram?(byte_address) }
|
|
117
|
+
|
|
118
|
+
raise Machine::Unsupported, "loads at $#{hex(address)}-$#{hex(last)}, outside the KIM-1's " \
|
|
119
|
+
"#{machine.bus.ram_kb}K of RAM; --ram 5k or --ram expanded adds more"
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def deposit(machine, records)
|
|
124
|
+
[NMI_VECTOR, IRQ_VECTOR].each do |vector|
|
|
125
|
+
machine.poke(vector, MONITOR & 0xff)
|
|
126
|
+
machine.poke(vector + 1, MONITOR >> 8)
|
|
127
|
+
end
|
|
128
|
+
records.each do |record|
|
|
129
|
+
address = record.address
|
|
130
|
+
record.bytes.each_with_index { |byte, offset| machine.poke(address + offset, byte) }
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# What starts the program at `start`, or stops at it without
|
|
135
|
+
# `autostart`.
|
|
136
|
+
def start_keys(machine, start, autostart)
|
|
137
|
+
if machine.tty?
|
|
138
|
+
opened = "#{hex(start)} "
|
|
139
|
+
return autostart ? "#{opened}G" : opened
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
keys = "AD #{hex(start).chars.join(' ')}"
|
|
143
|
+
autostart ? "#{keys} GO" : keys
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def hex(value) = value.to_s(16).upcase.rjust(4, "0")
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
@@ -27,8 +27,10 @@ module Badline
|
|
|
27
27
|
# BASIC 2 and 4 load the first program off the disk and run it.
|
|
28
28
|
# BASIC 1's LOAD finds no device on the IEEE-488 bus, so the first
|
|
29
29
|
# program, which the block gives, goes in as a program file does,
|
|
30
|
-
# once the KERNAL has booted.
|
|
30
|
+
# once the KERNAL has booted. The SuperPET's 6809 starts its own
|
|
31
|
+
# menu instead.
|
|
31
32
|
def disk_autostart(machine)
|
|
33
|
+
return unless machine.boots_basic?
|
|
32
34
|
return machine.type_text(AUTOSTART) unless machine.model.basic1?
|
|
33
35
|
|
|
34
36
|
data = yield
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module Badline
|
|
4
4
|
module Media
|
|
5
|
-
# A program loading into a C64, a C128, a 264 series machine
|
|
6
|
-
# once it has booted (Media.attach). The VIC-20 has its own
|
|
5
|
+
# A program loading into a C64, a C128, a 264 series machine, a PET or
|
|
6
|
+
# a CBM-II once it has booted (Media.attach). The VIC-20 has its own
|
|
7
7
|
# (Vic20Basic).
|
|
8
8
|
module Program
|
|
9
9
|
# Where BASIC 3.5 starts on the 264 series.
|
|
@@ -35,10 +35,13 @@ module Badline
|
|
|
35
35
|
# KERNAL's end address (EAL). BASIC 7.0 starts at $1C01 and keeps
|
|
36
36
|
# the end of its text at $1210, and the 264 KERNAL keeps EAL at $9D.
|
|
37
37
|
# PET BASIC 2 and 4 keep the end of their text at $2A and EAL at
|
|
38
|
-
# $C9, and BASIC 1 at $7C and $E5.
|
|
38
|
+
# $C9, and BASIC 1 at $7C and $E5. The CBM-II's BASIC starts at
|
|
39
|
+
# $0003 of segment 1 and keeps the end of its text at $2F, and its
|
|
40
|
+
# KERNAL EAL at $96, in segment 15.
|
|
39
41
|
def basic(computer)
|
|
40
42
|
return [PLUS4_BASIC_START, 0x2d, KernalTrap::PLUS4_ZERO_PAGE.end_address] if computer.family == :plus4
|
|
41
43
|
return pet_basic(computer) if computer.family == :pet
|
|
44
|
+
return [CBM2Media::BASIC_START, CBM2Media::TEXT_END, CBM2Media::EAL] if computer.family == :cbm2
|
|
42
45
|
return [0x1c01, 0x1210, 0xae] if computer.family == :c128 && computer.mode == :c128
|
|
43
46
|
|
|
44
47
|
[BASIC_START, 0x2d, 0xae]
|
|
@@ -4,19 +4,28 @@ module Badline
|
|
|
4
4
|
module Media
|
|
5
5
|
# Device 8 as a true drive instead of the KERNAL traps: a 1541, or on
|
|
6
6
|
# the C128 its 1571, or on the Plus/4 a 1551 if it asks for one, or a
|
|
7
|
-
# 1581, or on the PET a
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
# the
|
|
14
|
-
#
|
|
15
|
-
# 1581
|
|
16
|
-
#
|
|
7
|
+
# 1581, or on the PET or the CBM-II a drive on the IEEE-488 bus. Once a
|
|
8
|
+
# true drive is plugged in as device 8, disk media go into it rather
|
|
9
|
+
# than into the traps, so a LOAD runs the DOS and every byte crosses the
|
|
10
|
+
# serial bus, TCBM or the IEEE-488 bus. A .g64 holds the disk's raw
|
|
11
|
+
# GCR, which only a true drive reads, so it plugs one in when there's
|
|
12
|
+
# none yet. The 1541 reads only .d64 and .g64 images, the 1571 .d71 and
|
|
13
|
+
# .g71 as well, and the 1581 only .d81, so a .d81 swaps the drive on
|
|
14
|
+
# device 8 for a 1581 (Drives::Model1581::Slot), and another disk image
|
|
15
|
+
# swaps a 1581 back for the machine's own drive. On the PET and
|
|
16
|
+
# the CBM-II an image goes in the drive on device 8 if it reads it, or
|
|
17
|
+
# else in a drive of the machine's own model, plug_true_drive's, if
|
|
18
|
+
# that reads it, or else in the model made for it, swapped in
|
|
19
|
+
# (Drives::IEEEModels): a 2031 for a .d64, an 8050 for a .d80 and an
|
|
20
|
+
# 8250 for a .d82, in the drive of a dual unit the machine names
|
|
21
|
+
# (disk_drive_number): drive 1 on a SuperPET running its 6809. The
|
|
22
|
+
# traps' other disk media, a .t64 or a host directory, raise Error.
|
|
17
23
|
module TrueDrive
|
|
18
24
|
class Error < ArgumentError; end
|
|
19
25
|
|
|
26
|
+
# The families whose drives sit on the IEEE-488 bus.
|
|
27
|
+
IEEE_FAMILIES = %i[pet cbm2].freeze
|
|
28
|
+
|
|
20
29
|
class << self
|
|
21
30
|
# Plugs the machine's true drive in as device 8, unless one is there
|
|
22
31
|
# already, and returns it.
|
|
@@ -30,12 +39,12 @@ module Badline
|
|
|
30
39
|
drive if drive && drive.device == KernalTrap::Routine::DEVICE
|
|
31
40
|
end
|
|
32
41
|
|
|
33
|
-
# Whether the path goes in a true drive: a .g64 or .
|
|
34
|
-
# other disk media, which the traps would mount, when a true drive
|
|
42
|
+
# Whether the path goes in a true drive: a .g64, .g71 or .d90 always,
|
|
43
|
+
# and other disk media, which the traps would mount, when a true drive
|
|
35
44
|
# is device 8.
|
|
36
45
|
def takes?(computer, path)
|
|
37
46
|
kind = Extensions.kind(path)
|
|
38
|
-
return true if kind
|
|
47
|
+
return true if %i[gcr hard_disk].include?(kind)
|
|
39
48
|
|
|
40
49
|
!drive(computer).nil? && (File.directory?(path) || %i[disk archive ieee_disk].include?(kind))
|
|
41
50
|
end
|
|
@@ -45,15 +54,13 @@ module Badline
|
|
|
45
54
|
# mounted through the traps, so LOAD and SAVE reach the drive too.
|
|
46
55
|
# `read_only` puts it in write-protected.
|
|
47
56
|
def insert(computer, path, read_only: false)
|
|
48
|
-
|
|
49
|
-
return insert_d81(computer, path, read_only) if
|
|
57
|
+
return insert_ieee(computer, path, read_only) if IEEE_FAMILIES.include?(computer.family)
|
|
58
|
+
return insert_d81(computer, path, read_only) if File.extname(path).casecmp?(".d81")
|
|
50
59
|
|
|
51
60
|
drive = own_drive(computer)
|
|
52
61
|
name = drive&.model_name || default_model(computer)
|
|
53
62
|
types = name == "1571" ? %w[.d64 .g64 .d71 .g71] : %w[.d64 .g64]
|
|
54
63
|
unless types.include?(File.extname(path).downcase)
|
|
55
|
-
raise Error, "#{path} is not a #{types.join(' or ')} image, which the #{name} reads" if pet
|
|
56
|
-
|
|
57
64
|
raise Error, "#{path} is not a #{types.join(', ')} or .d81 image, which the #{name} and the 1581 read"
|
|
58
65
|
end
|
|
59
66
|
|
|
@@ -66,20 +73,39 @@ module Badline
|
|
|
66
73
|
private
|
|
67
74
|
|
|
68
75
|
# The model plug_true_drive plugs in.
|
|
69
|
-
def default_model(computer)
|
|
70
|
-
case computer.family
|
|
71
|
-
when :c128 then "1571"
|
|
72
|
-
when :pet then "2031"
|
|
73
|
-
else "1541"
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
+
def default_model(computer) = computer.family == :c128 ? "1571" : "1541"
|
|
76
77
|
|
|
77
|
-
# The drive on device 8 unless it's a 1581.
|
|
78
|
+
# The drive on device 8 unless it's a 1581, which a .d64 swaps back
|
|
79
|
+
# out.
|
|
78
80
|
def own_drive(computer)
|
|
79
81
|
drive = drive(computer)
|
|
80
82
|
drive unless drive&.model_name == "1581"
|
|
81
83
|
end
|
|
82
84
|
|
|
85
|
+
# The image in the model Drives::IEEEModels.taking picks, swapped in
|
|
86
|
+
# for the drive on device 8 unless it's that model already.
|
|
87
|
+
def insert_ieee(computer, path, read_only)
|
|
88
|
+
drive = drive(computer)
|
|
89
|
+
model = Drives::IEEEModels.taking(path, drive&.model_name, computer.true_drive_model)
|
|
90
|
+
unless model
|
|
91
|
+
name = computer.true_drive_model
|
|
92
|
+
types = Drives::IEEEModels::MEDIA.fetch(name)
|
|
93
|
+
raise Error, "#{path} is not a #{types.join(' or ')} image, which the #{name} reads"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
drive = computer.plug_ieee_drive(model) unless drive&.model_name == model
|
|
97
|
+
number = computer.disk_drive_number
|
|
98
|
+
if number.positive? && drive.is_a?(Drives::Model8050)
|
|
99
|
+
drive.insert_image(path, drive: number, read_only:)
|
|
100
|
+
computer.unmount
|
|
101
|
+
return "Inserted #{path} in the #{model}'s drive #{number} as device 8"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
drive.insert_image(path, read_only:)
|
|
105
|
+
computer.unmount
|
|
106
|
+
"Inserted #{path} in the #{model} as device 8"
|
|
107
|
+
end
|
|
108
|
+
|
|
83
109
|
def insert_d81(computer, path, read_only)
|
|
84
110
|
drive = drive(computer)
|
|
85
111
|
drive = computer.plug_drive1581 unless drive&.model_name == "1581"
|
data/lib/badline/media.rb
CHANGED
|
@@ -12,6 +12,8 @@ require "badline/media/vic20_cartridge"
|
|
|
12
12
|
require "badline/media/vic20_media"
|
|
13
13
|
require "badline/media/plus4_media"
|
|
14
14
|
require "badline/media/pet_media"
|
|
15
|
+
require "badline/media/cbm2_media"
|
|
16
|
+
require "badline/media/kim1_media"
|
|
15
17
|
require "badline/media/tune"
|
|
16
18
|
require "badline/media/program"
|
|
17
19
|
|
|
@@ -28,7 +30,8 @@ module Badline
|
|
|
28
30
|
".d81" => Storage::D81Image,
|
|
29
31
|
".t64" => Storage::T64,
|
|
30
32
|
".d80" => Storage::D80Image,
|
|
31
|
-
".d82" => Storage::D82Image
|
|
33
|
+
".d82" => Storage::D82Image,
|
|
34
|
+
".d67" => Storage::D67Image
|
|
32
35
|
}.freeze
|
|
33
36
|
|
|
34
37
|
class << self
|
|
@@ -53,9 +56,13 @@ module Badline
|
|
|
53
56
|
# .crt cartridges and raw .bin ROM images in its two cartridges'
|
|
54
57
|
# slots (Plus4Media), and no .sid tunes either. The PET mounts .d80
|
|
55
58
|
# and .d82 disks too, which no other machine takes, and has no
|
|
56
|
-
# cartridges, tunes or true drives (PETMedia)
|
|
57
|
-
# takes
|
|
58
|
-
|
|
59
|
+
# cartridges, tunes or true drives (PETMedia), and so does the CBM-II,
|
|
60
|
+
# which takes its own .crt cartridges and no tapes (CBM2Media). The
|
|
61
|
+
# C128 in C64 mode takes a C64's. The KIM-1 takes only its programs,
|
|
62
|
+
# which load as `kim1`, a KIM1Media::Loading, says (KIM1Media).
|
|
63
|
+
def attach(computer, path, autostart: true, subtune: nil, kim1: KIM1Media::DIRECT, **)
|
|
64
|
+
return KIM1Media.attach(computer, path, kim1, autostart:) if computer.family == :kim1
|
|
65
|
+
|
|
59
66
|
path = DiskList.disk(path)
|
|
60
67
|
refuse_unsupported(computer, path)
|
|
61
68
|
|
|
@@ -126,17 +133,20 @@ module Badline
|
|
|
126
133
|
private
|
|
127
134
|
|
|
128
135
|
# The VIC-20 and the 264 series have no SID to play a .sid tune on,
|
|
129
|
-
#
|
|
136
|
+
# only the PET and the CBM-II have the IEEE-488 drive a .d80, .d82
|
|
137
|
+
# or .d90 goes in, and only the KIM-1 reads papertape.
|
|
130
138
|
def refuse_unsupported(computer, path)
|
|
131
139
|
family = computer.family
|
|
132
|
-
if Extensions.kind(path) == :
|
|
133
|
-
|
|
140
|
+
raise Machine::Unsupported, "#{path} needs a KIM-1" if Extensions.kind(path) == :papertape
|
|
141
|
+
if %i[ieee_disk hard_disk].include?(Extensions.kind(path)) && !%i[pet cbm2].include?(family)
|
|
142
|
+
raise ArgumentError, "#{path} needs a PET's or a CBM-II's IEEE-488 drive"
|
|
134
143
|
end
|
|
135
144
|
|
|
136
145
|
refused, name = case family
|
|
137
146
|
when :vic20 then [Vic20Media::UNSUPPORTED, "a VIC-20"]
|
|
138
147
|
when :plus4 then [Vic20Media::UNSUPPORTED, "a Plus/4"]
|
|
139
148
|
when :pet then [PETMedia::UNSUPPORTED, "a PET"]
|
|
149
|
+
when :cbm2 then [CBM2Media::UNSUPPORTED, "a CBM-II"]
|
|
140
150
|
else [[], ""]
|
|
141
151
|
end
|
|
142
152
|
raise ArgumentError, "#{path} doesn't go in #{name}" if refused.include?(File.extname(path).downcase)
|
|
@@ -182,7 +192,11 @@ module Badline
|
|
|
182
192
|
# VIC-20 goes by that program, which the block gives
|
|
183
193
|
# (Vic20Media.disk_autostart).
|
|
184
194
|
def disk_autostart(computer)
|
|
185
|
-
computer.family
|
|
195
|
+
case computer.family
|
|
196
|
+
when :vic20 then Vic20Media.disk_autostart(yield)
|
|
197
|
+
when :cbm2 then CBM2Media::AUTOSTART
|
|
198
|
+
else AUTOSTART
|
|
199
|
+
end
|
|
186
200
|
end
|
|
187
201
|
|
|
188
202
|
# A VIC-20 or 264 series cartridge is its ROM chips. On the 264, the
|
|
@@ -194,6 +208,7 @@ module Badline
|
|
|
194
208
|
crt = Storage::CRTFile.new(path, machine: :vic20)
|
|
195
209
|
computer.attach_cartridge(crt.chips, crt.name.empty? ? File.basename(path, File.extname(path)) : crt.name)
|
|
196
210
|
when :plus4 then computer.attach_cartridge(Plus4Media.cartridge_chips(path, slot: options.fetch(:slot, nil)))
|
|
211
|
+
when :cbm2 then computer.attach_cartridge(CBM2Media.cartridge_chips(path))
|
|
197
212
|
else
|
|
198
213
|
computer.attach_cartridge(C64::Cartridge.from_file(path, **options))
|
|
199
214
|
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "badline/storage/crt_file"
|
|
3
4
|
require "badline/storage/p00"
|
|
4
5
|
require "badline/storage/tap"
|
|
5
6
|
|
|
@@ -11,9 +12,94 @@ module Badline
|
|
|
11
12
|
# Where C128 BASIC starts, which a program for the C128 loads at.
|
|
12
13
|
C128_BASIC_START = 0x1c01
|
|
13
14
|
|
|
15
|
+
# Whether the KIM-1 talks to a teletype: with --tty or --tty-load,
|
|
16
|
+
# and always on the terminal with --headless.
|
|
17
|
+
def tty? = @tty || @tty_load || kim1_terminal?
|
|
18
|
+
|
|
19
|
+
# The KIM-1 teletype's baud.
|
|
20
|
+
def baud = @baud
|
|
21
|
+
|
|
22
|
+
# Whether the KIM-1 loads a papertape through its monitor's L
|
|
23
|
+
# command, with --tty-load.
|
|
24
|
+
def tty_load? = @tty_load
|
|
25
|
+
|
|
26
|
+
# Where the KIM-1 loads a .bin, and where it starts its program, as
|
|
27
|
+
# --load-address and --start-address give them, or nil.
|
|
28
|
+
def load_address = @load_address
|
|
29
|
+
|
|
30
|
+
def start_address = @start_address
|
|
31
|
+
|
|
32
|
+
# Whether the KIM-1 runs on the terminal, its teletype there.
|
|
33
|
+
def kim1_terminal? = @family == :kim1 && @headless
|
|
34
|
+
|
|
14
35
|
private
|
|
15
36
|
|
|
16
|
-
#
|
|
37
|
+
# The KIM-1's keypad, until --tty or --baud name its teletype, and
|
|
38
|
+
# its programs where they load.
|
|
39
|
+
def initialize_kim1
|
|
40
|
+
@tty = false
|
|
41
|
+
@tty_load = false
|
|
42
|
+
@baud = 9600
|
|
43
|
+
@load_address = nil
|
|
44
|
+
@start_address = nil
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# The KIM-1 teletype's baud, and where it loads a .bin and starts a
|
|
48
|
+
# program.
|
|
49
|
+
def kim1_option(name, flag, value)
|
|
50
|
+
case name
|
|
51
|
+
when "--baud" then @baud = baud_for(value)
|
|
52
|
+
when "--load-address" then @load_address = address(flag, value)
|
|
53
|
+
else @start_address = address(flag, value)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def kim1_switch(name)
|
|
58
|
+
if name == "--tty"
|
|
59
|
+
@tty = true
|
|
60
|
+
else
|
|
61
|
+
@tty_load = true
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# An address in hex, with or without a $ or 0x before it.
|
|
66
|
+
def address(flag, value)
|
|
67
|
+
digits = value.delete_prefix("$").delete_prefix("0x").delete_prefix("0X")
|
|
68
|
+
raise Error, "invalid argument: #{flag} #{value}" unless digits.match?(/\A[0-9a-fA-F]{1,4}\z/)
|
|
69
|
+
|
|
70
|
+
digits.to_i(16)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def kim1_ram(value)
|
|
74
|
+
raise Error, "invalid argument: --ram #{value}" unless KIM1_RAM.key?(value)
|
|
75
|
+
|
|
76
|
+
KIM1_RAM[value]
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# The KIM-1 runs in the window, or with --headless on the terminal,
|
|
80
|
+
# without the C64's SID and REU. Only a papertape goes in through
|
|
81
|
+
# the teletype, and only a .bin has a load address to give.
|
|
82
|
+
def validate_kim1
|
|
83
|
+
raise Error, "--ntsc needs the C64" if @models.include?("ntsc")
|
|
84
|
+
raise Error, "--sid needs the C64" unless @sid_model.nil?
|
|
85
|
+
raise Error, "--reu needs the C64" unless @reu.nil?
|
|
86
|
+
raise Error, "--audio-out needs a .sid tune" unless @audio_out.nil?
|
|
87
|
+
|
|
88
|
+
extension = @media_path.nil? ? "" : File.extname(@media_path).downcase
|
|
89
|
+
raise Error, "--tty-load needs a .ptp or .pap" if @tty_load && !%w[.ptp .pap].include?(extension)
|
|
90
|
+
raise Error, "--load-address needs a .bin" unless @load_address.nil? || extension == ".bin"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Only the KIM-1 has a teletype, and programs without a load address.
|
|
94
|
+
def refuse_kim1_options
|
|
95
|
+
raise Error, "#{@tty ? '--tty' : '--baud'} needs kim1" if @tty || @baud != 9600
|
|
96
|
+
raise Error, "--tty-load needs kim1" if @tty_load
|
|
97
|
+
raise Error, "--load-address needs kim1" unless @load_address.nil?
|
|
98
|
+
raise Error, "--start-address needs kim1" unless @start_address.nil?
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Takes `sid`, `c64`, `vic20`, `c128`, `plus4`, `pet`, `cbm2` or `kim1`
|
|
102
|
+
# when given first.
|
|
17
103
|
def subcommand(args)
|
|
18
104
|
case args.first
|
|
19
105
|
when "sid" then @sid_command = true
|
|
@@ -22,6 +108,8 @@ module Badline
|
|
|
22
108
|
when "c128" then @family = :c128
|
|
23
109
|
when "plus4" then @family = :plus4
|
|
24
110
|
when "pet" then @family = :pet
|
|
111
|
+
when "cbm2" then @family = :cbm2
|
|
112
|
+
when "kim1" then @family = :kim1
|
|
25
113
|
else return
|
|
26
114
|
end
|
|
27
115
|
@family_named = !@sid_command
|
|
@@ -34,27 +122,41 @@ module Badline
|
|
|
34
122
|
when :c128 then C128_MODELS
|
|
35
123
|
when :plus4 then PLUS4_MODELS
|
|
36
124
|
when :pet then PET_MODELS
|
|
125
|
+
when :cbm2 then CBM2_MODELS
|
|
126
|
+
when :kim1 then KIM1_MODELS
|
|
37
127
|
else MODELS
|
|
38
128
|
end
|
|
39
129
|
end
|
|
40
130
|
|
|
41
131
|
# Without a family named, a program that loads at C128_BASIC_START is
|
|
42
|
-
# the C128's,
|
|
43
|
-
#
|
|
132
|
+
# the C128's, an 8050's or 8250's disk or a PET tape the PET's, a
|
|
133
|
+
# cartridge signed as a CBM-II's the CBM-II's, and a papertape the
|
|
134
|
+
# KIM-1's. A program that loads where PET BASIC starts could be a
|
|
135
|
+
# VIC-20's too.
|
|
44
136
|
def pick_family
|
|
45
137
|
return if @family_named || @sid_command || @media_path.nil? || !File.file?(@media_path)
|
|
46
138
|
|
|
47
|
-
if
|
|
139
|
+
if Media::Extensions.kind(@media_path) == :papertape
|
|
140
|
+
@family = :kim1
|
|
141
|
+
elsif pet_media?
|
|
48
142
|
@family = :pet
|
|
143
|
+
elsif cbm2_cartridge?
|
|
144
|
+
@family = :cbm2
|
|
49
145
|
elsif Media::Extensions::PROGRAMS.include?(File.extname(@media_path).downcase)
|
|
50
146
|
@family = :c128 if Storage::P00.load_address(@media_path) == C128_BASIC_START
|
|
51
147
|
end
|
|
52
148
|
end
|
|
53
149
|
|
|
54
|
-
# Whether the media is
|
|
150
|
+
# Whether the media is a cartridge signed as a CBM-II's.
|
|
151
|
+
def cbm2_cartridge?
|
|
152
|
+
Media::Extensions.kind(@media_path) == :cartridge && Storage::CRTFile.cbm2?(@media_path)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Whether the media is an 8050's or 8250's disk, a D9060's or D9090's
|
|
156
|
+
# hard disk, or a PET tape.
|
|
55
157
|
def pet_media?
|
|
56
158
|
kind = Media::Extensions.kind(@media_path)
|
|
57
|
-
kind
|
|
159
|
+
%i[ieee_disk hard_disk].include?(kind) || (kind == :tape && Storage::TAP.platform_of(@media_path) == Storage::TAP::PET_PLATFORM)
|
|
58
160
|
end
|
|
59
161
|
end
|
|
60
162
|
end
|