Saturday, June 27, 2020

Weak bits floppy disc protection: an alternate origins story on 8-bit

Floppy disc copy protection schemes are varied and interesting. It's an interesting intellectual challenge: what schemes can be created whereby home computers could reliably read a given disc, but not be able to easily (or at all) write that data back in the same format?

When talking about floppy disc copy protection code, I find it useful to split into two separate pieces:
  • The on-disc bits that are tricky to replicate.
  • The loader code that obfuscates the check of the on-disc bits and the game code, making the check hard to "patch out".
This post concerns the former: on-disc bits. Some of my favorite on-disc schemes include the so-called "Spiradisc" protection scheme and the fuzzy bits scheme used by Dungeon Master for the Atari ST, as explained in excellent detail in this article. I also recommend this great overview of Commodore 64 disc protection schemes. To be charitable, the Commodore 64 had a.... "quirky" disc drive setup.

I recently encountered an on-disc scheme on a BBC Micro disc that was more sophisticated than I was expecting: weak bits. Weak bits and similar schemes were celebrated in the 16-bit era but here we have it in the 8-bit era.

Floppy what now?

Only the left two are actually "floppy", and the middle 5.25" disc is actually called a "mini" floppy!

Floppy disc drives and controllers are likely simpler than you think. The job of the floppy drive is to take the analog magnetic information on a disc surface and turn it into a series of digital pulses. The job of the floppy controller is to take the series of digital pulses, discern timing, and generate a string of data bytes. The floppy controller usually also has the responsibility of spotting special marker bytes in the pulse stream so that distinct sectors can be identified.

This oscilloscope trace from a 1980s disc drive may help you visualize things better:

Blue line is the analog amplified read head signal; yellow pulses are the digital read output from the drive

Every peak in the blue line is the drive head sensing a magnetic flux reversal on the disc surface. Upper and lower peaks are treated identically and result in a digital pulse getting sent to the disc controller, which is the yellow line.
Note that tools such as an OmniFlop, KryoFlux or GreaseWeazle might occasionally refer to "raw flux" reads or dumps but beware they that only get to see the yellow line in the trace above, which is a lossy view of the blue line.

Looking at the yellow line, you may notice that there's a fairly regular cadence to the peaks. In fact, every 4 microseconds, there is a timing "slot" and there will either be a pulse or no pulse. If there's a pulse, that's a 1 bit. No pulse and that's a 0 bit. And as simple as that, there's a bit stream for the disc controller to interpret and hand off to the host computer.

Different computers use different encoding schemes. We're focusing on the BBC Micro this post, where most discs used FM encoding, aka. single density. This is a very simple encoding, an evidenced by the fact we can eyeball the 0 and 1 bits in the scope trace above. MFM encoding was generally more common in the era.

Sectors in the stream

The disc controller takes the pulse stream and makes sense of it. As mentioned above, in FM (sometimes called DFM) encoding, each pulse or non-pulse represents a 1 or 0 bit. These bits are a mix of clock bits and actual data bits. Clock bits are needed for a couple of reasons: as a source of timing to sync to, and also to prevent the disc drive from thinking it has lost the signal. There must be a pulse at least every 8us to keep everything reliable. FM encoding takes the simple route: every other on-disc bit is a clock bit and they will all be 1 almost all of the time.

So now we know how to separate data bits from clock bits, let's have a quick look at what a sequence of data bytes on the disc surface might look like. There's a simple protocol for describing sectors on the disc, called the "IBM Diskette", which is described in the 8271 datasheet.

It's fairly simple and it looks like this in hex:

FF FF FF 00 00 00 FE 00 00 00 01 F1 D3 FF FF FF 00 00 00 FB 01 02 03 04 05 ..

The green data bytes are padding between sectors, or between sector headers and sector data. They help the controller maintain correct synchronization, and to re-gain synchronization at the correct point. The padding sequences are typically longer on a real disc, but are shortened above for clarity; they would still suffice.

