Crazy Commodore Tricks - Part One
11 years ago
General
There are so many things I find amazing when looking back on the Commodore 64. A lot of "if I knew then what I knew now". Especially over the SID chip. Now that I'm big into music, I see it for what it was: a 3-voice synthesizer with envelopes, ring-modulation, variable pulse width waveforms and filters... even the ability to take the output of the third voice and feed it back into the filter control as an LFO. I never appreciated that stuff when I had the machine in my hands.
Lately I've been tripping down memory lane with back issues of COMPUTE! magazine. Our family got COMPUTE! regularly, until the Commodore-only spin-off COMPUTE!'s Gazette started up. Which means there's a whole section of COMPUTE! that overlapped Gazette that I never saw, but (oddly enough) seemed to share the same programs at times. And looking back into that archive, I've come across some mind-blowing tricks that people pulled with those great 8-bit machines.
Today, we're going to examine the story of TurboTape.
TurboTape was a utility for the C64 that (as the name implies) sped up tape access... sort of. What it did was save data in a different coding on the tape, allowing much faster loading... nearly as fast as they might load from disk. How was this accomplished? Very simply: each bit was encoded as either a short tone (1) or a long tone (0). (When I say "short" and "long", we're talking about milliseconds here... something that would sound like noise if you played it back on an audio player). Using the TurboSave utility, you could save your program in this new, efficient coding.
Reading the data back was criminally simple: the reader would set a hardware timer to a value between the short and long durations. Then it employed a tight loop that would fire the timer when the tone started, and check the timer status register when the tone ended. If the timer was still going, it was a short tone and the register held a 1. A long tone, the timer would have expired and the register would hold a 0. Copy the status register into the byte you were building and do it again.
The loading times were further cut by throwing out redundant information: none of this had any sort of checksumming or CRC, and Commodore machines would save two copies of a program on tape, just in case the first one had errors in it. TurboTape was then a bit of a high-wire act without a net, but it was rather reliable even without the extra redundancy.
Now you might think that you'd need a similar TurboLoad utility to load programs saved with TurboTape. After all, a stock C64 isn't going to recognize the custom coding. But you'd be wrong. Once you saved a program in TurboTape format, you could take it to your friend's house and load it right up on their plain-vanilla no-TurboTape Commodore 64. No joking! It would even load at turbo speed. How in the world did that work?
Well, the first thing you have to know about the Commodore 64 was there was that the memory was wide open. We probably didn't know the term at the time (I sure didn't) but this was working closer to the metal than machines these days. No fancy graphics or sound commands, no exception handlers, development environments. No execution protection to slap the hands of a program trying to mess with memory it shouldn't... you POKED your values into memory locations and the computer trusted you knew what you were doing. <Jeff Foxworthy>You wanna POKE weird numbers into zero-page memory? Try that out. OHH! Crashed the computer, didn't it? Don't do that no more.</Jeff Foxworthy>
So in that spirit, you could make saved data load anywhere in memory and the machine would happily do it for you. Every saved program, on tape and on disk, is saved with a starting memory location for loading. In the case of BASIC programs it's the start of BASIC memory. For machine language programs it's the starting address for the code. And it didn't have to be a program: this was super-efficient for loading sprite data directly into their indexed memory locations, or even dropping character data directly to screen memory for game playfields. These days this would be viewed as frighteningly insecure, but again... you were trusted to know what you were doing.
The second thing to know is about the standard format of saved data on tape. Mainly that the format called for 180 characters dedicated to a filename. And the machine will dutifully read all 180 characters into the cassette buffer memory, even though the kernel only uses the first 16 of them for the actual name.
So armed with those two items, how exactly does a TurboTape-saved program load correctly on a vanilla C64? Before the actual new coding starts on the tape, TurboTape saves a more standard program that any C64 can read. A very, very short program with an interesting filename. The first 16 characters of the filename are what you'd expect... the name of the program when it was saved. But after that... in the remaining 164 characters... are characters that when loaded into memory, comprise the values of the machine language code for the TurboTape loader. Which as noted in point two above, the system loads into the cassette buffer memory.
Somebody out there is scratching their head, thinking, "Wait, isn't that a...?" Yes, yes it is. A classic buffer overrun exploit. So now the TurboTape reader is loaded into memory. How does it get run?
Remember point one? Every saved program has a starting address, and the computer loads the data where it's told. So after the filename on the tape is the actual program. Only this "program" is a few bytes that make up the address in the cassette buffer memory where the reader is loaded. And the address to load them into is the jump-vector for the close-all-files routine that is run when a program is done loading.
So we have the TurboTape reader loaded into the cassette buffer via a buffer overrun. We have the close-all-files vector re-written to point to the reader by the actual loading of the "program" saved on tape. Now that program has finished loading, so what happens? The system needs to close out the file and jumps to the location pointed at by the re-written vector... which starts the TurboTape loader! Interception! The "play" button is still pressed on the Datasette, so TurboTape sets the bits to start the motor and takes over, reading the specially coded data saved afterward and decoding it into memory. Once it's done, it jumps to the proper close-all-files routine to wrap things up and life carries on normally.
Amazing, isn't it? Exploiting a buffer overrun and the ability to load anything anywhere allows you to save programs in a special, fast-reading format that contain their own self-executing loader code. Talk about thinking out of the box!
Now if you thought that was mind-bending, wait until our next installment. Wherein we learn how some very inspired memory-warping can get you programs (both BASIC or machine language) that run automatically when loaded.
COMPUTE! would later publish TurboDisk, a utility to speed up the Commodore 64's infamously slow 1541 disk drive. There's less trickery there, but only because the 1541 disk drive contained its own 6502 processor, ROM and even RAM. It was a computer unto itself, which let it do so much more than any disk drive before or after. But... that's a story for another journal entry.
Lately I've been tripping down memory lane with back issues of COMPUTE! magazine. Our family got COMPUTE! regularly, until the Commodore-only spin-off COMPUTE!'s Gazette started up. Which means there's a whole section of COMPUTE! that overlapped Gazette that I never saw, but (oddly enough) seemed to share the same programs at times. And looking back into that archive, I've come across some mind-blowing tricks that people pulled with those great 8-bit machines.
Today, we're going to examine the story of TurboTape.
TurboTape was a utility for the C64 that (as the name implies) sped up tape access... sort of. What it did was save data in a different coding on the tape, allowing much faster loading... nearly as fast as they might load from disk. How was this accomplished? Very simply: each bit was encoded as either a short tone (1) or a long tone (0). (When I say "short" and "long", we're talking about milliseconds here... something that would sound like noise if you played it back on an audio player). Using the TurboSave utility, you could save your program in this new, efficient coding.
Reading the data back was criminally simple: the reader would set a hardware timer to a value between the short and long durations. Then it employed a tight loop that would fire the timer when the tone started, and check the timer status register when the tone ended. If the timer was still going, it was a short tone and the register held a 1. A long tone, the timer would have expired and the register would hold a 0. Copy the status register into the byte you were building and do it again.
The loading times were further cut by throwing out redundant information: none of this had any sort of checksumming or CRC, and Commodore machines would save two copies of a program on tape, just in case the first one had errors in it. TurboTape was then a bit of a high-wire act without a net, but it was rather reliable even without the extra redundancy.
Now you might think that you'd need a similar TurboLoad utility to load programs saved with TurboTape. After all, a stock C64 isn't going to recognize the custom coding. But you'd be wrong. Once you saved a program in TurboTape format, you could take it to your friend's house and load it right up on their plain-vanilla no-TurboTape Commodore 64. No joking! It would even load at turbo speed. How in the world did that work?
Well, the first thing you have to know about the Commodore 64 was there was that the memory was wide open. We probably didn't know the term at the time (I sure didn't) but this was working closer to the metal than machines these days. No fancy graphics or sound commands, no exception handlers, development environments. No execution protection to slap the hands of a program trying to mess with memory it shouldn't... you POKED your values into memory locations and the computer trusted you knew what you were doing. <Jeff Foxworthy>You wanna POKE weird numbers into zero-page memory? Try that out. OHH! Crashed the computer, didn't it? Don't do that no more.</Jeff Foxworthy>
So in that spirit, you could make saved data load anywhere in memory and the machine would happily do it for you. Every saved program, on tape and on disk, is saved with a starting memory location for loading. In the case of BASIC programs it's the start of BASIC memory. For machine language programs it's the starting address for the code. And it didn't have to be a program: this was super-efficient for loading sprite data directly into their indexed memory locations, or even dropping character data directly to screen memory for game playfields. These days this would be viewed as frighteningly insecure, but again... you were trusted to know what you were doing.
The second thing to know is about the standard format of saved data on tape. Mainly that the format called for 180 characters dedicated to a filename. And the machine will dutifully read all 180 characters into the cassette buffer memory, even though the kernel only uses the first 16 of them for the actual name.
So armed with those two items, how exactly does a TurboTape-saved program load correctly on a vanilla C64? Before the actual new coding starts on the tape, TurboTape saves a more standard program that any C64 can read. A very, very short program with an interesting filename. The first 16 characters of the filename are what you'd expect... the name of the program when it was saved. But after that... in the remaining 164 characters... are characters that when loaded into memory, comprise the values of the machine language code for the TurboTape loader. Which as noted in point two above, the system loads into the cassette buffer memory.
Somebody out there is scratching their head, thinking, "Wait, isn't that a...?" Yes, yes it is. A classic buffer overrun exploit. So now the TurboTape reader is loaded into memory. How does it get run?
Remember point one? Every saved program has a starting address, and the computer loads the data where it's told. So after the filename on the tape is the actual program. Only this "program" is a few bytes that make up the address in the cassette buffer memory where the reader is loaded. And the address to load them into is the jump-vector for the close-all-files routine that is run when a program is done loading.
So we have the TurboTape reader loaded into the cassette buffer via a buffer overrun. We have the close-all-files vector re-written to point to the reader by the actual loading of the "program" saved on tape. Now that program has finished loading, so what happens? The system needs to close out the file and jumps to the location pointed at by the re-written vector... which starts the TurboTape loader! Interception! The "play" button is still pressed on the Datasette, so TurboTape sets the bits to start the motor and takes over, reading the specially coded data saved afterward and decoding it into memory. Once it's done, it jumps to the proper close-all-files routine to wrap things up and life carries on normally.
Amazing, isn't it? Exploiting a buffer overrun and the ability to load anything anywhere allows you to save programs in a special, fast-reading format that contain their own self-executing loader code. Talk about thinking out of the box!
Now if you thought that was mind-bending, wait until our next installment. Wherein we learn how some very inspired memory-warping can get you programs (both BASIC or machine language) that run automatically when loaded.
COMPUTE! would later publish TurboDisk, a utility to speed up the Commodore 64's infamously slow 1541 disk drive. There's less trickery there, but only because the 1541 disk drive contained its own 6502 processor, ROM and even RAM. It was a computer unto itself, which let it do so much more than any disk drive before or after. But... that's a story for another journal entry.
FA+

Hi Kerosel and Vyl! *tailsnuggle*
Thanks for the link, I learn something new from you guys every day.