In the below video I am showing how to use CBM Flux Studio to introduce long sequences of 0-bit cells in a Commodore floppy disk track which causes weak bits at read time, so that the copy protection in Zaxxon passes its check.
My TODO list for CBM Flux Studio is growing by the day, so the next few weeks should hopefully be exciting, that is unless I get swamped at work 😀
In the below video I go through the concept of weak bits and the protection that relies on them in Zaxxon [Mindscape]. I also share the details of the tool I wrote to write illegal GCR values to disk so that clones of the original will pass the copy protection check for weak bits.
The wording around weak bits might have to be revisited and presented in a more rigorous way in future articles and videos, but this is the gist of what they involve: writing long sequences of 0 bit cells so that a Commodore floppy disk drive loses synchronization at read time. The latter, in turn, causes two side effects:
intermittent loss of framings (e.g. the bit-stream will be 1 bit off during some reads) and
therefore the values read from the byte register ($1c01) will not be consistent across multiple reads (every here and there a bit will be set and the position of such bits will change on a per-read basis, although not entirely randomly).
Thanks go to Flavioweb, Sebastian, and SLC for thoughts and research material mentioned in the above video.
After I created my native tool, Flavioweb also suggested that Zibri / RamJam had made similar research on the disk copy protection for Rubicon that relies on weak bits. He shared his results here and you can see that he too might have got inspiration from the book Inside Commodore DOS, as I did.
In my next update I will show the new features I added in CBM Flux Studio to perform low level manipulation of the bits in a disk image so that Zaxxon can be “fixed” directly in my PC editor 🙂
As mentioned in the video, there is further research to be done on Zaxxon’s protections, but if you are interested in testing my native tool to write illegal GCR sequences to track/sector 1/0 of your non-working Zaxxon clone, you can build it using the GitHub repository here.
After posting my findings about the protection used by Mindscape in Zaxxon (based on weak bits in t/s 1/0), I was pondering whether I’d be able to write a tool that can re-create the underlying illegal GCR sequence thus causing weak bits. This tool could have been used back in the day to “fix” illegal copies of Zaxxon: one would simply have to make a whole disk copy with a standard copier and then run my tool on the clone.
Well, I actually wrote such tool this morning, before work. However, testing it is quite tricky because I haven’t got access to a working protected floppy disk of Zaxxon to use in a test workflow with real hardware: copy, “fix”, and finally nibble again for analysis.
If you have access to a working protected floppy disk of Zaxxon, or any Mindscape title protected with weak bits on t/s 1/0, and you have means to go through all steps in the above test workflow, feel free to get in touch to beta-test my tool 🙂
This evening I stayed up until late as I was having a look at the Mindscape protection used in Zaxxon, which is something Sebastian had asked about a couple of days ago in a comment.
So far I’ve reverse engineered the weak bits protection check on track/sector 1/0. I plan to add this information to my book eventually but here it is for your leisure:
; Drive code
.logical $04A0
; Copy protection to check weak bits at t/s 1/0
J04A0 LDA #$01 ; Set track
LDY #$00 ; Set sector
STY T04FB ; Also reset checksum value for our test at t/s 1/0
JSR S0616 ; Navigate and fetch CBM header for t/s 1/0 upon entry
JMP J04B0 ; Enter the loop at the waiting for a block-sync
; Loop start
B04AD JSR S069C ; Fetch CBM header on the current track at each iteration
J04B0 JSR S06D8 ; Wait for next block-sync (CBM data portion)
LDY #$F0
B04B5 BVC B04B5 ; Wait for byte ready
CLV
LDA $1C01 ; Read GCR byte
STA T0211,Y ; Store GCR data to $0301-$0310 (both inclusive)
INY
BNE B04B5
; Verify it's really the CBM data portion of t/s 1/0 by matching the pattern before and after weak bits
LDA $0302
CMP #$D5 ; Expected CBM Data GCR byte 1 (after the file ID GCR byte, $55)
BNE B04AD
LDA $0307
CMP #$AA ; Expected CBM Data GCR byte 6
BNE B04AD
LDA $0308
CMP #$D4 ; Expected CBM Data GCR byte 7
BNE B04AD
LDA T04FB ; Are we at the first pass?
BNE B04EA ; Branch if not
CLC ; We're at the first pass
LDA $0304
EOR $0305
EOR $0306
STA T04FB ; Store a checksum of the data where weak bits had been mastered
BCC B04AD ; Go for a second pass
B04EA EOR $0304 ; Later passes (second or more)
EOR $0305
EOR $0306
BEQ B04AD ; Loop if we consistently read the same data where weak bits had been mastered
; Success
LDA #$60 ; Disable the jump to us
STA M0579
RTS
As you can see, the test substantially performs what other researchers have written before me: the drive code checks if it is reading data consistently where more than two consecutive 0 bits were recorded at mastering time. Have a look at the screenshot below:
Due to the nature of the hardware of Commodore floppy disk drives, long sequences of 0 bit cells cause the contents of the read byte register to have an element of pseudo-randomness. Illegal copies would have troubles replicating the condition without using specialized code: disabling the protection at $04A0 with an RTS instruction would be one way around it.
Stay tuned for more, i.e. the reverse engineering of the main loader 🙂
As I tagged version 2.0-alpha-4 of CBM Flux Studio this evening, I thought to share a couple of updates here.
First one is that I rewrote the modules that manipulate G64 and NIB files. Going forward, support for the SPS extension to the G64 format should be pretty simple to keep all the way through the user workflow, including when saving a G64.
Second one is that I made a few changes to the routines that perform pattern matching and searching within the underlying data structures. I am not yet sure whether these have introduced unintended consequences. Time and more regression testing will tell.
Here’s the full changelog for version 2:
v2.0-alpha-4 - 30/06/2022
Improved access to data structures for pattern matching and searching
v2.0-alpha-3 - 30/06/2022
Refactored the modules that manipulate NIB and G64 file contents
v2.0-alpha-2 - 29/06/2022
Added a specialised Vorpal (later) track cycle detection logic
Directory contents are shown in a preview widget within the file chooser dialog when a disk image is selected
Added the popup menu to manipulate the selected track
Added V-MAX! version 3 track 20 decoder, currently used by the data report
v2.0-alpha-1 - 21/06/2022
The application was completely rewritten
Overall, I am quite happy with the pace and progress with CBM Flux Studio so far, although my TODO list for it looks pretty intimidating at the moment!
I am almost tempted to get one for fun but I think I am happy with my Black pill for now as I haven’t got much interest in wireless connectivity… yet 🙂
This evening I had enough time to draft the decoder for V-MAX! track 20, which contains the main loader. For Arkanoid, the decoded loader is $7c0 bytes in size. It has an interesting sync sequence and acknowledging user data gives me an opportunity to identify what’s not data, so I can safely add padding for NIB->G64 conversion and set the write splice for track 20 of V-MAX! disks.
Here’s a preview of the decoder as shown by the data report in CBM Flux Studio.
The part I highlighted in the above screenshot is NOT loaded to the drive’s RAM at $00C0. Neither its checksum is compared with the one that follows the data on track 20. However, the checksum is there and it matches the calculated one as you can see in the below screenshot 🙂
In this video I show how it’s possible to extend block syncs for all instances of block 0 in V-MAX! version 3 disks, thus ending up with a working G64.
In this video I share my observations around block syncs in legacy NIB files:
As mentioned in the video, the tooltip created when the mouse pointer hovers on track data now also reports on the size of the group of same value bits as the one under the pointer, which is quite useful to measure the length of block syncs.
In order to tackle the oddity with block syncs I am experiencing, it would really help if I were able to source some fresh NIB files created with IECHost of original disks that use V-MAX! version 3.
This morning I added some support for V-MAX! version 3 in CBM Flux Studio. Here’s a video in which I share a few observations I made while inspecting disk images for After Burner: a G64 created by KryoFlux/DTC and a NIB file created by nibread.