badline 0.7.0 → 0.8.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 +19 -0
- data/CLAUDE.md +3 -1
- data/README.md +96 -290
- data/doc/library.md +62 -0
- data/doc/media.md +69 -0
- data/doc/sid-player.md +132 -0
- data/doc/snapshots.md +69 -0
- data/lib/badline/cartridge/freezer.rb +2 -0
- data/lib/badline/cartridge.rb +3 -0
- data/lib/badline/frontend/app.rb +38 -35
- data/lib/badline/frontend/boot.rb +8 -1
- data/lib/badline/frontend/buttons.rb +101 -7
- data/lib/badline/frontend/confirmation.rb +50 -0
- data/lib/badline/frontend/controls.rb +44 -32
- data/lib/badline/frontend/file_browser.rb +225 -0
- data/lib/badline/frontend/frame_report.rb +52 -0
- data/lib/badline/frontend/menu_dialogs.rb +122 -0
- data/lib/badline/frontend/menu_media.rb +128 -0
- data/lib/badline/frontend/menu_pages.rb +198 -0
- data/lib/badline/frontend/painter.rb +10 -0
- data/lib/badline/frontend/pause_menu.rb +246 -0
- data/lib/badline/frontend/snapshots.rb +1 -1
- data/lib/badline/frontend/sound.rb +0 -1
- data/lib/badline/frontend/timeline.rb +5 -1
- data/lib/badline/frontend.rb +7 -0
- data/lib/badline/media/disk_set.rb +108 -0
- data/lib/badline/media.rb +1 -0
- data/lib/badline/options/table.rb +1 -1
- data/lib/badline/options.rb +3 -3
- data/lib/badline/version.rb +1 -1
- metadata +13 -1
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Media
|
|
5
|
+
# The disks of a set a disk image belongs to, found by name in its
|
|
6
|
+
# folder: images whose names differ only in their disk, side or part
|
|
7
|
+
# markers, such as "Disk 1", "Side B", "d2", "(Disk 1 of 3)", ordered
|
|
8
|
+
# by those markers. A name with no marker can end in a number or a
|
|
9
|
+
# letter, as in game_1.d64 and game_2.d64, which counts only when the
|
|
10
|
+
# folder has the first of the set too.
|
|
11
|
+
module DiskSet
|
|
12
|
+
KINDS = %w[disk disc side part].freeze
|
|
13
|
+
EXTENSIONS = %w[.d64 .d71 .d81 .g64].freeze
|
|
14
|
+
|
|
15
|
+
# The paths of the set's disks in order, or just `path` when it
|
|
16
|
+
# belongs to none.
|
|
17
|
+
def self.around(path)
|
|
18
|
+
extension = File.extname(path).downcase
|
|
19
|
+
return [path] unless EXTENSIONS.include?(extension)
|
|
20
|
+
|
|
21
|
+
marked = !parse(stem(path))[1].negative?
|
|
22
|
+
base = key(stem(path), marked)[0]
|
|
23
|
+
found = siblings(File.dirname(path), extension, base, marked)
|
|
24
|
+
return [path] if found.size < 2 || (!marked && found.none? { |pair| pair[0] == 1 })
|
|
25
|
+
|
|
26
|
+
found.sort_by { |pair| pair[0] }.map { |pair| File.join(File.dirname(path), pair[1]) }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# The name's words without their markers, joined, and the order the
|
|
30
|
+
# markers give it, -1 for none.
|
|
31
|
+
def self.parse(stem)
|
|
32
|
+
words = words(stem)
|
|
33
|
+
base = []
|
|
34
|
+
values = []
|
|
35
|
+
index = 0
|
|
36
|
+
index = take(words, index, base, values) while index < words.size
|
|
37
|
+
[base.join(" "), order(values)]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# The words before a trailing number or letter, joined, and its
|
|
41
|
+
# order, -1 for a name that doesn't end in one.
|
|
42
|
+
def self.trailing(stem)
|
|
43
|
+
words = words(stem)
|
|
44
|
+
last = words.last.to_s
|
|
45
|
+
return ["", -1] if words.size < 2 || !value?(last) || last.length > 2
|
|
46
|
+
|
|
47
|
+
[words[0, words.size - 1].join(" "), value(last)]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def self.words(stem) = stem.downcase.split(/[^a-z0-9]+/).reject(&:empty?)
|
|
51
|
+
|
|
52
|
+
def self.stem(path) = File.basename(path, File.extname(path))
|
|
53
|
+
|
|
54
|
+
def self.key(stem, marked) = marked ? parse(stem) : trailing(stem)
|
|
55
|
+
|
|
56
|
+
# The order and name of each image in the folder in the set.
|
|
57
|
+
def self.siblings(directory, extension, base, marked)
|
|
58
|
+
found = []
|
|
59
|
+
children(directory).each do |name|
|
|
60
|
+
next unless File.extname(name).downcase == extension
|
|
61
|
+
|
|
62
|
+
name_key = key(stem(name), marked)
|
|
63
|
+
found << [name_key[1], name] if name_key[0] == base && !name_key[1].negative?
|
|
64
|
+
end
|
|
65
|
+
found
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Adds the word at `index` to the base, or its marker's value to the
|
|
69
|
+
# values, and returns the index of the next word.
|
|
70
|
+
def self.take(words, index, base, values)
|
|
71
|
+
word = words[index]
|
|
72
|
+
following = words[index + 1].to_s
|
|
73
|
+
if KINDS.include?(word) && value?(following)
|
|
74
|
+
values << value(following)
|
|
75
|
+
index += 2
|
|
76
|
+
index += 2 if words[index] == "of" && words[index + 1].to_s.match?(/\A\d+\z/)
|
|
77
|
+
index
|
|
78
|
+
elsif marker?(word)
|
|
79
|
+
values << value(word.sub(/\A(disk|disc|side|part|d|s)/, ""))
|
|
80
|
+
index + 1
|
|
81
|
+
else
|
|
82
|
+
base << word
|
|
83
|
+
index + 1
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def self.marker?(word) = word.match?(/\A(disk|disc|side|part)(\d+|[a-z])\z/) || word.match?(/\A[ds]\d+\z/)
|
|
88
|
+
|
|
89
|
+
def self.value?(word) = word.match?(/\A(\d+|[a-z])\z/)
|
|
90
|
+
|
|
91
|
+
# A number counts as itself and a letter by its place in the
|
|
92
|
+
# alphabet, so side A is 1.
|
|
93
|
+
def self.value(word) = word.match?(/\A\d+\z/) ? word.to_i : word.ord - 96
|
|
94
|
+
|
|
95
|
+
def self.order(values)
|
|
96
|
+
return -1 if values.empty?
|
|
97
|
+
|
|
98
|
+
values.reduce(0) { |order, value| (order * 1000) + value }
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def self.children(directory)
|
|
102
|
+
Dir.children(directory)
|
|
103
|
+
rescue SystemCallError
|
|
104
|
+
[]
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
data/lib/badline/media.rb
CHANGED
|
@@ -16,7 +16,7 @@ module Badline
|
|
|
16
16
|
Option.new("--version", "Show the version and what built it", section: "Options", build: :native),
|
|
17
17
|
Option.new("--no-autostart", "Boot to READY. instead of running the program",
|
|
18
18
|
section: "Window options", needs: :window),
|
|
19
|
-
Option.new("--
|
|
19
|
+
Option.new("--writable", "Let the machine write to disk images, changing their files",
|
|
20
20
|
section: "Window options", needs: :window),
|
|
21
21
|
Option.new("--sound", "Play the SID through the host's audio device (F10 mutes)",
|
|
22
22
|
section: "Window options", needs: :window),
|
data/lib/badline/options.rb
CHANGED
|
@@ -61,7 +61,7 @@ module Badline
|
|
|
61
61
|
@sid_model = nil
|
|
62
62
|
@reu = nil
|
|
63
63
|
@autostart = true
|
|
64
|
-
@
|
|
64
|
+
@writable = false
|
|
65
65
|
@sound = native
|
|
66
66
|
@frames = 0
|
|
67
67
|
@paced = true
|
|
@@ -135,7 +135,7 @@ module Badline
|
|
|
135
135
|
|
|
136
136
|
def autostart? = @autostart
|
|
137
137
|
|
|
138
|
-
def
|
|
138
|
+
def writable? = @writable
|
|
139
139
|
|
|
140
140
|
def sound? = @sound
|
|
141
141
|
|
|
@@ -238,7 +238,7 @@ module Badline
|
|
|
238
238
|
def switch(name)
|
|
239
239
|
case name
|
|
240
240
|
when "--no-autostart" then @autostart = false
|
|
241
|
-
when "--
|
|
241
|
+
when "--writable" then @writable = true
|
|
242
242
|
when "--sound" then @sound = true
|
|
243
243
|
when "--no-sound" then @sound = false
|
|
244
244
|
when "--no-vsync" then @vsync = false
|
data/lib/badline/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: badline
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Inge Jørgensen
|
|
@@ -41,7 +41,11 @@ files:
|
|
|
41
41
|
- MIT-LICENSE
|
|
42
42
|
- README.md
|
|
43
43
|
- SECURITY.md
|
|
44
|
+
- doc/library.md
|
|
45
|
+
- doc/media.md
|
|
44
46
|
- doc/pinned-behaviour.md
|
|
47
|
+
- doc/sid-player.md
|
|
48
|
+
- doc/snapshots.md
|
|
45
49
|
- exe/badline-ruby
|
|
46
50
|
- lib/badline.rb
|
|
47
51
|
- lib/badline/address_bus.rb
|
|
@@ -137,16 +141,23 @@ files:
|
|
|
137
141
|
- lib/badline/frontend/audio_sink.rb
|
|
138
142
|
- lib/badline/frontend/boot.rb
|
|
139
143
|
- lib/badline/frontend/buttons.rb
|
|
144
|
+
- lib/badline/frontend/confirmation.rb
|
|
140
145
|
- lib/badline/frontend/controls.rb
|
|
141
146
|
- lib/badline/frontend/drive_led.rb
|
|
147
|
+
- lib/badline/frontend/file_browser.rb
|
|
142
148
|
- lib/badline/frontend/filter_view.rb
|
|
143
149
|
- lib/badline/frontend/frame_rate.rb
|
|
150
|
+
- lib/badline/frontend/frame_report.rb
|
|
144
151
|
- lib/badline/frontend/gamepads.rb
|
|
145
152
|
- lib/badline/frontend/info_view.rb
|
|
146
153
|
- lib/badline/frontend/keys.rb
|
|
154
|
+
- lib/badline/frontend/menu_dialogs.rb
|
|
155
|
+
- lib/badline/frontend/menu_media.rb
|
|
156
|
+
- lib/badline/frontend/menu_pages.rb
|
|
147
157
|
- lib/badline/frontend/pacer.rb
|
|
148
158
|
- lib/badline/frontend/pad_port.rb
|
|
149
159
|
- lib/badline/frontend/painter.rb
|
|
160
|
+
- lib/badline/frontend/pause_menu.rb
|
|
150
161
|
- lib/badline/frontend/player_commands.rb
|
|
151
162
|
- lib/badline/frontend/player_footer.rb
|
|
152
163
|
- lib/badline/frontend/player_header.rb
|
|
@@ -197,6 +208,7 @@ files:
|
|
|
197
208
|
- lib/badline/keyboard.rb
|
|
198
209
|
- lib/badline/keyboard_buffer.rb
|
|
199
210
|
- lib/badline/media.rb
|
|
211
|
+
- lib/badline/media/disk_set.rb
|
|
200
212
|
- lib/badline/media/queue.rb
|
|
201
213
|
- lib/badline/media/true_drive.rb
|
|
202
214
|
- lib/badline/memory.rb
|