[comp.sys.atari.8bit] Copy Protection Scheme

simonh@hpopd.pwd.hp.com (Simon Hunt) (04/11/91)

Over the last few evenings, I have been trying to discover how the copy
protection works on one of the disk-based games I have. The game loads itself
in several stages, to display a title screen whilst the rest of the program
loads...

Using a monitor/disassembler program, which allows you to read/write selected
disk sectors to a specified buffer, I eventually disassembled enough code to
discover how the program loaded itself in. Apart from the usual "unformatted
sectors" method, the program used a really neat trick which goes something
like this:

       :
       :   (set colours & display list pointers etc.)
       :
       * Read Sector <N> into buffer        [$600-$67F]
       * Read the SAME Sector into buffer   [$680-$7FF]
       * For X = #$00 to #$7F do..
	  * EOR $600,X with $680,X and store in $2800,X
       :
       :   (more stuff)
       :
       * JSR $2800
       :

The point is, on a normal disk (ie. a "copy" of the original) the values
loaded into the destination buffer [$2800-$287F] all equal #$00, since

  <n> EOR <n> = #$00

so the JSR encounters the BRK instruction and stops. However, on closer
inspection of the original disk, I discovered that reading sector <N>
several times in a row produced one of TWO sets of data in the buffer.
When I EOR'd the two sets of data together and disassembled the result, 
there was the "missing" subroutine.

Does anyone know how the disk was manufactured such that reading the same
sector gave TWO different, but CONSISTANT, sets of data?

Observations:
  1. The two sets of data NEED to be consistant to produce the correct code
      when EOR'd together.
  2. It doesn't matter which order the data sets arrive in as EOR is 
      commutative.
  3. Reading the sector several times did not guarantee alternation of the
      two data sets.
  4. There wasn't any provision for checking that the second read of the 
      sector had produced the OTHER data set.

What puzzles me is 3. and 4.  Together they seem to imply that occasionally, 
two consecutive reads of the sector would produce the same result which when
EOR'd together would, of course, produce a zero filled buffer. This in
turn would halt the program with the JSR call. However, in the numerous
times I have loaded and played the game in the past, I have NEVER seen this
happen.. it's always loaded fine.

Any ideas?

Simon Hunt.

simonh@hpopd.pwd.hp.com (Simon Hunt) (04/11/91)

Erratum:  

       :
       * Read Sector <N> into buffer        [$600-$67F]
       * Read the SAME Sector into buffer   [$680-$7FF]
                                                  ^^^^----- This should
							    read "$6FF"

Apologies.

Simon Hunt.

ken@hpcupt3.cup.hp.com (Kenneth M. Sumrall) (04/12/91)

>       * Read Sector <N> into buffer        [$600-$67F]
>       * Read the SAME Sector into buffer   [$680-$7FF]
>       * For X = #$00 to #$7F do..
>	  * EOR $600,X with $680,X and store in $2800,X
>                     [... Stuff deleted...]
>Does anyone know how the disk was manufactured such that reading the same
>sector gave TWO different, but CONSISTANT, sets of data?
>
Excellent hack work Simon.  I did this on Choplifter way back in 1981.
Very difficult to figure out when I never knew more than one sector
could have the same sector number.  (10th grade == not very bright :-)

>Observations:
>  1. The two sets of data NEED to be consistant to produce the correct code
>      when EOR'd together.
>  2. It doesn't matter which order the data sets arrive in as EOR is 
>      commutative.
>
Correct.

>  3. Reading the sector several times did not guarantee alternation of the
>      two data sets.
>
If you read them with a sector editor, of course not.  However, if read
in rapid succesion by an assembly program, the computer generates the
first read.  It is satisfied as soon as a sector with the correct number
passes under the disk drive head.  Then, immediately ask for the same
sector again.  The computer will send the request to the disk drive before
the other sector with the same number passes under the head, and now
the disk drive will satisfy the read request with the other sector.

>  4. There wasn't any provision for checking that the second read of the 
>      sector had produced the OTHER data set.
>
Not needed because the way the sectors are read in guarantees
the correct data.

