Jump to content
IGNORED

Disassembling the Educational System Master Cartridge


Recommended Posts

If anyone wishes to read, a snippet of what one of the sections will be like: This is an excerpt from three "chapters" of the Tape Format section. Very much first draft:

 

An FSK Primer

Computers deal with binary numbers. Both programs and data are expressed as streams of binary numbers. Digital data is expressed as a series of states, either on or off, 1 or 0. Each of these states can also be called a ‘bit’ or binary digit. Since the highest that you can count in binary is 1 (remembering that 0 is the first number), you have to add another bit to count to higher numbers. The Atari 400/800 computers were 8-bit computers. This meant that they could handle at most 8 bits of data at one time (with 0 being the smallest decimal number that can be represented, and 255 being the largest). Bigger numbers would require them to be broken down into 8-bit pieces and handled separately.

Typically, these numbers are handled in parallel inside a computer. However, medium such as compact cassette tapes have no way of handling data at 8 bits a time. Also, the Atari peripherals could not handle data in this parallel fashion, so the POKEY chip inside the Atari computer provides a way to ‘serialize’ this information, so that the data can be sent and received one bit at a time. The circuit inside POKEY that does this, is called a ‘shift register.’ Imagine a shift register as a queue of people, that can handle up to 8 people at a time entering, but it can only let one person out at a time. The shift register fills up with 8 bits, and then when requested, lets each of those 8 bits exit, one bit at a time. Let’s call the 1 bits MARKs, and the 0 bits are SPACEs. If these terms seem a bit odd today, it’s because they were defined during the days of radio telegraph transmission, where each transmitted character would be given a number made up of binary digits. The MARKed 1 bits would be signified by a tone, and the SPACEs would be represented by no tone.

Since 8-bits of parallel data, are now serialized, there needs to be a reliable way to determine the actual start of one set of 8-bits (a byte), with another. This is accomplished by providing a start bit at the beginning of each serialized 8 bits, followed by one stop bit at the end. This essentially means that for each 8-bit byte, there are 10 audio bits that are encoded.

While this works well on its own between peripherals, which can natively handle the voltages and nice square wave shaped transitions described by these bits, compact cassette tape mechanisms were designed for audio, and the tape heads expect an analog audio signal. So the question becomes, what is the simplest way you can express single binary digits in an audio form? The answer lies in Audio Frequency Shift Keying (FSK).

With Audio Frequency Shift Keying (AFSK), you assign two easily discernible sine wave tones to represent the binary digits 0 and 1, and when the next binary digit arrives, use the appropriate tone. FSK is typically implemented using a sine wave oscillator, which simply changes its frequency to represent the next tone required. This ensures that the phase of the sine waves are consistent, and that there are no discontinuities in the signal. If the appropriate tones are picked, with regards to the amount of audio bandwidth available, both determined by the width of the tape tracks, and the speed of the tape moving across the transport, one would be able to use a pair of band pass filters, one for each digit, to discern the 1 and 0 digits, and use a comparator circuit to convert them back into the nice square wave pulses used by POKEY. This can be done by a simple comparator circuit, because sine waves are the simplest tone that can be synthesized, which have only a fundamental frequency, and no harmonics that could be incorrectly detected by the filter circuits as false positives.

If this sounds familiar to the way MODEM (modulator/demodulators) work for telephone transmission, that’s because the slower MODEMs worked in exactly the same way. The difference lies in the selection of frequencies for MARK and SPACE tones that can reliably be sent over analogue telephone lines, which are even more constrained than compact cassettes.

In either case, each tone is called an ‘audio bit,’ or ‘baud.’ MODEMs that use frequency shift keying often transmit up to 600 audio bits a second, or 600 baud. With one start and stop bit, this equates to 60 8-bit values per second, and since 8-bits is often used to hold a single character, this is equivalent to 60 characters per second.

So, if all that is needed to reconstruct data encoded with frequency shift keying, is to filter out the requisite tones, and to feed them to comparators, what is needed to construct such tones? All that is needed is a sine wave oscillator that can produce the required frequencies, and that for each bit given, to simply change the frequency of the oscillator to match the bit required. This can easily be done in software, and I provide such an example specifically for the Atari Educational System, in a later chapter in this book.

The Atari form of AFSK

Given the above primer, what are the specifics as to the AFSK format used on the Atari 410 cassette recorder?

