27 KiB
The $DF00 strap option, exercised
Note: the two probe weaknesses in section 8 have since been closed. The probe now uses two patterns and requires both to read back, and
aciaPageLatch$E5BFlatches the page so that it is decided once per cold start instead of on every link open and every rate change - the two of the three hardenings section 8 suggested.hardenReport.mdmeasures both. One further change since: the$DF00fallback now reads that page's control register before it writes a probe pattern into it, so a cartridge on this strap has its own settings adopted rather than the open bus's (portCompatReport.mdsection 9.1,testReport.mdsection 11.6). The run below is left as it was taken.Note on addresses. This report records a run made before the probe-hardening pass, which relocated six internal helpers. Addresses quoted below are the ones those routines had at the time of the run. See
ADDRESS_CHANGES.mdfor the mapping onto the current source.
A SwiftLink has a jumper that moves its 6551 from I/O1 ($DE00) to I/O2 ($DF00), and a C64
Ultimate's SwiftLink emulation can be configured either way. The module probes $DE00 first and
falls back to $DF00, but every run in testReport.md, realtimeReport.md and hotkeyReport.md
answered at $DE00 on the first try, so the second half of aciaDetect had never executed.
That is the loose end this report closes.
Everything below was observed in VICE 3.7.1 (x64sc) on 2026-08-22, against
../Modem_Wars_SwiftLink.d64 built from the current source with ./build.sh
(checkAbi.py: 452 of 4096 bytes changed in 24 regions, ABI CHECK PASSED). Nothing is inferred
from the source alone unless it says so. As in every earlier session, each run picked its own X
display, its own TCP ports and its own VICE config file, and only processes these scripts started
were killed.
Short answer:
- The fallback works. With the cartridge at
$DF00the probe writes$1Eto$DE03, reads back something that is not$1E, re-aims the six accessors at$DF00, and every subsequent access in an 800-stop watchpoint log lands on$DF00-$DF03. All six accessor operands read$DFat run time and the module image on disk still says$DE. - The game behaves identically. Same options menu, same module load, same
"PICK UP PHONE THEN PRESS SPACE." prompt, same
$E000jump table, same Hayes string on the wire. - Two machines at
$DF00link and carry real ARQ frames. Both reached connection phase 3; at true C64 speed 300 baud gave 29.62 and 28.99 bytes/s with 599 and 682 frame lead bytes and zero link errors, and 2400 baud gave 8.98 bytes/s each way with no transmitter deadlock. A warp run got as far as the side-0/side-1 negotiation with a setup-overlay disk load over the live link. - Nothing else in the game touches the page. Two static passes over every image the C64 loads
find exactly one instruction that can reach
$DF00-$DFFF, and it is the stock driver'ssta $DF59,y, which this build does not contain. A watchpoint on$DE04-$DEFFand$DF04-$DFFF- the register mirrors - never fired in any run.
- Two things about the probe are worth knowing before trusting it on hardware, and neither is a
regression: the read of an empty
$DE00is open bus and is not deterministic, and the probe re-runs on every link open and every baud hot key. Section 8.
1. How the rig was pointed at the other base
x64sc takes -acia1base 0xDF00 and accepts it: the monitor's io command then reports
Swiftlink:
>C:df00 00 30 00 00
and reads of $DE00-$DE07, $DF40-$DF47 and $DFFC-$DFFF all return open bus. VICE maps only
the four bytes $DF00-$DF03 - it does not emulate the register mirrors a real cartridge has, which
matters for how section 7's tripwire has to be read. (probeBankOut.py.)
The rig learned the strap rather than having it hard-coded. viceHarness.py gained
ACIA_BASE = int(os.environ.get("SWIFTLINK_ACIA_BASE", "0xDE00"), 16)
and aciaArgs() defaults its base to it; testBoot.py, testModemSelect.py and testRealtime.py
now build their monitor commands from ACIA_BASE instead of the literal de00. The default is
unchanged, so every command line in the earlier reports still means what it meant. A $DF00 run
is the same command with SWIFTLINK_ACIA_BASE=0xDF00 in front of it.
| run | command |
|---|---|
| boot | SWIFTLINK_ACIA_BASE=0xDF00 python3 testBoot.py ../Modem_Wars_SwiftLink.d64 strapDf00Boot |
| modem select | SWIFTLINK_ACIA_BASE=0xDF00 python3 testModemSelect.py ../Modem_Wars_SwiftLink.d64 strapSelectDf00 |
| probe + mirrors | SWIFTLINK_ACIA_BASE=0xDF00 python3 testStrap.py ../Modem_Wars_SwiftLink.d64 strapDf00 |
| two machines, true speed | SWIFTLINK_ACIA_BASE=0xDF00 python3 testRealtime.py ../Modem_Wars_SwiftLink.d64 60 300 strapdf 1 1 |
| two machines, mirrors armed | SWIFTLINK_ACIA_BASE=0xDF00 python3 testStrapPair.py ../Modem_Wars_SwiftLink.d64 150 |
testStrap.py is new: it watches both pages at once, which is what makes the fallback visible
rather than merely plausible.
2. The probe takes the fallback
testStrap.py arms four watchpoint pairs before the module can touch anything - $DE00-$DE03,
$DF00-$DF03, $DE04-$DEFF, $DF04-$DFFF - and then answers the modem prompts. These are the
first six stops of the run, verbatim from testLogs/strapDf00.hits.txt:
#1 (Stop on store de03)
.C:e567 8D 03 DE STA $DE03 - A:1E X:00 Y:24 SP:ed ..-..... 200460609
#5 (Stop on load de03)
.C:e56b AD 03 DE LDA $DE03 - A:00 X:00 Y:24 SP:ed ..-...Z. 200460625
#2 (Stop on store df03)
.C:e567 8D 03 DF STA $DF03 - A:15 X:00 Y:24 SP:ef ..-..... 200460709
#6 (Stop on load df00)
.C:e55f AD 00 DF LDA $DF00 - A:00 X:00 Y:24 SP:ef ..-...Z. 200460828
#6 (Stop on load df01)
.C:e558 AD 01 DF LDA $DF01 - A:50 X:00 Y:24 SP:f1 ..-..... 200460841
#2 (Stop on store df02)
.C:e554 8D 02 DF STA $DF02 - A:09 X:00 Y:24 SP:f3 ..-..... 200460975
Read it against aciaDetect $E644:
LDA #$DE/JSR aciaSetPageaims all six accessors at$DE00;aciaProbe$E6F2writes its pattern$1EthroughaciaCtrlWrite- and the instruction at$E567is disassembled asSTA $DE03, so the self-modified operand really did still say$DE.aciaCtrlReadat$E56Breads it back and gets$00.CMP #$1Efails,Z = 0,BEQis not taken, andLDA #$DF/JSR aciaSetPagere-aims the accessors. The fallback is taken.- The very next access is
STA $DF03withA = $15from the same instruction at$E567- now disassembled asSTA $DF03. That isloadBaudParameterswriting the real control byte: 8N1, internal baud rate generator, 300 baud on a SwiftLink. LDA $DF00drains the receiver,LDA $DF01reads the status ($50), andSTA $DF02writes command$09- DTR on, RTS low, receiver interrupt on, transmit interrupt off.
That is exactly the opening sequence testReport.md section 3 recorded at $DE00, with one probe
failure in front of it and every register three pages higher.
The link was opened twice in that run - the script offers A and space repeatedly until the ACIA is
touched, so configureUserPortLines ran a second time - and the second probe read returned $FF
where the first returned $00. Same decision, different floating byte; see section 8.
Nothing else ever touched the $DE00 page. Over the whole 800-stop log:
| range | stops | what they were |
|---|---|---|
$DE03 store |
2 | the probe pattern $1E, once per link open |
$DE03 load |
2 | the probe read-back: $00, then $FF |
$DE00, $DE01, $DE02 |
0 | - |
$DF03 store |
2 | control $15, once per link open |
$DF02 store |
387 | command $09 / $05 as the transmitter is armed and disarmed |
$DF01 load |
203 | status reads, which are also the NMI acknowledge |
$DF00 store |
202 | transmitted characters |
$DF00 load |
2 | the receiver drain in configureUserPortLines |
$DE04-$DEFF, $DF04-$DFFF |
0 | the mirrors - see section 7 |
3. The six accessors end up pointing at $DF00
aciaSetPage $E663 patches the operand high byte of all six one-instruction accessors. Those six
bytes are the driver's entire record of where the hardware is. Read back through the monitor after
the link opened, on both machines of the two-machine run:
| accessor | instruction | operand high byte | on the disk | at run time |
|---|---|---|---|---|
aciaCmdWrite $E554 |
sta $xx02 command |
$E556 |
$DE |
$DF |
aciaStatusRead $E558 |
lda $xx01 status |
$E55A |
$DE |
$DF |
aciaDataRead $E55F |
lda $xx00 receive |
$E561 |
$DE |
$DF |
aciaDataWrite $E563 |
sta $xx00 transmit |
$E565 |
$DE |
$DF |
aciaCtrlWrite $E567 |
sta $xx03 control |
$E569 |
$DE |
$DF |
aciaCtrlRead $E56B |
lda $xx03 control read-back |
$E56D |
$DE |
$DF |
The raw dump, which is the same thing without the interpretation:
>C:e540 ae 55 e0 20 53 e3 a9 09 20 51 e5 20 5f e5 4c 58
>C:e550 e5 8d be e5 8d 02 df 60 ad 01 df 8d bc e5 60 ad
>C:e560 00 df 60 8d 00 df 60 8d 03 df 60 ad 03 df 60 ea
The "on the disk" column is not an assumption: scanIoAccess.py decoding
build/swiftlinkDriverE000.bin prints sta $DE02, lda $DE01, lda $DE00, sta $DE00,
sta $DE03, lda $DE03 at those six addresses, so the image is unmodified and the $DF bytes are
the running driver's own work.
4. The control and command registers really are written at $DF00
From the ordered log in section 2, and confirmed by a direct read of the chip at the end of the run
(m df00 df03 = 00 10 05 15):
- control
$DF03=$15-$10(8 data bits, one stop bit, internal baud rate generator) OR the rate bits for 300 baud on a SwiftLink's doubled crystal. - command
$DF02=$09when the transmitter is idle (DTR on, RTS low, receiver IRQ enabled, transmit IRQ disabled) and$05whenever there is something to send, exactly the patterntestReport.mdrecorded at$DE00. - data
$DF00carried$0D $41 $54 $51 $30 $56 $31 $58 $31 $41 $0D= CRATQ0V1X1ACR, the answer-mode Hayes string, followed by the$00stream ofbeginByteSyncPhase. The TCP sink at the far end of the emulated serial line received 8552 bytes beginningb'\rATQ0V1X1A\r\x00\x00\x00...', so those writes left the emulated chip.
A baud hot key also reaches the right page. In the two-machine real-time run, machine B's
C= + 2 landed and the state readback showed baudIndex=6 with $DF03 = $18 (2400 baud), i.e.
loadBaudParameters -> aciaSetControlIdle -> aciaCtrlWrite wrote the control register at the
strapped base. (Machine A's key did not land that time and the script fell back to writing $DF03
from the monitor, which is the documented fallback in testRealtime.setBaud.)
5. The game reaches the modem prompts exactly as it does at $DE00
- Options menu.
shots/strapDf00BootMenu.pngagainst the$DE00build'sshots/swiftlinkMenu.png: 1551 pixels differ, every one of them insidey = 119..126, the single character row the menu highlight blinks on. Everything else is identical. - The right module is loaded. After COMPETE WITH MODEM OPPONENT,
$E000read4c 11 e1 4c 9a e2 4c a9 e0 4c f6 e0 4c cb e3 60- byte for byte the same jump tabletestReport.mdsection 2 recorded at$DE00. - The prompts.
shots/strapSelectDf0003afterOpen.pngandshots/strapDf0003later.pngboth show "PICK UP PHONE THEN PRESS SPACE." over the options menu. Against the$DE00run'sshots/modemPromptPressSpace.pngeach differs by 403 pixels, all insidey = 200..206- the status line's own blink row. - No ACIA register is touched until both prompts are answered. The watchpoints on all four
ranges were armed at the options menu and the first stop came only after the A/O and space
answers, which is the same result the
$DE00run got. - The NMI vector is installed.
d fffa fffbdisassembles the two bytes as85 E6, i.e.$E685=commNmiHandler.
6. Two machines at $DF00
At true C64 speed (testRealtime.py, 60-second windows)
Both machines reached connection phase 3, the game's own packet protocol.
| rate | direction | bytes | throughput | frame lead bytes $55 |
countLinkError $E403 |
receive-ring overflow $E505 |
transmitter deadlock |
|---|---|---|---|---|---|---|---|
| 300 | A -> B | 1782 | 29.62 B/s = 296 bit/s | 599 | 0 | 0 | no |
| 300 | B -> A | 1744 | 28.99 B/s = 290 bit/s | 682 | 0 | 0 | no |
| 2400 | A -> B | 540 | 8.98 B/s | 203 | 0 | 0 | no |
| 2400 | B -> A | 540 | 8.98 B/s | 203 | 0 | 0 | no |
Per second, from testLogs/realtime.strapdf.*.samples.txt: at 300 baud 27 to 32 bytes in each
second on conn0 and 14 to 31 on conn1, at 2400 baud 6 to 12 each way, and no second at zero in
either window.
The emulators' own cycle counters put both windows at 100.7% to 101.2% of real time, so this is true
C64 speed and not warp. 30 bytes/s is the whole of what 300 baud can carry at 8N1, and the 2400-baud
figures match realtimeReport.md section 8's post-fix $DE00 numbers (8.94 to 8.98 B/s) to within a
byte. The $55 counts are the ARQ frame lead byte: these are real frames, not a byte-sync flood.
The 2400-baud rate was reached by switching on a live link, and the link came back to phase 3 after
the switch.
In warp, with the mirror tripwire armed (testStrapPair.py, 150-second window)
| direction | bytes | frame lead bytes $55 |
eight-byte $00 runs |
|---|---|---|---|
| conn0 -> peer | 21642 | 5988 | 53 |
| conn1 -> peer | 20511 | 6259 | 30 |
Both machines ended in connectionPhase = $03, isLinkActive = $01, linkErrorCount = $00, with
all six accessors still reading $DF. The tail of the relay log is frame traffic -
55 ed 54 55 05 6b 55 05 6b ... - lead byte, then length/control/sequence/checksum.
More useful than the byte count: machine A reached the GAME TYPE menu and machine B showed
"OPPONENT PICKING GAME/MAP." (shots/pairDf0003aLater.png, shots/pairDf0003bLater.png). That is
the state the side-0/side-1 negotiation ends in, and getting there means the two agreed over the link
which of them plays which side, and that machine A loaded the setup overlay from disk while the
link was open - the suspend/resume handshake - with the mirror watchpoints armed throughout.
7. The hazard: does anything else reach into the $DF00 page?
This is the question spec_uart.md raised (hazard 5, and the loadBaudParameters note): a real
SwiftLink decodes only A0 and A1 inside its page, so all 64 four-byte windows of $DF00-$DFFF are
the same four registers. Any read where address AND 3 = 0 consumes a received character and clears
RDRF; where address AND 3 = 1 it clears the interrupt flag. And a 6502 absolute-indexed store
performs a dummy read at the un-carried address first, so sta $DF59,y reads $DF56, $DF57,
$DF58 on its way - and $DF58 AND 3 = 0 is the data register. That instruction is at $E358 in
the stock module. It is gone from this build; the question is whether anything else does it.
7.1 Static: two passes over every image the C64 loads, and one over the indirect pointers
scanIoAccess.py (new, in this directory) disassembles the code regions of all 22 loaded images -
the complement of disassembly/build/dataMap.json, so data tables are not decoded as instructions -
and reports every absolute or absolute-indexed instruction whose effective address, or whose dummy
read, can land in $DE00-$DFFF. Whole-game result:
game/modemDriverE000 $E358: sta $DF59,y reaches $DF59-$E058, dummy read in $DF00-$DFFF
game/modemDriverE000 $E657: sta $DD05,x reaches $DD05-$DE04, dummy read in $DD00-$DDFF
game/modemDriverE000 $E65D: sta $DD04,x reaches $DD04-$DE03, dummy read in $DD00-$DDFF
All three are in the stock modem driver, which this build replaces. $E358 is the known one.
The other two are setBitPeriod writing CIA2's timer latches with X = 0 or 2, so they reach $DD04
to $DD07 in practice and their dummy read is in the CIA2 page, not the cartridge page; in this
build both addresses are a bare RTS. Nothing in the main program, the overlays, the text engine,
the high-memory block, the fast loader, the trainer or the trainer overlays appears at all.
The same scan over build/swiftlinkDriverE000.bin finds only the six accessors, all plain absolute:
swiftlinkDriverE000.bin $E554: sta $DE02 $E558: lda $DE01 $E55F: lda $DE00
swiftlinkDriverE000.bin $E563: sta $DE00 $E567: sta $DE03 $E56B: lda $DE03
A second, alignment-independent pass decodes every three-byte window of every image as if it were
an instruction, which catches a misaligned entry, a self-modified operand or code hidden inside a
data region. It adds fourteen hits and every one was checked by hand against the .s files:
| hit | what it really is |
|---|---|
boot/titleBitmapA000 x 9 |
title-screen bitmap data; the file is data end to end and is never executed |
boot/fastLoaderC000 $C047, game/mainProgram0800 $08A8 |
the middle of lda $DD00 / and #$DF - AD 00 DD 29 DF read one byte late |
game/mainProgram0800 $0D9B |
inside the keyboard matrix code table at $0D98; the $DE is a PETSCII code |
game/mainProgram0800 $1E76 |
the operand high byte of sta scrollScreenStepOpcode at $1E74 |
game/modemDriverE000 $E358 |
the stock sta $DF59,y again |
So the superset pass adds nothing: no instruction in the shipped code of this build can name an address in the cartridge page except the six accessors.
7.2 The one place the game does address $DF00-$DFFF - and why it is safe
Neither static pass can see an operand that only exists at run time, and there is one:
copyPageUnderIo $58B2 copies 256 bytes with lda abs,y / sta abs,y whose operands its callers
patch. The film-buffer callers walk a whole page pointer over the film:
7F64 lda #$D0 / sta D_58C7 ; "the destination page walks $D000..$DF00" (load a saved film)
816C lda #$D0 / sta D_58C4 ; "the source page walks $D000..$DF00" (save a film)
and readFilmByte $5874 / writeFilmByte $5893 dereference filmPtr $BC/$BD, which
rewindFilmPtr $58D5 sets to $D000 and which then walks the same 4 KB.
scanIoAccess.py pass 3 lists all eighteen zero-page pointers the loaded code dereferences with
(zp),y or (zp,x) and the immediate high bytes stored into each. $BC/$BD is the only one whose
high byte is ever given a value in $D0-$DF, and it has exactly two indirect uses in the whole
game - $5885 and $58A4, the two inside those routines. That pass is a narrowing, not a proof: a
pointer can also be given a computed high byte, and filmPtr is, since it is incremented across the
buffer. What closes it is that the two instructions which dereference it are both inside the banked-
out window below.
All four instructions - the two inside copyPageUnderIo and the two that dereference filmPtr -
run with $01 = $34, which replaces the $D000-$DFFF I/O block with the RAM underneath, and
every one of the three routines puts $01 back afterwards. That is checked in the emulator rather than
argued (probeBankOut.py):
control register written through the I/O window: $1E
same address written again with $01 = $34, read back banked out: $55
control register with the I/O area banked in again: $1E
the banked-out write reached the cartridge: no, it went to RAM
The write to $DF03 with the I/O area banked out landed in RAM and the 6551's control register was
untouched, which is what a real C64's PLA does too: it does not assert /IO2 in a memory configuration
that has no I/O. So the film system's traffic through $DF00-$DFFF cannot reach a $DF00-strapped
cartridge.
This is also the reason DESIGN_NOTES.md item 1 exists - the NMI handler has to bank the I/O area
back in itself, because it can fire in the middle of exactly these routines.
7.3 Empirical: a tripwire on the mirrors
VICE maps only $DF00-$DF03, so $DE04-$DEFF and $DF04-$DFFF answer nothing in the emulator -
which makes them a clean tripwire. A watchpoint there costs nothing while it stays silent, and a
stop is an instruction reaching into the cartridge page that would be a register access on real
hardware.
| run | what it covered | mirror stops |
|---|---|---|
testStrap.py |
options menu, module load, both prompts, link open, Hayes dialogue, byte sync, then 45 s more with only the mirror watch armed | 0 |
testStrapPair.py machine A |
boot to the GAME TYPE menu, including a setup-overlay disk load over the live link, 150 s window | 0 |
testStrapPair.py machine B |
boot to "OPPONENT PICKING GAME/MAP.", 150 s window | 0 |
Verdict. Static and empirical agree: with the cartridge at $DF00, the only code that reaches
the page is the driver's six accessors, and the only other code that names addresses in it - the film
buffer - does so with the I/O area banked out, where the cartridge is not selected.
8. What this does not say, and two things worth knowing
-
No real hardware. Every result is VICE 3.7.1 with
-acia1mode 1 -acia1base 0xDF00 -acia1irq 1. Nothing has been run on a physical SwiftLink or on a C64 Ultimate. -
VICE does not emulate the register mirrors. Its SwiftLink claims four bytes, not the page. So section 7.3's tripwire proves that no instruction addresses the mirror range; it cannot show what a real cartridge would do if one did. The mirror behaviour itself is taken from
spec_uart.md, not observed here. The same limitation means an accidental mirror access would be harmless in this emulator and destructive on hardware - which is precisely why the static scan matters. -
The probe's read of an empty
$DE00is open bus, and it is not deterministic. On a C64 an unmapped I/O read returns the last byte the VIC put on the bus. The driver's own two probe reads in one session returned$00and$FF; a memory dump later in the same session readf6 f6 f6 f6across$DE00-$DE03; a bare machine sitting in the KERNAL read$00in one run and$FFin another; andprobeOpenBus.py, sampling$DE03120 times at different points in the frame a few seconds after the loader finished, got:$F6 62 times (51.7%) $2C 32 times (26.7%) $2D 20 times (16.7%) $2E 6 times (5.0%) reads that would have made the probe believe an ACIA is at $DE00 ($1E): 0 of 120So on this screen the byte is nowhere near
$1E- but the value is screen data the driver does not control, and nothing rules$1Eout on a different screen. If it ever reads back$1E, the probe concludes the cartridge is at$DE00, aims all six accessors at open bus, and the link is dead until something re-probes. Note also that when the probe does fall back, it does not verify$DF00at all -aciaDetectsays so in its own comment: "aim the accessors there and hope". -
The probe re-runs on every open and every rate change.
aciaDetectis the first thingloadBaudParameters$E353does, and the baud hot keys fall through intoloadBaudParametersfrom$E350. Two consequences on a$DF00machine: every speed hot key re-decides which page the cartridge is on, so the open-bus gamble above is taken again on a live link; and every open and every rate change writes$1Einto$DE03, which is a foreign device's register if anything else is plugged in at$DE00- and something else at$DE00is a common reason to strap a SwiftLink to$DF00in the first place. If that device reads back$1Efrom its own offset 3, it shadows the SwiftLink permanently.None of this is a regression and none of it was hit in any run here. Three cheap hardenings, in increasing order of intrusiveness, if it is ever worth closing: probe with two different patterns and require both to read back; latch the page once a probe has succeeded so a live link cannot be re-aimed; or probe only on a cold open rather than on every rate change.
-
Only 300 and 2400 baud were exercised at
$DF00, matching what the earlier reports covered at$DE00. The other five rates were not driven. -
Only one hot key was seen to land at
$DF00- C= + 2 on one machine, which programmed$DF03=$18. C= + A, C= + O, C= + H, C= + P, C= + C and C= + RETURN were not exercised on this strap. -
No complete game was played, at either base.
-
One rig failure, recorded for honesty. The first
testStrapPair.pyrun produced a session in which machine A never left the options menu:testTwoMachines.answerModemPromptsdecides the link is open as soon as$E5BEreads non-zero, and$E5BEis ordinary RAM until the module is loaded over it - it happened to hold$AC, so the script stopped pressing keys. Only one machine ever connected to the relay and it poured out 2188 bytes of byte-sync$00. That run says nothing about the strap and its numbers are not used here.testStrapPair.pynow requires two independent conditions instead - the module's jump table resident at$E000and the control register programmed - and the re-run linked first time.testTwoMachines.pyitself was left alone.
Files
| file | what it is |
|---|---|
testStrap.py |
new: one machine at $DF00, watchpoints on both pages and both mirror ranges, ordered access log, accessor read-back |
testStrapPair.py |
new: two machines at $DF00 with the mirror tripwire armed for the whole session |
scanIoAccess.py |
new: the three static passes of section 7, over every loaded image and any extra binary given as path@LOADADDR |
probeBankOut.py |
new: VICE's I/O map, and the banked-out write experiment of section 7.2 |
probeOpenBus.py |
new: what an empty $DE00 reads back, sampled across the frame |
viceHarness.py |
changed: ACIA_BASE from SWIFTLINK_ACIA_BASE, default $DE00 |
testBoot.py, testModemSelect.py, testRealtime.py |
changed: monitor commands built from ACIA_BASE instead of a literal de00 |
testLogs/strapDf00.hits.txt |
the 800 watchpoint stops of section 2 |
testLogs/strapDf00.mirror.txt |
the mirror-only watch of section 7.3 - empty, which is the result |
testLogs/strapSelectDf00.hits.txt |
the modem-select run's 300 stops |
testLogs/strapDf00Probe.txt, strapSelectDf00.txt, strapRealtimeDf00.txt, strapPairDf00.txt, strapOpenBus.txt |
the five run transcripts |
testLogs/realtime.strapdf.run300.w1.samples.txt, realtime.strapdf.run2400.w1.samples.txt |
per-second byte counts for the two real-time windows |
shots/strapDf00*.png, shots/strapSelectDf00*.png, shots/pairDf00*.png, shots/rtstrapdf*.png |
the screenshots cited above |