badline 0.10.1 → 0.11.1
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 +23 -0
- data/CLAUDE.md +25 -6
- data/CONTRIBUTING.md +8 -3
- data/README.md +63 -4
- data/doc/pinned-behaviour.md +75 -0
- data/doc/snapshots.md +15 -0
- data/lib/badline/address_bus/pla.rb +3 -16
- data/lib/badline/address_bus.rb +14 -0
- data/lib/badline/c128/banks.rb +35 -0
- data/lib/badline/c128/bus.rb +347 -0
- data/lib/badline/c128/bus_state.rb +53 -0
- data/lib/badline/c128/color_lines.rb +39 -0
- data/lib/badline/c128/cpu.rb +10 -0
- data/lib/badline/c128/drives.rb +95 -0
- data/lib/badline/c128/fast_serial.rb +62 -0
- data/lib/badline/c128/keys.rb +35 -0
- data/lib/badline/c128/mmu.rb +197 -0
- data/lib/badline/c128/mmu_pages.rb +105 -0
- data/lib/badline/c128/model.rb +39 -0
- data/lib/badline/c128/modes.rb +48 -0
- data/lib/badline/c128/saved_state.rb +121 -0
- data/lib/badline/c128/vdc/memory.rb +54 -0
- data/lib/badline/c128/vdc/painter.rb +143 -0
- data/lib/badline/c128/vdc/raster.rb +97 -0
- data/lib/badline/c128/vdc/window.rb +215 -0
- data/lib/badline/c128/vdc.rb +268 -0
- data/lib/badline/c128.rb +322 -0
- data/lib/badline/chrout_trap.rb +3 -0
- data/lib/badline/cia/fast_forward.rb +42 -0
- data/lib/badline/cia/serial.rb +12 -0
- data/lib/badline/cia/timer.rb +39 -0
- data/lib/badline/cia.rb +2 -0
- data/lib/badline/computer/attachments.rb +10 -13
- data/lib/badline/computer/kernal_traps.rb +29 -0
- data/lib/badline/computer.rb +5 -0
- data/lib/badline/drive/core.rb +172 -0
- data/lib/badline/{drive1541 → drive}/idle.rb +18 -19
- data/lib/badline/drive/idle_cpu.rb +28 -0
- data/lib/badline/{drive1541 → drive}/orbit.rb +2 -1
- data/lib/badline/drive/serial_lines.rb +73 -0
- data/lib/badline/{drive1541 → drive}/sleep.rb +4 -3
- data/lib/badline/drive/watch.rb +150 -0
- data/lib/badline/drive.rb +9 -0
- data/lib/badline/drive1541/bus.rb +5 -129
- data/lib/badline/drive1541/byte_ready.rb +48 -0
- data/lib/badline/drive1541/cpu.rb +1 -19
- data/lib/badline/drive1541/disk.rb +77 -20
- data/lib/badline/drive1541/disk_state.rb +7 -2
- data/lib/badline/drive1541/disk_via.rb +3 -0
- data/lib/badline/drive1541/mechanism.rb +48 -14
- data/lib/badline/drive1541/mechanism_state.rb +5 -4
- data/lib/badline/drive1541/rotation.rb +5 -5
- data/lib/badline/drive1541/serial_port.rb +4 -60
- data/lib/badline/drive1541.rb +13 -172
- data/lib/badline/drive1571/bus.rb +111 -0
- data/lib/badline/drive1571/cpu.rb +11 -0
- data/lib/badline/drive1571/serial_port.rb +37 -0
- data/lib/badline/drive1571/serial_via.rb +25 -0
- data/lib/badline/drive1571/wd1770.rb +34 -0
- data/lib/badline/drive1571.rb +225 -0
- data/lib/badline/frontend/app.rb +35 -22
- data/lib/badline/frontend/boot.rb +31 -1
- data/lib/badline/frontend/controls.rb +11 -0
- data/lib/badline/frontend/drive_led.rb +1 -1
- data/lib/badline/frontend/keys.rb +28 -1
- data/lib/badline/frontend/machine_window.rb +16 -13
- data/lib/badline/frontend/menu_media.rb +3 -3
- data/lib/badline/frontend/menu_pages.rb +8 -2
- data/lib/badline/frontend/menu_ports.rb +1 -1
- data/lib/badline/frontend/pause_menu.rb +1 -0
- data/lib/badline/frontend/screen.rb +33 -8
- data/lib/badline/frontend/screens.rb +90 -0
- data/lib/badline/frontend/timeline.rb +15 -4
- data/lib/badline/frontend.rb +1 -0
- data/lib/badline/iec_bus.rb +54 -4
- data/lib/badline/kernal_trap/file.rb +1 -1
- data/lib/badline/kernal_trap/layout.rb +58 -8
- data/lib/badline/kernal_trap/load.rb +1 -1
- data/lib/badline/kernal_trap/save.rb +1 -1
- data/lib/badline/kernal_trap/serial.rb +5 -0
- data/lib/badline/machine.rb +20 -9
- data/lib/badline/media/true_drive.rb +26 -23
- data/lib/badline/media.rb +8 -6
- data/lib/badline/options/event.rb +5 -1
- data/lib/badline/options/family.rb +52 -0
- data/lib/badline/options/help.rb +7 -2
- data/lib/badline/options/table.rb +8 -2
- data/lib/badline/options/validation.rb +14 -1
- data/lib/badline/options.rb +20 -19
- data/lib/badline/roms/README +36 -0
- data/lib/badline/roms/c128/basic.rom +0 -0
- data/lib/badline/roms/c128/character.rom +0 -0
- data/lib/badline/roms/c128/kernal.rom +0 -0
- data/lib/badline/roms/dos1571.rom +0 -0
- data/lib/badline/snapshot/container.rb +2 -0
- data/lib/badline/snapshot/image.rb +14 -0
- data/lib/badline/snapshot.rb +9 -2
- data/lib/badline/storage/d64_image.rb +3 -0
- data/lib/badline/storage/d71_image.rb +9 -4
- data/lib/badline/storage/g64_image.rb +7 -2
- data/lib/badline/time_of_day.rb +9 -0
- data/lib/badline/version.rb +1 -1
- data/lib/badline/via/fast_forward.rb +3 -3
- data/lib/badline/vic/display_state.rb +12 -0
- data/lib/badline/vic/registers.rb +3 -0
- data/lib/badline/vic.rb +108 -7
- data/lib/badline/vic20/attachments.rb +6 -0
- data/lib/badline/z80/arithmetic.rb +117 -0
- data/lib/badline/z80/bit_page.rb +55 -0
- data/lib/badline/z80/block_io.rb +58 -0
- data/lib/badline/z80/block_transfers.rb +59 -0
- data/lib/badline/z80/bus_cycles.rb +111 -0
- data/lib/badline/z80/core.rb +111 -0
- data/lib/badline/z80/exchanges.rb +50 -0
- data/lib/badline/z80/extended_page.rb +89 -0
- data/lib/badline/z80/flags.rb +37 -0
- data/lib/badline/z80/interrupt_acceptance.rb +46 -0
- data/lib/badline/z80/jumps.rb +82 -0
- data/lib/badline/z80/loads.rb +98 -0
- data/lib/badline/z80/main_page.rb +134 -0
- data/lib/badline/z80/registers.rb +120 -0
- data/lib/badline/z80/shifts.rb +64 -0
- data/lib/badline/z80.rb +11 -0
- data/lib/badline.rb +1 -0
- metadata +59 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c2e262f4dbf07ef2d84f3a5eb673302102ecc9d4a5aa3ac87a908c6f0323c041
|
|
4
|
+
data.tar.gz: 026b7b26ce4cad94cf386a4b944c4ce34d34635e8dd8a568a352090320deabd9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d99d4042bdb920cfbaa9501a2fff2a6cc155dda76518b28a58e863d95bd18ef3d891f7dff5d935cc726ae380c9659bc09f5f11f7cefda657a4926bfc06974e76
|
|
7
|
+
data.tar.gz: 670579ee105286f5b5c04aaa63d5ae6a9fee9161f6735ccd9f7764152c43e421f6024a1ba7cfead0da92a7b87cab6f03b1b53a2d2e44693a62807b4f52ab81a3
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.11.1](https://github.com/elektronaut/badline/compare/v0.11.0...v0.11.1) (2026-10-09)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* emulate the C128D's 1571 drive in 1541 and 1571 mode ([2c32d99](https://github.com/elektronaut/badline/commit/2c32d993a0449b4b537d5f82e9711b0e14604f95))
|
|
9
|
+
* fast serial between the C128 and its 1571 ([34fe02f](https://github.com/elektronaut/badline/commit/34fe02f2098664c94233da9e40828b40e41b6b1a))
|
|
10
|
+
|
|
11
|
+
## [0.11.0](https://github.com/elektronaut/badline/compare/v0.10.1...v0.11.0) (2026-10-09)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
* add the C128 in C64 mode, headless ([17462eb](https://github.com/elektronaut/badline/commit/17462ebb94b27fe59c7cee8c51e82be340158979))
|
|
17
|
+
* boot badline c128 in C128 mode, with --c64 holding C= through the reset ([fbb57e5](https://github.com/elektronaut/badline/commit/fbb57e5e46bd1178bb63b2feedee6776a5e4cc57))
|
|
18
|
+
* boot the C128 in C128 mode through its own MMU and KERNAL ([8bdd810](https://github.com/elektronaut/badline/commit/8bdd810c03cb916b3484fabbf84172098af26835))
|
|
19
|
+
* bundle the C128's BASIC 7.0, KERNAL and character ROMs ([25329f8](https://github.com/elektronaut/badline/commit/25329f83e7a5e07c4df3ea49b85528184fd7f313))
|
|
20
|
+
* follow the C128 between its 40 and 80 column screens, with 40/80 DISPLAY on F6 and ESC on Esc ([4099600](https://github.com/elektronaut/badline/commit/4099600d413fa617dc7cea63ac80302b759c9f08))
|
|
21
|
+
* give the C128's VDC its 80 column display ([80b0831](https://github.com/elektronaut/badline/commit/80b083138629c6410c18a55b48f3e59d22d466f1))
|
|
22
|
+
* run the C128 in the window as badline c128, in both builds, with its VDC, keys and snapshots ([d58eaf6](https://github.com/elektronaut/badline/commit/d58eaf606932527fda9fd5de308c4010bd9fc4cf))
|
|
23
|
+
* run the C128's 2 MHz mode and TEST bit cycle by cycle ([9a0a483](https://github.com/elektronaut/badline/commit/9a0a483f775b2d06fabb32bd99988c1976753fa3))
|
|
24
|
+
* serve device 8 and CHROUT through the C128 KERNAL's traps in C128 mode ([76c1764](https://github.com/elektronaut/badline/commit/76c1764a54d68960194126e50d228a979ace93a2))
|
|
25
|
+
|
|
3
26
|
## [0.10.1](https://github.com/elektronaut/badline/compare/v0.10.0...v0.10.1) (2026-10-08)
|
|
4
27
|
|
|
5
28
|
|
data/CLAUDE.md
CHANGED
|
@@ -49,8 +49,9 @@ requires only the namespace file.
|
|
|
49
49
|
| --- | --- | --- |
|
|
50
50
|
| rspec (`spec/`) | `bundle exec rspec` | Unit behaviour, all of `lib/` |
|
|
51
51
|
| SingleStepTests 65x02 | `rake test` (100 sampled cases per opcode) | CPU, per-cycle bus traces |
|
|
52
|
+
| SingleStepTests z80 | `rake test` (the first 100 cases per opcode, `Z80_SAMPLE=all` for all 1,604,000) | `Z80`: registers, flags, ports and the bus pins on every T-state |
|
|
52
53
|
| Wolfgang Lorenz suite | `bin/lorenz` | CPU, CIA, interrupts |
|
|
53
|
-
| VICE testbench | `bin/testbench <subtree>` | `VICII/`, `CIA/`, `interrupts/`, `CPU/`, cartridges with `--carts`, the true 1541 drive with `--drive`,
|
|
54
|
+
| VICE testbench | `bin/testbench <subtree>` | `VICII/`, `CIA/`, `interrupts/`, `CPU/`, cartridges with `--carts`, the true 1541 drive with `--drive`, the VIC-20 with `--vic20`, and the C128 in C64 mode with `--c128c64` |
|
|
54
55
|
| VICE SID testprogs | `bin/sidtests` | SID |
|
|
55
56
|
| Drive scenarios | `bin/drive_scenarios` | The true 1541 running the DOS ROM: save, format, the error channel, idle, write protect and autostart |
|
|
56
57
|
| CIA offline grids | `bundle exec rspec --tag slow spec/badline/cia` | CIA timers and shift register, against a bare CIA in about 2 min |
|
|
@@ -103,7 +104,7 @@ worktree and owns a different set of files.
|
|
|
103
104
|
- The external suites under `vendor/` are gitignored, so a new worktree has
|
|
104
105
|
only `vendor/.gitkeep`. From the worktree root, symlink the main
|
|
105
106
|
checkout's suites into it:
|
|
106
|
-
`for d in 65x02 VICE-testprogs; do ln -sfn ../../../../vendor/$d vendor/$d; done`.
|
|
107
|
+
`for d in 65x02 z80-sample VICE-testprogs; do ln -sfn ../../../../vendor/$d vendor/$d; done`.
|
|
107
108
|
The main checkout also has `vendor/OneLoad64-Games-Collection-v5`, which
|
|
108
109
|
`rake vendor:checkout` doesn't fetch. Link it the same way only for
|
|
109
110
|
`.sid` or media work. Don't re-run `rake vendor:checkout` there, and
|
|
@@ -129,12 +130,28 @@ worktree and owns a different set of files.
|
|
|
129
130
|
|
|
130
131
|
## Testing and baselines
|
|
131
132
|
|
|
132
|
-
- `rake vendor:checkout` fetches SingleStepTests
|
|
133
|
-
`vendor/`
|
|
133
|
+
- `rake vendor:checkout` fetches SingleStepTests 65x02, the Z80 sample
|
|
134
|
+
and VICE-testprogs into `vendor/`
|
|
134
135
|
- `bundle exec rspec`: line coverage is about 97%. `spec/spec_helper.rb`
|
|
135
136
|
fails a whole-suite run (every spec file, no filters) below 90%, while
|
|
136
137
|
single-file and filtered runs skip the floor. `:slow` specs are excluded
|
|
137
138
|
by default: run them with `bundle exec rspec --tag slow`
|
|
139
|
+
- CI splits the spec files into shards, plain and `:slow`, by the run times
|
|
140
|
+
in `test/spec_times.json` (`bin/spec_shard`), and holds the plain shards'
|
|
141
|
+
merged coverage to the same 90%. After adding or moving expensive specs,
|
|
142
|
+
re-record the times with `bin/spec_shard --record` (its header says how)
|
|
143
|
+
- Keep each plain example to a few hundred ms. A million cycles of a C64 or
|
|
144
|
+
a C128 cost 3 to 5 s of CPU, and about three times that under coverage,
|
|
145
|
+
so an example that boots a machine or runs more than about a million
|
|
146
|
+
cycles goes under `:slow`
|
|
147
|
+
- Don't boot per example. Restore a machine from a State taken once
|
|
148
|
+
(`spec/support/taken_once.rb`), and share one machine between examples
|
|
149
|
+
that only read it. Assert on the cheapest oracle that proves the point: a
|
|
150
|
+
register or a RAM byte over a booted screen, a bare chip over a whole
|
|
151
|
+
machine, and the fewest cycles that reach the state
|
|
152
|
+
- Before opening a pull request, run `bundle exec rspec --profile 10` (with
|
|
153
|
+
`--tag slow` for `:slow` ones) on the spec files you added or changed,
|
|
154
|
+
and hold them to that budget
|
|
138
155
|
- `rake test`: SingleStepTests, plus the Minitest tests for the regression
|
|
139
156
|
runners in `test/`. Run it for any CPU change
|
|
140
157
|
|
|
@@ -144,7 +161,7 @@ overrides that, capped by the core count, but keep the default, because
|
|
|
144
161
|
other worktrees share the machine. Whole runs at 4 shards on an M-series
|
|
145
162
|
laptop take 15 min for `testbench` (`VICII/`), 11 for `testbench-cia`, 1 for
|
|
146
163
|
`testbench-interrupts`, 37 for `testbench-irqdma`, 11 for
|
|
147
|
-
`testbench-cpu`, 2 for `testbench-carts`, about 25 for `testbench-expansions` and
|
|
164
|
+
`testbench-cpu`, 2 for `testbench-carts`, about 25 for `testbench-expansions`, under 1 for `testbench-vic20` and about 30 for `testbench-c128c64`. `sid` takes about 12 min. `lorenz` chains itself and takes
|
|
148
165
|
about 2.5 h on CI whole. `rake regression:lorenz-1` to `lorenz-4` run it as
|
|
149
166
|
four stretches of about 40 min each, and they can run side by side.
|
|
150
167
|
`test/baselines/README.md` has the full table. A killed `bin/testbench` run
|
|
@@ -196,7 +213,9 @@ the 6526A) for anything the interrupt register or the CIA model reaches; cartrid
|
|
|
196
213
|
`testbench-carts`, plus `testbench-expansions` for banking; GEO-RAM, +60K,
|
|
197
214
|
+256K, the REU or the VIC's BA line the REU follows → `testbench-expansions`; the 1541 drive, VIA or IEC bus →
|
|
198
215
|
`testbench-drive` (`bin/testbench --drive`) and `drive-scenarios` (`bin/drive_scenarios <filter>`), plus `testbench-vic20` for the VIA; the VIC-20 (`vic20/`) →
|
|
199
|
-
`testbench-vic20` (`bin/testbench --vic20`);
|
|
216
|
+
`testbench-vic20` (`bin/testbench --vic20`); the C128 (`c128.rb`, `c128/`), or
|
|
217
|
+
the VIC-IIe, CPU or PLA code it shares with the C64 → `testbench-c128c64`
|
|
218
|
+
(`bin/testbench --c128c64`); SID → `sid`, plus `sid-8580` for anything the 8580
|
|
200
219
|
model reaches (`bin/sidtests --sid 8580`). Leave the Lorenz chain to CI,
|
|
201
220
|
unless your code has a rule in `doc/pinned-behaviour.md` that names Lorenz
|
|
202
221
|
tests: the interrupt polling, CPU port and CIA timer rules. Run just the
|
data/CONTRIBUTING.md
CHANGED
|
@@ -68,12 +68,17 @@ boot the whole machine and are skipped by default. Run them with
|
|
|
68
68
|
`bundle exec rspec --tag slow`.
|
|
69
69
|
|
|
70
70
|
The CPU is verified separately against the
|
|
71
|
-
[65x02 single step tests](https://github.com/SingleStepTests/65x02)
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
[65x02 single step tests](https://github.com/SingleStepTests/65x02), and
|
|
72
|
+
the Z80 against the [Z80 ones](https://github.com/SingleStepTests/z80).
|
|
73
|
+
`rake test` checks the 65x02 fixtures out into `vendor/65x02` first,
|
|
74
|
+
which takes a moment the first time. For the Z80 it fetches only the
|
|
75
|
+
first 100 cases of each opcode's file into `vendor/z80-sample`.
|
|
76
|
+
`Z80_SAMPLE=all` checks the whole Z80 suite out into `vendor/z80`
|
|
77
|
+
(about 1.5 GB) and runs every case:
|
|
74
78
|
|
|
75
79
|
```sh
|
|
76
80
|
bundle exec rake test
|
|
81
|
+
Z80_SAMPLE=all bundle exec rake test
|
|
77
82
|
```
|
|
78
83
|
|
|
79
84
|
Check style before pushing:
|
data/README.md
CHANGED
|
@@ -13,7 +13,7 @@ are modelled at the cycle level.
|
|
|
13
13
|
It runs programs, disk and tape images, cartridges and SID tunes, and
|
|
14
14
|
the SDL2 front end supports the keyboard, joysticks, game controllers,
|
|
15
15
|
paddles and a 1351 mouse. It also runs a PAL VIC-20, as
|
|
16
|
-
`badline vic20`. See [What's emulated](#whats-emulated) for the details.
|
|
16
|
+
`badline vic20`, and the C128, in C128 mode on 40 or 80 columns and in C64 mode, as `badline c128`. See [What's emulated](#whats-emulated) for the details.
|
|
17
17
|
|
|
18
18
|
It comes in two builds of the same emulator:
|
|
19
19
|
|
|
@@ -69,7 +69,8 @@ from it.
|
|
|
69
69
|
|
|
70
70
|
The first argument can name the machine, as in `badline c64 game.prg`.
|
|
71
71
|
The C64 is the default, and `--model` picks which C64. See
|
|
72
|
-
[The VIC-20](#the-vic-20) for `badline vic20
|
|
72
|
+
[The VIC-20](#the-vic-20) for `badline vic20` and [The C128](#the-c128)
|
|
73
|
+
for `badline c128`.
|
|
73
74
|
|
|
74
75
|
`badline-ruby` takes the same media and the same options, with the
|
|
75
76
|
differences noted in the table. `--help` lists the options for either.
|
|
@@ -87,6 +88,7 @@ differences noted in the table. `--help` lists the options for either.
|
|
|
87
88
|
| `--reu SIZE` | Plug in a RAM Expansion Unit of `SIZE` K: 128, 256, 512 (a 1750) or up to 16384 |
|
|
88
89
|
| `--model NAME` | Run another model of the machine, named as in VICE. For the C64: `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), `sx64` (the portable SX-64, with its own KERNAL and no datasette), `pet64` (the PET 64 or Educator 64, a PAL C64 in a PET's case with its own KERNAL and a green monochrome monitor) `c64gs` (the C64GS games console, a PAL C64C with its own BASIC and KERNAL, and no keyboard or datasette) or `ultimax` (the MAX Machine of Japan, NTSC with 2K of RAM, one CIA and no ROMs, which runs only a cartridge). `--sid` or a `.sid` tune's own SID takes the model's place |
|
|
89
90
|
| `--ntsc` | Run an NTSC C64, as `--model ntsc` does |
|
|
91
|
+
| `--c64` | Start a C128 in C64 mode, holding `C=` at power-on. See [The C128](#the-c128) |
|
|
90
92
|
| `--no-sound` | Don't play the SID (`badline` only, where sound is on by default) |
|
|
91
93
|
| `--sound` | Play the SID (`badline-ruby`, where sound is off by default) |
|
|
92
94
|
| `--no-vsync` | Pace the window by a timer, or by the sound while it plays, instead of the display's vsync |
|
|
@@ -163,6 +165,56 @@ goes in as a `.crt` does. Disks go through the KERNAL traps or, with
|
|
|
163
165
|
save and load the VIC-20 too, in badline's own snapshots: xvic's `.vsf`
|
|
164
166
|
files don't load.
|
|
165
167
|
|
|
168
|
+
## The C128
|
|
169
|
+
|
|
170
|
+
`badline c128` runs a C128 in C128 mode, with BASIC 7.0, and takes the
|
|
171
|
+
same media as the C64:
|
|
172
|
+
|
|
173
|
+
```sh
|
|
174
|
+
badline c128 # READY., in BASIC 7.0
|
|
175
|
+
badline c128 game.prg # Load and run a program
|
|
176
|
+
badline c128 game.d64 # Mount a disk image as device 8 and LOAD"*",8,1 it
|
|
177
|
+
badline c128 --c64 # Hold C= at power-on to start in C64 mode
|
|
178
|
+
badline c128 --model c128dcr game.crt
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
`--c64` holds `C=` down through the reset, so the C128 KERNAL starts C64
|
|
182
|
+
mode, as on a real C128. A program that loads at `$0801`, where C64 BASIC
|
|
183
|
+
starts, and a `.sid` tune start C64 mode the same way, and so does a C64
|
|
184
|
+
cartridge, through the KERNAL. `GO64` gets there from BASIC 7.0. A
|
|
185
|
+
program that loads at `$1C01`, where BASIC 7.0 starts, runs, and other
|
|
186
|
+
programs load at their own address. The disk in device 8 is served
|
|
187
|
+
through the KERNAL traps in either mode, or with `--true-drive` by the
|
|
188
|
+
C128D's 1571. The C128's Z80 isn't emulated:
|
|
189
|
+
the 8502 starts the machine. `--model` picks the board: `c128` (the default, the flat C128
|
|
190
|
+
and the plastic C128D, PAL, with the 6581 SID and a VDC with 16K of
|
|
191
|
+
RAM), `c128dcr` (the metal C128DCR, with the 8580, 6526As and a VDC with
|
|
192
|
+
64K), and `c128ntsc` and `c128dcrntsc` for their NTSC versions. `--sid`
|
|
193
|
+
takes the model's place. Without `c128`, a program that loads at
|
|
194
|
+
`$1C01`, where C128 BASIC starts, picks the C128 too, and a `.d71`
|
|
195
|
+
stays on the C64.
|
|
196
|
+
|
|
197
|
+
The window shows the screen the C128 prints to, and follows it when
|
|
198
|
+
it moves: to the VDC's 80 columns after `GRAPHIC 5`, `ESC X` or a reset
|
|
199
|
+
with `40/80 DISPLAY` locked down, and back to the VIC-IIe's 40 columns
|
|
200
|
+
after `GRAPHIC 0` or `ESC X` again. In C64 mode it shows the VIC-IIe.
|
|
201
|
+
`F8` switches the window to the other screen, as a monitor's 40/80
|
|
202
|
+
switch does, until the C128 next moves. The window takes the VDC's
|
|
203
|
+
size, which its registers set, a dot to a pixel with its lines doubled.
|
|
204
|
+
Only the chip shown is drawn.
|
|
205
|
+
|
|
206
|
+
Besides the C64's keys, the C128's own keys sit on their host keys: the
|
|
207
|
+
keypad on the keypad, `HELP` on `Insert` (or `Help`), `ALT` on the right
|
|
208
|
+
`Alt`, `NO SCROLL` on `Scroll Lock`, `CAPS LOCK` on `Caps Lock` and
|
|
209
|
+
`40/80 DISPLAY` on `F6` or `Pause`, both of which lock it down and up
|
|
210
|
+
like the real key. In C128 mode `Esc` is `ESC` and `RUN/STOP` is on
|
|
211
|
+
`Page Down` (`Fn`-`Down` on a Mac), and in C64 mode `Esc` stays
|
|
212
|
+
`RUN/STOP`. In C64 mode only a program that scans the C128's keys
|
|
213
|
+
itself sees them. `TAB`, `LINE FEED` and the separate cursor keys have
|
|
214
|
+
no host key yet: `Tab` and the arrows keep their C64 uses.
|
|
215
|
+
`F11`, `F12` and the pause menu save and load the C128 in badline's own
|
|
216
|
+
snapshots, and x128's `.vsf` files don't load.
|
|
217
|
+
|
|
166
218
|
## Snapshots
|
|
167
219
|
|
|
168
220
|
`F11` quicksaves the whole machine to the next of five slots in
|
|
@@ -200,7 +252,7 @@ types `"`. These keys have no same-named host key:
|
|
|
200
252
|
|
|
201
253
|
| C64 | Host |
|
|
202
254
|
|-----|------|
|
|
203
|
-
| `RUN/STOP` | `Escape` |
|
|
255
|
+
| `RUN/STOP` | `Escape`, or on the C128 `Page Down` (`Esc` is `ESC` in C128 mode) |
|
|
204
256
|
| `CLR/HOME` | `Home` |
|
|
205
257
|
| `INST/DEL` | `Backspace` |
|
|
206
258
|
| `CRSR ⇔` / `CRSR ⇕` | `Right` / `Down`, and `Left` / `Up` for the shifted directions |
|
|
@@ -258,7 +310,7 @@ too.
|
|
|
258
310
|
| Expansion port | The cartridge: insert, remove, and its freeze button if it has one |
|
|
259
311
|
| Ports | The device in each control port, and where the keys go |
|
|
260
312
|
| Sound | Mute, and the SID's model |
|
|
261
|
-
| Power | Reset, power cycle and quit |
|
|
313
|
+
| Power | Reset, power cycle and quit, and on a C128 its model and mode |
|
|
262
314
|
|
|
263
315
|
INSERT opens a file browser. A disk's set is the `.m3u` or `.vfl` list it
|
|
264
316
|
was opened from, or one in its folder that lists it. Without one, it comes
|
|
@@ -294,7 +346,14 @@ program or `.sid` dropped on it opens the menu to ask first.
|
|
|
294
346
|
both 6522 VIAs, the keyboard, the joystick and RESTORE, RAM
|
|
295
347
|
expansions up to 35K (`--ram`), cartridges, the datasette and the
|
|
296
348
|
serial bus to device 8 (`badline vic20`).
|
|
349
|
+
- **C128**: C128 mode with BASIC 7.0 and C64 mode, on the 8502 with its
|
|
350
|
+
port, FAST mode, the VIC-IIe with its extra keyboard lines, the 8722
|
|
351
|
+
MMU, the 8563 or 8568 VDC with its 80 column display, and 128K of RAM
|
|
352
|
+
(`badline c128`). The Z80 isn't emulated yet.
|
|
297
353
|
- **1541**: an emulated drive running its own DOS (`--true-drive`).
|
|
354
|
+
- **1571**: the C128D's drive running DOS 3.0, in 1541 mode and in 1571
|
|
355
|
+
mode at 2 MHz with both sides of a `.d71` or `.g71`, and fast serial
|
|
356
|
+
(burst) to a C128 in C128 mode (`badline c128 --true-drive`).
|
|
298
357
|
- **Cartridges**: standard 8K, 16K and Ultimax, Simons' BASIC, Ocean,
|
|
299
358
|
Fun Play / Power Play, Super Games, Epyx FastLoad, Westermann
|
|
300
359
|
Learning, Rex Utility, C64 Game System / System 3, Dinamic, Zaxxon /
|
data/doc/pinned-behaviour.md
CHANGED
|
@@ -25,6 +25,7 @@ only catches the rows that happen to move.
|
|
|
25
25
|
- [VIC phi1 bus](#vic-phi1-bus)
|
|
26
26
|
- [VIC light pen](#vic-light-pen)
|
|
27
27
|
- [VIC-II 8565](#vic-ii-8565)
|
|
28
|
+
- [VIC-IIe 2 MHz and TEST bit](#vic-iie-2-mhz-and-test-bit)
|
|
28
29
|
- [VIC-II NTSC](#vic-ii-ntsc)
|
|
29
30
|
- [VIC-II 6572 (Drean)](#vic-ii-6572-drean)
|
|
30
31
|
- [CIA 6526 timer pipeline](#cia-6526-timer-pipeline)
|
|
@@ -926,6 +927,80 @@ What the 8565 references don't settle, and so what stays as it is:
|
|
|
926
927
|
6569's idle access, without the 6569's `$38ff` read where a DMA delay
|
|
927
928
|
starts.
|
|
928
929
|
|
|
930
|
+
## VIC-IIe 2 MHz and TEST bit
|
|
931
|
+
|
|
932
|
+
The C128's VIC-IIe (`:mos8566`, `:mos8564`) adds $D030: bit 0 (FAST)
|
|
933
|
+
runs the 8502 at 2 MHz, and bit 1 (TEST) clocks the raster counter in
|
|
934
|
+
every cycle. `C128#cycle!` and `#clock_fast` drive both, through
|
|
935
|
+
`VIC#take_cpu_bus`, `#test_step!` and `#refresh_cycle?`. The oracles are
|
|
936
|
+
the testprogs' own references for `c128/2mhzVIC` (3 rows, from the
|
|
937
|
+
author's machine) and `c128/d030tester` (33 rows), and the real-machine
|
|
938
|
+
photos in `c128/2mhztest`. Those are C128-mode programs that switch to C64
|
|
939
|
+
mode as they start, so no testbench list runs them yet: `spec/badline/
|
|
940
|
+
c128_2mhz_spec.rb` runs six d030tester builds from their machine code at
|
|
941
|
+
$1C0E and checks the readings they print.
|
|
942
|
+
|
|
943
|
+
- FAST and TEST take hold in the second cycle after the write that sets
|
|
944
|
+
or clears them. Pinned by d030tester's "Lines cut": STA/STX $D030 keeps
|
|
945
|
+
TEST on for 4 cycles, but for 3 when the STA also sets FAST, because
|
|
946
|
+
the STX then runs its operand fetches at 2 MHz. With the delay at 0
|
|
947
|
+
the FAST builds cut 2 lines, not 3. Spec guard: `c128_spec.rb`.
|
|
948
|
+
- In FAST mode the CPU runs in both halves of every cycle but Bauer's
|
|
949
|
+
refresh cycles 11-15, whose phi1 stays with the VIC: 121 CPU cycles a
|
|
950
|
+
PAL line. BA doesn't halt it. Pinned by `2mhz-vic-hires`,
|
|
951
|
+
`-multicolor` and `-extended`, whose drawing code assumes 121 cycles a
|
|
952
|
+
line.
|
|
953
|
+
- An access to $D000-$DFFF waits for phi2: one in phi1 takes the whole
|
|
954
|
+
cycle. Pinned by `timing-change0`, whose `INC $D020` takes 8 half
|
|
955
|
+
cycles (its comment says "6 cycles + 2"). The machine finds out after
|
|
956
|
+
the CPU's step that it reached I/O, so `CPU::Core` needn't say where
|
|
957
|
+
its next access goes.
|
|
958
|
+
- The VIC's accesses in a FAST cycle latch the CPU's bytes: the g-access,
|
|
959
|
+
or idle access, the byte of phi1, and a c-access the byte of phi2, as
|
|
960
|
+
one made before AEC does on the C64: $FF for the video matrix and the
|
|
961
|
+
byte's low nibble for colour. Pinned by `2mhz-vic-*` (the operands are
|
|
962
|
+
the pixels and the opcodes' low nibbles the colours) and by the "VIC
|
|
963
|
+
internal data" row of d030tester, which shows char $FF's glyph in
|
|
964
|
+
slow-mode lines after a FAST bad line.
|
|
965
|
+
- A c-access in a cycle where the CPU reads or writes a VIC register
|
|
966
|
+
takes that byte for the video matrix as well. Pinned by d030tester:
|
|
967
|
+
`STX $D030` with X=0 leaves an `@` (McCabe's readme: "the `@`
|
|
968
|
+
represents a 0 written to $D030"), and the `DEC $D030` build (2mhzdec)
|
|
969
|
+
leaves char $FD, the byte it reads.
|
|
970
|
+
- In the phi1 an I/O access waits through, the VIC sees the byte the CPU
|
|
971
|
+
writes, or the last byte the bus held for a read. Pinned by d030tester
|
|
972
|
+
and 2mhzdec, whose g-access there shows $00 (X) and $D0 (the operand's
|
|
973
|
+
high byte).
|
|
974
|
+
- AEC can't follow BA down in FAST mode, so on a bad line it falls three
|
|
975
|
+
cycles after the last FAST cycle, and the c-accesses before it read
|
|
976
|
+
$FF and the halted CPU's nibble (`DisplayState#keep_bus`). Pinned by
|
|
977
|
+
d030tester's "VIC internal data" row, where three cells after the FAST
|
|
978
|
+
cycles show colour 0 (the halted read's $D0) and the rest the screen.
|
|
979
|
+
- The TEST bit steps the raster counter ahead of each cycle it is set
|
|
980
|
+
in, except the line's last cycle, which steps it anyway, and the step
|
|
981
|
+
from the frame's last line to line 0 takes two cycles. Pinned by
|
|
982
|
+
d030tester: TEST across the line end (`32c_02_00`, `32c_03_00`) cuts
|
|
983
|
+
one line fewer, and the frame it keeps 312 lines long with two TEST
|
|
984
|
+
windows of a whole frame each reads 19656 cycles ($4CC8) only with the
|
|
985
|
+
two-cycle wrap. A step into a bad line's raster halts the CPU through
|
|
986
|
+
BA for the one cycle the raster matches: `2ae_02_00` and `2ed_02_00`
|
|
987
|
+
cut 5 lines for 4 cycles. Spec guard: `vic_iie_spec.rb`.
|
|
988
|
+
- The beam doesn't follow the raster counter's steps: it draws the next
|
|
989
|
+
display line after the last one (`VIC#output_line`), so the lines TEST
|
|
990
|
+
skips move the picture up, until a line that ends in the vertical sync
|
|
991
|
+
(PAL lines 303-305, three lines from the fourth blanked one) puts the
|
|
992
|
+
beam back on the raster line. A blanked line the beam draws off the
|
|
993
|
+
raster line shows black. Pinned by d030tester's `vadjust` builds, which
|
|
994
|
+
move the picture up a line per cycle of TEST, `vadjust1` included,
|
|
995
|
+
where the first window leaves the raster counter on line 304, and by
|
|
996
|
+
the colour bar that `173_02_00` draws four lines taller.
|
|
997
|
+
- Not matched: the d030tester references come from an emulator that
|
|
998
|
+
models PAL decoding. A line cut an odd number of times flips the colour
|
|
999
|
+
phase, so every row below it shows other hues (all 11 builds whose cut
|
|
1000
|
+
is odd), and lines drawn while TEST runs show alternating hues and
|
|
1001
|
+
per-cycle blanking. Their 8566 shows no grey dots. The 2mhzVIC
|
|
1002
|
+
references have none either.
|
|
1003
|
+
|
|
929
1004
|
## VIC-II NTSC
|
|
930
1005
|
|
|
931
1006
|
The 6567R8 (`Region::NTSC`) and the 6567R56A (`Region::NTSC_OLD`) run
|
data/doc/snapshots.md
CHANGED
|
@@ -80,6 +80,21 @@ it, and badline doesn't open xvic's. Restoring a
|
|
|
80
80
|
VIC-20 snapshot while a C64 runs, or a C64 one while a VIC-20 runs,
|
|
81
81
|
swaps the machine in the window.
|
|
82
82
|
|
|
83
|
+
## The C128
|
|
84
|
+
|
|
85
|
+
`badline c128` saves and restores the same way too. A C128 snapshot
|
|
86
|
+
holds its 128K of RAM, both colour RAM banks, the CPU port, the MMU's
|
|
87
|
+
registers and the page pointer writes it holds, the VIC-IIe, both CIAs,
|
|
88
|
+
the SID, the VDC with its RAM and registers, the CPU, a cartridge, the
|
|
89
|
+
tape, the disk device 8 serves through the traps and a true 1541, and
|
|
90
|
+
restores into a C128 of the same model with the same SID, built for the
|
|
91
|
+
same mode. The VDC's picture is left out and painted again while the
|
|
92
|
+
window shows it, and the window shows the VIC-IIe after a restore. Its
|
|
93
|
+
file names its machine `C128`, as x128's do, and holds only the
|
|
94
|
+
`BADLINE` module, so x128 doesn't open it, and badline doesn't open
|
|
95
|
+
x128's. Restoring a C128 snapshot while another machine runs swaps the
|
|
96
|
+
machine in the window, as for the VIC-20.
|
|
97
|
+
|
|
83
98
|
## VICE
|
|
84
99
|
|
|
85
100
|
Snapshots use VICE's `.vsf` format. badline writes VICE's modules for
|
|
@@ -5,8 +5,9 @@ module Badline
|
|
|
5
5
|
# The C64's PLA: what each page of the CPU's view maps to, from the
|
|
6
6
|
# CPU port's LORAM, HIRAM and CHAREN lines and the cartridge's EXROM
|
|
7
7
|
# and GAME. The bus that includes it supplies the page tables, the
|
|
8
|
-
# ROMs, the chips,
|
|
9
|
-
# ROMs, the cartridge and I/O map over
|
|
8
|
+
# ROMs, the chips, #map_ram_pages, which lays out the RAM that the
|
|
9
|
+
# ROMs, the cartridge and I/O map over, and #map_io_pages, which lays
|
|
10
|
+
# out the chips at $D000-$DFFF, with #map_cartridge_io for I/O 1 and 2.
|
|
10
11
|
module PLA
|
|
11
12
|
# A chip's registers seen at another page, which reads and writes
|
|
12
13
|
# them as at the page the chip starts at.
|
|
@@ -108,20 +109,6 @@ module Badline
|
|
|
108
109
|
@write_pages.fill(bank, first_page, 0x20) if bank.is_a?(Cartridge::RAMBank)
|
|
109
110
|
end
|
|
110
111
|
|
|
111
|
-
def map_io_pages
|
|
112
|
-
{
|
|
113
|
-
vic => 0xd0..0xd3, sid => 0xd4..0xd7, color_ram => 0xd8..0xdb,
|
|
114
|
-
cia1 => 0xdc..0xdc, cia2 => 0xdd..0xdd, @open_bus => 0xde..0xdf
|
|
115
|
-
}.each do |chip, pages|
|
|
116
|
-
pages.each { |p| @read_pages[p] = @write_pages[p] = chip }
|
|
117
|
-
end
|
|
118
|
-
@ram_expansion.map_io(@read_pages, @write_pages)
|
|
119
|
-
@read_pages[0xd7] = @write_pages[0xd7] = @debug_register if @debug_register
|
|
120
|
-
@read_pages[0xdf] = @write_pages[0xdf] = @reu if @reu
|
|
121
|
-
map_cartridge_io if @cartridge
|
|
122
|
-
map_extra_sids unless @sid_slots.empty?
|
|
123
|
-
end
|
|
124
|
-
|
|
125
112
|
def map_cartridge_io
|
|
126
113
|
@write_pages.fill(@cartridge, 0xde, 2)
|
|
127
114
|
@cartridge.readable_io_pages.each { |p| @read_pages[p] = @cartridge }
|
data/lib/badline/address_bus.rb
CHANGED
|
@@ -217,5 +217,19 @@ module Badline
|
|
|
217
217
|
def map_ram_pages
|
|
218
218
|
@ram_expansion.map(@read_pages, @write_pages)
|
|
219
219
|
end
|
|
220
|
+
|
|
221
|
+
def map_io_pages
|
|
222
|
+
{
|
|
223
|
+
vic => 0xd0..0xd3, sid => 0xd4..0xd7, color_ram => 0xd8..0xdb,
|
|
224
|
+
cia1 => 0xdc..0xdc, cia2 => 0xdd..0xdd, @open_bus => 0xde..0xdf
|
|
225
|
+
}.each do |chip, pages|
|
|
226
|
+
pages.each { |p| @read_pages[p] = @write_pages[p] = chip }
|
|
227
|
+
end
|
|
228
|
+
@ram_expansion.map_io(@read_pages, @write_pages)
|
|
229
|
+
@read_pages[0xd7] = @write_pages[0xd7] = @debug_register if @debug_register
|
|
230
|
+
@read_pages[0xdf] = @write_pages[0xdf] = @reu if @reu
|
|
231
|
+
map_cartridge_io if @cartridge
|
|
232
|
+
map_extra_sids unless @sid_slots.empty?
|
|
233
|
+
end
|
|
220
234
|
end
|
|
221
235
|
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
class C128
|
|
5
|
+
# The RAM the C128 KERNAL's bank numbers 0-15 reach, as its INDFET and
|
|
6
|
+
# INDSTA reach it for LOAD, SAVE and the file name: the RAM bank of the
|
|
7
|
+
# CR value the KERNAL's table at $F7F0 holds for the bank, with common
|
|
8
|
+
# RAM in bank 0. The ROMs and I/O some of those CR values map are left
|
|
9
|
+
# out.
|
|
10
|
+
class Banks
|
|
11
|
+
CONFIGURATIONS = 0xf7f0
|
|
12
|
+
|
|
13
|
+
def initialize(ram, mmu, kernal_rom)
|
|
14
|
+
@ram = ram
|
|
15
|
+
@mmu = mmu
|
|
16
|
+
@kernal_rom = kernal_rom
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def peek(bank, addr) = @ram.peek(physical(bank, addr))
|
|
20
|
+
|
|
21
|
+
def write(bank, addr, bytes)
|
|
22
|
+
bytes.each_with_index { |byte, i| @ram.poke(physical(bank, (addr + i) & 0xffff), byte) }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def physical(bank, addr)
|
|
28
|
+
page = addr >> 8
|
|
29
|
+
common = page < @mmu.common_low_pages || page >= @mmu.common_high_start
|
|
30
|
+
ram_bank = common ? 0 : (@kernal_rom.peek(CONFIGURATIONS + (bank & 0x0f)) >> 6) & 0x01
|
|
31
|
+
(ram_bank << 16) | addr
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|