"Beeping the horn on the data bus"

T.M.R's Workstation
General Stuff

 Home Page
 About T.M.R
 Photo Galleries
 Web Links
 Random Quotes
 Old Web Log

8-Bit Stuff

 Projects
 T.M.R's Dev Blog
 The Scrapyard
 Ye Olde Stuff
 Articles

Other Stuff

 Rendered Images
 PHP Toys

Random Quote

"Supercars are supposed to run over Arthur Scargill, and then run over him again, for good measure. They're designed to melt ice-caps, kill the poor, poison the water table, destroy the ozone layer, decimate indigenous wildlife, recapture the Falkland Islands, and turn the entire Third World into a huge uninhabitable desert... but only after they've nicked all the oil."

Jeremy Clarkson 
T.M.R'S WORKSTATION :: C64 MEMORY MAPS 

C64 MEMORY MAPS

Written by T.M.R of Cosine

Okay, welcome to part two in an ongoing series to bemuse and confuse would-be C64 coders as to how the machine works!

The C64 is, like all other 8-bits, a unitasking environment; because of this, any program running normally doesn't have to make many special concessions to the system as regards memory use or processing. In fact, as the system becomes more familiar it's possible for a programmer to kick the C64's operating system out and use the memory that the ROM chips sit over.

Quick And Dirty Memory Map
The best way i've found to talk about the memory is to do my virtual tour guide routine; in other words wandering through the RAM, highlighting points of interest on the way. However, this isn't a definitive guide and anybody taking this seriously should by now have a download of the C64 Programmers Reference Guide from Project 64 for more detail.

Before i wander off, the C64 has one unique feature in that the VIC-II video chip sees the RAM in four possible blocks, referred to as banks. i'll highlight the change from bank to bank as it happens, but for easy reference they're called banks 0 to 3 and located at $0000-$3fff, $4000-$7fff, $8000-$bfff and $c000-$ffff respectively.

$0000-$00FF
The zeropage is a common feature of 6502 microprocessors (the C64's 6510 is a variant of the '02) and some people find it very useful. The zeropage's main advantage is that any transaction with it takes one cycle less than the rest of the RAM (since it's possible to use sta $fe as opposed to sta $00fe) but the down side is that the C64 needs most of it for general operation. The most commonly used spaces are at $02, $50 to $57 and $fb to $ff.

$0100-$01FF
The stack, used to store... erm, vectors and stuff. When a program calls a subroutine, the present position in the program is shoved to the stack for later retrieval.

$0200-$033B
This is all sorts of odds and sods used by the C64's Kernel and BASIC (the operating system essentially); it's a mixture of temporary stores, buffers and pointers to other parts of the system. Amongst other things, the Kernel's IRQ and NMI interrupt pointers are knocking around here.

$033C-$03FF
The tape buffer, two thirds of a page of free space. i've taken to using it for labels in my programs because it's convenient.

