The story of 15 Second Copy for the C-64

by Mike Pall, published with permission.

[This is a follow-up to Thomas Tempelmann’s Story of FCopy for the C-64.]

Ok, I have to make a confession … more than 25 years late:

I’ve reverse-engineered Thomas Tempelmann’s code, added various improvements and spread them around. I guess I’m at least partially responsible for the slew of fast-loaders, fast-copys etc. that circulated in the German C64 scene and beyond. Uh, oh …

I’ve only published AFLG (auto-fast-loader-generator) under my real name in the German “RUN” magazine. It owes quite a bit to TT’s original ideas. I guess I have to apologize to Thomas for not giving proper credit. But back then in the 80’s, intellectual property matters wasn’t exactly something a kid like me was overly concerned with.

Later on, everyone was soldering parallel-transfer cables to the VIA #1 of the 1541 and plugging them into the C64 userport. This provided extra bandwidth compared to the standard serial cable. It allowed much faster loading of programs with a tiny parallel loader (a file named “!”, that was prepended on all disks). Note that the commercial kits with cables, custom EPROMs and silly dongles followed only much later.

So I wrote “15 second copy”, which worked with a plain parallel cable. Yes, it copied a full 35 track disk in 15 seconds! There was only one down-side: this was only the time for reading/writing from and to disk — you had to swap the floppies seven times (!) and that usually took quite a bit more extra time! ;-)

It worked by transferring the “live” GCR-encoded data from the 1541’s disk head to the C64 and simultaneously doing a fast checksum. Part of the checksumming was done on the 1541, part was done on the C64. There simply weren’t enough cycles left on either side! Most of the transfer happened asynchronously by adjusting for the slightly different CPU frequencies and with only a minimum number of handshakes. This meant meticulous cycle counting and use of some odd tricks.

The raw GCR took up more space (684*324 bytes) in the C64 RAM, so that’s why it required 4 passes. Other copy programs fully decoded the GCR and required only 3 passes. But GCR decoding was rather time-consuming, so they had to skip some sectors and read every track multiple times. OTOH my program was able to read/write at the full 300rpm, i.e. 5 tracks per second plus stepper time, which boils down to 2x ~7.5 seconds for read and write. Yep, you had to swap the floppies every 2 seconds …

Ok, so I spread the program. For free. I even made a 40 track version, which took 17 seconds. Only to see these coming back in various mutations, with the original credits ripped out, decorated with multiple intros, different groups pretending they wrote it or cracked it (it was free, there was nothing to crack!). The only thing they left alone were the copy routines, probably because they were extremely fragile and hard to understand. So it was really easy to recognize my own code. Some of the commercial parallel-cable + ROM kits even bragged with “Backups in 15 seconds!”. These were blatant rip-offs: they basically changed the screen colors and added a check for their dongles. Duh.

Let’s just say this rather frustrating experience taught me a lot and that’s why I’m doing open source today.

So I shelved my plans to write an enhanced version which would try to compress the memory to reduce the number of passes. Ah, yes … I wrote quite a few packers, too … but I’ll save that story for another time.

I still have the disks with the source code somewhere in my basement. But I’m not so sure I’ll be able to read them anymore. They weren’t of high quality to begin with … and I’d have to find my homegrown toolchain, too. ;-)

But I took the time to reverse-engineer my own code from one of the copies that are floating around on the net. For better understanding on the C64/1541 handshake issues, refer to this article. If you’re wondering about the weird bvc * loops: the 6502 CPU of the 1541 has an SO pin, which is triggered by a full shift register for the data from the disk head. This directly sets the overflow flag in the CPU and allows reading the contents from the shift register with very low latency.

Yes, there’s a lot more weird code in there. For the sake of brevity, here are only the inner loops of the I/O routines for the read, write and verify pass for the C64 and the 1541 side. Enjoy!

  ;--- 1541: Read ---
  ldy #$20
f_read:
  bvc *        ; Wait for disk shift register to fill
  clv
  lda $1c01    ; Load data from disk
  sta $1801    ; Send byte to C64 via parallel cable
  inc $1800    ; Toggle serial pin
  eor $80      ; Compute checksum for 1st GCR byte in $80
  sta $80
  bvc *
  clv
  lda $1c01    ; Load data from disk
  sta $1801    ; Send byte to C64 via parallel cable
  dec $1800    ; Toggle serial pin
  eor $81      ; Compute checksum for 2nd GCR byte in $81
  sta $81
  ; ...
  ; Copy and checksum to $82 $83 $84
  ; And another time for $80 $81 $82 $83 $84 with inverted toggles
  ; ...
  dey
  beq f_read_end
  jmp f_read