The sector header identification byte is the FE, which is followed by 4 bytes of sector header and a 2-byte CRC. The sector is declaring it is on track 0, head 0, and it is sector 0, sized 256 bytes. The CRC is correct. The sector data identification byte for non-deleted data is FB, and 256 bytes of data are expected to follow, then another 2-byte CRC. A typical track might contain 10 such padding + sector header + padding + sector data sequences.

The astute reader would ask: "oh! but what if the FE or FB bytes occur in actual sector data, as they are bound to do from time to time?"
That is a great question and the answer lies in the clock bits. Every byte above has 0xFF for its clock bits (all set) except 0xFE and 0xFB, which have 0xC7 for the clock bits. i.e. some of the clock bits are missing! That makes it possible to identify sector header and sector data markers accurately. Note that the combination of these special data bytes plus clock byte is chosen so that still, the invariant is keep that there are never 2 0 bits in a row on the disc surface.

BBC Micro disc protection journey

The BBC Micro disc protection journey is a fairly meandering one. It seems to have been based on a classical arms race approach: a software publisher would publish a new disc with some new quirk on it, and then a new disc copy program would come out which understood the quirk. And repeat a few iterations!
The journey is also complicated by two very different disc controller chips being used during the machine's lifetime: the Intel 8271 and the Western Digital 1770/1772. Both chips had different capabilities and quirks. A good copy protection on one of the chips might be trivial to copy on the other. Also, some earlier BBC Micro discs were made that did not end up being compatible with 1770 based systems.

To enumerate some of the techniques seen:
  • Early Micro Power titles, such as Ghouls, used non-standard numbers of sectors on many tracks, such as 5 sectors of 512 bytes each instead of 10 sectors of 256 bytes each. This is easy to copy if you have a copy program that checks the sector headers first and then decides how many there are and what sizes based on that. It would be easy to scoff at such a simple protection but it's likely it did what it needed to at the time of launch: prevent casual disc copying using the built-in DFS (Disc Filing System) commands *COPY or *BACKUP (both of which expected well-formatted DFS discs, which meant 10 sectors per track).
  • The Superior Software classic, Citadel, used "deleted data". Every sector on a disc can be marked as either normal or deleted by the one byte mark that occurs directly before the sector data bytes. This is again a simple protection that a copier can handle as long as it knows about the concept of deleted data. What's interesting is that Superior did release a few titles with more advanced protection -- most notably the legendary Exile. However there are stories about the protection not loading correctly with some setups, so Superior discs from then on can all be seen using just the simple deleted data protection. Presumably: once bitten, twice shy.
  • The most iconic game on the BBC Micro may well be Elite. One of the tricks it used was an "unformatted track" in the middle of the disc. An unformatted track does not have any recognizable sector headers. This is perhaps the first protection that made disc copy programs sweat. Particularly on the 8271 floppy controller, there is no "unformat" command, only a "format" command. This was resolved decisively in favor of the disc copy programs, though, with a clever trick: if you format a track as one giant 4096 byte sector, you win immediately. What happens is that the single sector header is written at the start of the track, but then the 4096 bytes of sector data wrap around across the end of the track (which is 3125 bytes long) and trash the only sector header! So the track isn't really unformatted, but all that is needed is that the disc controller doesn't see any sector headers -- mission accomplished.
  • Another fairly ubiquitous protection was mismatched physical / logical track IDs in the sector header. This was also used by Elite, which also used unusually large logical sector IDs. This is easy to copy if you know you're looking for the situation. Normally, the disc controller (particularly the 8271) will get upset if it sees a track mismatch but you can fake the controller out by setting its internal track register to match, with a special command.
  • Later on in the BBC Micro's life, some publishers of software on disc upped their game. It became common to see extra data bytes "hidden" in between sectors. Simplistic attempts to copy these bytes would fail by overwriting a following sector. 1770-based disc copiers can handle this situation easily unless the hidden bytes are "reserved" in the 1770's write track protocol. It is possible to copy these situations well with both an 8271 or 1770 based copier, but I haven't yet found one that makes a decent effort. It is necessary to do things like take direct control of the disc controller chip, and issue commands with precise timing, and abort the controller mid-command with similarly precise timing.