$0400-$07FF
The default C64 screen; 1000 bytes are dedicated to the screen itself (40 bytes across by 25 down) and the final 8 bytes of the 1K block are for the sprite pointers. The screen can be relocated in memory (although the system will keep pointing at the $0400 screen until it's told otherwise as well) but always defaults back to $0400 when the machine is warm started in any way.

$0800-$0FFF
Free memory, for all your programming needs. BASIC programs start from $0801 and head upwards.

$1000-$1FFF
More free RAM but with a difference, there's a shadow of the ROM character set over the top of this space (one character set is 2K and there are two sets for upper and lower case). Although program data can be stored in this space, the C64 can't see graphics placed here because the shadow of the character set always appears instead.

$2000-$3FFF
Back to the normal free RAM, running up to the back end of video bank 0.

$4000-$7FFF
Video bank 1. This is the most accessible of the video banks, a clear 16K of space with no ROMs shadowed over it and conveniently placed for the shops and railway station. Erm, conveniently placed for use as a graphics store.

$8000-$8FFF
The start of bank 2 and a block of 4K all ready for graphics use.

$9000-$9FFF
Another shadow of the ROM character set, as before program data will work in this space but graphics will appear as the system's character set.

$A000-$BFFF
This RAM can be used for graphics but contains a shadow of the C64's BASIC ROM when the machine is in it's default state so program code can't be run here. It's possible to switch out the BASIC ROM (the lowest bit of $01 controls the banking) and run code in this space if BASIC isn't going to be used. This is also the back end of bank 2's RAM.

$C000-$CFFF
A small block of generally free RAM at the start of bank 3.

$D000-$DFFF
The registers for the VIC-II, SID, the communication chips and stuff. The VIC-II will be covered in more detail after the main map. This space can, as with the BASIC ROM, be utilised for graphics and it's possible to bank the chips out and run program code in their space too although any writes will be to the RAM rather than the chips themselves.

$E000-$FFFF
This is where the Kernel ROM lives; the Kernel is the core of the system (hence the name) and it provides useful routines, for example interrupt handling, disk operations (slow ones, it has to be said) and character output routines. Once more, the Kernel's RAM can be used for graphics data with no trick; the only thing to watch out for is there are some interrupt vectors right at the top of the memory. As with BASIC, this ROM can be banked out to allow program code to run from it's memory but unlike BASIC it's a more complex job; the Kernel handles the system IRQ interrupt so if it's just banked out the system falls on it's bum!

Commonly Used Registers
As a finale, a more indepth coverage of the registers that tend to be used the most, the VIC-II (and one CIA) registers that handle the C64's graphics.

$D000-$D010
These seventeen registers supply the sprite positions; the first two are X and Y for sprite 0, the next two do sprite 1 and so forth until $D00F. $D010 is the Most Significant Bit (or MSB from here onwards) for the eight sprite X co-ordinates, the lowest bit for sprite 0 and the highest for sprite 7.

$D011
This register does a lot of jobs, bits 0 to 2 control the vertical smooth scroll position and has a range of $0 to $7. Then bit 3 is 25/24 row mode (hardware clipping essentially), bit 4 turns the screen off, bit 5 enables bitmap mode, bit 6 enables extended background colour mode and bit 7 is the MSB for $D012, the raster register. One useful quirk is that if extended background colour mode and bitmap mode are turned on at once, the screen goes black; this can be used for masks and so forth since the screen can only be turned off at the very top.

$D012
The raster register has two uses; it can be used to check for the position of the raster simply by reading it ($00 is the top of the screen and $32 to $fa is where the text area appears). $D012 is also written to during raster interrupts and becomes a trigger for the IRQ so when it reaches the written value an interrupt occurs. Since the raster passes through more than 256 lines on a PAL machine, the MSB is the highest bit of $D011 to give it that extra range.

$D013 and $D014
Used to read lightpens or light guns; the horizontal register has to be multiplied by two to get the relevant screen position.

$D015
Sprite enable register; the eight bits of this register represent the eight hardware sprites, set a bit to enable a sprite.

$D016
Another combo register like $D011, the lowest three bits are the horizontal smooth scroll again with a range of $0 to $7. Bit 3 enables 38 or 40 column mode (again, hardware clipping), bit 4 fires up multi-colour character mode for those lovely, chunky pixels, bit 5 should always be zeroed and bits 6 and 7 serve no purpose.

$D017
Sprite vertical expansion register, just like the enable register in that each sprite is represented by a bit, setting that bit makes the sprite double in height.

$D018
This register controls where the VIC-II looks for character definition and screen data in the current video bank. The lower nybble specifies where the character set is, simply multiply by 1024 and offset into the current bank to work out where it is (since character sets are 2K long, the lowest bit is ignored). The upper nybble points to the screen, once again multiply the value by 1024 and offset by the bank.

$D019
Loads of functions under one roof, this time used for saying which VIC-II based event triggers IRQ interrupts; bit 0 is the raster compare flag, bit 1 the sprite top background collision, bit 2 for sprite to sprite collisions, bit 3 looks for the lightpen and finally bit 7 gets set whenever any VIC-II related interrupt occurs.

$D01A
The IRQ mask register, the lowest bit says if the IRQ is enabled.

$D01B
Sprite to background priority. As with the enable register, one bit represents one sprite. An odd quirk with this register is that one of the multi-colours never takes priority over sprites so any background detail in that colour always remains behind the sprites.

$D01C
Another byte that uses a bit per sprite, this time it enables multi-colour mode.

$D01D
The horizontal sprite expansion register; set the bits to double the width of the sprites.

$D01E
Generally speaking, the sprite to sprite collision register is a bit of a chocolate teapot because all it does is flag when a collision has occurred. If four sprites collide their relative bits will be set but there's no way to tell which sprites have collided with which; sprite 0 may have collided with sprites 1, 2 or 3 or any combination of the above. Most game coders write their own co-ordinate checks instead.

$D01F
The sprite to background collision works like the sprite to sprite register; one bit representing each sprite which sets if a collision occurs. As with the priority register there's a quirk in that one of the two multi-colours doesn't register as a collision. This register is, however, a damn sight more useful than the sprite to sprite register.

$D020 and $D021
The lower nybble of these registers set the border and screen colours respectively.

$D022-$D024
The three multi-colour registers, again the the lower nybble sets the values. $D024 is only ever used in extended background colour mode.

$D025 and $D026
Sprite multi-colours; when the multi-colour mode is enabled, these two registers control the shared colours.

$D027-$D02E
Eight registers controlling the colours for the eight sprites.

$D030
Not strictly a C64 register, but it should always be set to $00 because the C128 uses it as a flag to enable 2MHz mode. That may sound a good thing, but the VIC-II gets scrambled when that happens and 2MHz mode takes a little more dealing with than simply setting the register.

$DD00
This one is actually a register aboard CIA 2 (one of the communications chips) but it's lowest two bits also control which bank the VIC-II is looking into for it's data. The bits are reversed so %11 is the lowest bank and %00 the highest. Because this register has a few other functions, it's best to not write directly to it and instead read the register, AND off the other bits and OR in the ones you're wanting to set before writing back.

The Programmers Reference Guide is kept online by Project 64
The VIC Article is available from Fairlight Tools

This article originally appeared on the UKScene website in October 2002.

Site content and design copyright © 2001-2012 T.M.R of Cosine Systems