badline 0.2.1 → 0.4.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/.claude/hooks/session-start.sh +57 -0
- data/.claude/settings.json +14 -0
- data/CHANGELOG.md +107 -0
- data/CLAUDE.md +51 -16
- data/CONTRIBUTING.md +95 -3
- data/README.md +119 -51
- data/SECURITY.md +9 -0
- data/doc/pinned-behaviour.md +293 -39
- data/exe/badline-ruby +59 -0
- data/lib/badline/address_bus.rb +28 -14
- data/lib/badline/addressable.rb +1 -1
- data/lib/badline/audio/aiff.rb +8 -3
- data/lib/badline/audio/bare_player.rb +20 -3
- data/lib/badline/audio/cli.rb +17 -12
- data/lib/badline/audio/console.rb +12 -58
- data/lib/badline/audio/machine_player.rb +9 -6
- data/lib/badline/audio/playback.rb +3 -0
- data/lib/badline/audio/renderer.rb +3 -3
- data/lib/badline/audio/sdl_sink.rb +20 -52
- data/lib/badline/audio/stream.rb +117 -0
- data/lib/badline/audio/terminal.rb +90 -0
- data/lib/badline/audio.rb +3 -2
- data/lib/badline/cartridge/easy_flash.rb +6 -2
- data/lib/badline/cartridge/epyx_fastload.rb +1 -1
- data/lib/badline/cartridge/geo_ram.rb +63 -0
- data/lib/badline/cartridge/mach5.rb +1 -1
- data/lib/badline/cartridge/magic_desk.rb +5 -1
- data/lib/badline/cartridge/ocean.rb +5 -2
- data/lib/badline/cartridge/rex_utility.rb +1 -1
- data/lib/badline/cartridge/rgcd.rb +1 -1
- data/lib/badline/cartridge/simons_basic.rb +2 -2
- data/lib/badline/cartridge/westermann.rb +2 -2
- data/lib/badline/cartridge.rb +9 -0
- data/lib/badline/checkpoint.rb +98 -0
- data/lib/badline/cia/interrupt_register.rb +34 -10
- data/lib/badline/cia.rb +19 -10
- data/lib/badline/color_memory.rb +2 -2
- data/lib/badline/computer.rb +34 -14
- data/lib/badline/cpu.rb +2 -2
- data/lib/badline/gui/application.rb +70 -26
- data/lib/badline/gui/gamepads.rb +22 -22
- data/lib/badline/gui/joy_map.rb +1 -1
- data/lib/badline/gui/key_map.rb +6 -1
- data/lib/badline/gui/pane.rb +7 -6
- data/lib/badline/gui/screen_pane.rb +9 -13
- data/lib/badline/gui/window.rb +35 -20
- data/lib/badline/gui.rb +1 -1
- data/lib/badline/input/mouse1351.rb +21 -6
- data/lib/badline/input/paddles.rb +11 -6
- data/lib/badline/kernal_trap/channel.rb +102 -7
- data/lib/badline/kernal_trap/drive/block_commands.rb +108 -0
- data/lib/badline/kernal_trap/drive/channels.rb +53 -0
- data/lib/badline/kernal_trap/drive/memory.rb +109 -0
- data/lib/badline/kernal_trap/drive/parameters.rb +28 -0
- data/lib/badline/kernal_trap/drive/status.rb +3 -0
- data/lib/badline/kernal_trap/drive/write_file.rb +41 -0
- data/lib/badline/kernal_trap/drive/writes.rb +92 -0
- data/lib/badline/kernal_trap/drive.rb +109 -131
- data/lib/badline/kernal_trap/file.rb +6 -14
- data/lib/badline/kernal_trap/load.rb +6 -0
- data/lib/badline/kernal_trap/save.rb +13 -7
- data/lib/badline/keyboard.rb +19 -3
- data/lib/badline/media.rb +44 -13
- data/lib/badline/memory.rb +2 -2
- data/lib/badline/options.rb +209 -0
- data/lib/badline/ram_expansion/banking.rb +30 -0
- data/lib/badline/ram_expansion/plus256k.rb +38 -0
- data/lib/badline/ram_expansion/plus60k.rb +31 -0
- data/lib/badline/ram_expansion/unexpanded.rb +22 -0
- data/lib/badline/ram_expansion.rb +21 -0
- data/lib/badline/region.rb +51 -0
- data/lib/badline/rom.rb +14 -5
- data/lib/badline/sdl/events.rb +47 -0
- data/lib/badline/sdl/functions.rb +73 -0
- data/lib/badline/sdl.rb +67 -0
- data/lib/badline/sid/catch_up.rb +110 -0
- data/lib/badline/sid/decimator.rb +6 -1
- data/lib/badline/sid/filter.rb +5 -5
- data/lib/badline/sid/waveform/fast_forward.rb +10 -10
- data/lib/badline/sid/waveform/noise_writeback.rb +32 -14
- data/lib/badline/sid/waveform.rb +8 -8
- data/lib/badline/sid.rb +19 -93
- data/lib/badline/storage/d64_image.rb +10 -0
- data/lib/badline/storage/d71_image.rb +12 -0
- data/lib/badline/storage/d81_image.rb +9 -0
- data/lib/badline/storage/disk_image/bam.rb +111 -0
- data/lib/badline/storage/disk_image/directory.rb +79 -0
- data/lib/badline/storage/disk_image/writing.rb +110 -0
- data/lib/badline/storage/disk_image.rb +49 -4
- data/lib/badline/storage/host_directory.rb +17 -4
- data/lib/badline/storage/sid_file.rb +36 -2
- data/lib/badline/storage.rb +18 -1
- data/lib/badline/time_of_day.rb +11 -2
- data/lib/badline/version.rb +1 -1
- data/lib/badline/via/control_lines.rb +104 -0
- data/lib/badline/via/interrupt_register.rb +58 -0
- data/lib/badline/via/shift_register.rb +135 -0
- data/lib/badline/via/timer1.rb +82 -0
- data/lib/badline/via/timer2.rb +84 -0
- data/lib/badline/via.rb +262 -0
- data/lib/badline/vic/bank.rb +4 -3
- data/lib/badline/vic/color_patches.rb +6 -3
- data/lib/badline/vic/display_state.rb +4 -0
- data/lib/badline/vic/graphics_shifter.rb +49 -8
- data/lib/badline/vic/registers.rb +19 -27
- data/lib/badline/vic/sequencer.rb +18 -18
- data/lib/badline/vic/sequencer_output.rb +4 -4
- data/lib/badline/vic/sprite/internal_bus.rb +4 -0
- data/lib/badline/vic/sprite/shifter.rb +25 -3
- data/lib/badline/vic/sprite.rb +5 -4
- data/lib/badline/vic/sprites.rb +8 -3
- data/lib/badline/vic.rb +98 -46
- data/lib/badline.rb +5 -0
- data/packaging/homebrew/badline.rb +34 -0
- metadata +37 -20
- data/exe/badline +0 -75
- data/exe/badline-sid +0 -34
- data/lib/badline/audio/options.rb +0 -137
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "optparse"
|
|
4
|
-
|
|
5
|
-
module Badline
|
|
6
|
-
module Audio
|
|
7
|
-
# The command line of `badline-sid`. It loads nothing else from badline,
|
|
8
|
-
# so the executable can parse and reject its arguments before paying for
|
|
9
|
-
# the emulator.
|
|
10
|
-
class Options
|
|
11
|
-
class Error < StandardError; end
|
|
12
|
-
|
|
13
|
-
FALLBACK_SECONDS = 60.0
|
|
14
|
-
|
|
15
|
-
DEFAULT_RATE = 44_100
|
|
16
|
-
|
|
17
|
-
SID_MODELS = { "6581" => :mos6581, "8580" => :mos8580 }.freeze
|
|
18
|
-
|
|
19
|
-
BANNER = <<~BANNER.freeze
|
|
20
|
-
Usage: badline-sid [options] tune.sid [-o output]
|
|
21
|
-
|
|
22
|
-
Plays a .sid tune on the host's audio device, or with an output file
|
|
23
|
-
renders it to 16-bit PCM instead. The container follows the output
|
|
24
|
-
file's extension, .wav or .aiff.
|
|
25
|
-
|
|
26
|
-
A .sid file carries no length of its own. Without --seconds the tune is
|
|
27
|
-
looked up by MD5 in HVSC's Songlengths.md5, taken from --songlengths, from
|
|
28
|
-
the DOCUMENTS directory of an HVSC collection above the tune, or from
|
|
29
|
-
$HVSC_BASE. Failing all of those it runs for #{FALLBACK_SECONDS.to_i} seconds.
|
|
30
|
-
|
|
31
|
-
Played on a terminal, n or → skips to the next song, p or ← to the
|
|
32
|
-
previous one, space pauses and q quits.
|
|
33
|
-
|
|
34
|
-
PSID tunes run on a bare CPU and SID, faster than real time. RSID
|
|
35
|
-
tunes boot the whole machine and run at about half real time, so
|
|
36
|
-
they stutter when played. --filter-chunk 1 runs the filter cycle by
|
|
37
|
-
cycle, which is exact but takes about twice as long.
|
|
38
|
-
|
|
39
|
-
Options:
|
|
40
|
-
BANNER
|
|
41
|
-
|
|
42
|
-
attr_reader :tune_path, :output, :song, :seconds, :songlengths, :sid_model, :filter_chunk
|
|
43
|
-
|
|
44
|
-
def self.parse(argv) = new.parse(argv)
|
|
45
|
-
|
|
46
|
-
def initialize
|
|
47
|
-
@jit = true
|
|
48
|
-
@quiet = false
|
|
49
|
-
@tui = true
|
|
50
|
-
@help = false
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def parse(argv)
|
|
54
|
-
arguments = parser.parse(argv)
|
|
55
|
-
@tune_path, positional_output, *extra = arguments
|
|
56
|
-
raise Error, "unexpected argument: #{extra.first}" if extra.any?
|
|
57
|
-
|
|
58
|
-
@output ||= positional_output
|
|
59
|
-
validate unless help?
|
|
60
|
-
self
|
|
61
|
-
rescue OptionParser::ParseError => e
|
|
62
|
-
raise Error, e.message
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def render? = !output.nil?
|
|
66
|
-
|
|
67
|
-
def rate = @rate || DEFAULT_RATE
|
|
68
|
-
|
|
69
|
-
def rate_given? = !@rate.nil?
|
|
70
|
-
|
|
71
|
-
def help = parser.help
|
|
72
|
-
|
|
73
|
-
def help? = @help
|
|
74
|
-
|
|
75
|
-
def quiet? = @quiet
|
|
76
|
-
|
|
77
|
-
def tui? = @tui
|
|
78
|
-
|
|
79
|
-
def jit? = @jit
|
|
80
|
-
|
|
81
|
-
private
|
|
82
|
-
|
|
83
|
-
def validate
|
|
84
|
-
raise Error, "no tune given" unless tune_path
|
|
85
|
-
|
|
86
|
-
validate_numbers
|
|
87
|
-
validate_paths
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def validate_numbers
|
|
91
|
-
raise Error, "invalid argument: --song #{song}" if song&.< 1
|
|
92
|
-
raise Error, "invalid argument: --seconds #{seconds}" unless seconds.nil? || seconds.positive?
|
|
93
|
-
raise Error, "invalid argument: --rate #{rate}" unless rate.positive?
|
|
94
|
-
raise Error, "invalid argument: --filter-chunk #{filter_chunk}" if filter_chunk&.< 1
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
def validate_paths
|
|
98
|
-
[tune_path, songlengths].compact.each do |path|
|
|
99
|
-
raise Error, "no such file: #{path}" unless File.exist?(path)
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def parser
|
|
104
|
-
@parser ||= OptionParser.new do |opts|
|
|
105
|
-
opts.banner = BANNER
|
|
106
|
-
define_tune_options(opts)
|
|
107
|
-
define_output_options(opts)
|
|
108
|
-
define_run_options(opts)
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
def define_tune_options(opts)
|
|
113
|
-
opts.on("-s", "--song N", Integer, "Subtune to play, from 1 (default: the tune's own)") { |n| @song = n }
|
|
114
|
-
opts.on("--seconds N", Float, "Length to play (default: the tune's own)") { |n| @seconds = n }
|
|
115
|
-
opts.on("--songlengths PATH", "HVSC Songlengths.md5 to take the length from") { |path| @songlengths = path }
|
|
116
|
-
opts.on("--sid MODEL", SID_MODELS,
|
|
117
|
-
"SID to play on: 6581 or 8580 (default: the tune's own, else 6581)") { |model| @sid_model = model }
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
def define_output_options(opts)
|
|
121
|
-
opts.on("-o", "--output PATH", "Render to a .wav or .aiff file instead of playing") { |path| @output = path }
|
|
122
|
-
opts.on("--rate HZ", Integer,
|
|
123
|
-
"Sample rate (default: #{DEFAULT_RATE}, or the audio device's own)") { |n| @rate = n }
|
|
124
|
-
opts.on("--filter-chunk N", Integer, "Filter step in cycles, 1 is exact (default: 4)") do |n|
|
|
125
|
-
@filter_chunk = n
|
|
126
|
-
end
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
def define_run_options(opts)
|
|
130
|
-
opts.on("--quiet", "Don't report progress") { @quiet = true }
|
|
131
|
-
opts.on("--no-tui", "Play without the interactive display, even on a terminal") { @tui = false }
|
|
132
|
-
opts.on("--disable-jit", "Run without enabling YJIT") { @jit = false }
|
|
133
|
-
opts.on("-h", "--help", "Show this help") { @help = true }
|
|
134
|
-
end
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
|
-
end
|