Another favorite pastime of disc protection authors was a creative way of reducing copying without necessarily improving the underlying protection mechanism: attack the copy program itself. The copy programs needed a bunch of logic to work out what sector setup they were encountering. It's not easy logic, so breaking it was fruitful. Here's a few shots (under emulation, but real hardware behaves identically :) of Exile breaking Vector 2:

Loading Vector 2

Second track correctly identified as having 18 sectors

A beeeeeep and a crash / hang processing the second track

Sherston Software weak bits protection: introducing "soft lock"

Given the copy protection arms race described for games above, it was a surprise to find a smaller educational software house with an on-disc protection format light years ahead. Sherston Software had a great catalog of software that my kids still enjoy today, with our current favorite being Space Mission Mada.

Many Sherston Software discs use weak bits protection. We should briefly define terms because they are not consistently used; the most sensible and broadly agreed terms appear to be:
  • Flaky bits. Any on-disc bits that do not read back consistently. They are flaky.
  • Weak bits. Flaky bits caused by a weak signal or non-existent magnetic signal on the disc surface. You might also see the term no-flux area (NFA), which is the same as a non-existent signal. Weak bits are almost always a non-existent signal, as opposed to a weak signal. The flaky nature of weak bits actually comes out of the drive electronics: when there are no clear flux changes, the drive just amplifies harder until it starts seeing and signaling ghosts within the noise.
  • Fuzzy bits. Flaky bits caused by a strong, clear signal but where the timings of the read pulses are borderline. The borderline timing means the disc controller chip cannot be sure whether a pulse is supposed to be a 1 bit or a 0 bit. It'll change its mind from read to read.
The use of weak bits is advanced because it's one of the on-disc protections that arise when you do a first principles analysis:
  • Weak bits give a "reliable" read result: you can reliably depend on them to read back differently from read-to-read!
  • Weak bits cannot be written by the standard disc controllers. The disc controllers do everything in their power to lay down bits that read back deterministically. That's their job! There's no "write weak signal" flag and there's no "write timing violations" flag.
I wrote to the author of Space Mission Mada, Simon Hosler. It turns out he also devised the weak bits protection, along with his electronics geek next door neighbor! In Simon's words:

"Soft lock (was what we called it) was actually my system, so what I remember… This came about because I lived next door to an electronics geek! 😊 So break the write data line of the parallel disk cable. Add a bit of electronics to this line. (thank you Mike) Most of the time this electronics does nothing – lets the data go through as normal. If you turn it on (I think I did this through the serial port) and write to a single sector - it would count the bits going through say 256 – and then stop the next 256 bits going through"

I happen to have an original Sherston disc with weak bits protection, Animated Alphabet. Here's what the weak bits patch of disc looks like with the drive wired up to an oscilloscope:

The blue line shows the on-disc magnetic signal come and go as Simon's widget toggles on and off. The yellow line shows the drive still emitting read pulses to the floppy controller (quasi-randomly) even in patches of no signal

The effect of Simon's widget in creating batches of weak bits can clearly be seen. This really was genius for the time, being one of the earlier swings at creating disc surfaces fundamentally uncopyable without special hardware. Not only that, but it works the same on both 8271 and 1770 based systems since it's the drive electronics that are being induced to create the quasi-randomness. This leads to a simpler, more reliable setup with just a single code path. It is also very compatible with all the myriad of different DFS (Disc Filing System) variants because the code to check the copy protection doesn't need fancy DFS calls. It just needs to read a sector -- very standard! -- a few times and see if the bytes coming back vary or not.

State of the art

I don't know when the first flaky bits based disc protection was released. There's probably someone out there who can point to an example from the 1970s! But it's worth comparing dates on some examples we do know about.