The Atari 410 cassette recorder expects the MARK tone (the tone for 1) to be 5327Hz, and it expects the SPACE tone (the tone for 0) to be 3996Hz, respectively. The standard convention for Atari tapes is to place a leader for approximately 15 seconds at the beginning of the tape, to allow for the tape recorder to not only reach a consistent speed, but to also to ensure that the tape recorder has reached the magnetic part of the tape (often, tapes had 10 seconds of a non-magnetic tape strip at the beginning of the tape) The POKEY expects the start bit to be a MARK, 8 data bits, transmitted bit 0 to bit 7, followed by the stop bit, which is a SPACE. The process repeats for each 8 bit byte that needs to be recorded. As mentioned before, this would mean that 8 data bits would become 10 audio bits.

One unique aspect of the Atari Educational System tapes is that all data bits are inverted, that is, an Exclusive OR of $FF is applied to each 8-bit byte, before it is written to tape, and after it is read from the tape. An Exclusive-OR is a logical operation performed on a bit that ensures that the resulting bits get flipped if they aren’t equal. (INSERT TABLE FOR EXCLUSIVE OR) This fact is important, as it means that the NUL byte ($00), which is used for timing, gets written as $FF (all ones), and therefore the data bits look exactly like the stop bit! Two successive 10-bit sequences of 0111111111 are interpreted by the Master Cartridge as “timing marks.”, But why do we need timing marks?

Given that tape medium is subject to jitter, that is, variations in motor speed, asynchronous clocking of the serial data is critical to reconstituting it. Once POKEY is instructed as to how fast the bits are being transmitted, it can watch for the start bit, and time things to properly retrieve the next 8 data bits. The stop bit is then used to tell POKEY that it can pause for a moment, before the next bit of serial data appears. This means that in order to compensate for the possible jitter, the speed of the incoming bits need to be recalculated, and POKEY’s clock readjusted. When two successive timing marks are encountered, a running binary dumped average of the variance from 0 modulus 131 of the difference between VCOUNT when each timing mark was read. Why 131? Because there are 262 total scan lines on an NTSC display, and VCOUNT is only updated every other line. In a perfect world, these timing marks would be 262 scan lines (for NTSC television standards) apart, and the counts would be equal. The difference is expressed as a fraction, which is then used to adjust POKEY’s baud rate to match the rate coming in off the tape.

In contrast to the cassette routines defined in the Atari Operating System, which batch transfers to the cassette tape in blocks, with timing marks framing each block, the Educational System data is streamed character by character to the tape, in order to keep in synch with the audio on the left track. Each incoming byte is then received by POKEY interrupt, and immediately interpreted, the details of which are explained in the disassembly chapter.

Method Used for Forensic Analysis

Modern software emulators are a wonderful tool for debugging and forensic analysis. You can, at any point, stop the running simulation of a machine, and instantly observe virtually every single aspect of its current state, a feature that before the advent of emulation, was only available to hardware logic analyzers and in-circuit hardware emulators that were part of microprocessor development systems costing in the 5 to 6 figures. With this ability, every memory location, program instruction, input/output register, and processor state can be tracked, and thus program behavior can be determined. From the program behavior, or sometimes, even from simply looking at the contents of a buffer in memory, data can be extracted, and subsequently analyzed for meaningful patterns. In addition, memory locations can be changed while the program is running, which can speed up introspection even further once important memory locations have been found, by providing a quick way to observe values and observing their effects.

When I initially tried to decode the existing tapes, I used the existing operating system routines to try and read data off the tape. Since the data is not block based, with the requisite timing blocks wrapping each data block, no data was being returned, and the operating system immediately returned from attempting to read the tape, with an error. I was very confused, until I actually listened to the differences between a typical Atari cassette, and an Educational System cassette in headphones. It became clear to my ears that the data was streamed, one byte at a time, with spaces between each bit.

Discovering this, I dug into the Atari Hardware Reference Manual, and the Altirra Hardware Reference manual, as well as the Atari Operating System Reference manual, to discover how the computer normally tried to read cassette data. As it turned out, if I turned on the cassette motor, not only was data appearing at SERIN, but SKSTAT was being set. I was definitely seeing data come across the serial bus, but it was all nonsensical. What was I doing wrong?

At this point, I received a disassembly from Xuel, of the Educational System Master Cartridge, which, when loaded into the emulator, along with the Educational Master System cartridge, and turning on the debugger and disassembly views, I was able to trace through the code. I will present a detailed disassembly of the master cartridge in the disassembly chapter, but I will sufficiently say that once I found that the cartridge replaced the POKEY immediate IRQ vector with a routine of its own, I was able to trace into it on the cartridge on each serial byte input, and therefore get the encoded data one byte at a time. This helped, but the data still seemed to be garbage, was the data being transformed while it was being read?

