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