Dating the first Sherston Software title to use weak bits protection is tough. I have an image of Mr. Yog and the Nippet, (c) 1984, with weak bits protection. There's even an image of Short Vowel Sounds, (c) 1983, with weak bits protection. However, we also have seen the same Sherston title released with multiple different disc revisions with different copy protection systems. We can establish an initial latest bound on the weak bits protection with an image of The Wizard's Revenge that happens to use the weak bits protection and also includes a commercial duplicator fingerprint on its one-past-the-end track, as seen here in this hex editor view:

This data, starting with 01 02 03 04 05 on the first line, appears to be added by a commercial duplicator from the era

Fingerprints of this nature contain a date and time: 87 01 05, or Jan 5th, 1987 in this case.

So in terms of release timing of early flaky bits based protection, we have:
  • Weak bits: The Wizard's Revenge, Sherston Software, Jan 5th 1987.
  • Fuzzy bits: Dungeon Master, Dec 15th 1987.
So it seems likely that the Sherston weak bits went to production at least a year prior to the Dungeon Master fuzzy bits. Although these disc protections are not identical, they have very similar properties and capabilities.

What's further interesting is that the Dungeon Master fuzzy bits were the subject of a patent filed in 1986. This could be one of those cases where other clever people had come up with prior art. It happens a lot.

Copying weak bits with original 1980s BBC Micro drives and controllers

No retro research would be complete without an attempt to push the bounds of what was thought possible back in the day. Accordingly, would it be possible to create a software only solution to write weak bits to discs? Another way to ask the same question is: would it have been possible to create a disc copier that copied weak bits correctly?

It turns out the answer is yes! Or more specifically, the answer is a double yes. Using two different tricks, it is possible to create actual weak bits with the 8271 disc controller, and non-deterministic reads (resulting in the same sort of read effects as weak bits) with the 1770 disc controller.

8271

The 8271 is a slightly strange chip to program. One thing is has is the concept of "special registers" which can be read and written. One such special register is the "Drive Control Output Port":


The special registers aren't particularly well covered in the data sheet, perhaps because they aren't supposed to be necessary for usage. That said, most 8271 driver implementations write this register to spin up the drive (by setting the LOAD HEAD bit and appropriate drive SELECT bit) in order to control the 8271's propensity to fail read/write commands with "drive not ready".

The trick is to use this register to set the WRITE ENABLE bit as well as the LOAD HEAD and SELECT bits. This can only be done outside any other command, because Write Special Register is itself a command and selecting it will abort any other in-progress command. When WRITE ENABLE is active outside of a command, the disc drive's write head will be energized but no data pulses will be transmitted on the write data pin to the disc drive. The result is that the write head sweeps the disc surface clean of flux transitions. That creates weak bits / a no flux area. With a bit of careful timing, the write head can be energized and de-energized and any point(s) needed on a track to create weak bits where desired.

1770

The trick on the 1770 is different. It may be possible to directly create weak bits by creatively programming the 1770 -- but if it is, I haven't found it. Instead, we focus on the BBC Micro's 1770 control register. This is a register external to the 1770 that is necessary to control external 1770 pins. For example, unlike the 8271, the 1770 selects disc drive 0 vs. drive 1 via an external pin instead of as parameters passed to controller commands. The "Drive Control Register" is documented well at the bottom of this document.

Since this register is external to the 1770, we can mess with it while a command is in progress. The specific trick we use is to start a single density write command and then flip to double density some number of bytes in. Double density (MFM) timing is completely different to single density timing, so reading back the resulting patterns as single density read confuses the disc controller significantly, to the point that non-deterministic read results are returned. This is not weak bits on the disc but the effect is the same as far as the copy protection check is concerned: read the sector twice and check the result varies! The bits definitely end up flaky.

Does it work? Yes. Here's a video of me using my work-in-progress "discbeast" utility. We fix a failed copy of Sherston weak bits by using commands to directly and precisely create flaky bits at the correct point on the disc.


Tuesday, June 23, 2020

