badline 0.8.0 → 0.9.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 +29 -0
- data/README.md +22 -16
- data/doc/library.md +10 -3
- data/doc/media.md +11 -2
- data/doc/pinned-behaviour.md +53 -9
- data/doc/sid-player.md +8 -4
- data/doc/snapshots.md +66 -33
- data/lib/badline/address_bus/roms.rb +32 -0
- data/lib/badline/address_bus.rb +4 -4
- data/lib/badline/audio/bare_player.rb +24 -0
- data/lib/badline/audio/checkpoints.rb +42 -0
- data/lib/badline/audio/jukebox.rb +11 -4
- data/lib/badline/audio/machine_player.rb +16 -0
- data/lib/badline/audio/renderer.rb +80 -9
- data/lib/badline/audio/stereo.rb +3 -5
- data/lib/badline/audio.rb +1 -0
- data/lib/badline/computer/attachments.rb +5 -5
- data/lib/badline/computer.rb +12 -10
- data/lib/badline/core.rb +48 -0
- data/lib/badline/data_path.rb +37 -0
- data/lib/badline/datasette.rb +24 -9
- data/lib/badline/drive1541/disk.rb +3 -3
- data/lib/badline/drive1541/disk_state.rb +14 -5
- data/lib/badline/frontend/app.rb +4 -3
- data/lib/badline/frontend/boot.rb +9 -4
- data/lib/badline/frontend/confirmation.rb +17 -11
- data/lib/badline/frontend/menu_dialogs.rb +52 -14
- data/lib/badline/frontend/menu_media.rb +36 -7
- data/lib/badline/frontend/menu_pages.rb +24 -2
- data/lib/badline/frontend/name_field.rb +88 -0
- data/lib/badline/frontend/pause_menu.rb +25 -7
- data/lib/badline/frontend/player_window.rb +3 -3
- data/lib/badline/frontend/snapshots.rb +145 -17
- data/lib/badline/frontend/sound.rb +11 -5
- data/lib/badline/frontend.rb +1 -0
- data/lib/badline/kernal_trap/load.rb +10 -0
- data/lib/badline/kernal_trap/routine.rb +28 -0
- data/lib/badline/kernal_trap/serial.rb +19 -7
- data/lib/badline/media/disk_list.rb +75 -0
- data/lib/badline/media/disk_set.rb +13 -3
- data/lib/badline/media.rb +8 -3
- data/lib/badline/model.rb +62 -0
- data/lib/badline/options/event.rb +5 -3
- data/lib/badline/options/help.rb +16 -12
- data/lib/badline/options/table.rb +5 -1
- data/lib/badline/options/validation.rb +9 -0
- data/lib/badline/options.rb +7 -4
- data/lib/badline/region.rb +16 -4
- data/lib/badline/reu/ram.rb +27 -0
- data/lib/badline/reu/saved_state.rb +27 -0
- data/lib/badline/roms/README +10 -0
- data/lib/badline/roms/kernal-sx64.rom +0 -0
- data/lib/badline/sid/decimator.rb +13 -0
- data/lib/badline/sid/filter.rb +6 -3
- data/lib/badline/sid.rb +19 -0
- data/lib/badline/snapshot/fields.rb +1 -0
- data/lib/badline/snapshot/setup.rb +20 -8
- data/lib/badline/snapshot/state.rb +14 -7
- data/lib/badline/snapshot/vice/main_cpu.rb +1 -1
- data/lib/badline/snapshot/vice/peripherals.rb +12 -2
- data/lib/badline/snapshot/vice/restore.rb +3 -1
- data/lib/badline/snapshot/vice/reu1764.rb +55 -0
- data/lib/badline/snapshot/vice/vicii.rb +59 -13
- data/lib/badline/snapshot/vice/vicii_import.rb +14 -3
- data/lib/badline/snapshot/vice.rb +25 -23
- data/lib/badline/storage/t64.rb +7 -4
- data/lib/badline/storage/tap.rb +7 -5
- data/lib/badline/storage/unavailable.rb +1 -1
- data/lib/badline/storage.rb +5 -5
- data/lib/badline/version.rb +1 -1
- data/lib/badline/vic/sprite/timing.rb +5 -9
- data/lib/badline/vic/sprite.rb +4 -3
- data/lib/badline.rb +2 -38
- metadata +10 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2916044b89e174698de9dd60a2a72121dc6aa91058a9de914dfbaa5e70170f29
|
|
4
|
+
data.tar.gz: 56adae369f806a6adb31dea00b5164d6e02e4b88d6a6cc08209808abdae0392b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cac3c6ba20fff4bbabd7e77dd8eae4e53cb12a3785f946908407627eb29783764684c0e2cf208b6a8030ad31bcfb35811526873119d51cb5badd0f2598257b41
|
|
7
|
+
data.tar.gz: 93cecca78dbb7f4ca6393a629d113fa80a68a573359193ae4bcc54b87aadea883fdba0f84ad3ccb8acbad54539867b676e82e9f940420b50365f0fc7b93c33ff
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.9.0](https://github.com/elektronaut/badline/compare/v0.8.0...v0.9.0) (2026-10-05)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add a per-user data folder for badline's own files ([27bdf0e](https://github.com/elektronaut/badline/commit/27bdf0edc16d95fc57dea940741cc0b7de74bbb1))
|
|
9
|
+
* add the Drean C64, PAL-N with the 6572, as --model drean ([0562d8e](https://github.com/elektronaut/badline/commit/0562d8eb5b11239039eac934fd21eb7824868f98))
|
|
10
|
+
* add the SX-64 as --model sx64 ([e947cba](https://github.com/elektronaut/badline/commit/e947cba8ff46f0f01eeb6e1a49c0bd4bf91324ea))
|
|
11
|
+
* autosave, and a Snapshots page in the pause menu ([78aede9](https://github.com/elektronaut/badline/commit/78aede9a6052ce6c32184952a7b1d380e7c129e2))
|
|
12
|
+
* keep five quicksave slots in the data folder ([6043543](https://github.com/elektronaut/badline/commit/6043543632aa61a42ff69bdff8ea15ae354ce810))
|
|
13
|
+
* pick the C64 to run with --model ([d5539c8](https://github.com/elektronaut/badline/commit/d5539c8ade245b1e96e78765f15906ce4a80da5b))
|
|
14
|
+
* restore snapshots without their tape, .t64 or true drive disk files ([0c0733a](https://github.com/elektronaut/badline/commit/0c0733a5c7eaf9c217466f7569769eb005c5248f))
|
|
15
|
+
* run the testlist's Drean rows as testbench-drean ([dc8a075](https://github.com/elektronaut/badline/commit/dc8a07524168d399fb7c0305c661ab694c53bc2c))
|
|
16
|
+
* save NTSC, Drean and REU machines as .vsf snapshots ([c4126cf](https://github.com/elektronaut/badline/commit/c4126cfa878d8efe7aaaa9e5113c4ee2a4886e6b))
|
|
17
|
+
* seek within a subtune from checkpoints kept as it plays ([3ac57be](https://github.com/elektronaut/badline/commit/3ac57beac448a43a76387a0ff1f370cd07d06d81))
|
|
18
|
+
* take disk sets from .m3u and .vfl lists ([b4e6845](https://github.com/elektronaut/badline/commit/b4e6845eb04cde80f87c1fcb372987311bf1dd97))
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### Bug Fixes
|
|
22
|
+
|
|
23
|
+
* describe F11's quicksave slots, F12 and the autosave in --help ([6cbf148](https://github.com/elektronaut/badline/commit/6cbf148d327699070ef4fba4f2b3e3dd39d41348))
|
|
24
|
+
* keep the board's low-pass stable for long filter steps ([c5af022](https://github.com/elektronaut/badline/commit/c5af0224aad60dbb665e6804bb536746e354da96))
|
|
25
|
+
* leave CIA 1's timer B and the serial lines as the KERNAL's LOAD does ([b4f1a41](https://github.com/elektronaut/badline/commit/b4f1a4173b9413fd59b05bab12d173e0679c4c17))
|
|
26
|
+
* play an NTSC machine's sound at its own clock ([510aab1](https://github.com/elektronaut/badline/commit/510aab1052a58a54b1790802e2a5705fcb208c5c))
|
|
27
|
+
* put CIA 2's port A on the serial bus without a drive ([31f8a4f](https://github.com/elektronaut/badline/commit/31f8a4fad0ea210d4272b4672a84414527b68e31))
|
|
28
|
+
* run the 6567R8 and 6572 X counter over $180-$187 twice ([08a4da3](https://github.com/elektronaut/badline/commit/08a4da33d4bd68a85d61895dcf8c1ea5fa5b539c))
|
|
29
|
+
* set CIA 1's timer B for each byte the serial traps stand in for ([f98e6d7](https://github.com/elektronaut/badline/commit/f98e6d7666d2326ce4d8d3ab7f938dc4fd60cbd1))
|
|
30
|
+
* take .m3u and .vfl lists of disks in --at's insert ([d1e771e](https://github.com/elektronaut/badline/commit/d1e771e6781fc5560dda2e10e6d76abb53be0807))
|
|
31
|
+
|
|
3
32
|
## [0.8.0](https://github.com/elektronaut/badline/compare/v0.7.0...v0.8.0) (2026-10-03)
|
|
4
33
|
|
|
5
34
|
|
data/README.md
CHANGED
|
@@ -78,7 +78,8 @@ differences noted in the table. `--help` lists the options for either.
|
|
|
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 |
|
|
80
80
|
| `--reu SIZE` | Plug in a RAM Expansion Unit of `SIZE` K: 128, 256, 512 (a 1750) or up to 16384 |
|
|
81
|
-
| `--
|
|
81
|
+
| `--model NAME` | Run another C64, named as in VICE: `c64` (the default, a PAL C64 with the 6569 VIC-II, 6526 CIAs and the 6581 SID), `c64c` (the PAL C64C, with the 8565, 6526As and the 8580), `ntsc` (the 6567R8), `newntsc` (the NTSC C64C, with the 8562, 6526As and the 8580), `oldntsc` (the first NTSC C64s' 6567R56A), `drean` (the Drean C64 of Argentina, PAL-N with the 6572) or `sx64` (the portable SX-64, with its own KERNAL and no datasette). `--sid` or a `.sid` tune's own SID takes the model's place |
|
|
82
|
+
| `--ntsc` | Run an NTSC C64, as `--model ntsc` does |
|
|
82
83
|
| `--no-sound` | Don't play the SID (`badline` only, where sound is on by default) |
|
|
83
84
|
| `--sound` | Play the SID (`badline-ruby`, where sound is off by default) |
|
|
84
85
|
| `--no-vsync` | Pace the window by a timer, or by the sound while it plays, instead of the display's vsync |
|
|
@@ -117,6 +118,7 @@ library, are covered in [doc/library.md](doc/library.md).
|
|
|
117
118
|
| `.prg`, `.p00` | Loaded into memory after boot. A program at the BASIC start (`$0801`) is `RUN`, anything else is left for you to `SYS` |
|
|
118
119
|
| `.d64`, `.d71`, `.d81` | Mounted as device 8, then `LOAD"*",8,1` and `RUN`. Write-protected unless `--writable` |
|
|
119
120
|
| `.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
|
+
| `.m3u`, `.vfl` | A list of disk images, one path a line, relative to the list: an `.m3u` playlist, or a VICE flip list, which only unit 8's entries are taken from. Its first disk goes in as above, and the list is its set for the pause menu |
|
|
120
122
|
| `.t64` | Mounted read-only as device 8 and loaded like a disk image. The files load by name, and no tape is involved |
|
|
121
123
|
| `.tap` | Inserted in the datasette with PLAY pressed, then `LOAD` and `RUN`. It loads at the speed of a real tape |
|
|
122
124
|
| `.crt` | The hardware types listed under [Cartridges](#whats-emulated). Other types are rejected |
|
|
@@ -134,12 +136,14 @@ from Ruby.
|
|
|
134
136
|
|
|
135
137
|
## Snapshots
|
|
136
138
|
|
|
137
|
-
`F11`
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
139
|
+
`F11` quicksaves the whole machine to the next of five slots in
|
|
140
|
+
badline's data folder, replacing the oldest, and `F12` restores the
|
|
141
|
+
newest, even after badline has quit and started again. badline also
|
|
142
|
+
autosaves every two minutes of play, and the pause menu's Snapshots page
|
|
143
|
+
saves under a name and loads any of them. Snapshots use
|
|
144
|
+
VICE's `.vsf` format: badline opens those x64sc saves, and x64sc opens
|
|
145
|
+
badline's. See [doc/snapshots.md](doc/snapshots.md) for where they're
|
|
146
|
+
kept, what they hold and how far the two agree.
|
|
143
147
|
|
|
144
148
|
## Playing and rendering SID tunes
|
|
145
149
|
|
|
@@ -217,6 +221,7 @@ too.
|
|
|
217
221
|
|
|
218
222
|
| Page | What it holds |
|
|
219
223
|
|------|---------------|
|
|
224
|
+
| Snapshots | Quicksave, save under a name, load a named save, and the latest quicksaves and autosaves |
|
|
220
225
|
| Drive 8 | The disk: insert, eject, the previous or next disk of its set, and whether it's writable |
|
|
221
226
|
| Datasette | The tape: insert, eject, PLAY and REWIND |
|
|
222
227
|
| Expansion port | The cartridge: insert, remove, and its freeze button if it has one |
|
|
@@ -224,15 +229,17 @@ too.
|
|
|
224
229
|
| Sound | Mute, and the SID's model |
|
|
225
230
|
| Power | Reset, power cycle and quit |
|
|
226
231
|
|
|
227
|
-
INSERT opens a file browser. A disk's set
|
|
228
|
-
|
|
229
|
-
|
|
232
|
+
INSERT opens a file browser. A disk's set is the `.m3u` or `.vfl` list it
|
|
233
|
+
was opened from, or one in its folder that lists it. Without one, it comes
|
|
234
|
+
from the names in its folder: `Disk 1`, `Side B`, `d2`, TOSEC's
|
|
235
|
+
`(Disk 1 of 2)`, or a trailing `_1`, `_2` when the first of the set is
|
|
236
|
+
there. WRITABLE starts as
|
|
230
237
|
`--writable` sets it and stays as set for the next disk. Quick open starts
|
|
231
238
|
a file in a new machine, as the command line does. It asks first, as
|
|
232
239
|
inserting or removing a cartridge does, since each power cycles the
|
|
233
240
|
machine.
|
|
234
241
|
|
|
235
|
-
A disk or tape dropped on the window goes into its drive. A cartridge,
|
|
242
|
+
A disk, list of disks or tape dropped on the window goes into its drive. A cartridge,
|
|
236
243
|
program or `.sid` dropped on it opens the menu to ask first.
|
|
237
244
|
|
|
238
245
|
## What's emulated
|
|
@@ -242,8 +249,8 @@ program or `.sid` dropped on it opens the menu to ask first.
|
|
|
242
249
|
[65x02 single step tests](https://github.com/SingleStepTests/65x02).
|
|
243
250
|
- **Memory**: banking through the 6510 port, the cartridge lines and
|
|
244
251
|
Ultimax mode, and the +60K and +256K RAM expansions.
|
|
245
|
-
- **VIC-II**: the PAL 6569, the C64C's 8565,
|
|
246
|
-
and
|
|
252
|
+
- **VIC-II**: the PAL 6569, the C64C's 8565, NTSC's 6567R8, 8562 and
|
|
253
|
+
6567R56A, and the Drean's PAL-N 6572 (`--model`): every graphics mode, sprites, collisions, bad lines,
|
|
247
254
|
sprite DMA, the border and the light pen.
|
|
248
255
|
- **CIA 1 and 2**: the 6526 and the C64C's 6526A, with timers,
|
|
249
256
|
time-of-day clocks, the serial shift register, the keyboard matrix
|
|
@@ -261,8 +268,8 @@ program or `.sid` dropped on it opens the menu to ask first.
|
|
|
261
268
|
Power / Nordic Power, Retro Replay / Nordic Replay, Final Cartridge III
|
|
262
269
|
/ III+ and the KCS Power Cartridge. Flash writes stay in memory.
|
|
263
270
|
|
|
264
|
-
|
|
265
|
-
built from Ruby: see [doc/library.md](doc/library.md).
|
|
271
|
+
Chip combinations `--model` doesn't name, and the cartridges' jumpers,
|
|
272
|
+
are built from Ruby: see [doc/library.md](doc/library.md).
|
|
266
273
|
|
|
267
274
|
Known gaps:
|
|
268
275
|
|
|
@@ -270,7 +277,6 @@ Known gaps:
|
|
|
270
277
|
turns on, stutters: it plays in bursts with silent gaps between them.
|
|
271
278
|
- Without `--true-drive`, fast loaders and anything else that runs code
|
|
272
279
|
on the drive won't work.
|
|
273
|
-
- No PAL-N (Drean) machine.
|
|
274
280
|
|
|
275
281
|
## Contributing
|
|
276
282
|
|
data/doc/library.md
CHANGED
|
@@ -19,7 +19,9 @@ computer.address_bus.peek(0x0400) # screen RAM starts at $0400
|
|
|
19
19
|
## Building a machine
|
|
20
20
|
|
|
21
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
|
|
22
|
+
6569 VIC-II, 6526 CIAs and a 6581 SID. Its keywords build others, and
|
|
23
|
+
`Badline::Model.named("c64c")` gives the ones `--model` names for each
|
|
24
|
+
model (`Badline::Model::ALL`):
|
|
23
25
|
|
|
24
26
|
- `vic_model: :mos8565` fits the C64C's 8565, with its grey dots on
|
|
25
27
|
colour register writes and its own timing for mode splits, sprite
|
|
@@ -28,7 +30,8 @@ computer.address_bus.peek(0x0400) # screen RAM starts at $0400
|
|
|
28
30
|
65 cycles by 263 lines at 1,022,727 Hz, with its later sprite fetches
|
|
29
31
|
and its X counter, and TOD clocks on 60 Hz mains.
|
|
30
32
|
`Badline::Region::NTSC_OLD` is the first NTSC C64s' 6567R56A, 64 cycles
|
|
31
|
-
by 262 lines
|
|
33
|
+
by 262 lines, and `Badline::Region::DREAN` the Drean C64's PAL-N
|
|
34
|
+
6572, 65 cycles by 312 lines at 1,023,440 Hz. The stock KERNAL tells them from PAL by the raster, so
|
|
32
35
|
every region boots the same ROMs.
|
|
33
36
|
- `cia_model: :mos6526a` fits the C64C's 6526As, whose interrupt
|
|
34
37
|
register timing differs.
|
|
@@ -36,6 +39,9 @@ computer.address_bus.peek(0x0400) # screen RAM starts at $0400
|
|
|
36
39
|
- `ram_expansion: :plus60k` or `:plus256k` fits the +60K or +256K RAM
|
|
37
40
|
expansion, banked through its register at `$D100`.
|
|
38
41
|
- `reu: 512` plugs in a RAM Expansion Unit of that many K.
|
|
42
|
+
- `kernal: :sx64` fits the SX-64's KERNAL, and `datasette: false`
|
|
43
|
+
leaves the cassette port empty, so inserting a tape raises
|
|
44
|
+
`Badline::Datasette::Missing`. The SX-64 has both.
|
|
39
45
|
|
|
40
46
|
## Cartridges
|
|
41
47
|
|
|
@@ -57,6 +63,7 @@ Its contents are lost when the emulator quits.
|
|
|
57
63
|
The KERNAL, BASIC and character ROMs come with the gem. To run other
|
|
58
64
|
images, such as a patched KERNAL, point `BADLINE_ROM_PATH` at a
|
|
59
65
|
directory that holds `kernal.rom`, `basic.rom` and `character.rom`, plus
|
|
60
|
-
`eapi/eapi-am29f040-14` if you
|
|
66
|
+
`kernal-sx64.rom` for the SX-64 and `eapi/eapi-am29f040-14` if you
|
|
67
|
+
attach EasyFlash cartridges.
|
|
61
68
|
`Badline.rom_path = dir` does the same before a `Badline::Computer` is
|
|
62
69
|
built, and `nil` restores the bundled set.
|
data/doc/media.md
CHANGED
|
@@ -59,8 +59,17 @@ traps, so `LOAD` and `SAVE` reach the 1541 too. With the 1541 in device
|
|
|
59
59
|
8, a `.d64` goes in its drive as well.
|
|
60
60
|
|
|
61
61
|
`Badline::Media::DiskSet.around(path)` lists the disks of the set a disk
|
|
62
|
-
image belongs to,
|
|
63
|
-
|
|
62
|
+
image belongs to, which the pause menu's PREVIOUS DISK and NEXT DISK step
|
|
63
|
+
through. An `.m3u` or `.vfl` list in the disk's folder that names it
|
|
64
|
+
gives the set. Without one, the set is found by name in the folder.
|
|
65
|
+
Given a list, it returns the disks the list names.
|
|
66
|
+
|
|
67
|
+
A list names one disk image a line, as a path relative to the list or an
|
|
68
|
+
absolute one. Blank lines and lines starting with `#` are skipped, and
|
|
69
|
+
entries that aren't there are left out. In a VICE `.vfl` flip list, only
|
|
70
|
+
the entries after a `UNIT 8` line, or before any `UNIT` line, count.
|
|
71
|
+
`Media.attach` and the command line take a list as media and attach its
|
|
72
|
+
first disk.
|
|
64
73
|
|
|
65
74
|
## The light pen
|
|
66
75
|
|
data/doc/pinned-behaviour.md
CHANGED
|
@@ -26,6 +26,7 @@ only catches the rows that happen to move.
|
|
|
26
26
|
- [VIC light pen](#vic-light-pen)
|
|
27
27
|
- [VIC-II 8565](#vic-ii-8565)
|
|
28
28
|
- [VIC-II NTSC](#vic-ii-ntsc)
|
|
29
|
+
- [VIC-II 6572 (Drean)](#vic-ii-6572-drean)
|
|
29
30
|
- [CIA 6526 timer pipeline](#cia-6526-timer-pipeline)
|
|
30
31
|
- [CIA 6526A interrupt register](#cia-6526a-interrupt-register)
|
|
31
32
|
- [CIA serial shift register](#cia-serial-shift-register)
|
|
@@ -293,7 +294,9 @@ only catches the rows that happen to move.
|
|
|
293
294
|
early in the next one for 3–7.
|
|
294
295
|
- A sprite still shifting at K loses the rest of its row. Its output
|
|
295
296
|
holds its last pixel from K through **K+6**, then goes dark.
|
|
296
|
-
- A comparator hit in K..K+11 shows nothing.
|
|
297
|
+
- A comparator hit in K..K+11 shows nothing. Where K falls in the
|
|
298
|
+
last 11 pixels of the line, as sprite 3's does on a 65-cycle line,
|
|
299
|
+
the twelve run on into the next line's first pixels.
|
|
297
300
|
- A hit from K+12 on shows the row the reload brought. For sprites 0–2
|
|
298
301
|
that is the *next* line's row, a line early. For sprites 3–7 it is the
|
|
299
302
|
current row, and a hit ahead of their K shows the previous line's row.
|
|
@@ -307,6 +310,11 @@ only catches the rows that happen to move.
|
|
|
307
310
|
`spritex/demusinterruptus` and `spritegap2` pass on it too.
|
|
308
311
|
- Spec guard: *the reload* in
|
|
309
312
|
[`vic/sprite_spec.rb`](../spec/badline/vic/sprite_spec.rb).
|
|
313
|
+
- The run into the next line is pinned by `spritescan_drean`'s 6572
|
|
314
|
+
dump, where sprite 3 shows nothing for X = $193 to $19e, the twelve
|
|
315
|
+
pixels from K = 515 on a 520-pixel line. Without it a hit at $198 to
|
|
316
|
+
$19e collides. Spec guard: *the reload near the end of a 65-cycle
|
|
317
|
+
line*. The `testbench-ntsc` sprite rows pass either way.
|
|
310
318
|
- The hold's length is pinned by `spritefetchbug/test-136-2a`, whose
|
|
311
319
|
X-expanded sprite 0 sits at X = $136 and is still shifting at 459. Its
|
|
312
320
|
reference holds the last pixel through 465. Holding it for one pixel
|
|
@@ -941,14 +949,22 @@ region moves the sprites. The positions live in `Region::Profile` and
|
|
|
941
949
|
- Spec guard: *sprite DMA cycle stealing on NTSC* and *#phi1_data on
|
|
942
950
|
NTSC* in [`vic_spec.rb`](../spec/badline/vic_spec.rb), and
|
|
943
951
|
[`timing_spec.rb`](../spec/badline/vic/sprite/timing_spec.rb).
|
|
944
|
-
- **Display compare
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
+
- **Display compare.** The 6567R8 turns a sprite's display on and off in
|
|
953
|
+
cycle 59 (`sprite_display_cycle`), where the 6567R56A keeps the 6569's
|
|
954
|
+
cycle 58. This isn't pinned yet: moving the 6567R8's to 58 or the
|
|
955
|
+
6567R56A's to 59 fails no row of those subsets.
|
|
956
|
+
- **X counter.** The 6567R8's X counter spends 8 pixels more on a line
|
|
957
|
+
(`x_hold`): after $187 it runs over $180-$187 a second time, then on
|
|
958
|
+
from $188, so it reaches $1ff on a 520-pixel line. The 6567R56A's runs
|
|
959
|
+
straight through 512 pixels.
|
|
960
|
+
- Pinned for the 6572, which shares the line, by `spritescan_drean`'s
|
|
961
|
+
dump (see [VIC-II 6572 (Drean)](#vic-ii-6572-drean)).
|
|
962
|
+
- The 6567R8's own lightpen dump (`split-tests/lightpen`'s
|
|
963
|
+
`dump6567.prg`, run by hand on `--model ntsc`) agrees: the sample the
|
|
964
|
+
test takes 8 pixels into the hold reads $c2 ($180-$181). Reading
|
|
965
|
+
$184-$187 there instead, as badline did before, gives $c4. The 6572's
|
|
966
|
+
`dump6572.prg` has the same values. The `testbench-ntsc` rows pass
|
|
967
|
+
either way.
|
|
952
968
|
- **Blanking and crop.** The blanked lines are the ones VICE's NTSC view
|
|
953
969
|
leaves out, 12-27 on the 6567R8 and 13-27 on the 6567R56A, so the
|
|
954
970
|
`testbench-ntsc` screenshots, VICE's 247 lines from line 28 running on
|
|
@@ -970,6 +986,34 @@ What the NTSC references don't settle, and so what stays as it is:
|
|
|
970
986
|
readme says it was matched against screenshots, and the one 6567R8
|
|
971
987
|
photograph in the testprogs is of revision R01.
|
|
972
988
|
|
|
989
|
+
## VIC-II 6572 (Drean)
|
|
990
|
+
|
|
991
|
+
The 6572 of the Drean C64 (`Region::DREAN`) runs the 6567R8's line, 65
|
|
992
|
+
cycles with its sprite fetches in cycle 59, its display compare in cycle
|
|
993
|
+
59 and its X counter running over $180-$187 twice, on PAL-N's 312 lines at
|
|
994
|
+
1,023,440 Hz. The oracle is `split-tests/spritescan/spritescan_drean.prg`,
|
|
995
|
+
which checks itself against its `dump6572.bin`, from a real 6572R1. The
|
|
996
|
+
testlist comments that row out, and `testbench-drean`
|
|
997
|
+
(`bin/testbench --drean`) runs it.
|
|
998
|
+
|
|
999
|
+
- Pinned by that dump: every byte the test compares matches, and the
|
|
1000
|
+
test passes.
|
|
1001
|
+
- The X counter's second run over $180-$187 is pinned by sprite 1,
|
|
1002
|
+
pattern C (a one-pixel sprite against one shifted a pixel left), which
|
|
1003
|
+
collides for X = $180 to $186 on the 6572. Those are inside sprite 1's
|
|
1004
|
+
twelve dead pixels (K = 483), so the sprite only shows from the second
|
|
1005
|
+
time the counter reads its X. Repeating $184-$187 in the hold instead
|
|
1006
|
+
misses $180-$183 (4 bytes), repeating $180-$183 misses $184-$186 (3),
|
|
1007
|
+
and repeating $17c-$183 or $184-$18b moves 18 bytes. Spec guard: the
|
|
1008
|
+
6567R8 and 6572 examples in
|
|
1009
|
+
[`timing_spec.rb`](../spec/badline/vic/sprite/timing_spec.rb).
|
|
1010
|
+
- The display compare isn't pinned: the dump matches with it in cycle
|
|
1011
|
+
58 as well as 59.
|
|
1012
|
+
- Not matched: `spritegap3`'s 6572 dump has sprite 0 at X = 0 miss the
|
|
1013
|
+
sprite at X = 1 for every pair it is in, where badline, like the
|
|
1014
|
+
6567R8 dump, has them collide. The test still passes, because it
|
|
1015
|
+
accepts the 6567R8's dump too.
|
|
1016
|
+
|
|
973
1017
|
## CIA 6526 timer pipeline
|
|
974
1018
|
|
|
975
1019
|
- Start and stop go through two stages. A force load lands one tick after
|
data/doc/sid-player.md
CHANGED
|
@@ -46,7 +46,7 @@ channels.
|
|
|
46
46
|
Playback asks the device for 44.1 kHz and takes whatever rate it
|
|
47
47
|
offers, unless `--rate` says otherwise. Ctrl-C stops it. The emulator
|
|
48
48
|
window's own options, `--no-autostart`, `--writable`, `--sound`,
|
|
49
|
-
`--true-drive`, `--reu`, `--ntsc` and `--verbose`, don't apply.
|
|
49
|
+
`--true-drive`, `--reu`, `--model`, `--ntsc` and `--verbose`, don't apply.
|
|
50
50
|
|
|
51
51
|
## The window
|
|
52
52
|
|
|
@@ -86,9 +86,13 @@ first and last. `n` and `p` step to the next and previous tune. `s`
|
|
|
86
86
|
turns shuffle on and off, which plays the queue's tunes in a random
|
|
87
87
|
order, and `l` turns looping on and off, so that the end of the queue
|
|
88
88
|
goes on to its start. `,` and `.` seek 10 seconds back and forward
|
|
89
|
-
within the subtune
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
within the subtune. As a subtune plays, the player saves its state every
|
|
90
|
+
10 seconds. A seek back runs silently from the latest of those saved
|
|
91
|
+
states at or before the point asked for, or from the subtune's start
|
|
92
|
+
before the first. A seek forward runs on silently from where the
|
|
93
|
+
subtune is, or from a saved state further on, when an earlier seek back
|
|
94
|
+
left one there. The saved states last until the tune or subtune
|
|
95
|
+
changes. Space pauses and `q` quits. The status line shows which
|
|
92
96
|
modes are on, and they last until the player quits.
|
|
93
97
|
|
|
94
98
|
`--no-tui`, or output that isn't a terminal, gives plain progress output
|
data/doc/snapshots.md
CHANGED
|
@@ -1,11 +1,35 @@
|
|
|
1
1
|
# Snapshots
|
|
2
2
|
|
|
3
|
-
In the window, `F11`
|
|
4
|
-
`
|
|
5
|
-
|
|
6
|
-
saved
|
|
7
|
-
the
|
|
8
|
-
|
|
3
|
+
In the window, `F11` quicksaves the whole machine to one of five slots,
|
|
4
|
+
`quicksave-1.vsf` to `quicksave-5.vsf` in the `quicksaves` folder of
|
|
5
|
+
badline's data folder. It fills the empty slots first, then replaces the
|
|
6
|
+
one saved longest ago. `F12` restores the newest quicksave, or a named
|
|
7
|
+
save in the data folder's `saves` folder if one is newer, in a new
|
|
8
|
+
machine built as the saved one was. Quicksaves stay after badline quits,
|
|
9
|
+
so `F12` finds them the next time it starts. What's printed on a save or
|
|
10
|
+
a restore names the slot and the file.
|
|
11
|
+
|
|
12
|
+
A run without `--frames` also autosaves every 6,000 frames the machine
|
|
13
|
+
has run, two minutes on PAL, to `autosave-1.vsf` to `autosave-3.vsf` in
|
|
14
|
+
the `autosaves` folder, replacing the oldest. Time in the pause menu
|
|
15
|
+
doesn't count, nothing is printed, and `F12` never picks an autosave. An
|
|
16
|
+
autosave that fails warns once and stops autosaving.
|
|
17
|
+
|
|
18
|
+
The pause menu's Snapshots page quicksaves, saves under a name in the
|
|
19
|
+
`saves` folder and loads a named save. The name starts as the game's,
|
|
20
|
+
from its cartridge, disk or tape, or BASIC, with the next free number,
|
|
21
|
+
and saving over a name already taken asks first. Below those, the
|
|
22
|
+
newest quicksaves and autosaves, with the time each was saved, load
|
|
23
|
+
with a press.
|
|
24
|
+
|
|
25
|
+
The data folder is `~/Library/Application Support/badline` on macOS,
|
|
26
|
+
and `$XDG_DATA_HOME/badline` or `~/.local/share/badline` elsewhere.
|
|
27
|
+
`BADLINE_DATA_PATH` puts it somewhere else.
|
|
28
|
+
|
|
29
|
+
Both executables do this, and both open a `.vsf` given as the media,
|
|
30
|
+
in a machine built as the saved one was, whatever `--model` says.
|
|
31
|
+
`--save-snapshot FILE` saves one to `FILE` after the last frame. A
|
|
32
|
+
snapshot that fails to open leaves the machine running as it was.
|
|
9
33
|
|
|
10
34
|
## From Ruby
|
|
11
35
|
|
|
@@ -25,45 +49,54 @@ a disk or directory mounted through the traps with its open channels,
|
|
|
25
49
|
and the tape with its place on it. A restored machine runs on exactly
|
|
26
50
|
as the saved one would have.
|
|
27
51
|
|
|
28
|
-
A
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
52
|
+
A tape, a `.t64` archive and a disk image mounted through the traps come
|
|
53
|
+
back with their contents from the snapshot, so they need no file to
|
|
54
|
+
restore. A true drive's disk opens again from its image's path, with its
|
|
55
|
+
tracks as the drive last saw them. When that file is gone, the disk
|
|
56
|
+
comes back from the tracks alone, write-protected. A directory mounted
|
|
57
|
+
as device 8 opens again from its path. What the host holds stays the
|
|
32
58
|
host's: the keyboard, the joysticks, the mouse and paddles, sound, and
|
|
33
59
|
blocks given to `on_init` that hadn't run yet, which a restore reports.
|
|
34
60
|
|
|
35
|
-
|
|
36
|
-
machine with
|
|
37
|
-
|
|
38
|
-
a machine with
|
|
39
|
-
|
|
40
|
-
|
|
61
|
+
Every model saves this way, PAL, NTSC, old NTSC and Drean alike, and so
|
|
62
|
+
does a machine with an REU, with its RAM, its registers and a transfer
|
|
63
|
+
part way through. A snapshot only restores in the badline version that
|
|
64
|
+
wrote it, into a machine with the same chip models, region, RAM
|
|
65
|
+
expansion, REU, KERNAL and datasette. One saved before badline recorded
|
|
66
|
+
the KERNAL and the datasette restores as a machine with the C64's KERNAL
|
|
67
|
+
and a datasette.
|
|
41
68
|
|
|
42
69
|
## VICE
|
|
43
70
|
|
|
44
71
|
Snapshots use VICE's `.vsf` format. badline writes VICE's modules for
|
|
45
|
-
the CPU, RAM and CPU port, both CIAs, the SID and the VIC-II,
|
|
46
|
-
ones x64sc needs to open the file, with
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
72
|
+
the CPU, RAM and CPU port, both CIAs, the SID and the VIC-II, and an
|
|
73
|
+
REU's `REU1764`, plus the ones x64sc needs to open the file, with
|
|
74
|
+
nothing else attached to the cartridge port, nothing on the tape or user
|
|
75
|
+
ports and no true drive. The VIC-II module names the chip as VICE does:
|
|
76
|
+
the 6569 or 8565 on PAL, the 6567R8 or 8562 on NTSC, the 6567R56A on old
|
|
77
|
+
NTSC and the 6572 on PAL-N. A `BADLINE` module, which VICE skips, holds
|
|
78
|
+
the whole machine, and badline restores its own snapshots from it.
|
|
50
79
|
|
|
51
80
|
x64sc 3.10 opens badline's snapshots, taken at the end of the
|
|
52
|
-
instruction the CPU was in,
|
|
53
|
-
|
|
54
|
-
|
|
81
|
+
instruction the CPU was in, and of an REU transfer under way, as long
|
|
82
|
+
as its VIC-II model matches: `-model c64`, `c64c`, `ntsc`, `newntsc`,
|
|
83
|
+
`oldntsc` or `drean`, as `--model` names the machine. It takes the REU
|
|
84
|
+
from the snapshot, keeps its own drives and leaves out the cartridge,
|
|
85
|
+
the other expansions and the tape. A program x64sc runs on from badline's
|
|
86
|
+
snapshot reads the raster as badline does, cycle for cycle.
|
|
55
87
|
|
|
56
88
|
Snapshots x64sc saves open in badline through the same modules: the CPU
|
|
57
89
|
at its instruction boundary, RAM, the CPU port, the CIAs' registers,
|
|
58
|
-
timers and clocks, the SID's registers and reSID voice state,
|
|
59
|
-
VIC-II's registers, beam position, counters and colour RAM
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
90
|
+
timers and clocks, the SID's registers and reSID voice state, the
|
|
91
|
+
VIC-II's registers, beam position, counters and colour RAM, and an
|
|
92
|
+
REU's size, registers and RAM. The VIC-II's model builds the machine's
|
|
93
|
+
region, and the 6569R1 runs as the 6569. The VIC-II's pixel pipeline
|
|
94
|
+
starts empty. badline reads the modules x64sc 3.7 to 3.10 write, and
|
|
95
|
+
VICE's development versions' `MAINC64CPU` and `VIC-IISC`. A module
|
|
96
|
+
version it doesn't know is left out, or fails the restore for the CPU
|
|
97
|
+
and RAM. It reports the modules it leaves out, such as the 1541 drives,
|
|
98
|
+
the cartridge port, the datasette and the keyboard, and carries on
|
|
99
|
+
without them. Restored into a running machine, a VICE snapshot
|
|
67
100
|
fails for a machine built another way, such as a C64C's snapshot in a
|
|
68
101
|
C64, and otherwise takes the cartridge out and switches the machine off
|
|
69
102
|
and on.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
class AddressBus
|
|
5
|
+
# The BASIC, character and KERNAL ROMs, and which KERNAL is fitted.
|
|
6
|
+
module ROMs
|
|
7
|
+
# The KERNAL ROMs a machine can be fitted with, by name: the C64's
|
|
8
|
+
# and the SX-64's.
|
|
9
|
+
KERNALS = { c64: "kernal.rom", sx64: "kernal-sx64.rom" }.freeze
|
|
10
|
+
|
|
11
|
+
attr_reader :basic_rom, :character_rom, :kernal_rom, :kernal
|
|
12
|
+
|
|
13
|
+
# Fits the KERNAL ROM KERNALS names `name`, in place of the one before.
|
|
14
|
+
def kernal=(name)
|
|
15
|
+
raise ArgumentError, "no KERNAL named #{name}" unless KERNALS.key?(name)
|
|
16
|
+
|
|
17
|
+
@kernal = name
|
|
18
|
+
@kernal_rom = ROM.load(KERNALS[name], 0xe000)
|
|
19
|
+
update_overlays!
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def load_roms
|
|
25
|
+
@basic_rom = ROM.load("basic.rom", 0xa000)
|
|
26
|
+
@character_rom = ROM.load("character.rom", 0xd000)
|
|
27
|
+
@kernal = :c64
|
|
28
|
+
@kernal_rom = ROM.load(KERNALS[:c64], 0xe000)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
data/lib/badline/address_bus.rb
CHANGED
|
@@ -4,6 +4,7 @@ require "badline/address_bus/saved_state"
|
|
|
4
4
|
require "badline/address_bus/sid_slots"
|
|
5
5
|
require "badline/address_bus/extra_sids"
|
|
6
6
|
require "badline/address_bus/ultimax_pages"
|
|
7
|
+
require "badline/address_bus/roms"
|
|
7
8
|
|
|
8
9
|
module Badline
|
|
9
10
|
# Memory layout:
|
|
@@ -35,6 +36,7 @@ module Badline
|
|
|
35
36
|
include Addressable
|
|
36
37
|
include UltimaxPages
|
|
37
38
|
include ExtraSIDs
|
|
39
|
+
include ROMs
|
|
38
40
|
|
|
39
41
|
# I/O 1 and 2, and the Ultimax holes, with nothing on the bus. A read
|
|
40
42
|
# picks up the byte the VIC fetched in the preceding phi1 half-cycle,
|
|
@@ -58,7 +60,7 @@ module Badline
|
|
|
58
60
|
# See doc/pinned-behaviour.md.
|
|
59
61
|
RAM_POWER_ON = Array.new(2**16) { |addr| (((addr + 2) / 4) ^ (addr / 0x4000)).odd? ? 0xff : 0x00 }.freeze
|
|
60
62
|
|
|
61
|
-
attr_reader :io_port, :ram,
|
|
63
|
+
attr_reader :io_port, :ram,
|
|
62
64
|
:vic, :sid, :color_ram, :cia1, :cia2, :keyboard, :joystick1, :joystick2,
|
|
63
65
|
:control_ports, :cartridge, :ultimax, :phi1_ultimax, :datasette, :region, :video_ram, :reu
|
|
64
66
|
|
|
@@ -71,9 +73,7 @@ module Badline
|
|
|
71
73
|
@cartridge = @reu = nil
|
|
72
74
|
@debug_register = nil
|
|
73
75
|
|
|
74
|
-
|
|
75
|
-
@character_rom = ROM.load("character.rom", 0xd000)
|
|
76
|
-
@kernal_rom = ROM.load("kernal.rom", 0xe000)
|
|
76
|
+
load_roms
|
|
77
77
|
|
|
78
78
|
@keyboard = Keyboard.new
|
|
79
79
|
@joystick1 = Joystick.new
|
|
@@ -74,6 +74,30 @@ module Badline
|
|
|
74
74
|
settle
|
|
75
75
|
end
|
|
76
76
|
|
|
77
|
+
# The rig between frames: the bus and its chips, the extra SIDs, the
|
|
78
|
+
# CPU, and the call waiting for the idle loop.
|
|
79
|
+
def save_state(out)
|
|
80
|
+
out.marker("BARE PLAYER")
|
|
81
|
+
@bus.save_state(out)
|
|
82
|
+
@extras.each { |sid| sid.save_state(out) }
|
|
83
|
+
@cpu.save_state(out)
|
|
84
|
+
out.optional_int(@pending).int(@argument).boolean(@idle)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Takes a rig that hasn't started to where #save_state found one, in
|
|
88
|
+
# place of #start.
|
|
89
|
+
def load_state(input)
|
|
90
|
+
input.marker("BARE PLAYER")
|
|
91
|
+
@bus.load_state(input)
|
|
92
|
+
@extras.each { |sid| sid.load_state(input) }
|
|
93
|
+
@cpu.load_state(input)
|
|
94
|
+
@pending = input.optional_int
|
|
95
|
+
@argument = input.int
|
|
96
|
+
@idle = input.boolean?
|
|
97
|
+
@stereo.synthesize!
|
|
98
|
+
install_dispatch
|
|
99
|
+
end
|
|
100
|
+
|
|
77
101
|
# Advances one call of play, or `budget` cycles if that is shorter,
|
|
78
102
|
# then yields whatever the SIDs recorded over it, in stereo. Returns
|
|
79
103
|
# the cycles advanced.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Audio
|
|
5
|
+
# The states a subtune's renderer saved as it played, at the first
|
|
6
|
+
# frame end past every `every` seconds, so that a seek starts from the
|
|
7
|
+
# latest one at or before where it goes rather than from the subtune's
|
|
8
|
+
# start. Whoever plays the subtune keeps them across its renderers, and
|
|
9
|
+
# drops them for another subtune.
|
|
10
|
+
class Checkpoints
|
|
11
|
+
EVERY = 10.0
|
|
12
|
+
|
|
13
|
+
def initialize(every: EVERY)
|
|
14
|
+
@every = every
|
|
15
|
+
@cycles = []
|
|
16
|
+
@states = []
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Whether the frame ending `cycles` into the subtune is the first past
|
|
20
|
+
# the next mark.
|
|
21
|
+
def due?(cycles, clock_hz) = cycles >= ((@cycles.length + 1) * @every * clock_hz).round
|
|
22
|
+
|
|
23
|
+
def keep(cycles, state)
|
|
24
|
+
@cycles << cycles
|
|
25
|
+
@states << state
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# The state saved latest at or before `cycles`, or nil.
|
|
29
|
+
def latest(cycles)
|
|
30
|
+
index = @cycles.rindex { |at| at <= cycles }
|
|
31
|
+
index.nil? ? nil : @states[index]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# The cycles into the subtune of the state saved latest at or before
|
|
35
|
+
# `cycles`, or 0 for the start.
|
|
36
|
+
def reach(cycles)
|
|
37
|
+
index = @cycles.rindex { |at| at <= cycles }
|
|
38
|
+
index.nil? ? 0 : @cycles[index]
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|