f_read_end:
  ; Copy the remaining 4 bytes and checksum to $80 $81 $82
  ; Lots of bit-shifting and xoring to indirectly verify
  ; the sector checksum from the 5 byte xor of the raw GCR data

  ;--- C64: Read ---
  ; Setup ($5d) and ($5f) to point to GCR buffer
  ldy #$00
c_read:
  bit $dd00    ; Wait for serial pin to toggle
  bpl *-3
  lda $dd01    ; Read incoming data (from 1541)
  sta ($5d),y  ; Store to buffer
  iny
  bit $dd00    ; Wait for serial pin to toggle
  bmi *-3
  lda $dd01    ; Read incoming data (from 1541)
  sta ($5d),y  ; Store to buffer
  iny
  bne c_read
c_read2:
  bit $dd00    ; Wait for serial pin to toggle
  bpl *-3
  lda $dd01    ; Read incoming data (from 1541)
  sta ($5d),y  ; Store to buffer
  iny
  bit $dd00    ; Wait for serial pin to toggle
  bmi *-3
  lda $dd01    ; Read incoming data (from 1541)
  sta ($5d),y  ; Store to buffer
  iny
  cpy #$44
  bne c_read2

  ;--- C64: Write ---
  ; Setup ($5d) and ($5f) to point to GCR buffer
  ldy #$00
  tya
c_write:
  eor ($5d),y  ; Load from buffer and compute checksum
  bit $dd00    ; Wait for serial pin to toggle
  bpl *-3
  sta $dd01    ; Store xor'ed outgoing data (to 1541)
  iny
  eor ($5d),y  ; Load from buffer and compute checksum
  bit $dd00    ; Wait for serial pin to toggle
  bmi *-3
  sta $dd01    ; Store xor'ed outgoing data (to 1541)
  iny
  bne c_write
c_write2:
  eor ($5f),y  ; Load from buffer and compute checksum
  bit $dd00    ; Wait for serial pin to toggle
  bpl *-3
  sta $dd01    ; Store xor'ed outgoing data (to 1541)
  iny
  eor ($5f),y  ; Load from buffer and compute checksum
  bit $dd00    ; Wait for serial pin to toggle
  bmi *-3
  sta $dd01    ; Store xor'ed outgoing data (to 1541)
  iny
  cpy #$44
  bne c_write2
  ldx $5b
  sta $0200,x  ; Store checksum for verify pass
  inx
  stx $5b

  ;--- 1541: Write ---
  ldy #$a2
  lda #$00
f_write:
  bvc *        ; Wait for disk shift register to clear
  clv
  eor $1801    ; Xor with incoming data (from C64)
  sta $1c01    ; Write data to disk shift register
  dec $1800    ; Toggle serial pin
  lda $1801    ; Reload data to undo xor for next byte
  bvc *        ; Wait for disk shift register to clear
  clv
  eor $1801    ; Xor with incoming data (from C64)
  sta $1c01    ; Write data to disk shift register
  inc $1800    ; Toggle serial pin
  lda $1801    ; Reload data to undo xor for next byte
  dey
  bne f_write

  ;--- 1541: Verify ---
  ; Get checksum computed by c_write on the C64 side
  ldy #$a2
f_verify:
  bvc *        ; Wait for disk shift register to fill
  clv
  eor $1c01    ; Xor with data from disk
  bvc *        ; Wait for disk shift register to fill
  clv
  eor $1c01    ; Xor with data from disk
  dey
  bne f_verify
  ; Verify is ok if checksum is zero