A wild bug: 1970s Intel 8271 disc chip ate my data!

If you must suffer data loss then at least make sure you collect a good story from the experience!

I believe I have such a story.

Recently, I've been enjoying keeping my inner engineer sharp by playing around with retro software and hardware. I've taken a particular interest in floppy disc drives and old-school floppy disc protection on the BBC Micro. The BBC Micro had a couple of different popular floppy drive controllers: the older Intel 8271 and the newer Western Digital 1770/1772. Both controllers have different capabilities, and quirks by the bucketload!

My data loss occurred while experimenting with the Intel 8271, a 1970s chip and design. It's a good size and runs a little hot.

Intel 8271 (left) in a BBC Micro model B

There is not a lot about this chip on the internet, but there's a pretty good datasheet, which includes this description regarding the reset register:


It is no doubt my security background that caused me to read this description and then promptly write the value 100 (not 1 or 0) to this register.

It is at this point that my drive became possessed. Re-trying showed that setting bit D2 alone by writing the value 4 is sufficient to cause the demonic infestation:


Different drives behave differently. This drive, an older single head Chinon F-051MD seems to activate all of its widgets: the head wobbles wildly and the motor sometimes spins. My newer Mitsubishi drive makes a terrible, awful high pitch screech. It is my favorite drive and I do not wish to hear that sound ever again so there is no video.

Here is where it gets crazy: when I first did this, there was a disc in my Chinon drive and the data on that drive became toast... despite the hardware write protect tab being present.

What?

Indeed. This is sufficiently bizarre that it is worth investigation! What signals is the floppy drive receiving when the poltergeist is present? As a reminder, the BBC Micro uses a Shugart style (not PC style!) connection to the drive:

From the controller to the drive, we have Select 0, Select 1, notDIR (step direction), pin 20 (step; not labeled in the service manual diagram above), Write/DATA, WRite/ENable, Side/SELect. To sample a couple of these:

Pin 16, MOTOR

Pin 24, WRite/ENable

There are similar signals on other pins from the controller to the drive -- and they are not normal! Flipping the motor on and off at 375kHz is not an expected controller behavior and it may even be bad for a motor; I don't know.

The disc corruption comes from the abnormal signal above on the write enable pin. This is how the controller requests the drive to power up its write head, and the drive is being asked to do so at 300+kHz. There's also one of these crazy signals on the step and step direction pins, so the drive is seeking all over a range of tracks while being asked to activate the write head. Not good.

It is probably reasonable for us to fault the controller here. Under the heading "Write Protect" on page 8-124 of the data sheet, it says "The 8271 will not write to a disk when this input pin is active". This contract is clearly being violated as the write protect is being signaled by the drive.

It takes two to tango

But there is more to this! Most floppy drives also have a last-line-of-defense. For example, the application notes for my Mitubishi MF503B drive clearly state "This signal goes to ‘0’ when a write protected disk is inserted into the drive. Writing is inhibited even if the write gate is active." My Chinon drive seems to get this right most of the time, but not in the presence of wild oscillating signals. There appears to be a race condition -- perhaps if the drive is selected while the write enable gate is already active -- where a bit of current will go through the write head before the write protect condition is noticed.

Looks like I got unlucky -- wrong controller, wrong drive.

Two of my more colorful BBC Micro original discs, silver write protect tabs on display. Luckily neither of these is the disc I trashed!

Intel 8271 speculation

There isn't a whole lot on the internet about the Intel 8271. It's a slightly older floppy controller chip from the 1970s. Some of its capabilities hint of design tastes and directions that were retired in the 80s. For example, the chip is able to use host memory DMA to asynchronously scan within disc sectors for arbitrary byte strings. Perhaps a relic from the mainframe era? It wasn't used on the BBC Micro. The DMA capability wasn't wired up at all.

No other 1980s home computer that I'm aware of used the 8271. There were good reasons not to. Probably most significantly, the 8271 doesn't support double density aka. MFM, which the Western Digital 1770/1772 did. So using the 8271 carried a hit on storage capacity. The BBC Micro lived with this hit even as 1770 based machines became common. Commercial software needed to work on all machines, including 8271 based ones.