>What puzzles me is 3. and 4.  Together they seem to imply that occasionally, 
>two consecutive reads of the sector would produce the same result which when
>EOR'd together would, of course, produce a zero filled buffer. This in
>turn would halt the program with the JSR call. However, in the numerous
>times I have loaded and played the game in the past, I have NEVER seen this
>happen.. it's always loaded fine.
>
>Any ideas?
>
Choplifter used a slightly different scheme, if I remember correctly.
It seems that three sectors had the same number.  The loading routine
would read the same sector 10 times into two different locations
alternatively.  Some how, this produced the correct data in the right
locations.  I never figured out why.  Anyway, I copied the two
neccesary sectors to two DIFFERENT sectors on my copy, changed the loader
to read one sector into one location, and the other sector into another,
and jump to it.  Luckily, the boot loader didn't checksum itself before
running the program.  I believe that Way Out did this.  Made it a little more
difficult to hack.  Of course, now that I have a Happy Drive, backups
aren't so difficult!

>Simon Hunt.

| Ken Sumrall                          |     Internet: ken%hpda@hplabs.hp.com |
| HP California Language Labs          |           UUCP:  ...!hplabs!hpda!ken |
|    "I'd stomp desert dope heads for some gas in my moped!" - Bill the Cat   |
|              "What a stupid world" -Calvin (speaking to Hobbes)             |

smb@cs.purdue.EDU (Scott M. Ballew) (04/12/91)

In article <40060005@hpopd.pwd.hp.com> simonh@hpopd.pwd.hp.com (Simon Hunt) writes:
>Does anyone know how the disk was manufactured such that reading the same
>sector gave TWO different, but CONSISTANT, sets of data?

>Observations:
>  1. The two sets of data NEED to be consistant to produce the correct code
>      when EOR'd together.
>  2. It doesn't matter which order the data sets arrive in as EOR is 
>      commutative.
>  3. Reading the sector several times did not guarantee alternation of the
>      two data sets.
>  4. There wasn't any provision for checking that the second read of the 
>      sector had produced the OTHER data set.

>What puzzles me is 3. and 4.  Together they seem to imply that occasionally, 
>two consecutive reads of the sector would produce the same result which when
>EOR'd together would, of course, produce a zero filled buffer. This in
>turn would halt the program with the JSR call. However, in the numerous
>times I have loaded and played the game in the past, I have NEVER seen this
>happen.. it's always loaded fine.

This is a very old copy protection scheme that relies on some timing
properties of disk drives.  Consider a single track of data which
contains 18 sectors.  These are normally numbered from 0 to 17 but are
NOT in order around the disk surface.  I forget what the optimal
format is but basically, sector 1 is almost 180 degrees around the
disk from sector 0 and then sector 2 is almost 180 degrees from sector
1, etc.  This is because while the computer and disk drive transfer
the data across the SIO cable, the disk is still spinning and it just
so happens that it is almost 180 degrees later when the drive and
computer are ready to read the next sector.

Now, in the case you mention above, if you labeled two sectors with
the same sector number in a track, which one you got would now depend
on the timing of other reads around you.  Various methods have used
the idea that if you read the sectors in the order of say 0 - 1 - 3 - 1,
then you got two different reads for sector 1.  With what you
describe, they are counting on the following fact:  If I read a sector
"1" from the track and immediately read another sector "1" from the
track and these two sector "1"s are approx 180 degrees apart, I am all
but guaranteed that I will get two different sets of data, ie., I will
read both of the sector "1"s on the disk.  As to how they did it, it
is simply a matter of reprogramming the drive (not possible on a stock
810 or 1050) to format the disk in a different manner than the normal
way.  It turns out that Happy enhanced drives have been able to do
this for some time and have absolutely no problem duplicating the
format on the destination disk.

By the way, you probably do not really have as many "unformatted"
sectors as you think since if  you have 18 sectors and renumber one of
them to be a duplicate number, one of the 18 sector numbers will not
exist so the drive will treat it as if it were unformatted.

Scott M. Ballew