badline 0.6.1 → 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 +56 -0
- data/CLAUDE.md +3 -1
- data/README.md +132 -247
- 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/exe/badline-ruby +9 -1
- data/lib/badline/address_bus/extra_sids.rb +30 -0
- data/lib/badline/address_bus/sid_slots.rb +42 -0
- data/lib/badline/address_bus.rb +5 -0
- data/lib/badline/audio/aiff.rb +2 -2
- data/lib/badline/audio/bare_player.rb +23 -12
- data/lib/badline/audio/cli.rb +153 -58
- data/lib/badline/audio/jukebox.rb +121 -36
- data/lib/badline/audio/machine_player.rb +25 -10
- data/lib/badline/audio/pcm_writer.rb +10 -6
- data/lib/badline/audio/playback.rb +6 -5
- data/lib/badline/audio/queued_tune.rb +89 -0
- data/lib/badline/audio/renderer.rb +57 -10
- data/lib/badline/audio/stereo.rb +97 -0
- data/lib/badline/audio/terminal.rb +39 -6
- data/lib/badline/audio/wav.rb +1 -1
- data/lib/badline/audio.rb +2 -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/audio_sink.rb +6 -5
- data/lib/badline/frontend/boot.rb +9 -2
- data/lib/badline/frontend/buttons.rb +184 -0
- 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/filter_view.rb +96 -0
- data/lib/badline/frontend/frame_report.rb +52 -0
- data/lib/badline/frontend/info_view.rb +120 -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 +185 -0
- data/lib/badline/frontend/pause_menu.rb +246 -0
- data/lib/badline/frontend/player_commands.rb +33 -0
- data/lib/badline/frontend/player_footer.rb +86 -0
- data/lib/badline/frontend/player_header.rb +60 -0
- data/lib/badline/frontend/player_screen.rb +124 -0
- data/lib/badline/frontend/player_state.rb +67 -0
- data/lib/badline/frontend/player_window.rb +228 -0
- data/lib/badline/frontend/scope.rb +42 -0
- data/lib/badline/frontend/sid_history.rb +175 -0
- data/lib/badline/frontend/sid_view.rb +140 -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/visualizer_view.rb +101 -0
- data/lib/badline/frontend.rb +21 -0
- data/lib/badline/media/disk_set.rb +108 -0
- data/lib/badline/media/queue.rb +158 -0
- data/lib/badline/media.rb +14 -8
- data/lib/badline/options/help.rb +34 -5
- data/lib/badline/options/option.rb +1 -1
- data/lib/badline/options/table.rb +5 -3
- data/lib/badline/options/validation.rb +54 -0
- data/lib/badline/options.rb +65 -46
- data/lib/badline/sdl.rb +16 -6
- data/lib/badline/sid/catch_up.rb +11 -1
- data/lib/badline/sid/filter.rb +9 -0
- data/lib/badline/sid/voice.rb +6 -0
- data/lib/badline/sid/waveform.rb +20 -5
- data/lib/badline/sid.rb +35 -3
- data/lib/badline/storage/hvsc.rb +41 -0
- data/lib/badline/storage/sid_file.rb +45 -25
- data/lib/badline/storage/song_lengths.rb +6 -29
- data/lib/badline/storage/stil/credit.rb +50 -0
- data/lib/badline/storage/stil.rb +126 -0
- data/lib/badline/storage.rb +8 -0
- data/lib/badline/version.rb +1 -1
- metadata +36 -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,61 @@
|
|
|
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
|
+
|
|
22
|
+
## [0.7.0](https://github.com/elektronaut/badline/compare/v0.6.1...v0.7.0) (2026-10-02)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### ⚠ BREAKING CHANGES
|
|
26
|
+
|
|
27
|
+
* call a .sid tune's parts subtunes everywhere
|
|
28
|
+
|
|
29
|
+
### Features
|
|
30
|
+
|
|
31
|
+
* add a badline sid subcommand that plays tunes and directories ([7dfc21b](https://github.com/elektronaut/badline/commit/7dfc21b5e4ba47cd37a4593da61e95bb1d2329ab))
|
|
32
|
+
* drop .sid files and folders on the SID player to queue them ([cc1f434](https://github.com/elektronaut/badline/commit/cc1f434b7404ded067ef43d1d3d5aa53d338de4c))
|
|
33
|
+
* end a subtune with no known length when it falls silent ([46c4f10](https://github.com/elektronaut/badline/commit/46c4f1064f6382872ec22989253bc9c159f78dcf))
|
|
34
|
+
* open a .sid tune, or no tune at all, in the SID player ([396c010](https://github.com/elektronaut/badline/commit/396c010ee626f95fbb71ced8bf3905909c470c8e))
|
|
35
|
+
* play 2SID and 3SID tunes in stereo in the SID player ([7c72eef](https://github.com/elektronaut/badline/commit/7c72eeff7e5e7b1c56286f9bf6030ae3408f7176))
|
|
36
|
+
* play a queue of tunes, with shuffle, loop and play-all subtunes ([d163106](https://github.com/elektronaut/badline/commit/d163106eea99d90f6ffe74fb91474a2aca4c64eb))
|
|
37
|
+
* play sid tunes in a window that shows what the SID is doing ([60bfd3f](https://github.com/elektronaut/badline/commit/60bfd3f75fe82d928afa374d257d3d21e5ac29ad))
|
|
38
|
+
* seek forward from where the subtune is, not from its start ([34059e8](https://github.com/elektronaut/badline/commit/34059e8f9b12cab44c94124e6455fef9c915d8eb))
|
|
39
|
+
* seek within a subtune, and let the slow warning lapse ([b98ac6e](https://github.com/elektronaut/badline/commit/b98ac6eb6f9c0ce088545f55cc5f2445dd38dd2d))
|
|
40
|
+
* show a tune's STIL entry in the SID player ([82d9dca](https://github.com/elektronaut/badline/commit/82d9dca26d7cefe853a6af41e50fc723a3e90170))
|
|
41
|
+
* show each voice's live output in the SID view ([c61a128](https://github.com/elektronaut/badline/commit/c61a1289983887c0175fca3dc4c37b470e96de92))
|
|
42
|
+
* show HVSC's STIL in the SID player ([bd55c0c](https://github.com/elektronaut/badline/commit/bd55c0c87695ba8cc84dbfd51ab2119a97eccded))
|
|
43
|
+
* show where a seek is headed on the SID player's bar ([1a84b37](https://github.com/elektronaut/badline/commit/1a84b3746a960dba28dc9c789b3d2cd1520d2f94))
|
|
44
|
+
* step subtunes and tunes on separate keys, add --all-subtunes ([eaef338](https://github.com/elektronaut/badline/commit/eaef3384e6205163e2a4b63f5aa8d9204fe5190f))
|
|
45
|
+
* switch a SID between the 6581 and 8580 while it runs ([5920391](https://github.com/elektronaut/badline/commit/592039123d7936b8d22c8fd5f144a9bc9a8f383b))
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
### Bug Fixes
|
|
49
|
+
|
|
50
|
+
* build the native badline with a Spinel that keeps an array joined mid-expression alive ([d2c4eb2](https://github.com/elektronaut/badline/commit/d2c4eb20d6b80494fb2a20105c0532f3778b205c))
|
|
51
|
+
* build the native badline with a Spinel that reports render progress ([58524ea](https://github.com/elektronaut/badline/commit/58524eaf4881661e7e0e9dd38c32071545bf1fae))
|
|
52
|
+
* show non-ASCII text from a .sid header in the native badline ([959bb6f](https://github.com/elektronaut/badline/commit/959bb6f7d07de4c90ac50ae51ae63f3c66601a78))
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
### Performance Improvements
|
|
56
|
+
|
|
57
|
+
* draw the SID player's traces in one call each ([afcae15](https://github.com/elektronaut/badline/commit/afcae15ed273aa7a6dd49cb31e0f7180c56feb75))
|
|
58
|
+
|
|
3
59
|
## [0.6.1](https://github.com/elektronaut/badline/compare/v0.6.0...v0.6.1) (2026-09-30)
|
|
4
60
|
|
|
5
61
|
|
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
|
@@ -56,46 +56,47 @@ badline game.prg # Load and run a program
|
|
|
56
56
|
badline game.d64 # Mount a disk image as device 8 and load it
|
|
57
57
|
badline game.tap # Insert a tape and load it
|
|
58
58
|
badline game.crt # Attach a cartridge
|
|
59
|
-
badline tune.sid # Play a SID tune
|
|
59
|
+
badline tune.sid # Play a SID tune in the SID player
|
|
60
60
|
badline game.vsf # Restore a snapshot, from badline or VICE
|
|
61
61
|
badline ~/c64 # Mount a directory as device 8
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
-
`badline-ruby` takes the same media and the same options, with the
|
|
65
|
-
differences noted below.
|
|
66
|
-
|
|
67
64
|
Programs, disk and tape images and SID tunes start automatically, and
|
|
68
65
|
a cartridge starts itself. A mounted directory waits for you to `LOAD`
|
|
69
|
-
from it.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
`
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
`--
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
66
|
+
from it.
|
|
67
|
+
|
|
68
|
+
`badline-ruby` takes the same media and the same options, with the
|
|
69
|
+
differences noted in the table. `--help` lists the options for either.
|
|
70
|
+
|
|
71
|
+
### Options
|
|
72
|
+
|
|
73
|
+
| Option | Effect |
|
|
74
|
+
| --- | --- |
|
|
75
|
+
| `--no-autostart` | Attach the media and stop at `READY.`, so you can type the `LOAD` yourself |
|
|
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
|
+
| `--true-drive` | Put an emulated 1541 on device 8 instead of the KERNAL traps. See [Media](#media) |
|
|
78
|
+
| `-s`, `--subtune N` | Pick a subtune of a `.sid` file, counting from 1 |
|
|
79
|
+
| `--sid 6581`, `--sid 8580` | Fit the older or newer SID. `--sid auto`, the default, takes a `.sid` tune's own |
|
|
80
|
+
| `--reu SIZE` | Plug in a RAM Expansion Unit of `SIZE` K: 128, 256, 512 (a 1750) or up to 16384 |
|
|
81
|
+
| `--ntsc` | Run an NTSC C64, with the 6567R8 VIC-II, instead of a PAL one |
|
|
82
|
+
| `--no-sound` | Don't play the SID (`badline` only, where sound is on by default) |
|
|
83
|
+
| `--sound` | Play the SID (`badline-ruby`, where sound is off by default) |
|
|
84
|
+
| `--no-vsync` | Pace the window by a timer, or by the sound while it plays, instead of the display's vsync |
|
|
85
|
+
| `--verbose` | Print the display's refresh rate, the sound's sample rate and the game controllers found as the window opens, then the frame rate and the time each frame takes, once a second |
|
|
86
|
+
| `--disable-jit` | Run without YJIT, otherwise switched on at startup (`badline-ruby` only) |
|
|
87
|
+
| `--version` | Show the version and what built it (`badline` only) |
|
|
88
|
+
| `-h`, `--help` | List the options |
|
|
89
|
+
|
|
90
|
+
### Scripted runs
|
|
91
|
+
|
|
92
|
+
| Option | Effect |
|
|
93
|
+
| --- | --- |
|
|
94
|
+
| `--frames N` | Quit after N frames |
|
|
95
|
+
| `--unpaced` | Run as fast as it can, without vsync or pacing |
|
|
96
|
+
| `--at FRAME:EVENT` | Press keys, type, swap media or take a screenshot once `FRAME` frames have run |
|
|
97
|
+
| `--script FILE` | Run the events in `FILE`, one `FRAME:EVENT` a line |
|
|
98
|
+
| `--screenshot FILE` | Save the last frame as a `.bmp` |
|
|
99
|
+
| `--save-snapshot FILE` | Save the machine as a `.vsf` snapshot after the last frame |
|
|
99
100
|
|
|
100
101
|
```sh
|
|
101
102
|
badline --unpaced --frames 12000 --true-drive disk1.d64 \
|
|
@@ -106,161 +107,57 @@ badline --unpaced --frames 12000 --true-drive disk1.d64 \
|
|
|
106
107
|
`--help` lists the events, and [native/README.md](native/README.md#running)
|
|
107
108
|
describes them.
|
|
108
109
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
in bursts with silent gaps between them, at the right pitch, and never
|
|
112
|
-
slows the emulation down.
|
|
110
|
+
Other KERNAL, BASIC or character ROMs, and using badline as a Ruby
|
|
111
|
+
library, are covered in [doc/library.md](doc/library.md).
|
|
113
112
|
|
|
114
113
|
## Media
|
|
115
114
|
|
|
116
115
|
| Format | Handling |
|
|
117
116
|
|--------|----------|
|
|
118
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` |
|
|
119
|
-
| `.d64`, `.d71`, `.d81` | Mounted
|
|
120
|
-
| `.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` |
|
|
121
120
|
| `.t64` | Mounted read-only as device 8 and loaded like a disk image. The files load by name, and no tape is involved |
|
|
122
121
|
| `.tap` | Inserted in the datasette with PLAY pressed, then `LOAD` and `RUN`. It loads at the speed of a real tape |
|
|
123
122
|
| `.crt` | The hardware types listed under [Cartridges](#whats-emulated). Other types are rejected |
|
|
124
123
|
| `.sid` | PSID and RSID tunes, started through a small driver after boot |
|
|
125
124
|
| `.vsf` | A snapshot of a running machine, badline's own or one VICE's x64sc saved. See [Snapshots](#snapshots) |
|
|
126
|
-
| A directory | Mounted
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
`@0:` to replace a file), files opened for writing or appending, `S` to
|
|
136
|
-
scratch, `U2` and `B-W` block writes, and `B-A` and `B-F`. Loaders that
|
|
137
|
-
upload their own code to the drive with `M-W` and `M-E`, and copy
|
|
138
|
-
protection that reads raw GCR, won't work there, but do on a true
|
|
139
|
-
drive.
|
|
140
|
-
|
|
141
|
-
`--true-drive` puts an emulated 1541 on device 8 instead, running its
|
|
142
|
-
own DOS ROM on its own 6502 and talking to the machine over the serial
|
|
143
|
-
bus. It reads `.d64` and `.g64` images, which it autostarts with the
|
|
144
|
-
same `LOAD"*",8,1` and `RUN`, but not `.d71`, `.d81` or `.t64` images
|
|
145
|
-
or directories. `--read-only` puts the disk in write-protected. Loading
|
|
146
|
-
runs at the speed of a real 1541, and the drive's red LED lights in the
|
|
147
|
-
bottom right corner of the border. Both executables take it.
|
|
148
|
-
|
|
149
|
-
`Badline::Media.insert_disk(computer, path)` swaps the disk image or
|
|
150
|
-
directory in device 8 while the machine runs, for software that asks for
|
|
151
|
-
another disk. It takes `read_only: true`, and `Badline::Media.attach`
|
|
152
|
-
takes `disk: { read_only: true }`, to mount a disk image write-protected,
|
|
153
|
-
as the test harnesses under `bin/` do. A `.g64` goes in the true 1541,
|
|
154
|
-
and takes out a disk mounted through the traps, so `LOAD` and `SAVE`
|
|
155
|
-
reach the 1541 too. With the 1541 in device 8, a `.d64` goes in its
|
|
156
|
-
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.
|
|
157
134
|
|
|
158
135
|
## Snapshots
|
|
159
136
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
`computer.restore_snapshot(path)` takes a machine back to a snapshot,
|
|
167
|
-
and `Badline::Snapshot.load(path)` builds a new machine as the saved one
|
|
168
|
-
was built and restores it. `computer.snapshot` and
|
|
169
|
-
`computer.restore(state)` do the same in memory, without a file. A
|
|
170
|
-
restore that fails leaves the machine as it was.
|
|
171
|
-
|
|
172
|
-
A snapshot holds the machine as it was on the cycle it was saved: the
|
|
173
|
-
chips down to the instruction step and the pixel pipeline, the RAM and
|
|
174
|
-
any +60K or +256K expansion, the cartridge with its RAM and flash, a
|
|
175
|
-
GEO-RAM, a true 1541 with its RAM, its VIAs and the disk under the head,
|
|
176
|
-
a disk or directory mounted through the traps with its open channels,
|
|
177
|
-
and the tape with its place on it. A restored machine runs on exactly
|
|
178
|
-
as the saved one would have. A directory, a tape and a true drive's
|
|
179
|
-
disk image open again from their paths when the snapshot is restored,
|
|
180
|
-
the disk with its tracks as the drive last saw them. A disk image mounted through the traps comes back
|
|
181
|
-
with its contents from the snapshot. What the host holds stays the host's: the keyboard, the
|
|
182
|
-
joysticks, the mouse and paddles, sound, and blocks given to `on_init`
|
|
183
|
-
that hadn't run yet, which a restore reports. A snapshot only restores
|
|
184
|
-
in the badline version that wrote it, into a machine with the same
|
|
185
|
-
chip models, RAM expansion and REU. `computer.snapshot` holds an REU's
|
|
186
|
-
RAM, registers and transfer too, but a machine with an REU doesn't save
|
|
187
|
-
to a file yet, as badline doesn't write VICE's REU module.
|
|
188
|
-
|
|
189
|
-
Snapshots use VICE's `.vsf` format. badline writes VICE's modules for
|
|
190
|
-
the CPU, RAM and CPU port, both CIAs, the SID and the VIC-II, plus the
|
|
191
|
-
ones x64sc needs to open the file, with nothing attached to the
|
|
192
|
-
cartridge, tape or user ports and no true drive. A `BADLINE` module,
|
|
193
|
-
which VICE skips, holds the whole machine, and badline restores its own
|
|
194
|
-
snapshots from it.
|
|
195
|
-
|
|
196
|
-
x64sc 3.10 opens badline's snapshots, taken at the end of the
|
|
197
|
-
instruction the CPU was in, as long as its VIC-II model matches
|
|
198
|
-
(`-model c64` for the default machine). It keeps its own drives and
|
|
199
|
-
leaves out the cartridge, the expansions and the tape. Snapshots x64sc
|
|
200
|
-
saves open in badline through the same modules: the CPU at its
|
|
201
|
-
instruction boundary, RAM, the CPU port, the CIAs' registers, timers and
|
|
202
|
-
clocks, the SID's registers and reSID voice state, and the VIC-II's
|
|
203
|
-
registers, beam position, counters and colour RAM. The VIC-II's pixel
|
|
204
|
-
pipeline starts empty. badline reads the modules x64sc 3.7 to 3.10
|
|
205
|
-
write, and VICE's development versions' `MAINC64CPU` and `VIC-IISC`. A module version
|
|
206
|
-
it doesn't know is left out, or fails the restore for the CPU and RAM.
|
|
207
|
-
It reports the modules it leaves out, such as the 1541 drives, the
|
|
208
|
-
cartridge, the datasette and the keyboard, and carries on without them.
|
|
209
|
-
An NTSC snapshot fails, as badline runs PAL only. Restored into a
|
|
210
|
-
running machine, a VICE snapshot fails for a machine built another way,
|
|
211
|
-
such as a C64C's snapshot in a C64, and otherwise takes the cartridge
|
|
212
|
-
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.
|
|
213
143
|
|
|
214
144
|
## Playing and rendering SID tunes
|
|
215
145
|
|
|
216
|
-
`badline-ruby --headless` plays a `.sid` tune on the host's audio
|
|
217
|
-
device without opening the window, and `--audio-out` renders it to a
|
|
218
|
-
16-bit PCM file instead. The file's extension picks the format, `.wav`
|
|
219
|
-
or `.aiff`. The native `badline` has both modes too.
|
|
220
|
-
|
|
221
146
|
```sh
|
|
222
|
-
badline
|
|
223
|
-
badline
|
|
224
|
-
badline
|
|
225
|
-
badline
|
|
226
|
-
badline-ruby --headless --sid 8580 tune.sid
|
|
227
|
-
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
|
|
228
151
|
```
|
|
229
152
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
release, the song number and the time played against the song's
|
|
239
|
-
length. When a song reaches its length it goes on to the next, and it
|
|
240
|
-
stops after the last. `n` or → skips to the next song, `p` or ← goes
|
|
241
|
-
back one, space pauses and `q` quits. `--no-tui`, or output that isn't a
|
|
242
|
-
terminal, gives plain progress output instead and plays just the one
|
|
243
|
-
song, as `--audio-out` renders just the one.
|
|
244
|
-
|
|
245
|
-
A `.sid` file doesn't store its length, so `badline-ruby` looks the
|
|
246
|
-
tune up by MD5 in HVSC's `Songlengths.md5`. It finds the database
|
|
247
|
-
through `--songlengths`, in a `DOCUMENTS` directory in any of the
|
|
248
|
-
tune's parent directories (the layout of an HVSC collection), or under
|
|
249
|
-
`$HVSC_BASE/DOCUMENTS`. Without a database or `--seconds` it runs for
|
|
250
|
-
60 seconds.
|
|
251
|
-
|
|
252
|
-
PSID tunes run on a CPU and RAM with only the SID clocked, at about
|
|
253
|
-
twice real time, so they play smoothly. RSID tunes set up their own
|
|
254
|
-
interrupts, so they boot a full C64 first and run at about half real
|
|
255
|
-
time. They render fine but stutter when played, and `badline-ruby` says
|
|
256
|
-
so when it falls behind. The filter steps four cycles at a time;
|
|
257
|
-
`--filter-chunk 1` steps it every cycle, which is exact and takes about
|
|
258
|
-
twice as long. `badline-ruby --help` lists the options.
|
|
259
|
-
|
|
260
|
-
The native `badline` takes the same options and runs the same code, so
|
|
261
|
-
it renders the same file sample for sample, and it plays RSID tunes
|
|
262
|
-
without stuttering. See
|
|
263
|
-
[native/README.md](native/README.md#without-the-window).
|
|
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.
|
|
159
|
+
|
|
160
|
+

|
|
264
161
|
|
|
265
162
|
## Input
|
|
266
163
|
|
|
@@ -283,109 +180,97 @@ types `"`. These keys have no same-named host key:
|
|
|
283
180
|
| `+` / `*` | Keypad `+` / Keypad `*` |
|
|
284
181
|
| `RESTORE` | `Page Up` |
|
|
285
182
|
|
|
286
|
-
`Tab`
|
|
287
|
-
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:
|
|
288
186
|
|
|
289
|
-
|
|
|
290
|
-
|
|
187
|
+
| Title | What the host drives |
|
|
188
|
+
|-------|----------------------|
|
|
291
189
|
| (none) | The keyboard |
|
|
292
|
-
| `[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 |
|
|
293
191
|
| `[MOUSE 1]` / `[MOUSE 2]` | A 1351 mouse in control port 1 or 2 |
|
|
294
192
|
| `[PADDLE 1]` / `[PADDLE 2]` | A pair of paddles in control port 1 or 2 |
|
|
295
193
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
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.
|
|
301
200
|
|
|
302
201
|
Game controllers work in every mode. The first one is joystick 2 and
|
|
303
202
|
the second is joystick 1. The D-pad and left stick steer, the face and
|
|
304
203
|
shoulder buttons fire, and controllers can be connected or removed while
|
|
305
204
|
the emulator runs.
|
|
306
205
|
|
|
307
|
-
Control port 1's fire line is also the VIC-II's light pen input, so
|
|
308
|
-
joystick 1's fire button and the 1351's left button in port 1 latch the
|
|
309
|
-
light pen registers.
|
|
310
|
-
|
|
311
206
|
`F10` mutes and unmutes the sound, and the window title shows `[MUTED]`
|
|
312
207
|
while it's off.
|
|
313
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
|
+
|
|
314
238
|
## What's emulated
|
|
315
239
|
|
|
316
240
|
- **6510**: every opcode, documented and undocumented, with per-cycle
|
|
317
241
|
bus behaviour checked against the
|
|
318
242
|
[65x02 single step tests](https://github.com/SingleStepTests/65x02).
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
- **
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
machine instead: the 6567R8's 65 cycles by 263 lines at 1,022,727 Hz,
|
|
333
|
-
with its later sprite fetches and its X counter, and TOD clocks on
|
|
334
|
-
60 Hz mains. `Badline::Region::NTSC_OLD` is the first NTSC C64s'
|
|
335
|
-
6567R56A, 64 cycles by 262 lines. The stock KERNAL tells them from PAL
|
|
336
|
-
by the raster, so every region boots the same ROMs. `--ntsc` picks the
|
|
337
|
-
6567R8.
|
|
338
|
-
- **CIA 1 and 2**: timers, time-of-day clocks with alarms, the serial
|
|
339
|
-
shift register, interrupts, the keyboard matrix with its ghost keys,
|
|
340
|
-
the control ports and the paddle multiplexer. The machine has the
|
|
341
|
-
original 6526s; `Badline::Computer.new(cia_model: :mos6526a)` fits the
|
|
342
|
-
C64C's 6526As instead, whose interrupt register timing differs.
|
|
343
|
-
- **SID**: the 6581 and the 8580, with oscillators, ring modulation and
|
|
344
|
-
sync, the envelope generator including the ADSR delay bug, the filter,
|
|
345
|
-
and the RC network on the board that removes the DC offset from the
|
|
346
|
-
output. The machine has a 6581 unless a `.sid` tune asks for an 8580
|
|
347
|
-
in its header, and `--sid 6581` or `--sid 8580` overrides either.
|
|
348
|
-
- **REU**: the 1700, 1764 and 1750 RAM Expansion Units, and the bigger
|
|
349
|
-
units up to 16M built on the same REC chip, with DMA timed against the
|
|
350
|
-
VIC's bad lines and sprites. `--reu SIZE` plugs one in, and
|
|
351
|
-
`Badline::Computer.new(reu: 512)` does the same from Ruby. An
|
|
352
|
-
REU beside a cartridge loses I/O 2 to the cartridge.
|
|
353
|
-
- **Datasette**: `.tap` playback into CIA 1's FLAG line, with the motor
|
|
354
|
-
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`).
|
|
355
256
|
- **Cartridges**: standard 8K, 16K and Ultimax, Simons' BASIC, Ocean,
|
|
356
|
-
Fun Play / Power Play, Super Games, Epyx FastLoad, Westermann
|
|
357
|
-
Rex Utility, C64 Game System / System 3, Dinamic, Zaxxon /
|
|
358
|
-
Magic Desk, Comal-80, EasyFlash, Mach 5, Pagefox, RGCD
|
|
359
|
-
the freezers Action Replay (v4.2 to v6), Atomic
|
|
360
|
-
Retro Replay / Nordic Replay, Final Cartridge III
|
|
361
|
-
Power Cartridge.
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
the Am29F040 EAPI on attach, as VICE does. The writes stay in memory
|
|
366
|
-
and are lost when the emulator quits: the `.crt` file is never
|
|
367
|
-
overwritten. The Retro Replay's flash
|
|
368
|
-
works the same way in flash mode, which the flash jumper enables:
|
|
369
|
-
`Media.attach(computer, path, cartridge: { flash_jumper: true })`, with
|
|
370
|
-
`bank_jumper: true` to run from the second 64K of a 128K image. The
|
|
371
|
-
GMod2 EEPROM and the Retro Replay clock port aren't there.
|
|
372
|
-
- **GEO-RAM**: 64K to 4M of RAM seen through the `$DE00` page, with the
|
|
373
|
-
`$DFFE`/`$DFFF` page and block registers. It takes the expansion port,
|
|
374
|
-
so it can't sit alongside a cartridge:
|
|
375
|
-
`computer.attach_cartridge(Badline::Cartridge::GeoRAM.new(size: 512))`.
|
|
376
|
-
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).
|
|
377
266
|
|
|
378
267
|
Known gaps:
|
|
379
268
|
|
|
380
|
-
- `badline-ruby` runs below real time, so its
|
|
381
|
-
|
|
382
|
-
`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.
|
|
383
271
|
- Without `--true-drive`, fast loaders and anything else that runs code
|
|
384
|
-
on the drive won't work
|
|
385
|
-
doesn't rename, copy, format or validate disks.
|
|
272
|
+
on the drive won't work.
|
|
386
273
|
- No PAL-N (Drean) machine.
|
|
387
|
-
- The emulator window has no freeze button yet, so a freezer cartridge
|
|
388
|
-
runs its menu but can't freeze a program.
|
|
389
274
|
|
|
390
275
|
## Contributing
|
|
391
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.
|