One suspicion I have is that the 8271 could be based on the Intel MCS-48 microcontroller. A few things line up, such as dates of design and manufacture. But there are also clues in the API offered. The "Read/Write Special Registers" commands is of particular interest:

As you can see there are a lot of special registers, with a fairly sparse few documented. The highest documented index is 0x22, or 34 in decimal.
One theory would be that the read/write special register simply reads or writes one of the 64 bytes of RAM present in an 8048 (or variant). There's plenty of evidence that most special register indexes seem to do something. For example, the seek and settle timing parameters end up in special registers 0x0D and 0x0E even though it is not documented anywhere. Also undocumented, 0x1D appears to mirror the formal data register. And so on.

And if the 8048 theory holds water, perhaps the undocumented and crazy bits of the reset register correspond to one of the test modes, single step mode, or external memory access mode?

From the archived MCS-48 users' manual

Summary

This is the most fun I've had while sustaining serious data corruption.

If you have any knowledge or memories of how the 8271 is actually architected, or details of undocumented behaviors, please get in touch!

Tuesday, June 2, 2020

Sampled sound 1980s style: from SN76489 square waves to samples

In the early 1980s, the Texas Instruments SN76489 sound chip was found in a variety of personal computers, consoles and arcade cabinets.

The legend, the chip itself

It is a fairly simple chip, consisting of 3 "tone channels", and one "noise channel", typically mapped to 3 note channels and one drum channel. The tone channels play square waves and the noise channel can emit either white noise or "periodic" noise. Despite this simplicity, human creativity -- as usual -- came to the rescue to bang out some good sounding tunes.

A couple of examples for you: Galaforce title music and Icarus title music (both BBC Micro).

Programmers even worked out how to coax sampled sound out of this beast back in the day! Sampled sound, from square waves?! The (very brief) sampled speech intro to Spy Hunter is a good example.

This blog post concerns how the mechanics of the sampled sound actually work, but first a quick demo of my own attempt to advance the art from sample discs produced back it the day. My own sample disc playback looks like this:

"sampstream" running in beebjit
 
Amusingly, the sample playback quality on a 1980 chip is obviously not too badly mangled because YouTube content ID recognizes emulator recordings of the commercial songs I chose as demos 😆 But you can click here or click here to play these sampstream demo discs in the jsbeeb emulator. It sounds similar to real hardware, although real hardware sounds less harsh and louder (you may need to crank your volume up).

"sampstream" features:
  • Near instant start and uninterrupted 400k of sample playback. It uses a custom asynchronous disc loader that auto-detects the Intel 8271 vs. Western Digital 1770 disc controller and drives it directly and asynchronously.
  • A real-time 50Hz oscilloscope view.
  • Noise bands that show disc read bandwidth vs. sample consumption bandwidth
sampstream does not feature best-in-class sample pre-processing and playback. It also does not use compression, despite samples being pretty compressible. So it's a tech demo that could be made to sound better and play for longer. The pcmenc project is the state-of-the-art I'm aware of for good quality playback. (A lot of what it does it fight against poor 4-bit and non-linear per-sample resolution, using clever techniques such as multi-channel balancing and mid-point rejigging.)

[sampstream, and the quicdisc library is it based, are open source and hosted on GitHub here]

So how does sample playback actually work? The sampstream example keeps things simple and uses only one tone channel. For a SN76489 tone channel, we control:
  • The channel period, i.e. the frequency of the square wave output -- 1024 possible values.
  • The channel volume -- 16 possible values.
  • A special register that outputs a byte of sampled sound. (Hahaha no.)
There's a few good references on the SN76489 online, including how to get sampled sound out of the thing. I recommend this resource over at SMS Power, as well as the MAME SN76489 driver source code to give you an idea of the flavors and variants.

