Maniac Mansion, the 1987 version, is protected against copies using what is often referred to as a “fat track”: data perfectly identical and aligned across multiple tracks and half tracks.
As Pete Rittwage’s website suggests, Maniac Mansion uses a fat track at tracks 35.0, 35.5, and 36.0. Having a look in my Flux Studio, indeed data in these tracks is identical and perfectly aligned:
Let’s have a look at the drive code that scans through tracks 35.0, 35.5, and 36.0 and protects against copies:
; Loaded from t/s 18/8
*=$0400
V0400 SEI
LDY #$FF
B0403 INY
LDA $0412,Y
EOR T04AE ; Decode the following code segment
STA $0412,Y
CPY T04B0
BNE B0403
; Decoded segment follows
JSR S046F
LDX #$00 ; Zero FDC return value storage
STX $0009
LDX #$02 ; Set count for stepping 2 times
STX $0008
LDA #$23 ; Start at track 35
STA $0006
B0424 LDY #$10 ; Sector 16
STY $0007
B0429 LDA #$80 ; Job: Read sector in buffer 0
STA $0000
JSR S047F ; Wait for job to finish
CMP #$01
BEQ *+5 ; Branch if successful
STA $0009 ; Store FDC error
DEC $0007 ; Sector--
BPL B0429 ; Repeat for other sectors, down to sector 0 (included)
JSR S048E ; Step head to the next half track
DEC $0008 ; Decrement count of steps to do (35.0:0x01, 35.5:0x00, 36.0:0xFF)
BPL B0424 ; Loop until we finished with track 36
LDY #$02
JSR S0487 ; Step head to the previous half track
DEY
BPL *-4
; Now we are back on track 35, which is a valid DOS one
LDA $0009 ; Was there an error reading any sector? None in the original
BNE *+7 ; Branch if not
LDA #$FF ; Flag this as a copy (and fail the protection check)
STA $01FF
LDA #$12 ; Track 18
STA $0006
LDA #$00 ; Sector 0
STA $0007
LDA #$B0 ; Job: seek track
STA $0000
JSR S047F ; Wait for job to finish
JSR S046F
JMP J04B2
S046F LDA $1C0C
ORA #$0E ; %00001110
BNE *+7
LDA $1C0C
AND #$FD ; %11111101
STA $1C0C
RTS
; Wait for job to finish
S047F CLI
LDA $0000
BMI *-3
SEI
RTS
; Step head to the previous half track
S0487 LDX $1C00
DEX
JMP J0492
; Step head to the next half track
S048E LDX $1C00
INX
J0492 TXA
AND #$03
STA $0044
LDA $1C00
AND #$FC
ORA $0044
STA $1C00
LDA #$D0 ; $80 | $50
STA $1805
BIT $1805
BMI *-3
RTS
T04AE .byte $BA ; Byte used to decrypt the code
T04AF .byte $00
T04B0 .byte $9B,$00
J04B2 LDA $0001 ; Remove the above code from the drive's RAM
LDY #$00
STA $0400,Y
INY
CPY #$B2
BCC *-6
CLI
RTS
There is nothing in this code that checks for tracks 35.0, 35.5, and 36.0 being perfectly aligned. The only timing code (using $1805) is the one that delays after the read head steps on a different track, which is commonly done to allow the head itself to stabilize (in fact, the stepping produces mechanical oscillations).
So what does this code do and protect against? Very simply, it starts at track 35 and reads in all sectors, from 16 down to 0, using the job queue of the 1541 corresponding to buffer 0. It then repeats the same on tracks 35.5 and 36.0. If any sector read error occurs during this test, the protection check fails (and $9 in the drive’s RAM is set to the last FDC status code, while $01FF is set to $FF).
You might contend: “There’s no need to have a fat track on disk since the reciprocal alignment of all three tracks is not checked!”.
Well, yes and no. You see, it’s hardware from the 80s we are talking about. It’s perfectly reasonable to expect that emulators will be able to read data off those half tracks that are “squeezed” in the middle of adjacent tracks without errors. But can a real Commodore drive do the same? Well, that depends on the drive’s electronic characteristics.
The truth is that when reading half track 35.5 in Maniac Mansion a real Commodore drive will probably be influenced by the data on at least one adjacent track, i.e. either 35.0 or 36.0. The result is that the read head will pick up a signal that’s the combination of the flux reversals on track 35.5 and of one adjacent track: that’s inter-track interference.
Now the question is: what happens if the data on track 35.5 and one of the adjacent tracks from where signal is also picked up is not aligned? Well, a mish-mash of signals from both tracks that is likely to result in errors while attempting to read at least one sector (out of the 51 sectors Maniac Mansion tries to read in total).
So the perfect alignment in a fat track is required due to the inability of the read head to read half tracks without being influenced by the signal in neighboring tracks, which is also consistent with the fact half tracks are not used by the Commodore DOS: such choice ensures good separation between tracks to avoid inter-track interference.
There is still more work and testing to do, but so far the above is what the testing suggests. Also, emulators should really try to emulate inter-track interference when loading data from half tracks in a G64, otherwise there will always be a difference in behavior when compared to real Commodore drives: even by skewing data in the tracks and half tracks that make up a fat track, emulators will read half tracks cleanly, where real hardware will likely not.
I have been discussing the above with Flavioweb and SLC, who also went the extra mile by testing on the field, so a big “thank you” goes to them for this article.
Nothing has so far been said about writing fat tracks. I’ve been focusing exclusively on how the real hardware reads them. In my next article on the fat track subject I will also comment on the task of writing fat tracks and whether or not it’s possible to do so on a Commodore 1541 or compatible drive.
Stay tuned for more on the fat track subject!
Pingback: Dissecting the Vorpal (later) disk protection – part 1 | Luigi Di Fraia's e-Footsteps