NEWS, EDITORIALS, REFERENCE
Introducing the Kernal rom
For years I used a C64 and loved it but I didn't really know how it worked, neither the hardware or the software. In the future, on this blog, I'll talk a bit about what I discover about the hardware, but mostly I want to focus on software.
I'd heard about the KERNAL but didn't really know much about it. It well and truly is the OS of the C64. I'd heard that before too but didn't quite grasp it. Because the routines that are exposed to the programmer via the jump table don't do all that much. There are only 39 calls. And a lot of them have to do with I/O. Either putting characters on the screen or reading and writing data to the serial bus. Plus a handful of others for adjusting variables and testing ram.
When I stumbled upon the Fully Commented C64 ROM Disassembly it completely changed my Commodore Life.
There is far too much to comment on in a single blog post. So, I wanted this post to be an introduction to the "Fully Commented Disassembled C64 ROMs" document itself. It's available in both English and German, and it's available as ASCII plaintext and HTML. I highly recommend the HTML version as many addresses that are referenced by the code itself are hyperlinked to that address found elsewhere in one of the C64 ROMs.
The document actually represents more than the KERNAL, it includes the BASIC rom. But I haven't had an opportunity to really dig into how BASIC works yet.
Here's an interesting thing I discovered though. As you may or may not know, a lot of the magic of a C64 comes from the fact that its 6510 CPU is a variant of the 6502 that has the ability to set high or low three legs on the chip. We can call these three bits of data, and they are controlled by the lowest three bits of the value stored at memory address $0001. This is known as the CPU's I/O Port.
In a Commodore 64, and the C128, these pins are wired up to a programmable logic array. Better known as a PLA, or better known still as "The PLA." The PLA plays a crucial role in make a C64 a C64. Depending on the values of those 3 bits the PLA selectively raises and lowers the "Chip Select" or "Chip Enable" lines on a variety of ROM and I/O chips and RAM controller. This allows the programmer to change exactly what it is the CPU is able to address, in real time! This is the magic that allows a C64 to have 64 kilobytes of addressable memory, plus 16K of ROM, plus a 4K character ROM, plus a 4K of I/O space and still has room for an 8K pluggable cartridge.
You can see the PLA in the above schematic, wiring itself up to the Chip Select pin of the KERNAL rom, BASIC rom and Character rom. It was very convenient that I also stumbled upon a large, double-sided foldout schematic of a C64 motherboard. Its printed date is 1982. It's a pretty nice find.
Now, the really interesting bit that I'll leave with you today is exactly how those I/O Port bits represent what to turn on and what to turn off. It's actually fairly confusing at first. You can read about this in much more detail on the C64 Wiki article about Bank Switching.
3 bits gives us 8 possible values, from %000 (0) to %111 (7). There are however 4 possible regions that can be substituted in place of RAM.
Pages $A0 - $BF can be either the BASIC ROM or RAM. Pages $D0 - $DF can be either I/O, the Character ROM or RAM. And Pages $E0 - $FF can be either the KERNAL ROM or RAM.
Altogether there are more combinations of these 4 switchable banks than can be represented with only 3 bits. If it weren't for the Character ROM (which doesn't need to be accessed all that often), it could have been so clean:
Bit 1 toggles between BASIC and RAM, Bit 2 toggles between I/O and RAM, and Bit 3 toggles between KERNAL and RAM
What you'll notice if you look closely though is that it is possible to have the KERNAL banked in alone with the rest RAM, but it is not possible to have BASIC banked in without also having the KERNAL banked in. As it happens this is actually pretty convenient, because the KERNAL provides a bunch of low level routines that make the system work and it can easily be used in isolation. The BASIC ROM on the other hand is essentially a frontend interface to controlling KERNAL routines.
When the BASIC ROM executes a PRINT statement, it is under-the-hood calling the KERNAL routine for CHROUT. And it is the KERNAL routine that is interpreting the PETSCII value to be output and how that will affect the state of the screen. And so, it makes absolutely no sense to bank in BASIC but bank out the KERNAL. That's handy because there aren't enough bits in the I/O port to do it anyway.
UPDATE: November 5, 2018
I'm updating this rather old post, just over 2 years after I wrote it. I need to issue a correction. The 6510 indeed has a special processor port. And three of the bits of that port, the 3 controlled by the lower three bits of address $01, do control the C64's Rom, I/O and memory map, via the PLA.
However, the processor port is not only 3 bits wide. It's actually 6 bits wide. In the segment of schematic below, you can see the 6510's labeled pins. Along the upper right hand side, you can see P0, P1, and P2. These are for Port pins, 0, 1 and 2. These run down and over to little pill shaped blobs with a pointed right end. These little labeled blobs indicate that the connection continues somewhere else on the schematic at a similar blob of the same label. In this case, the full schematic is split onto both front and back of the large fold-out page. The other side of these connections are wired into the PLA. Note that the direction of the arrow indicates the direction of information flow. Here, the processor is writing 3 bits to the PLA to set the memory map configuration.
If you notice though, the top end of the CPU, in the schematic, also lists P3, P4 and P5. These are three additional bits of the same port. Controlled by the next three bits of address $01. These are connected to the cassette port's motor, sense, and write. The cassette port's read line is controlled by one of the CIA's, not shown here.
As an interesting aside, I've known for a long time that datasettes were used in Europe for longer than they were in North America. I also knew that it was related to the high cost of a disk drive, compared to a relatively inexpensive datasette. But I never really understood why a datasette was so much cheaper to build.
Now I understand. The motor, the sensor, the read and write data lines as well as the 9V and 5V DC required to power and drive the datasette, are all controlled directly by hardware that is already in the computer. The KERNAL ROM has datasette reading and writing routines that control the CPU's port lines to directly control what is read from and written to the cassette magnetic media. A disk drive, on the other hand, is an entire 8-bit computer with its own OS, that intelligently speaks the IEC serial bus protocol, buffers data, executes commands, and more. On the inside of a datasette, by contrast, there is virtually nothing. Just the motor, sensor assembly and read/write head, wired directly to the computer. That is why a datasette is so much less expensive than a fancy disk drive.