CharPad 2.3 User Manual - Subchrist Software, 2019.
VIC-II Register Map.
The VIC-II graphics chip has 47 (8-bit) registers that can be collectively switched in or
out of the Commodore 64's address space but they will always appear between addresses $d000
and $d02e when switched in, these addresses are included in the register map below.
Reg# | | Addr Hex | | Addr Dec | | Description... |
0 | $d000 | 53248 | Sprite 0 X-position. |
1 | $d001 | 53249 | Sprite 0 Y-position. |
2 | $d002 | 53250 | Sprite 1 X-position. |
3 | $d003 | 53251 | Sprite 1 Y-position. |
4 | $d004 | 53252 | Sprite 2 X-position. |
5 | $d005 | 53253 | Sprite 2 Y-position. |
6 | $d006 | 53254 | Sprite 3 X-position. |
7 | $d007 | 53255 | Sprite 3 Y-position. |
8 | $d008 | 53256 | Sprite 4 X-position. |
9 | $d009 | 53257 | Sprite 4 Y-position. |
10 | $d00a | 53258 | Sprite 5 X-position. |
11 | $d00b | 53259 | Sprite 5 Y-position. |
12 | $d00c | 53260 | Sprite 6 X-position. |
13 | $d00d | 53261 | Sprite 6 Y-position. |
14 | $d00e | 53262 | Sprite 7 X-position. |
15 | $d00f | 53263 | Sprite 7 Y-position. |
16 | $d010 | 53264 | Sprites 0-7 X-position MSb's, one bit per sprite. |
17 | $d011 | 53265 | Control register 1 (default = X0011011)... |
Bit 7 - Raster line (Bit 8), read current, write for IRQ. | |||
Bit 6 - Extended colour text mode (1 = Enabled). | |||
Bit 5 - Bitmap mode (1 = Enabled). | |||
Bit 4 - Blank screen to border colour (0 = Blank). | |||
Bit 3 - Select 24/25 row text display (1 = 25 Rows). | |||
Bit 2 - Screen scroll Y-offset (Bit 2). | |||
Bit 1 - Screen scroll Y-offset (Bit 1). | |||
Bit 0 - Screen scroll Y-offset (Bit 0). | |||
18 | $d012 | 53266 | Raster line (Bits 0-7), read current, write for IRQ. |
19 | $d013 | 53267 | Light-pen latch X-position. |
20 | $d014 | 53268 | Light-pen latch Y-position. |
21 | $d015 | 53269 | Sprite display enable (one bit per sprite, 1 = Enabled). |
22 | $d016 | 53270 | Control register 2 (default = 11001000)... |
Bit 7 - NC | |||
Bit 6 - NC | |||
Bit 5 - RES: ALWAYS SET THIS BIT TO 0!. | |||
Bit 4 - Screen multi-colour mode. (1 = Enabled). | |||
Bit 3 - Select 38/40 column text display (1 = 40 columns). | |||
Bit 2 - Screen scroll X-offset (Bit 2). | |||
Bit 1 - Screen scroll X-offset (Bit 1). | |||
Bit 0 - Screen scroll X-offset (Bit 0). | |||
23 | $d017 | 53271 | Sprites 0-7 expand 2x vertical (one bit per sprite, 1 = Enabled). |
24 | $d018 | 53272 | Memory pointer register (default = 00010101)... |
Bit 7 - Video matrix (1KB) base address (Bit 3). | |||
Bit 6 - Video matrix (1KB) base address (Bit 2). | |||
Bit 5 - Video matrix (1KB) base address (Bit 1). | |||
Bit 4 - Video matrix (1KB) base address (Bit 0). | |||
Bit 3 - Character set (2KB) base address (Bit 2). | |||
Bit 2 - Character set (2KB) base address (Bit 1). | |||
Bit 1 - Character set (2KB) base address (Bit 0). | |||
Bit 0 - NC | |||
nb. In bitmap mode, bit 3 selects the upper or lower 8KB for use, bits 1 and 2 are ignored). | |||
25 | $d019 | 53273 | Interrupt flag register (1 = IRQ occurred)... |
Bit 7 - Set on any enabled VIC IRQ condition. | |||
Bit 6 - NC | |||
Bit 5 - NC | |||
Bit 4 - NC | |||
Bit 3 - IRQ: Light-pen. | |||
Bit 2 - IRQ: Sprite-to-sprite collision. | |||
Bit 1 - IRQ: Sprite-to-character collision. | |||
Bit 0 - IRQ: Raster beam reached written line. | |||
nb. Read to determine IRQ status/sources, write (1's) to acknowledge IRQ(s). | |||
26 | $d01a | 53274 | Interrupt mask register. (1 = IRQ enabled)... |
Bit 7 - NC | |||
Bit 6 - NC | |||
Bit 5 - NC | |||
Bit 4 - NC | |||
Bit 3 - IRQ: Light-pen. | |||
Bit 2 - IRQ: Sprite-to-sprite collision. | |||
Bit 1 - IRQ: Sprite-to-character collision. | |||
Bit 0 - IRQ: Raster line comparison. | |||
nb. Write (1's) to enable IRQ source(s). | |||
27 | $d01b | 53275 | Sprite to background display priority (one bit per sprite, 0 = Sprite has priority). |
28 | $d01c | 53276 | Sprites 0-7 multi-colour mode select (one bit per sprite, 1 = Multi-colour). |
29 | $d01d | 53277 | Sprites 0-7 expand 2x horizontal (one bit per sprite, 1 = Expand). |
30 | $d01e | 53278 | Sprite-to-sprite collision detection (one bit per sprite, cleared on reading). |
31 | $d01f | 53279 | Sprite-to-character collision detection (one bit per sprite, cleared on reading). |
32 | $d020 | 53280 | Screen border colour (0-15). |
33 | $d021 | 53281 | Background colour 0 (0-15, Screen colour). |
34 | $d022 | 53282 | Background colour 1 (0-15, Character multi-colour 1). |
35 | $d023 | 53283 | Background colour 2 (0-15, Character multi-colour 2). |
36 | $d024 | 53284 | Background colour 3 (Only used in 'Extended-colour' text mode). |
37 | $d025 | 53285 | Sprite multi-colour 1 (0-15). |
38 | $d026 | 53286 | Sprite multi-colour 2 (0-15). |
39 | $d027 | 53287 | Sprite 0 colour (0-15). |
40 | $d028 | 53288 | Sprite 1 colour (0-15). |
41 | $d029 | 53289 | Sprite 2 colour (0-15). |
42 | $d02a | 53290 | Sprite 3 colour (0-15). |
43 | $d02b | 53291 | Sprite 4 colour (0-15). |
44 | $d02c | 53292 | Sprite 5 colour (0-15). |
45 | $d02d | 53293 | Sprite 6 colour (0-15). |
46 | $d02e | 53294 | Sprite 7 colour (0-15). |
Notes...
Bits marked NC are not connected and will always read as set (1).
All colour registers only have their low nybbles (4 bits) connected, the bits of their upper nybbles will always read as set (1).
The 24/25 row mode switch ($d011, bit 3) is something of a misnomer, there are always 25 rows in the video matrix, this switch just toggles the visual expansion of the top and bottom borders, "24 row mode" is usually used to conceal the sudden appearance of fresh data when scrolling the screen vertically.
The 38/40 column mode switch ($d016, bit 3) is something of a misnomer, there are always 40 columns in the video matrix, this switch just toggles the visual expansion of the left and right borders, "38 column mode" is usually used to conceal the sudden appearance of fresh data when scrolling the screen horizontally.
The VIC-II can only access 16KB of memory (it only has 14 address lines), this can be deduced by examining the memory pointer register (reg #24, $d018) which only provides a 4-bit pointer (values 0-15) to specify a 1KB video matrix, a 3-bit pointer (values 0-7) to specify a 2KB character set and a 1-bit pointer (0 or 1) to specify an 8KB bitmap image.
The Commodore 64 (with it's 64KB memory) solves the above issue by providing two additional address bits in CIA chip #2, using these, the VIC-II can be made to "see" any one (but only one) of the four possible 16KB quarters ("video banks") of the available 64KB RAM.
Sprite images (63 bytes each) are selected using the Sprite Pointers, these are not available as on-chip registers, instead they are always located in the last 8 bytes of the active 1024 byte video matrix (which itself requires only 1000 bytes, 40x25 cells).
ie. If the VIC-II is using video bank 0 ($0000-$3fff, 16KB) and the video matrix pointer ($d018, upper nybble) is also set to 0 ($0000-$03ff, 1KB) then the 8 Sprite Pointers will be available at addresses $03f8-$03ff.
Although each sprite image requires only 63 bytes, each image's data should always be aligned on a 64 byte boundary, as each Sprite Pointer stores an 8-bit value (0-255) then we have space for a possible 256 sprite images in a 16KB video bank (256 * 64).
When the VIC-II is switched in to the Commodore 64's address space (as is normal) it's 47 registers appear from $d000 to $d02e but they are also mirrored every 64 bytes up to $d3ff, a total of 16 times across this 1024 byte (1KB) memory area as listed below.
nb. After each range of 47 addresses follows 17 disconnected addresses (64 total) that will always read $ff (ie. $d02f-$d03f).
$d000 - $d02e (the VIC-II registers are normally accessed using this
address range).
$d040 - $d06e
$d080 - $d0ae
$d0c0 - $d0ee
$d100 - $d12e
$d140 - $d16e
$d180 - $d1ae
$d1c0 - $d1ee
$d200 - $d22e
$d240 - $d26e
$d280 - $d2ae
$d2c0 - $d2ee
$d300 - $d32e
$d340 - $d36e
$d380 - $d3ae
$d3c0 - $d3ee
We can say then that the chip has a 1KB (1024 byte) footprint despite only
having 47 registers.