Jump to content
  • entries
    334
  • comments
    900
  • views
    258,578

more Disk ][ musings


EricBall

1,065 views

As I mentioned in my previous entry, I've been taking a deep look at the Apple ][ Disk ][ controller. IMHO it's an elegant blend of hardware, software & firmware.

 

The crux of the controller is the P6 (8bitx8bit) PROM which describes the state machine along with an 8 bit shift register and a 4 bit state register.

 

The CPU selects one of four modes via two PROM address bits (called Q7 Q6):

00 read a byte

01 sense write protect

10 write byte

11 load byte for write

 

The other 2 address bits come from the high bit of the shift register and a read pulse (indicating a change in magnetic field). The four output bits select the shift register function (NOP, LD, CLR, SR, SL1, SL0). The high bit of the state register is also connected to the write head.

 

Mode 01 is very simple. It shifts the write protect state into the high bit of the shift register (SR) and goes to state zero. This is also used to initialize the state machine to a known state.

 

Modes 10 & 11 work together in a tight 8 cycle (4 CPU cycle) loop. The CPU loads the byte to be written then does a

cycle 0/32/64 STA $C08D,X // load shift register

cycle 4/36/68 CMP $C08C,X // start shifting out bits

The state numbers do an interesting back & forth to encode '1' bits as a change in magnetic field. As I noted previously, the controller does not limit the bit encoding used. It does, however, restrict the timing. So any copy protection designed to confuse the read mode state machine, e.g. by changing the magnetic field very quickly, would have to be written using something other than a standard Apple ][ Disk ][ controller.

 

I'll discuss Mode 00 in my next entry, 'cause it isn't simple.

11 Comments


Recommended Comments

Wow, that Disk ][ is something. Really quite a contrast with the rest of the Apple ][, actually, a machine which aside from the amazing disk drives is not IMHO that well thought-out.

 

The keyboard hardware, for example, could have been replaced by a 8 diodes and eight resistors and either couple of 74373's and a couple of address decodes, or a 74165, 74164, and a decoded (1 bit) input. This change would have made the hardware more versatile while reducing the cost.

 

The divide-by-seven on the display is, of course, the bane of Apple programmers everywhere. Divide-by-eight or divide-by-six would have been much nicer.

 

Using 65 divide-by-seven clocks per line instead of 65.14 would have made hires programming a little more difficult (though not really much worse than forced by the seven-pixel bytes) but would have made the resulting displays look better. Or, for simplicity, clock the scan lines 1.6% fast. Early Commodore 64's did with no apparent ill effect.

 

Woz's love of seven-bit everything means that graphics printing is 14% slower than it should be. And the lack of a pollable timebase is just plain annoying.

 

BTW, if I were trying to design a copy-protection scheme on that thing, I'd write each track to contain one "sector" with a simple header and then nothing but alternating "1" and "0" bits. I'd probably group the bits into bunches of 64 (8 bytes' worth); the real data would be determined by whether each group of 8 bytes took more or less time, or about the same amount of time, to read as the one before.

 

I wonder if any of the copy programs ever marketed would be able to reproduce that?

Link to comment

Wow, that Disk ][ is something. Really quite a contrast with the rest of the Apple ][, actually, a machine which aside from the amazing disk drives is not IMHO that well thought-out.

...

Or, for simplicity, clock the scan lines 1.6% fast. Early Commodore 64's did with no apparent ill effect.

Keep in mind that the C64 was released 5 years after the Apple II. You can't really compare them. That's like trying to compare the design of the 2600 with the 5200 on the same level.

 

EDIT: if you want a level comparison, consider the first Commodore PET (the 2001 I think), which was released within a couple of months of the Apple II. Look into that machine and I think you'll agree that the Apple II is vastly superior.

 

Yes, the graphics do suck, as do other things about it, but there are some nice things about it. It had eight expansion slots, easily expandable memory using DRAM (not SRAM like basically everything else at the time), a monitor, BASIC interpreter, miniassembler built into the ROM. These things gave the user plenty of power over the machine right out of the box.

Link to comment
Keep in mind that the C64 was released 5 years after the Apple II. You can't really compare them. That's like trying to compare the design of the 2600 with the 5200 on the same level.

 

I mentioned the C64 merely to say that running the scan lines 1.6% fast would have been a reasonable thing to do.

 

Some of the limitations seem surprising in light of Woz's desire to do everything in software (keyboard scanning would seem a natural). On some of the other issues, my surprise is that subsequent machines never addressed them. By the time the Apple //e came out, I would think it would be pretty clear that something resembling a real-time clock would be useful. I think a multi-tap shift register chip and a quad XOR gate, and a spare input bit would have sufficed, though other approaches might have been nicer.

Link to comment
Keep in mind that the C64 was released 5 years after the Apple II. You can't really compare them. That's like trying to compare the design of the 2600 with the 5200 on the same level.

 

I mentioned the C64 merely to say that running the scan lines 1.6% fast would have been a reasonable thing to do.

 

Some of the limitations seem surprising in light of Woz's desire to do everything in software (keyboard scanning would seem a natural). On some of the other issues, my surprise is that subsequent machines never addressed them. By the time the Apple //e came out, I would think it would be pretty clear that something resembling a real-time clock would be useful. I think a multi-tap shift register chip and a quad XOR gate, and a spare input bit would have sufficed, though other approaches might have been nicer.

Fair enough.

 

By then there were several real-time clocks for the Apple II in the aftermarket, making one by Apple sort of redundant. But if you just wanted something that kept somewhat inaccurate time, there was a quite simple hack published that took the 60 Hz clock from the video and ran it into the NMI pin. I can't remember the details but it worked quite well and even a novice could do it.

Link to comment

BTW, if I were trying to design a copy-protection scheme on that thing, I'd write each track to contain one "sector" with a simple header and then nothing but alternating "1" and "0" bits. I'd probably group the bits into bunches of 64 (8 bytes' worth); the real data would be determined by whether each group of 8 bytes took more or less time, or about the same amount of time, to read as the one before.

 

I wonder if any of the copy programs ever marketed would be able to reproduce that?

Kinda - there were copy protection schemes which added extra zero bits between bytes (which the read sequencer would automatically discard) and then time how long it took to read the bytes. Standard copy programs wouldn't add the extra zero bits, which could then be detected by the program. Of course, such copy protection schemes would be more sensitive to drive speed variations. Also, the many programs were cracked by simply making a copy of the program after it was loaded in memory and then patching out any copy protection checks.

Link to comment
Kinda - there were copy protection schemes which added extra zero bits between bytes (which the read sequencer would automatically discard) and then time how long it took to read the bytes. Standard copy programs wouldn't add the extra zero bits, which could then be detected by the program. Of course, such copy protection schemes would be more sensitive to drive speed variations. Also, the many programs were cracked by simply making a copy of the program after it was loaded in memory and then patching out any copy protection checks.

 

Yeah, obviously memory snapshotting is an issue (though Apple, in a nod to developers, decided to trash memory on a forced reset). Still, it would be interesting to know whether an approach such as I described had been done. Unlike excessively long strings of zeroes (which will read flakey) the data here would all be seemingly normal, but there would be hidden data undetectable by anyone who didn't know how to look for it.

Link to comment

(though Apple, in a nod to developers, decided to trash memory on a forced reset).

For which the hardcore crackers burned their own boot PROMs... complete with auto-save of zero page memory etc. And it wasn't Apple's decision, really. They just enhanced the original boot PROM to check a hotspot for a particular value to decide whether to do a cold or warm boot and also to check for boot PROMs on any expansion boards. The copy protectors simply took advantage of this default behaviour, i.e. clearing the hotspot to force a cold boot and using areas of RAM (like the text screen) which the boot PROMs would overwrite.

 

Still, it would be interesting to know whether an approach such as I described had been done. Unlike excessively long strings of zeroes (which will read flakey) the data here would all be seemingly normal, but there would be hidden data undetectable by anyone who didn't know how to look for it.

 

I'm not sure how your copy protection scheme would work since ones and zeros are written using the same number of cycles, it's the magnetic field transition which is significant. i.e. 1010 would be stored as NSSNN

And the timing copy protection would only add a couple of zero bits to the end of each byte, i.e. load the shift register every 40 cycles when writeing instead of every 32.

Link to comment

The copy protectors simply took advantage of this default behaviour, i.e. clearing the hotspot to force a cold boot and using areas of RAM (like the text screen) which the boot PROMs would overwrite.

 

More likely they cleared the hotspot to point back into their code; it could then either clear itself and reboot, give the user an "are you sure you want to reboot?" or simply refuse to allow a reboot. But on the Apple //e, the user could force a cold boot with the open-apple key. Doing so, however, would cause the kernel to trash two bytes on every page before rebooting. Such memory-trashing behavior was new on the Apple //e and I'm sure was a deliberate effort to discourage memory snapshotting for the purpose of breaking copy protection.

 

I'm not sure how your copy protection scheme would work since ones and zeros are written using the same number of cycles, it's the magnetic field transition which is significant. i.e. 1010 would be stored as NSSNN And the timing copy protection would only add a couple of zero bits to the end of each byte, i.e. load the shift register every 40 cycles when writeing instead of every 32.

 

An alternating pattern of zeroes and ones will nominally be represented by one field transition every 16 MPU cycles, but the controller will still read a "10" pattern if it is fed one transition every 13 cycles or every 20. One could detect the rate of field reversals in a string of "10101010" bytes via something like:

 sec
 ldx #$20
... then jump to T20 with proper timing.

; The following instruction should occur 10 CPU cycles after the start of the
; LDY that fetched the previous byte.
GotIt:; 14 cycles after ldy
 cpy #$AA
 bne WRONG
 dex
 beq DONE
; The following instruction should occur 20 CPU cycles after the start of the
; instruction that read the last byte of data.  It may be necessary to read a dummy byte.
T20:
 ldy PORT,x
 bmi G20
T26:
 ldy PORT,x
 bmi G26
T32:
 ldy PORT,x
 bmi G32
T38:
 ldy PORT,x
 bmi G38
T44:
 ldy PORT,x
 bmi G44
 jmp WRONG
; The following labels will be hit 7 cycles after the LDY
G20:
 nop
 bne GotIt
G26:
 adc #0 ; Carry SET!
 bne GotIt
G32:
 adc #1
 bne GotIt
G38:
 adc #2
 bne GotIt
G44:
 adc #3
 bne GotIt

Note that code could be in RAM, patched to use whatever drive was appropriate.

 

This routine should be happy with any sequence of $AA bytes written at any reasonable speed, but the value in the accumulator will vary depending upon how fast the bytes were written. Drive speeds vary enough that a value from a single sequence of bytes wouldn't be very meaningful, but if a disk were written with a bunch of mini-sectors written at different speeds, software could look to ensure that the relative speeds of the different sectors resembled what they should.

 

Modifying a controller card to output such a data probably wouldn't be hard. I don't think such disks could be copied without modified hardware, however.

 

And would any existing disk-copy software even know where to begin?

Link to comment

More likely they cleared the hotspot to point back into their code; it could then either clear itself and reboot, give the user an "are you sure you want to reboot?" or simply refuse to allow a reboot. But on the Apple //e, the user could force a cold boot with the open-apple key. Doing so, however, would cause the kernel to trash two bytes on every page before rebooting. Such memory-trashing behavior was new on the Apple //e and I'm sure was a deliberate effort to discourage memory snapshotting for the purpose of breaking copy protection.

It might prevent casual cracking, but that's about it. There were many ways to prevent this.

 

One was a program called that mirrored the system ROM (including NMI, Reset and IRQ vectors) in RAM, then swapped in the RAM bank. This would hijack the Reset key before any program could get to it. The program pointed to a very small RWTS (Read/Write Track/Sector) routine that dumped the lower 48k of RAM. It worked on most things.

 

Serious crackers could buy an expansion card that fit into a slot. All slots had their own BIOS ROM space (256 bytes of it, but still enough to do something.) It had a switch that interrupted the CPU and jumped to its own ROM, which then was able to write the entire contents of RAM, including the stack, zero page, registers, etc. There wasn't much one could do to protect against something like this.

 

Even without special programs, one could *still* crack most anything. Every Apple disk HAD to have track 0, sector 0 readable by normal means so the Disk II's ROM BIOS could initially read it. This portion always contained a 256-byte bootloader at $0800-$08FF. One could manually read in the bootloader using a hacked version of the Disk II's BIOS, then one modify the bootloader to stop once the next stage was loaded, and so on until the entire disk was read into memory. You could skirt by all manner of protections by simply making the program happily load itself from the nether regions of the disk, then exit to the monitor instead of running the program.

Modifying a controller card to output such a data probably wouldn't be hard. I don't think such disks could be copied without modified hardware, however.

 

And would any existing disk-copy software even know where to begin?

I'm not sure about how your scheme works, but disk copy software often didn't "know" where to look, even for copyable disks. The software came with a manual containing "parameters" that were entered by hand, showing how to instruct the software to copy particular protected disks.

 

The parameters were discovered by reverse-engineering the disks and/or a special disk drive that logged the tracks and sectors it accessed (I've seen one, and it was really slick.)

Link to comment

baratri, I'm not sure it was as simple as you indicate. Sure tools like NMI cards could halt the program, exposing whatever was in RAM; and boot tracing would reveal some of the disk structure, but not all.

 

Really, A2 copy protection came down to two main fronts:

1. Make it as difficult as possible to duplicate the diskette without detection.

2. Make it as difficult as possible to find and remove any disk access code once it was loaded into RAM.

 

I've only seen some references to #2, but it's amazing what you can do when code is in RAM - i.e. self-modifying code and on-the-fly decryption & re-encryption.

 

I also read one reference to one game which was nearly uncrackable - each level was loaded off disk and contained fresh copy protection code.

Link to comment

baratri, I'm not sure it was as simple as you indicate. Sure tools like NMI cards could halt the program, exposing whatever was in RAM; and boot tracing would reveal some of the disk structure, but not all.

 

Really, A2 copy protection came down to two main fronts:

1. Make it as difficult as possible to duplicate the diskette without detection.

2. Make it as difficult as possible to find and remove any disk access code once it was loaded into RAM.

 

I've only seen some references to #2, but it's amazing what you can do when code is in RAM - i.e. self-modifying code and on-the-fly decryption & re-encryption.

 

I also read one reference to one game which was nearly uncrackable - each level was loaded off disk and contained fresh copy protection code.

The NMI cards did more than that. They interrupted the processor and saved all RAM, flags, and registers to disk, so you could reload this from disk at a later date and then issue an RTI, and the program would continue where it left off. As far as the 6502 was concerned, it was just returning from an interrupt. So even a novice could "copy" most software this way.

 

For multiload games, you create a snapshot for each level, and go in and examine the code and replace the protected disk loading with your own custom routine that loads in the new snapshot instead. You don't need to track down the actual disk loading routine or reverse-engineer any decryption; just the event that triggers the disk loading, e.g. finishing the level. And it was rarely necessary to load an entire snapshot. I doubt that many programs did a CRC check of all of RAM, so in most cases, you would just need to load in the parts of RAM that were different (usually not much.)

 

Now, granted the above isn't "simple" in the sense that you need to be quite proficient at assembly programming to pull it off. But cracking was certainly a lot easier than inventing a new protection scheme.

Link to comment
Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...