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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: feaedb95b99aa7efed205645c112426a2649ad7a08c975708d085bf69a7e9555
|
|
4
|
+
data.tar.gz: b284281a2e1256f0fe94abf5174990ac8dc8a98cd7035f1cd53aebd3ccbefbd6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 870ff9cb5c9a9d65c8e9dd8dee6cc87a45871c1a07c79c4b9dc69a692600c3167f92b1debca0f860ab96b783a81bb608276542322b17e305acb82e95c9fc560b
|
|
7
|
+
data.tar.gz: 7c12bf1fd073b2b0e58e41195d67316f0c518a0f5b8c013ded19f025b48456fea738e5ad3df26a796c84151638e8c0449b5bf14b7d013fcb876c61db5d2d9469
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.8.0](https://github.com/elektronaut/badline/compare/v0.7.0...v0.8.0) (2026-10-03)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### ⚠ BREAKING CHANGES
|
|
7
|
+
|
|
8
|
+
* F9 opens the pause menu instead of swapping the joysticks, which the Ports page does now, and Tab no longer steps through the mouse and paddle modes.
|
|
9
|
+
* --read-only is gone, and disks are write-protected by default. Pass --writable to let the machine write to a disk image.
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* find the disks of a set by their names ([b2a4ba4](https://github.com/elektronaut/badline/commit/b2a4ba47bb4c9d4175130104c4dd2d3d2d5e570a))
|
|
14
|
+
* pause the machine in a menu on F9 ([8b2568c](https://github.com/elektronaut/badline/commit/8b2568c8ebe894c3da56d404217189dc7b27db84))
|
|
15
|
+
* put disks in write-protected unless --writable ([aed9fa1](https://github.com/elektronaut/badline/commit/aed9fa173007c85a5b9c19840e011d34f5b6b615))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* stop printing that the window runs below real time ([86a57a6](https://github.com/elektronaut/badline/commit/86a57a635189a8e46e285773ce62ecbf1dd5adde))
|
|
21
|
+
|
|
3
22
|
## [0.7.0](https://github.com/elektronaut/badline/compare/v0.6.1...v0.7.0) (2026-10-02)
|
|
4
23
|
|
|
5
24
|
|
data/CLAUDE.md
CHANGED
|
@@ -164,7 +164,9 @@ the rows your change can't reach tell you nothing about it.
|
|
|
164
164
|
- A pull request's CI is the verdict. It runs every suite on the Spinel
|
|
165
165
|
build, compared row by row against
|
|
166
166
|
`test/baselines/`, and every job is a required check. A row that moved
|
|
167
|
-
fails it.
|
|
167
|
+
fails it. A pull request that changes only docs, or only a release's
|
|
168
|
+
version bump, skips the specs and suites; pushes to main always run
|
|
169
|
+
them. Re-record only those rows, in the same change:
|
|
168
170
|
`rake "regression:record:<suite>[filter,...]"` (quote it, because zsh
|
|
169
171
|
globs the brackets). It runs only the matching tests on CRuby and
|
|
170
172
|
splices their rows into the baseline, and every other row keeps its
|
data/README.md
CHANGED
|
@@ -73,7 +73,7 @@ differences noted in the table. `--help` lists the options for either.
|
|
|
73
73
|
| Option | Effect |
|
|
74
74
|
| --- | --- |
|
|
75
75
|
| `--no-autostart` | Attach the media and stop at `READY.`, so you can type the `LOAD` yourself |
|
|
76
|
-
| `--
|
|
76
|
+
| `--writable` | Let the machine write to disk images. Without it, a disk goes in write-protected: the drive reports `26,WRITE PROTECT ON` for any write and the image file stays as it was |
|
|
77
77
|
| `--true-drive` | Put an emulated 1541 on device 8 instead of the KERNAL traps. See [Media](#media) |
|
|
78
78
|
| `-s`, `--subtune N` | Pick a subtune of a `.sid` file, counting from 1 |
|
|
79
79
|
| `--sid 6581`, `--sid 8580` | Fit the older or newer SID. `--sid auto`, the default, takes a `.sid` tune's own |
|
|
@@ -87,12 +87,6 @@ differences noted in the table. `--help` lists the options for either.
|
|
|
87
87
|
| `--version` | Show the version and what built it (`badline` only) |
|
|
88
88
|
| `-h`, `--help` | List the options |
|
|
89
89
|
|
|
90
|
-
Both run the same window. `badline` plays the SID through the host's
|
|
91
|
-
audio device, and `F10` mutes and unmutes it. In `badline-ruby` the
|
|
92
|
-
machine runs below real time, so the sound stutters: it plays in bursts
|
|
93
|
-
with silent gaps between them, at the right pitch, and never slows the
|
|
94
|
-
emulation down.
|
|
95
|
-
|
|
96
90
|
### Scripted runs
|
|
97
91
|
|
|
98
92
|
| Option | Effect |
|
|
@@ -113,234 +107,58 @@ badline --unpaced --frames 12000 --true-drive disk1.d64 \
|
|
|
113
107
|
`--help` lists the events, and [native/README.md](native/README.md#running)
|
|
114
108
|
describes them.
|
|
115
109
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
The KERNAL, BASIC and character ROMs come with the gem. To run other
|
|
119
|
-
images, such as a patched KERNAL, point `BADLINE_ROM_PATH` at a
|
|
120
|
-
directory that holds `kernal.rom`, `basic.rom` and `character.rom`,
|
|
121
|
-
plus `eapi/eapi-am29f040-14` if you attach EasyFlash cartridges. From
|
|
122
|
-
Ruby, `Badline.rom_path = dir` does the same before a
|
|
123
|
-
`Badline::Computer` is built, and `nil` restores the bundled set.
|
|
110
|
+
Other KERNAL, BASIC or character ROMs, and using badline as a Ruby
|
|
111
|
+
library, are covered in [doc/library.md](doc/library.md).
|
|
124
112
|
|
|
125
113
|
## Media
|
|
126
114
|
|
|
127
115
|
| Format | Handling |
|
|
128
116
|
|--------|----------|
|
|
129
117
|
| `.prg`, `.p00` | Loaded into memory after boot. A program at the BASIC start (`$0801`) is `RUN`, anything else is left for you to `SYS` |
|
|
130
|
-
| `.d64`, `.d71`, `.d81` | Mounted
|
|
131
|
-
| `.g64` | Put in a true 1541,
|
|
118
|
+
| `.d64`, `.d71`, `.d81` | Mounted as device 8, then `LOAD"*",8,1` and `RUN`. Write-protected unless `--writable` |
|
|
119
|
+
| `.g64` | Put in a true 1541, then `LOAD"*",8,1` and `RUN`. It holds the disk's raw GCR, so copy protection that reads it works. Write-protected unless `--writable` |
|
|
132
120
|
| `.t64` | Mounted read-only as device 8 and loaded like a disk image. The files load by name, and no tape is involved |
|
|
133
121
|
| `.tap` | Inserted in the datasette with PLAY pressed, then `LOAD` and `RUN`. It loads at the speed of a real tape |
|
|
134
122
|
| `.crt` | The hardware types listed under [Cartridges](#whats-emulated). Other types are rejected |
|
|
135
123
|
| `.sid` | PSID and RSID tunes, started through a small driver after boot |
|
|
136
124
|
| `.vsf` | A snapshot of a running machine, badline's own or one VICE's x64sc saved. See [Snapshots](#snapshots) |
|
|
137
|
-
| A directory | Mounted
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
`@0:` to replace a file), files opened for writing or appending, `S` to
|
|
147
|
-
scratch, `U2` and `B-W` block writes, and `B-A` and `B-F`. Loaders that
|
|
148
|
-
upload their own code to the drive with `M-W` and `M-E`, and copy
|
|
149
|
-
protection that reads raw GCR, won't work there, but do on a true
|
|
150
|
-
drive.
|
|
151
|
-
|
|
152
|
-
`--true-drive` puts an emulated 1541 on device 8 instead, running its
|
|
153
|
-
own DOS ROM on its own 6502 and talking to the machine over the serial
|
|
154
|
-
bus. It reads `.d64` and `.g64` images, which it autostarts with the
|
|
155
|
-
same `LOAD"*",8,1` and `RUN`, but not `.d71`, `.d81` or `.t64` images
|
|
156
|
-
or directories. `--read-only` puts the disk in write-protected. Loading
|
|
157
|
-
runs at the speed of a real 1541, and the drive's red LED lights in the
|
|
158
|
-
bottom right corner of the border. Both executables take it.
|
|
159
|
-
|
|
160
|
-
`Badline::Media.insert_disk(computer, path)` swaps the disk image or
|
|
161
|
-
directory in device 8 while the machine runs, for software that asks for
|
|
162
|
-
another disk. It takes `read_only: true`, and `Badline::Media.attach`
|
|
163
|
-
takes `disk: { read_only: true }`, to mount a disk image write-protected,
|
|
164
|
-
as the test harnesses under `bin/` do. A `.g64` goes in the true 1541,
|
|
165
|
-
and takes out a disk mounted through the traps, so `LOAD` and `SAVE`
|
|
166
|
-
reach the 1541 too. With the 1541 in device 8, a `.d64` goes in its
|
|
167
|
-
drive as well.
|
|
125
|
+
| A directory | Mounted as device 8. It serves the `.prg` and `.p00` files in it and the contents of any `.t64`, and `SAVE` writes a new `.prg` |
|
|
126
|
+
|
|
127
|
+
Without `--true-drive`, device 8 is no drive at all but traps on the
|
|
128
|
+
KERNAL's disk routines. Loading is instant, but fast loaders and copy
|
|
129
|
+
protection that run code on the drive need `--true-drive`, which puts
|
|
130
|
+
an emulated 1541 there, running its own DOS at a real 1541's speed. Its
|
|
131
|
+
red LED lights in the bottom right corner of the border.
|
|
132
|
+
[doc/media.md](doc/media.md) has the details, and how to attach media
|
|
133
|
+
from Ruby.
|
|
168
134
|
|
|
169
135
|
## Snapshots
|
|
170
136
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
`computer.restore_snapshot(path)` takes a machine back to a snapshot,
|
|
178
|
-
and `Badline::Snapshot.load(path)` builds a new machine as the saved one
|
|
179
|
-
was built and restores it. `computer.snapshot` and
|
|
180
|
-
`computer.restore(state)` do the same in memory, without a file. A
|
|
181
|
-
restore that fails leaves the machine as it was.
|
|
182
|
-
|
|
183
|
-
A snapshot holds the machine as it was on the cycle it was saved: the
|
|
184
|
-
chips down to the instruction step and the pixel pipeline, the RAM and
|
|
185
|
-
any +60K or +256K expansion, the cartridge with its RAM and flash, a
|
|
186
|
-
GEO-RAM, a true 1541 with its RAM, its VIAs and the disk under the head,
|
|
187
|
-
a disk or directory mounted through the traps with its open channels,
|
|
188
|
-
and the tape with its place on it. A restored machine runs on exactly
|
|
189
|
-
as the saved one would have. A directory, a tape and a true drive's
|
|
190
|
-
disk image open again from their paths when the snapshot is restored,
|
|
191
|
-
the disk with its tracks as the drive last saw them. A disk image mounted through the traps comes back
|
|
192
|
-
with its contents from the snapshot. What the host holds stays the host's: the keyboard, the
|
|
193
|
-
joysticks, the mouse and paddles, sound, and blocks given to `on_init`
|
|
194
|
-
that hadn't run yet, which a restore reports. A snapshot only restores
|
|
195
|
-
in the badline version that wrote it, into a machine with the same
|
|
196
|
-
chip models, RAM expansion and REU. `computer.snapshot` holds an REU's
|
|
197
|
-
RAM, registers and transfer too, but a machine with an REU doesn't save
|
|
198
|
-
to a file yet, as badline doesn't write VICE's REU module.
|
|
199
|
-
|
|
200
|
-
Snapshots use VICE's `.vsf` format. badline writes VICE's modules for
|
|
201
|
-
the CPU, RAM and CPU port, both CIAs, the SID and the VIC-II, plus the
|
|
202
|
-
ones x64sc needs to open the file, with nothing attached to the
|
|
203
|
-
cartridge, tape or user ports and no true drive. A `BADLINE` module,
|
|
204
|
-
which VICE skips, holds the whole machine, and badline restores its own
|
|
205
|
-
snapshots from it.
|
|
206
|
-
|
|
207
|
-
x64sc 3.10 opens badline's snapshots, taken at the end of the
|
|
208
|
-
instruction the CPU was in, as long as its VIC-II model matches
|
|
209
|
-
(`-model c64` for the default machine). It keeps its own drives and
|
|
210
|
-
leaves out the cartridge, the expansions and the tape. Snapshots x64sc
|
|
211
|
-
saves open in badline through the same modules: the CPU at its
|
|
212
|
-
instruction boundary, RAM, the CPU port, the CIAs' registers, timers and
|
|
213
|
-
clocks, the SID's registers and reSID voice state, and the VIC-II's
|
|
214
|
-
registers, beam position, counters and colour RAM. The VIC-II's pixel
|
|
215
|
-
pipeline starts empty. badline reads the modules x64sc 3.7 to 3.10
|
|
216
|
-
write, and VICE's development versions' `MAINC64CPU` and `VIC-IISC`. A module version
|
|
217
|
-
it doesn't know is left out, or fails the restore for the CPU and RAM.
|
|
218
|
-
It reports the modules it leaves out, such as the 1541 drives, the
|
|
219
|
-
cartridge, the datasette and the keyboard, and carries on without them.
|
|
220
|
-
An NTSC snapshot fails, as badline runs PAL only. Restored into a
|
|
221
|
-
running machine, a VICE snapshot fails for a machine built another way,
|
|
222
|
-
such as a C64C's snapshot in a C64, and otherwise takes the cartridge
|
|
223
|
-
out and switches the machine off and on.
|
|
137
|
+
`F11` saves the whole machine to a new `badline-<date>-<time>.vsf` in
|
|
138
|
+
the working directory, and `F12` goes back to the snapshot last saved
|
|
139
|
+
or opened. Snapshots use VICE's `.vsf` format: badline opens those
|
|
140
|
+
x64sc saves, and x64sc opens badline's. See
|
|
141
|
+
[doc/snapshots.md](doc/snapshots.md) for what they hold and how far the
|
|
142
|
+
two agree.
|
|
224
143
|
|
|
225
144
|
## Playing and rendering SID tunes
|
|
226
145
|
|
|
227
|
-
`badline-ruby --headless` plays a `.sid` tune on the host's audio
|
|
228
|
-
device without opening the window, and `--audio-out` renders it to a
|
|
229
|
-
16-bit stereo PCM file instead. The file's extension picks the format, `.wav`
|
|
230
|
-
or `.aiff`. The native `badline` has both modes too.
|
|
231
|
-
|
|
232
146
|
```sh
|
|
233
|
-
badline sid
|
|
234
|
-
badline sid
|
|
235
|
-
badline
|
|
236
|
-
badline
|
|
237
|
-
badline-ruby --headless --all-subtunes tune.sid # play on through every subtune
|
|
238
|
-
badline-ruby --seconds 180 tune.sid --audio-out out.aiff
|
|
239
|
-
badline-ruby -s 3 --rate 48000 tune.sid --audio-out out.wav
|
|
240
|
-
badline-ruby --headless --sid 8580 tune.sid
|
|
241
|
-
badline-ruby --filter-chunk 1 tune.sid --audio-out out.wav # exact filter, slower
|
|
147
|
+
badline tune.sid # play a tune in the SID player
|
|
148
|
+
badline sid ~/C64Music/MUSICIANS/H/Hubbard_Rob # play every tune below a directory
|
|
149
|
+
badline sid --headless tune.sid other.sid # play a queue in the terminal
|
|
150
|
+
badline --seconds 180 tune.sid --audio-out out.wav # render to a .wav or .aiff
|
|
242
151
|
```
|
|
243
152
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
takes
|
|
251
|
-
the options below except `--audio-out`, and `--subtune` picks the first
|
|
252
|
-
tune's subtune. `--sid auto`, the default, fits each of a tune's SIDs
|
|
253
|
-
the model its header names. A tune written for 2 or 3 SIDs plays on as
|
|
254
|
-
many, at the addresses its header gives, in stereo: SID 1 on the left,
|
|
255
|
-
SID 2 on the right and SID 3 in the centre. A tune on one SID plays the
|
|
256
|
-
same on both channels. A file that isn't a tune is skipped.
|
|
257
|
-
`badline tune.sid` plays the tune in the SID player too, unless an
|
|
258
|
-
option of the emulator's window, such as `--ntsc` or `--reu`, asks for
|
|
259
|
-
the machine: then a tune for one SID runs on the emulated C64, started
|
|
260
|
-
through a small driver after boot.
|
|
261
|
-
|
|
262
|
-
Both modes take the same options. The window's own, `--no-autostart`,
|
|
263
|
-
`--read-only`, `--sound`, `--true-drive`, `--reu`, `--ntsc` and
|
|
264
|
-
`--verbose`, don't apply to them. `--subtune` (or `-s`) picks the subtune, counting from 1 as HVSC
|
|
265
|
-
does, and defaults to the tune's own start subtune. Playback asks the
|
|
266
|
-
device for 44.1 kHz and takes whatever rate it offers, unless `--rate`
|
|
267
|
-
says otherwise. Ctrl-C stops it.
|
|
268
|
-
|
|
269
|
-
Played on a terminal, `--headless` and `sid` show each tune's name,
|
|
270
|
-
author and release as it starts, then the tune's place in the queue,
|
|
271
|
-
the subtune number and the time played against the subtune's length. `--headless`
|
|
272
|
-
queues just the one tune. Each tune plays its own subtune: `--subtune`, or
|
|
273
|
-
the tune's start subtune. When that subtune ends the player goes on to the next
|
|
274
|
-
tune, and it stops after the last. `a`, or `--all-subtunes`, turns on
|
|
275
|
-
playing all subtunes, so that a subtune that ends goes on to the tune's next
|
|
276
|
-
subtune, and a tune stepped to starts on its first subtune.
|
|
277
|
-
|
|
278
|
-
→ and ← step to the tune's next and previous subtune, stopping at its
|
|
279
|
-
first and last. `n` and `p` step to the next and previous tune. `s`
|
|
280
|
-
turns shuffle on and off, which plays the queue's tunes in a random
|
|
281
|
-
order, and `l` turns looping on and off, so that the end of the queue
|
|
282
|
-
goes on to its start. `,` and `.` seek 10 seconds back and forward
|
|
283
|
-
within the subtune, which plays it again from its start and runs silently
|
|
284
|
-
up to the point asked for. Space pauses and `q` quits. The status line
|
|
285
|
-
shows which modes are on, and they last until the player quits.
|
|
153
|
+
The SID player plays a queue of tunes, looking up each subtune's length
|
|
154
|
+
and STIL entry in an HVSC collection. Its window shows each voice's
|
|
155
|
+
note and output, the SID's registers, envelopes and filter, and the
|
|
156
|
+
tune's STIL entry, and is worked with the mouse. Tunes for 2 or 3 SIDs
|
|
157
|
+
play in stereo. [doc/sid-player.md](doc/sid-player.md) covers the
|
|
158
|
+
options, the keys and the window.
|
|
286
159
|
|
|
287
160
|

|
|
288
161
|
|
|
289
|
-
The SID player's window is worked with the mouse. Its header shows the
|
|
290
|
-
tune's name, author and release, the tune the subtune covers at the
|
|
291
|
-
moment when HVSC's STIL credits one, following the times STIL gives, and
|
|
292
|
-
buttons that switch between three views and between the tune's own SID
|
|
293
|
-
model, the 6581 and the 8580, which changes the chips playing on the
|
|
294
|
-
spot. Its footer shows the time played on a bar you can click to seek,
|
|
295
|
-
and buttons that pause, step between tunes and between a tune's
|
|
296
|
-
subtunes, and turn shuffle, looping and all subtunes on and off. The
|
|
297
|
-
visualizer view shows each voice's note, and how far off it is in cents,
|
|
298
|
-
over a scope of the voice's output, and the mixed output below them. A
|
|
299
|
-
tune on more than one SID gets a row of voices for each SID, and the mix
|
|
300
|
-
splits into its left and right. The SID view shows one SID at a time,
|
|
301
|
-
and for a tune on more than one, a row of SID 1, 2 and 3 buttons at its
|
|
302
|
-
top picks which. It shows each voice's waveforms and the shape
|
|
303
|
-
they make, its control bits, pulse width, envelope settings, and the
|
|
304
|
-
envelope's level and stage, and the filter's modes, cutoff, resonance,
|
|
305
|
-
volume and its response on the chip playing. The INFO view shows the
|
|
306
|
-
tune's STIL entry and the subtune's, with a scroll bar, the mouse wheel
|
|
307
|
-
or the up and down keys for the long ones. The terminal's keys work in
|
|
308
|
-
the window too, along with Tab to switch views and `c` to step through
|
|
309
|
-
the SID models.
|
|
310
|
-
|
|
311
|
-
`--no-tui`, or output that isn't a terminal, gives plain progress
|
|
312
|
-
output instead and plays through the queue without the keys, while
|
|
313
|
-
`--audio-out` renders just the one subtune.
|
|
314
|
-
|
|
315
|
-
A `.sid` file doesn't store its length, so `badline-ruby` looks the
|
|
316
|
-
tune up by MD5 in HVSC's `Songlengths.md5`. It finds the database
|
|
317
|
-
through `--songlengths`, in a `DOCUMENTS` directory in any of the
|
|
318
|
-
tune's parent directories (the layout of an HVSC collection), or under
|
|
319
|
-
`$HVSC_BASE/DOCUMENTS`. Without a database or `--seconds` it runs for
|
|
320
|
-
60 seconds, but a subtune that falls silent for 5 seconds before then
|
|
321
|
-
ends there, when played and when rendered alike. Silent means the
|
|
322
|
-
output holds within 16 steps of one level, since a 6581 idles at a DC
|
|
323
|
-
offset rather than at zero. A subtune with a known length plays to its
|
|
324
|
-
length whatever it sounds like.
|
|
325
|
-
|
|
326
|
-
A tune in an HVSC collection also gets its entry in HVSC's `STIL.txt`,
|
|
327
|
-
found the same way: comments, covers, and subtune names and composers.
|
|
328
|
-
The tune's own fields follow its header, and each subtune's print as it
|
|
329
|
-
starts.
|
|
330
|
-
|
|
331
|
-
PSID tunes run on a CPU and RAM with only the SID clocked, at about
|
|
332
|
-
twice real time, so they play smoothly. RSID tunes set up their own
|
|
333
|
-
interrupts, so they boot a full C64 first and run at about half real
|
|
334
|
-
time. They render fine but stutter when played, and `badline-ruby` says
|
|
335
|
-
so when it falls behind. The filter steps four cycles at a time;
|
|
336
|
-
`--filter-chunk 1` steps it every cycle, which is exact and takes about
|
|
337
|
-
twice as long. `badline-ruby --help` lists the options.
|
|
338
|
-
|
|
339
|
-
The native `badline` takes the same options and runs the same code, so
|
|
340
|
-
it renders the same file sample for sample, and it plays RSID tunes
|
|
341
|
-
without stuttering. See
|
|
342
|
-
[native/README.md](native/README.md#without-the-window).
|
|
343
|
-
|
|
344
162
|
## Input
|
|
345
163
|
|
|
346
164
|
Keys map by their position on a US keyboard, whatever the host's layout,
|
|
@@ -362,109 +180,97 @@ types `"`. These keys have no same-named host key:
|
|
|
362
180
|
| `+` / `*` | Keypad `+` / Keypad `*` |
|
|
363
181
|
| `RESTORE` | `Page Up` |
|
|
364
182
|
|
|
365
|
-
`Tab`
|
|
366
|
-
window title shows
|
|
183
|
+
`Tab` switches the keys between the C64 keyboard and the joysticks. The
|
|
184
|
+
window title shows where they go, and any device plugged into a control
|
|
185
|
+
port:
|
|
367
186
|
|
|
368
|
-
|
|
|
369
|
-
|
|
187
|
+
| Title | What the host drives |
|
|
188
|
+
|-------|----------------------|
|
|
370
189
|
| (none) | The keyboard |
|
|
371
|
-
| `[JOY 2]` / `[JOY 1]` | Arrows and Space (or Right Ctrl) are the joystick named, `WASD` and Left Shift the other.
|
|
190
|
+
| `[JOY 2]` / `[JOY 1]` | Arrows and Space (or Right Ctrl) are the joystick named, `WASD` and Left Shift the other. SWAP JOYSTICKS on the pause menu's Ports page swaps them |
|
|
372
191
|
| `[MOUSE 1]` / `[MOUSE 2]` | A 1351 mouse in control port 1 or 2 |
|
|
373
192
|
| `[PADDLE 1]` / `[PADDLE 2]` | A pair of paddles in control port 1 or 2 |
|
|
374
193
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
194
|
+
A 1351 mouse or a pair of paddles plugs into either port on the pause
|
|
195
|
+
menu's Ports page, and stays there whichever way `Tab` sends the keys.
|
|
196
|
+
While one is plugged in it holds the host mouse, and opening the pause
|
|
197
|
+
menu lets go. Moving it moves the 1351 or turns the two paddle knobs,
|
|
198
|
+
and the left and right buttons are the 1351's buttons, or the fire
|
|
199
|
+
buttons of paddles A and B. Games differ in which port they read.
|
|
380
200
|
|
|
381
201
|
Game controllers work in every mode. The first one is joystick 2 and
|
|
382
202
|
the second is joystick 1. The D-pad and left stick steer, the face and
|
|
383
203
|
shoulder buttons fire, and controllers can be connected or removed while
|
|
384
204
|
the emulator runs.
|
|
385
205
|
|
|
386
|
-
Control port 1's fire line is also the VIC-II's light pen input, so
|
|
387
|
-
joystick 1's fire button and the 1351's left button in port 1 latch the
|
|
388
|
-
light pen registers.
|
|
389
|
-
|
|
390
206
|
`F10` mutes and unmutes the sound, and the window title shows `[MUTED]`
|
|
391
207
|
while it's off.
|
|
392
208
|
|
|
209
|
+
## The pause menu
|
|
210
|
+
|
|
211
|
+
`F9` pauses the machine and opens a menu over the frozen picture, and
|
|
212
|
+
`F9` or `Esc` closes it again. On a Mac, hold `Fn` for `F9`, unless the
|
|
213
|
+
function keys are set to work as standard function keys. Up and Down move
|
|
214
|
+
through the rows, Right goes into a page and Left back out, and Return or
|
|
215
|
+
Space presses a row. A row with choices steps to the next. The mouse works
|
|
216
|
+
too.
|
|
217
|
+
|
|
218
|
+
| Page | What it holds |
|
|
219
|
+
|------|---------------|
|
|
220
|
+
| Drive 8 | The disk: insert, eject, the previous or next disk of its set, and whether it's writable |
|
|
221
|
+
| Datasette | The tape: insert, eject, PLAY and REWIND |
|
|
222
|
+
| Expansion port | The cartridge: insert, remove, and its freeze button if it has one |
|
|
223
|
+
| Ports | The device in each control port, and where the keys go |
|
|
224
|
+
| Sound | Mute, and the SID's model |
|
|
225
|
+
| Power | Reset, power cycle and quit |
|
|
226
|
+
|
|
227
|
+
INSERT opens a file browser. A disk's set comes from the names in its
|
|
228
|
+
folder: `Disk 1`, `Side B`, `d2`, TOSEC's `(Disk 1 of 2)`, or a trailing
|
|
229
|
+
`_1`, `_2` when the first of the set is there. WRITABLE starts as
|
|
230
|
+
`--writable` sets it and stays as set for the next disk. Quick open starts
|
|
231
|
+
a file in a new machine, as the command line does. It asks first, as
|
|
232
|
+
inserting or removing a cartridge does, since each power cycles the
|
|
233
|
+
machine.
|
|
234
|
+
|
|
235
|
+
A disk or tape dropped on the window goes into its drive. A cartridge,
|
|
236
|
+
program or `.sid` dropped on it opens the menu to ask first.
|
|
237
|
+
|
|
393
238
|
## What's emulated
|
|
394
239
|
|
|
395
240
|
- **6510**: every opcode, documented and undocumented, with per-cycle
|
|
396
241
|
bus behaviour checked against the
|
|
397
242
|
[65x02 single step tests](https://github.com/SingleStepTests/65x02).
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
- **
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
machine instead: the 6567R8's 65 cycles by 263 lines at 1,022,727 Hz,
|
|
412
|
-
with its later sprite fetches and its X counter, and TOD clocks on
|
|
413
|
-
60 Hz mains. `Badline::Region::NTSC_OLD` is the first NTSC C64s'
|
|
414
|
-
6567R56A, 64 cycles by 262 lines. The stock KERNAL tells them from PAL
|
|
415
|
-
by the raster, so every region boots the same ROMs. `--ntsc` picks the
|
|
416
|
-
6567R8.
|
|
417
|
-
- **CIA 1 and 2**: timers, time-of-day clocks with alarms, the serial
|
|
418
|
-
shift register, interrupts, the keyboard matrix with its ghost keys,
|
|
419
|
-
the control ports and the paddle multiplexer. The machine has the
|
|
420
|
-
original 6526s; `Badline::Computer.new(cia_model: :mos6526a)` fits the
|
|
421
|
-
C64C's 6526As instead, whose interrupt register timing differs.
|
|
422
|
-
- **SID**: the 6581 and the 8580, with oscillators, ring modulation and
|
|
423
|
-
sync, the envelope generator including the ADSR delay bug, the filter,
|
|
424
|
-
and the RC network on the board that removes the DC offset from the
|
|
425
|
-
output. The machine has a 6581 unless a `.sid` tune asks for an 8580
|
|
426
|
-
in its header, and `--sid 6581` or `--sid 8580` overrides either.
|
|
427
|
-
- **REU**: the 1700, 1764 and 1750 RAM Expansion Units, and the bigger
|
|
428
|
-
units up to 16M built on the same REC chip, with DMA timed against the
|
|
429
|
-
VIC's bad lines and sprites. `--reu SIZE` plugs one in, and
|
|
430
|
-
`Badline::Computer.new(reu: 512)` does the same from Ruby. An
|
|
431
|
-
REU beside a cartridge loses I/O 2 to the cartridge.
|
|
432
|
-
- **Datasette**: `.tap` playback into CIA 1's FLAG line, with the motor
|
|
433
|
-
and sense lines on the 6510 port.
|
|
243
|
+
- **Memory**: banking through the 6510 port, the cartridge lines and
|
|
244
|
+
Ultimax mode, and the +60K and +256K RAM expansions.
|
|
245
|
+
- **VIC-II**: the PAL 6569, the C64C's 8565, and NTSC's 6567R8 (`--ntsc`)
|
|
246
|
+
and 6567R56A: every graphics mode, sprites, collisions, bad lines,
|
|
247
|
+
sprite DMA, the border and the light pen.
|
|
248
|
+
- **CIA 1 and 2**: the 6526 and the C64C's 6526A, with timers,
|
|
249
|
+
time-of-day clocks, the serial shift register, the keyboard matrix
|
|
250
|
+
and the control ports.
|
|
251
|
+
- **SID**: the 6581 and the 8580, filter and all.
|
|
252
|
+
- **REU**: the 1700, 1764 and 1750 and bigger units up to 16M
|
|
253
|
+
(`--reu`), with DMA timed against the VIC's bad lines and sprites.
|
|
254
|
+
- **Datasette**: `.tap` playback.
|
|
255
|
+
- **1541**: an emulated drive running its own DOS (`--true-drive`).
|
|
434
256
|
- **Cartridges**: standard 8K, 16K and Ultimax, Simons' BASIC, Ocean,
|
|
435
|
-
Fun Play / Power Play, Super Games, Epyx FastLoad, Westermann
|
|
436
|
-
Rex Utility, C64 Game System / System 3, Dinamic, Zaxxon /
|
|
437
|
-
Magic Desk, Comal-80, EasyFlash, Mach 5, Pagefox, RGCD
|
|
438
|
-
the freezers Action Replay (v4.2 to v6), Atomic
|
|
439
|
-
Retro Replay / Nordic Replay, Final Cartridge III
|
|
440
|
-
Power Cartridge.
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
the Am29F040 EAPI on attach, as VICE does. The writes stay in memory
|
|
445
|
-
and are lost when the emulator quits: the `.crt` file is never
|
|
446
|
-
overwritten. The Retro Replay's flash
|
|
447
|
-
works the same way in flash mode, which the flash jumper enables:
|
|
448
|
-
`Media.attach(computer, path, cartridge: { flash_jumper: true })`, with
|
|
449
|
-
`bank_jumper: true` to run from the second 64K of a 128K image. The
|
|
450
|
-
GMod2 EEPROM and the Retro Replay clock port aren't there.
|
|
451
|
-
- **GEO-RAM**: 64K to 4M of RAM seen through the `$DE00` page, with the
|
|
452
|
-
`$DFFE`/`$DFFF` page and block registers. It takes the expansion port,
|
|
453
|
-
so it can't sit alongside a cartridge:
|
|
454
|
-
`computer.attach_cartridge(Badline::Cartridge::GeoRAM.new(size: 512))`.
|
|
455
|
-
Its contents are lost when the emulator quits.
|
|
257
|
+
Fun Play / Power Play, Super Games, Epyx FastLoad, Westermann
|
|
258
|
+
Learning, Rex Utility, C64 Game System / System 3, Dinamic, Zaxxon /
|
|
259
|
+
Super Zaxxon, Magic Desk, Comal-80, EasyFlash, Mach 5, Pagefox, RGCD,
|
|
260
|
+
GMod2 and GEO-RAM, and the freezers Action Replay (v4.2 to v6), Atomic
|
|
261
|
+
Power / Nordic Power, Retro Replay / Nordic Replay, Final Cartridge III
|
|
262
|
+
/ III+ and the KCS Power Cartridge. Flash writes stay in memory.
|
|
263
|
+
|
|
264
|
+
Machines other than the default, and the cartridges' jumpers, are
|
|
265
|
+
built from Ruby: see [doc/library.md](doc/library.md).
|
|
456
266
|
|
|
457
267
|
Known gaps:
|
|
458
268
|
|
|
459
|
-
- `badline-ruby` runs below real time, so its
|
|
460
|
-
|
|
461
|
-
`badline-ruby --headless`.
|
|
269
|
+
- `badline-ruby` runs below real time, so its sound, which `--sound`
|
|
270
|
+
turns on, stutters: it plays in bursts with silent gaps between them.
|
|
462
271
|
- Without `--true-drive`, fast loaders and anything else that runs code
|
|
463
|
-
on the drive won't work
|
|
464
|
-
doesn't rename, copy, format or validate disks.
|
|
272
|
+
on the drive won't work.
|
|
465
273
|
- No PAL-N (Drean) machine.
|
|
466
|
-
- The emulator window has no freeze button yet, so a freezer cartridge
|
|
467
|
-
runs its menu but can't freeze a program.
|
|
468
274
|
|
|
469
275
|
## Contributing
|
|
470
276
|
|
data/doc/library.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Using badline from Ruby
|
|
2
|
+
|
|
3
|
+
The gem is also a library, which runs a `Badline::Computer` from Ruby
|
|
4
|
+
without a window.
|
|
5
|
+
|
|
6
|
+
```ruby
|
|
7
|
+
require "badline"
|
|
8
|
+
|
|
9
|
+
computer = Badline::Computer.new
|
|
10
|
+
Badline::Media.attach(computer, "game.d64") # attaches and autostarts
|
|
11
|
+
computer.on_init { computer.type_text("print 6*7\r") } # once the machine has booted
|
|
12
|
+
3_500_000.times { computer.cycle! }
|
|
13
|
+
computer.address_bus.peek(0x0400) # screen RAM starts at $0400
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
[media.md](media.md) covers attaching and swapping media, and
|
|
17
|
+
[snapshots.md](snapshots.md) saving and restoring the machine.
|
|
18
|
+
|
|
19
|
+
## Building a machine
|
|
20
|
+
|
|
21
|
+
`Badline::Computer.new` builds the default machine: a PAL C64 with the
|
|
22
|
+
6569 VIC-II, 6526 CIAs and a 6581 SID. Its keywords build others:
|
|
23
|
+
|
|
24
|
+
- `vic_model: :mos8565` fits the C64C's 8565, with its grey dots on
|
|
25
|
+
colour register writes and its own timing for mode splits, sprite
|
|
26
|
+
multicolour splits and the light pen.
|
|
27
|
+
- `region: Badline::Region::NTSC` builds an NTSC machine: the 6567R8's
|
|
28
|
+
65 cycles by 263 lines at 1,022,727 Hz, with its later sprite fetches
|
|
29
|
+
and its X counter, and TOD clocks on 60 Hz mains.
|
|
30
|
+
`Badline::Region::NTSC_OLD` is the first NTSC C64s' 6567R56A, 64 cycles
|
|
31
|
+
by 262 lines. The stock KERNAL tells them from PAL by the raster, so
|
|
32
|
+
every region boots the same ROMs.
|
|
33
|
+
- `cia_model: :mos6526a` fits the C64C's 6526As, whose interrupt
|
|
34
|
+
register timing differs.
|
|
35
|
+
- `sid_model: :mos8580` fits the 8580.
|
|
36
|
+
- `ram_expansion: :plus60k` or `:plus256k` fits the +60K or +256K RAM
|
|
37
|
+
expansion, banked through its register at `$D100`.
|
|
38
|
+
- `reu: 512` plugs in a RAM Expansion Unit of that many K.
|
|
39
|
+
|
|
40
|
+
## Cartridges
|
|
41
|
+
|
|
42
|
+
`Media.attach(computer, path, cartridge: { flash_jumper: true })` sets
|
|
43
|
+
the Retro Replay's flash jumper, which makes its flash take writes, and
|
|
44
|
+
`bank_jumper: true` runs it from the second 64K of a 128K image.
|
|
45
|
+
EasyFlash and GMod2 flash take writes through the chip's command set
|
|
46
|
+
(program, sector and chip erase, autoselect), so games and EAPI can save
|
|
47
|
+
to it. An EasyFlash image's EAPI is swapped for a bundled copy of the
|
|
48
|
+
Am29F040 EAPI on attach, as VICE does. Flash writes stay in memory and
|
|
49
|
+
are lost when the emulator quits: the `.crt` file is never overwritten.
|
|
50
|
+
|
|
51
|
+
A GEO-RAM takes the expansion port, so it can't sit alongside a
|
|
52
|
+
cartridge: `computer.attach_cartridge(Badline::Cartridge::GeoRAM.new(size: 512))`.
|
|
53
|
+
Its contents are lost when the emulator quits.
|
|
54
|
+
|
|
55
|
+
## ROMs
|
|
56
|
+
|
|
57
|
+
The KERNAL, BASIC and character ROMs come with the gem. To run other
|
|
58
|
+
images, such as a patched KERNAL, point `BADLINE_ROM_PATH` at a
|
|
59
|
+
directory that holds `kernal.rom`, `basic.rom` and `character.rom`, plus
|
|
60
|
+
`eapi/eapi-am29f040-14` if you attach EasyFlash cartridges.
|
|
61
|
+
`Badline.rom_path = dir` does the same before a `Badline::Computer` is
|
|
62
|
+
built, and `nil` restores the bundled set.
|