The Commodore 128: Meet the Memory Magician

February 19, 2021

My second computer was a Commodore 128. I remember two things about it: it felt like a real computer as opposed to the weird brown toy that the original C64 looked like, and it was the first computer that I learned to program on.

The C128 had double the RAM of the Commodore 64 (128 kilobytes vs. 64 kilobytes! Yeah!), and an upgraded processor. The MOS 8502 in a Commodore 128 ran at almost double the speed of the C64 (2 MHz vs. 1 MHz! Yeah!). However, its address width was still only 16 bits, which means it could technically only see 64K of RAM at a time. So how the heck did the Commodore 128 double that?

A magician, standing in front of a Commodore help wanted sign, saying 'Well this would certainly be a step up from balloon animals...'

They hired a memory magician!

With older computers, you had to trick them into thinking they only had as much RAM that a particular constraint could handle. With IBM PCs, you had to lop off the top parts of addresses with a hardware switch for older software to work. With Macs, you had to pretend memory above 16MB didn’t exist with a software switch. With the Commodore 128, it was by putting each 64K block of RAM behind a door, and putting in a hardware memory management unit – a memory magician – to trick the CPU into only working with 64K at a time.

The CPU in the Commodore knew how to point to a spot in a 64K block of RAM and get and set data there. With only one 64K block, no magic is needed. It just works. To take advantage of that other 64K, the magician has to, very quickly and on command, swap which block of RAM the CPU is accessing, without the CPU knowing what’s up.

A magician showing off bank switching to an 8502 and a Commodore representative

It was standard Commodore protocol that program code went in the first 64K block – Bank 0 – and data went in the second 64K block – Bank 1. All the necessary computer-y things (operating system, how to run BASIC programs, floppy and tape drive access, display) also lived in Bank 0, but there were ways to turn parts of those off and free up some RAM if you didn’t need to use them. You, the programmer, could tell the magician to deactivate parts of the computer you didn’t need, like the tape drive or BASIC, which gave you more RAM to use.

If you wrote your program in BASIC, the BASIC interpreter already knew to put all of your data into Bank 1, and handled talking to the magician for you. If you really needed performance, you’d write your program in assembly. In that case, you’d have to work out with the magician the times when youall, the programmer/magician team, needed to trick the CPU.

As part of your program, you’d tell the CPU to put a value (0 or 1) into a particular address in memory. The CPU does not know why it’s doing this. The magician watched this particular address and, when it changed, would swap the Bank it was presenting to the CPU based on that value. Think of it as a light up sign the magician would act upon. The magician would see the new value on the sign and switch to that. This was done right before the CPU accessed RAM, and the CPU has no idea a switch took place – the magician simply presents the 64K the programmer asked it to.

The magician watches a memory location for changes and, when it changes, swaps out the memory bank presented to the processor.

Since only one Bank was visible to the CPU at a time, and since the CPU had to always know about things like joystick and keyboard inputs, certain parts of the Banks were shared – a change in one changed the other. This included the place where you change the light up sign. The magician handled the duplication for both the developer and the CPU.

Magicians – I mean, memory management units – became a critical component of computers, both to work around limitations and to give the CPU some help doing the thing it does a heck of a lot of – reading and writing RAM.

Changelog

  • 2021-02-19: Initial post