The answer came from an anonymous and internal Atari Engineering document, “All About Cassette Tapes”, which had a section on the format of “Dorsett Educational Tapes.” After explaining that the data was not only streamed, it made a small mention that every byte being written to tape was Exclusive-ORed with the bit pattern $FF (all bits 1), which has the effect of inverting each and every bit for transmission. The reason why was discussed previously, but once I had realized this, I opened up a calculator, and punched in each byte as it appeared in SERIN, into calculator, EOR $FF, and suddenly the bytes started to make sense, I was seeing letters, numbers, and other control characters appear.

Reading the disassembly, I was able to read and understand enough of the initialization routines, and the IRQ routines, that I was able to transplant those pieces into a stand alone program, that on each POKEY serial interrupt would simply loop while grabbing the next character from the cassette, place it into a buffer beginning on page 6 of memory ($0600, 1536 decimal), while incrementing X. Since X is an 8-bit register, and since pages of memory on the 6502 are 256 bytes long, this loop would wrap around the buffer at 256 bytes, and that is how much of the buffer I could see at one time. At 32 characters a line, that provides 8 lines of visible text, which was more than sufficient to verify that I was at least getting valid data from the cassette. But how to display it so I could see it?

I could just as easily have stopped the program at random points, and looked at the contents of page 6 of memory. The memory tab in the debugger is sufficient for this task, providing not only a hexadecimal representation of each byte at this block of memory, but a human readable ASCII representation as well, filtering out any non printable characters. However, having to stop the program to view the changed contents of memory would prove very cumbersome, and ineffective at best. If I were to use this technique, I would be stopping the program every few seconds to “sift through the tea leaves.” At this point, I just needed to check that I was understanding how the data was being decoded off of tape.

Remember that ANTIC handles the interaction of display and memory access for the computer. Recall that in ANTIC, mapped modes function as a grid of tiles (which could be graphics or text), and that each combination of modes can get their data from a specific point in the computer’s memory. Using this, I can construct a display list of 8 lines of text characters (also known as mode 2), and tell ANTIC to fetch this data from page 6. After setting the ANTIC to use a narrow play field (128 pixels across, or 32 characters), I am left with a nice, simple window into page 6 of memory that I can see on my display in real time. Upon adding a few small niceties to the program (such as waiting for the START key to be pressed, before starting the cassette.), I assembled, and ran the program, and was surprised at the result. I began to see text appear in the small window I had constructed!

It wasn’t perfect, the text wasn’t centering itself nicely, and I was seeing other characters, particularly uppercase characters were being displayed with graphic characters, and highlighted characters were being displayed as inverse graphic characters. This was because the character set as used in memory does not exactly map to the ASCII method of character encoding, but upon doing a few quick calculator checks with the “weird looking” characters, I was able to determine that they were indeed correct as encoded on the tape, and that my method for decoding the data was also correct.

I then returned to the Master Cartridge in the debugger, and spent the next few hours comparing what I was seeing in my bespoke decoder, with the results of the Master Cartridge. The data was matching byte for byte, almost. What accounted for the difference?

Recall that in the explanation of the tape format in a previous chapter, two successive NUL bytes were used as “timing marks” as specified by “All About Cassette Tapes.” This causes the program to time and calculate the difference between these timing marks as a fraction to adjust the baud rate that POKEY clocks itself to. Can this be observed? Of course, we can look at the frequency that POKEY clocks the data to, this is stored in the frequency register of sound channel four, also known as AUDF4, but this value is in essence a value which must be calculated from the selected clock (15KHz in this case), and it’s a bit cumbersome to recalculate this value by hand on a calculator when it potentially changes frequently. Is there a better way? Yes, Altirra has an “audio monitor” facility, which not only shows the clocks of each POKEY timer, but their frequency values, and waveforms, as well. Since POKEY in this case is only being used to clock the incoming data, the waveform display isn’t useful, but the frequency values are, and they are displayed as hertz values, already calculated for us. Running the Master Cartridge, with a lesson, while watching the audio monitor did indicate that at various points, pauses and the like, that the clock rate was indeed recalculated and the frequency of the incoming data ever so slightly adjusted to account for jitter in the tape.

Knowing this, and knowing that the Master Cartridge was decoding the data correctly, I opted to periodically look at page 6 of memory to decode the data on the tape. The proceeding chapters show the results of this work.

Still far too much to do, manuscript is only the first step.

-Thom

  • Like 5
Link to comment
Share on other sites

  • 4 weeks later...

Thank you for the kind words, Doctor.

 

There is more coming, I am currently working with Kevin Savetz to do a massive archiving of the remaining Dorsett Talk&Teach tapes (there are 45 sets, 8 cassettes a piece), we have roughly 10 sets to go, then I return to working on the manuscript.

 

-Thom

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   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...