However, some sources hand-wave regarding how it actually works, so let's cover that here by getting out our trusty oscilloscope and applying it to the SN76489 in the BBC Micro.

The usual basis of sampled sound playback is driving the SN76489 as a PCM device, i.e. a sequence of sample amplitude values. Everyone seems to agree this is initiated by setting a tone channel to a very high frequency, or very short period. There is disagreement on what period value to use, and why it works.

In the BBC Micro, the clock input to the sound chip is 2MHz and it has an internal divide-by-8, making it a 250kHz device. If we set a tone channel period to 1, it will invert that channel's output every clock tick (high, low, high, low...), forming a square wave. A full waveform cycle will need to have a high segment and a low segment, meaning that the output waveform should be a 125kHz square wave.

Investigating the output with an oscilloscope is easy because the SN76489 pinout is trivial:
Not too many pins!

The pin of interest is pin 7, "SND OUT". What does that look like with all channels silent, except for one tone channel, set to period 1 and maximum volume?

SND OUT from the SN76489 in blue

In this scope capture, the blue line is the SND OUT output from the SN76489. As can be seen it is a square wave as expected. It's at a 125kHz frequency, 720mV from peak to peak with its upper peak around 3.3v. Right away we notice a surprise: we might have expected an audio signal to center around 0v, but this signal is centered around 3v or so! The chip works like this:
  • Each audio channel contributes two alternating voltages (peak and trough) to the SND OUT total voltage.
  • Neither of the alternating voltages are negative.
  • For silent channels, the two alternating voltages will in fact be the same (about 0.8v).
  • For max volume channels, the two alternating voltages will be 0v and about 0.8v.
  • For this particular SN variant, it is "inverted" compared to what you might expect: a silent channel will output a constant voltage of 0.8v or so, not 0v. This inversion is interesting but does not affect ability to play sampled sound.
The yellow line above is the output a couple of components later in the audio chain: an LM386N-1 audio amplifier, after traversing an LM324N op-amp. We can see that already, the 125kHz frequency has been partially filtered out by the LM chips. This is why we use such a high frequency as a PCM carrier: it won't affect the audible output. The audio chain will filter it out; the speaker won't be able to respond fast enough to any remnants; and at any rate, the human ultimately at the end of the audio chain cannot hear it.

The PCM stream is modulated simply by rapidly altering the volume of the 125kHz wave, resulting in a voltage output looking like this (for our 1 tone channel case):


The above graph shows a few samples at max volume at the start, some interim, and a few at silent volume (the flat top line) at the end. The red trend line shows what the actual PCM waveform will look like with the 125kHz carrier filtered out. The key for sample playback is likely that the mid-point voltage differs for each volume. Note how its amplitude is half that of the carrier wave. This is likely one reason sampled sound playback is relatively quiet.

So now we've seen how a PCM waveform can emerge from just a 125kHz square wave and volume changes. There's some extra ciruitry between the LM386N-1 and the speaker, to keep the speaker happy. It normalizes the oscillation around the positive voltage point to be an oscillation around 0v.

It's important to recap how the SN76489 voltage output does not behave. It does not oscillate evenly around a fixed 0v point, which would look like this:


The above would not be conducive to sampled sound playback as the average signal after eliminating the 125kHz carrier would be a constant 0v!

Although we're done with explaining sampled sound output, it's also worth looking at a few other oscilloscope traces to understand SN76489 behavior. Here's a look at the other extreme, the longest period this particular model can output for a 121Hz sound:

SN76489 output in green, LM386N-1 in blue

Some references state that the SN76489 cannot hold a steady square wave output, particularly for longer periods. However, this is clearly not true -- at least for this variant. The square wave output is very clean and it is likely the LM324N or LM386N-1 that is introducing interesting voltage decays into the output waveforms.

Finally, here's another SN76489 vs. LM386N-1 output for an 8kHz square wave:


The output is close to a sine wave, not a square wave! This interesting distortion at 8kHz may be because some sources reference an 8kHz low-pass filter as a part of the LM324N setup.