Fat tracks on Commodore disks: myth or truth? Investigating the case of Maniac Mansion

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:

Flux Studio: visualizing a G64 of Maniac Mansion by Luigi Di Fraia
Flux Studio: visualizing a G64 of Maniac Mansion

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!

About Luigi Di Fraia

I am a Senior DevOps Engineer so I get to work with the latest technologies and open-source software. However, in my private time I enjoy retro-computing.
This entry was posted in Retrocomputing, Reverse Engineering, Technical and tagged , , , , , . Bookmark the permalink.

1 Response to Fat tracks on Commodore disks: myth or truth? Investigating the case of Maniac Mansion

  1. Pingback: Dissecting the Vorpal (later) disk protection – part 1 | Luigi Di Fraia's e-Footsteps

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s