Ram under Rom - a brief look into C64 memory
64k is enough for anyone
Imagine the C64 world to be a very long street with exactly 65536 properties. You usually have bungalow with one floor or apartment buildings with two floors occupying each a piece of land.
Each building has a house number or even a range of house numbers starting from 0 up to 65535 ($0000 - $FFFF).
If we translate the actually kinda weak metaphor to software engineering we have first of all 65536 memory locations in your Commodore C64 and each can hold one single byte - this is the C64 RAM. On top of this RAM there are a few areas with read only memory (ROM) which hold the BASIC interpreter, the KERNEL Routines and the Character Generator ROM. Last but not least there are some I/O mapped areas which basically means that memory locations are mapped to features in the I/O chips, e.g. in the SID and VIC-II. This overlapping memory design is often referred as "RAM under ROM" and addressing chips via memory address registers is called memory-mapped I/O.
That also means that as a C64 coder you for the most part are concerned about reading or writing to some location in memory.
The Memory Layout when the C64 is turned on
The initial memory configuration when turning on the C64 is targeted to BASIC programmers though there is 4Kbyte of RAM not used by BASIC and dedicated for machine language from $C000 to $CFFF. For games and demo programming, this is obviously not the best configuration though.
To read from addresses which are located under ROM you have to briefly switch out a portion of ROM overlapping that area. If you would not do that, any READ access to those locations will return values from ROM but writing to the same addresses will put information into the respective RAM under ROM.
As opposed to other 8bit-computers using the 6502 processor, the C64 has a slightly modified version of the CPU called 6510. The only significant difference to the standard 6502 is the possibility to choose between different memory layouts which makes the Commodore C64 very flexible. This is feature you use to switch out ROM overlapping RAM as required.
Mapping to the Chipset
There is a special block of ROM overlapping the RAM from $D000 to $DFFF. First of all, there is the 4K large Character Generator ROM. The name sounds more complicated than it actually is. This area simply carries all available characters and symbols you can put on your screen using your C64 keyboard. Actually it's four different character sets each 1K in size. Since one single character is made of a 8x8 bits matrix every 1K-set holds 128 single chars. Not all chars are alphanumeric though, as there are also tons of different symbols available to print to the C64 screen. Additionally there are different version of each character stored in the Character Generator ROM: shifted, unshifted and reversed where reversed means that background color and character color are replaced with each other.
In the same address space starting at $D000 the I/O mapping to the C64 chips take place. The Video Controller VIC-II, the SID and also both CIAs are simply accessed by reading and writing to memory adresses in that area. The 1000 bytes of Color RAM maps the positions in Screen RAM 1:1. This means you can define colors in any position of the 40x25 screen matrix. Of each Color RAM byte only the lower nibble is actually used so smart programmers can utilize another 512 bytes by using the higher nibble of each Color RAM byte for something different.
- There is 64 Kbyte RAM...
- ... plus 20 Kbyte ROM (Read Only) for BASIC, KERNEL and Character Generator ROM sharing address information with RAM
- To read any byte in RAM which is "under ROM" you have to switch out the section of ROM which overlaps that particular RAM area. This ROM switching concept is the major difference between the 6510 CPU in the C64 and the 6502 CPU used in other 8Bit-Computers. The concept also allows many different memory configurations which can be optimized towards whatever use case needs to be taken care of.
- The I/O chips are memory-mapped. You access features of SID, VIC-II etc by reading and writing to memory addresses.
Update June 14, 2014: In an earlier version I mistakenly assumed that there might be an additional 512 Bytes of spare bytes available due to the fact that Color RAM only uses one Nibble to set color information. As it turned out (thanks Csaba!), the Color RAM is organized as 1024x4 Bit Static RAM, so there is no High Nibble to access, hence, there is no spare RAM here.