28 thoughts on “The story of 15 Second Copy for the C-64”

  1. Your experience with others ripping your program, replacing your name with theirs, removing your credits is exactly the same that happened to me with my first FCopy releases. I did understand the pirating but was very upset about them taking credits for my original work. Had I not done the research on how to make use of the intelligent 1541 DOS, none of these fast would have come out any time soon. After all, the 1540/41 were already out for quite a while, and there were many attempts at faster disk copy programs, all limited to ~25 minutes due to them all relying on the standard DOS operations. When I did my research, there was practically NO docs available to me, other than the 6502 instructions book. There was not even a description of what the VIAs in the 1541 actually did, how they worked, what they were connected to. So I looked at 8 or 16KB of disassembly without even knowing what any of it would do. E.g, only much later I learned why there was a weird two-level processing going on (its bigger predecessors used two CPUs for different tasks and the 1541 simulated these in one CPU). There was, however, one thing that helped me understanding the DOS better: The Apple ][ DOS 3.3 handbook, which explained how (GCR-like) disk encoding worked in principle. I had not been able to afford a Apple back then, but some friends of mine all had one, while I was the only with that “pityful” VC-20, later C-64. They were all smart and friendly people, and I learned a lot from them (Jörg Noack, Thomas Schumacher, Meinolf Schneider, Ulf Reimann and Jürgen Müller).

  2. @TT: Oh, I can definitely relate to the general lack of information. One of my first programs I wrote was a 6502 disassembler (in BASIC, ugh), because I wanted to understand the VIC-20 ROMs (I was 12 at the time). Those convenient ROM listing books came out much, much later.

    The other issue was a general lack of tools. My friends were only interested in swapping games, but I wanted tools! Assemblers, disassemblers, monitors — tools! Of course, these were completely unaffordable for a kid. Not that you’d find them in any of the local stores, anyway. That was what really held me back in the beginning. So I resorted to disassembling everything that crossed my path and learned a lot in the process. We’ve always been standing on the shoulders of giants.

    About the blatant rip-offs and lack of giving credit: we were operating in a community with corrupt values, anyway. You can’t expect to form a meritocracy when everyone was violating authors’ rights en masse. Yes, that was part of the success story of the C64. But I guess it was a nightmare for many software authors. After that incident with 15 second copy, I could at least relate to their experience.

    IMHO that’s the most clever aspect of open source: it encourages sharing of code and ideas, but requires you to give credit at the time. This makes stealing code a totally pointless and antiquated concept.

  3. Very cool, I remember paying a hacker acquaintance to have a custom parallel cable installation soldered onto my C64/1541 for the purpose of doing fast disk copies. If I remember correctly, the program I used was called Fast Hack’Em and I seem to recall that it pretended to make copies in 21 seconds. I don’t know if that program was a ripoff of your code or not but I remember that there were quite a few other disk utilities from the same group, all sharing a similar look and feel. Those were good times, I have very fond memories of that era. I even wrote my own C-128 assembly-language level debugger and an Internet Friend (Randy Winchester) included it a utilities ROM chip that he made available for the C-128. Apparently my debugger program (called Hexpert) is still available on the Internet: http://www.fragit.net/cbm/c128/utils/index.html

    Thanks for the memories!!!

  4. I wrote a fast loaded for the C64 back in the day too. I had access to a print out of the source code for the 4040 disk drive and using it as a guide I disassembled the 1541 roms and figured out what was going on. My fast loader worked using the standard cable. The hardest part was getting around the fact that the screen hardware stole cycles from the CPU. So my code had to look at the current raster value and pause when it was on a line that stole cycles from the CPU and then run full speed again when it could (other loaders got around this by turning off the screen). It was a lot of fun but also very frustrating debugging code inside the 1541 when it crashed.

    • Now there is a name I recognize.. Yes it was hard to find into at the time but once some of it leaked into the public, it was easy to figure out how to go from there. The idea is what is hard. That such and such can be done.

  5. hi, I read all and I have a question ?some of you used two of this modified drives at the same time? I mean, Im Atari user and is more common to use two drives at the same time, one like D1: and the second D2: via set dip switchs on the rear. ?some of you do some similar with parallel-transfer cables instaled?

    • Yea its getting there.. Friends are falling left and right these days.. Loose a few every year now.

    • I had copiers that would use one source and you could write to 3 drives!

      I was a good little pirate by rarely needed that kind of firepower.

    • Well yea there were many.. You could daisy chain the drives upto 4 of them..

      Our copier played music while it was copying disks.. You could just remove the cable and it kept doing its thing..

      The drives waited until the source disk was inserted and the drive door closed.. Then the destination drive waited until a disk was inserted and the drive door closed and they then started duplicating the disk..

      You did not need the computer at this point so the demo screens and music etc were pointless.. You could just turn off the computer and keep copying disks all day long.

  6. Yes, there was a program that would load up two 1541’s and they would copy a disk by themselves, you could even turn off the computer. Wasn’t as fast as c64 based copiers though.

    • The drives only had 2k memory.. So it had to read and decode the data and check for errors before sending it over to the destination which was the same speed as sending it to the computer.. It saved time because the computer did not have to send the data back to the drive.. But the destination had to re-encode the data and find the correct sector and write out the sector. And do that for each sector.. And if the destination missed the proper sector, it had to wait until it reappeared again to write that data out and that stooped the sourced drive from reading any further data.

      It seems, sending the data from the computer was faster since this problem was not as bad as you could calculate the sector to write out and time it and index into the correct block to data to write out.

      But then whats the novelty??? You had to have the computer on and its like whats the biggie???

      Now to really surprised someone, you started the copy and turned off the computer unplugged it and took it to the other room and they would just stare with bulging eyes and look at the drives which still seemed to be doing their thing..

      ahhhhhhhhhhhhh…

  7. I wonder if anyone did a version with REU-support to store the data there and copy without changing disks. That would have been something.

    • C64 was my first computer, got one around 1994. I learned assembler pretty quickly, even wrote code for a part of some shitty music player my friend was doing (he was hardcore into C64 scene).

      >I wonder if anyone did a version with REU-support to store the data there and copy without changing disks. That would have been something.

      I think such fast copier existed. I remember seeing C64 + ram expansion cart + floppy copying whole disks at a time while flashing demo scene logo of some kind. It was at the “Commodore & Amiga” editor’s office ~1995 about a month after they closed shop.

    • Yes. I did a REU version for this nice copy program. That saved a lot of time for disk swapping.

  8. I can’t remember if there was an REU based single-pass disk copy (but there probably was), however I know for sure that Super Snapshot (cartridge like Action Replay) came with a copier that made use of an extra 32K ram module which could optionally be upgraded in the cartridge. This could be 2-3 passes theoretically.

  9. Fast Hack’em was not a ripoff, and was by Mike J. Henry, one of the original crackers. e wa sbetter at copy programs then cracking though.

    That said, people just LOVED to steal each other parameters even with the reputable programs.

    And yeah, anytime someone made a fast loader, it got ripped off, though new legit fast loaders got written all the time too. Does’t help that there’ pretty much only one way to do the standard 5x speedup with screen on. SO independent development in parallel happened.

    Vorpal was the original “omg fastest serial loader EVAR!!!” for the c64 (which was developed for the Barbie game, as I recall, and used to great effect legitimately on MANY Epyx, Locasfilm, and other titles), and a number of freezer carts ripped it off (Warp*25, Lazer load, etc.). There also was Heureka Sprint, which was also a ripoff with the decode tables shuffled around.

    Freeload (also known as Ocean Loader) on the tape side was shamelessly ripped off back in the day too. by many publishers. Oddly enough, since it provided great anti dubbing protection, it’s author was not too bitter about discovering that.

    Disk IRQ loaders were ripped all the time too, such as the one used for G.I. Joe.

    • Vorpal Utility Kit also allowed users to make their files Vorpal! So all those 200 block games loaded in 3 seconds!

      Also, RapidLok was pretty good but Kracker Jax (Washington State store) sold a $19 disk that copied all RapidLok.

      I considered Vorpal and RapidLok my two worst enemies for a long time until we could copy them.

  10. Amazing things here. I’m very satisfied to see your post.
    Thank you so much and I am having a look ahead to contact you.
    Will you please drop me a mail?

  11. I remember quite well Fast Hack’em by Mike J. Henry, it was probably the most amazing fast and reliable copier at the time, using two unmodified 1541 drives (ID 8 and 9) without having to swap disk at all, copied a full single sided disk in about 30 seconds. The only option to speed it up a bit was to disable “verify” which wasn’t recommended due to the unreliability of the disks and drives at that time. Those who have used that program will probably remember the cool menu opening routine, which opened up from the middle of the screen and expanded like some binds in both directions. Ahh those magical times! ;)

  12. Yes I know what releasing something and then seeing someone else’s name on it feels like. I released a file copier I was doing for an upgrade into PD and saw some came back as cracked.. Crack what??? It was unprotected share ware.. It had a text file about who wrote it and address if they wanted to send some compensation for it. Maybe removing that text file was the crack.

Leave a Reply to nitro2k01 Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.