In this page...


Index

$D000-$D030

53248-53264 $D000-$D010 Sprite horizontal and vertical position registers

The position of each sprite is controlled by a pair of these registers plus a bit in the register at 53264/$D010. The extra bit is required because the horizontal position value can exceed 255. The extra bit is effectively the ninth (most significant) bit of the horizontal position register. The relationship of registers to sprites is as follow:

Sprite Horizontal register Bit in $D010 Vertical register
0 53248/$D000 0 53249/$D001
1 53250/$D002 1 53251/$D003
2 53252/$D004 2 53253/$D005
3 53254/$D006 3 53255/$D007
4 53256/$D008 4 53257/$D009
5 53258/$D00A 5 53259/$D00B
6 53260/$D00C 6 53261/$D00D
7 53262/$D00E 7 53263/$D00F

The values in these registers specify a sprite’s position on the screen. Actually, the values set the position of the upper left corner of the 24 X 21-pixel sprite pattern. The coordinate system used is slightly different from the one used for bitmapped graphics, as illustrated in next figure. Note that the sprite coordinate system remains the same regardless of the current screen mode (character or bitmapped) or sprite mode (standard or multicolor).

Vic sprite position values

The horizontal position range includes both the active screen area and the inactive left and right borders, in units that equal standard screen pixel widths. The vertical position range also includes the top and bottom borders in addition to the active screen area. Note that the horizontal position can be greater than 255, which is the largest value that can be stored in a horizontal position register. To move a sprite to horizontal position 256, you must set the horizontal position register to 0/$00 and set the most significant horizontal bit for that sprite (in the register at 53264/$D010) to %1.

The most significant bit must remain set for all positions greater than 255. Because of the extra programming required to move the sprite to this right portion of the screen, the vertical column at horizontal position 256 is frequently referred to as the seam. The values in these registers cannot be changed directly while the normal BASIC IRQ routine [$A84D] is in use. That routine copies the contents of the shadow sprite position locations (4566-4582/$11D6-$11E6) into these registers during each system IRQ interrupt. There are two ways to deal with this. The simplest solution is to store the desired sprite position values in the proper shadow location.

If you wish to use the true registers, you can prevent the execution of the BASIC portion of the IRQ interrupt. This will disable most BASIC sprite and sound commands, but that shouldn’t be a problem for machine language programmers. To prevent execution of the BASIC IRQ routine, you can either set bit 0 of the initialization status flag at $0A04 to %0 (which tells the Kernal that BASIC is not initialized), or you can store any nonzero value in the BASIC IRQ status flag at 4861/$12FD.

53265 $D011 Vertical smooth scrolling and control register

Bits 0-2: these bits control the VIC’s vertical fine scrolling feature. The value here specifies how many scan lines downward the display should be shifted. The available three bits allow the screen to be scrolled up to seven scan lines. The IOINIT routine $E109 initializes these bits to %011 = 3, so the default display will be scrolled down three scan lines from its highest possible position. The display scrolls without wrapping; blank scan lines are moved in from the top and scan lines on the bottom move off the visible screen. Pixels in scan lines scrolled off the bottom of the display are not erased. They become visible again if the display is scrolled back upward by reducing the value in these bits. The 24-row feature is useful with scrolling because it creates hidden scan lines at the top and bottom of the screen that can be scrolled onto the visible area.

Bit 3: this bit determines the vertical height of the active portion of the screen display. Setting this bit to %1 selects a 25-row (200 scan-line) active screen. The bit is initialized to this setting during the IOINIT routine $E109, and neither the operating system nor BASIC changes this value. Setting this bit to %0 reduces the height of the active portion of the display to 24 rows (192 scan lines) by blanking the top four and bottom four scan lines of the display. The pixels in the blanked columns aren’t erased; they’ll still be intact when the screen is switched back to 25 rows. The 24-row feature is useful in conjunction with the vertical scrolling feature described in bits 0-2.

Bit 4: this bit enables or disables the VIC screen display. While the bit is %1, the VIC provides its normal screen output. The bit is initialized to this setting during the IOINIT routine $E109. When the bit is set to %0, the VIC suspends the active portion of the display and provides a solid screen in the border color specified in the register at 53280/$D020. The screen is not erased, just blanked. Any text or graphics will still be intact if the screen is again enabled. With the display blanked, the VIC doesn’t have to steal timing cycles from the processor as it normally does. As a result, the 128 actually runs about 7 percent faster with the VIC display off. There are several uses for this blanking feature. For example, you could blank the display while drawing a complex bitmapped graphics screen, then dramatically unveil the completed picture by reenabling the display. Since the VIC cannot provide a proper display at the 2-MHz clock rate, the VIC display is normally blanked when the system is switched to fast mode. One step in the BASIC statement FAST involves setting this bit to %0. The SLOW statement returns it to %1. This bit is also set to %0 to blank the screen during tape operations, and restored to %1 upon completion of the operations.

Bit 5: this bit selects whether the VIC will generate a character mode display or a bitmapped mode display. Setting this bit to %0 selects character mode, while setting it to %1 selects bitmapped mode. This bit cannot be directly modified while the normal system interrupt sequence is active because a step in the screen editor IRQ routine [$C194] sets this bit according to the screen mode flag (location 216/$D8). To change the setting of this bit, you can either store the appropriate value in the flag location, or you can disable the screen-setup portion of the IRQ routine and change this bit directly. To use the flag location, set bit 5 of location 216/$D8 to the desired setting (%0 or %1) for the register bit. To turn off the screen-setup portion of the interrupt routine, store the value 255/$FF in location 216/$D8.

Bit 6: this bit controls extended background color mode, which offers a choice of four different background colors for each character position. For details about this mode, refer to the introduction for this section. Extended background color mode is enabled when this bit is set to %1. The mode works only in conjunction with character mode. You should not select extended background color mode while bit 5 is set to %1 to select bitmapped mode.

Bit 7: this bit is effectively the ninth bit of the raster register at 53266/$D011. Refer to the discussion of that register for details. The extra bit is necessary because a full screen contains more than 256 scan lines.

53266 $D012 Raster compare register

This register has two different functions, depending on whether it is being read from or written to. As explained in the introduction for this section, the video screen display consists of a stack of thin horizontal lines of dots called a raster. When the register is read, the value returned is the number of the raster scan line currently being drawn. The range of scanline numbers depends on the video system in use. For NTSC (North American) systems, values can be in the range 0-262, while PAL (European) systems have a maximum count of over 300.

In either case, the active portion of the screen consists of scan lines 50-249. The maximum scan-line number in either system is larger than can be held in a single eight-bit register, so bit 7 of the register at 53265/$D011 is used to hold the ninth bit of the value. When bit 7 of 53265/$D011 is %1, you should add 256/$100 to the value in this register to get the true scan-line number. For scan line 262, for example, bit 7 of 53265/$D011 will be %1 and the value in this register will be 6/$06.

Because the value in this register changes so rapidly (over 15,000 times per second), it can’t be read usefully from BASIC. By the time you PEEKed the value into a variable, the raster scan line would have moved far beyond the line recorded in the variable value. When you write to this register or to bit 7 of 53265/$D011, the value written is stored in an internal nine-bit raster compare latch register. Whenever the current scan-line count equals the value in this register, bit 0 of the interrupt register at 53273/$D019 will be set to %1. If bit 0 of the interrupt mask register at 53274/$D01A was previously set to %1, this will also trigger an external interrupt request to the processor. The value you store in this register represents the scan line at which you wish the interrupt to occur.

For scan-line values less than 256, you must also set bit 7 of 53265/$D011 to %0. For scan-line values of 256 or greater, you must set bit 7 of 53265/$D011 to %1 and store the line number minus 256 in this register. To calculate the top scan line corresponding to any row of character positions, use the following formula:

scan line = (row * 8) + 50

where the row value is in the range 0-24.

Raster interrupts can be used to program a variety of special video effects, including split screens like those in the GRAPHIC 2 and GRAPHIC 4 modes. The 128 also uses a raster interrupt off the visible screen (at scan line 255) to drive the system IRQ sequence. Because of this, you cannot write a new value directly to this register while the the normal system interrupt sequence is in use. The screen-setup portion of the screen editor IRQ routine [$C194] will write the value 255/$FF to this register on every pass, except when setting up the bitmapped portion of a split bitmapped/text screen. In that case, the value in location 2612/$0A34 will be copied into the register.

In either case, bit 7 of the register at 53265/$D011 will be set to %0. To use a raster interrupt for your own purposes, you must write a new interrupt routine.

53267/$D013 53268/$D014 Light pen horizontal and vertical positions

Whenever the VIC’s LP input line is brought to a low (0 volts) state, the raster beam’s horizontal dot position and vertical scan line are latched into these registers. The register at 53267/$D013 will hold the horizontal position value, and the one at 53268/$D014 will hold the vertical position value. To signal that a new value has been latched, bits 7 and 3 of the interrupt register at 53273/$D019 will be set to %1. These registers are read-only; writing to them has no effect. The registers are not cleared when read; the latched values will be retained until the LP line is again brought low. The range of scan-line values in the register at 53268/$D014 is the same as the range of sprite vertical positions shown in previous one figure. For example, the top scan line of the active screen area is 50. In that figure, you’ll note that the range of horizontal positions extends to 343, which is greater than can be represented in a single eight-bit register. To compensate, the range of horizontal values in the register at 53267/$D013 is the equivalent of one-half the range of horizontal values shown in previous one figure. For example, the horizontal-position value for the center of the screen is 184, so the corresponding light pen position will be about 92.

The LP line is connected to pin 6 of control port 1 (control port 2 does not support a light pen). A light pen has at its tip an electronic device known as a phototransistor, which is connected so as to cause a low pulse whenever the video beam moves past the pen. These registers can be tricked into reading false values. Pin 6 of control port 1 is also used for light pen input for the VIC chip, so a light pen signal generated on the 80-column screen will latch meaningless values in these registers. In lieu of a light pen, several other events can cause a pulse on the LP line. That control port pin is also used for the joystick fire button, so pressing the button of a joystick plugged into port 1 will also latch values in these registers. Because of this joystick button function, the port line is also connected to the line from row 4 of the keyboard matrix. This has two consequences. First, pressing any of the following keys with no light pen connected will latch meaningless values: Fl, Z, C, B, M, period, right SHIFT, space, the 2 and ENTER keys on the numeric keypad, and the ^ key in the cursor group. More significantly, while a light pen is connected, all of these keys will be “dead,” and cannot be typed.

53269 $D015 Sprite enable register

This register controls which sprites are enabled. Only enabled sprites can be visible, and only enabled sprites can be involved in collisions. Setting a bit in this register to %1 enables the corresponding sprite. However, an enabled sprite won’t be visible unless it is also positioned within the visible screen area, has a pattern definition that includes some nonzero bits, and is set to a color different from the screen background color. Setting a bit in this register to %0 turns off the corresponding sprite, but does not change the setting of any other parameters. When reenabled, the sprite will still have the same position, color, and pattern (unless those were changed while the sprite was turned off). The sprites are controlled as follows:

Bit Bit value Sprite controlled
0 1/$01 0
1 2/$02 1
2 4/$04 2
3 8/$08 3
4 16/$10 4
5 32/$20 5
6 64/$40 6
7 128/$80 7

This register is initialized to 0/$00 (all sprites disabled) by the IOINIT routine $E109, part of the reset and RUN/ STOP-RESTORE sequences. Sprites are normally disabled during tape and serial bus operations to prevent timing problems. In this case, the contents of the register are stored in location 2616/$0A38 for the duration of the operation, then restored to the register when the operation is completed. You can prevent this and keep sprites enabled by setting bit 7 of the custom mode flag (2618/$0A3A) to %1.

53270 $D016 Horizontal smooth scrolling and control register

Bits 0-2: these bits control the VIC’s horizontal smooth scrolling feature. The value here specifies the number of pixels the display is to be shifted to the right. The available three bits allow the screen to be shifted as many as seven pixels. The display scrolls without wrapping; blank pixels are moved in from the left and pixels on the right move off the visible screen. Pixels scrolled off the right are not erased, just hidden. They will become visible again if the display is scrolled back to the left by reducing the value in these bits. The 38-column feature is useful with scrolling because it creates a hidden left column that can hold pixels to be scrolled onto the visible area.

Bit 3: this bit determines the horizontal width of the screen. Setting this bit to %1 selects a 40-column (320-pixel) screen. The bit is initialized to this setting during the IOINIT routine $E109, and neither the operating system nor BASIC ever change this value. Changing this bit to %0 reduces the width of the active portion of the display to 38 columns (304 pixels) by blanking the leftmost and rightmost columns. Actually, 7 pixels on the left and 9 on the right are blanked. The contents of the blanked columns aren’t erased; they’ll still be intact when the screen is switched back to 40 columns. The 38-column feature is useful in conjunction with the horizontal scrolling feature in bits 0-2. Scrolling the 38-column screen the maximum 7 pixels to the right will make the contents of the previously hidden leftmost column visible.

Bit 4: this bit controls multicolor mode for both the character and bitmapped screens. While this bit is %0, foreground pixels will be limited to one color (although the color can be different for every character position). Setting this bit to %1 enables multicolor mode, which allows a choice of three different colors for each foreground pixel. However, selecting multicolor mode also cuts horizontal resolution for the screen in half. Selecting multicolor mode for the screen has no effect on any sprites that might be displayed on that screen.

Sprite multicolor mode is controlled by the register at 53276/$D01C. This bit cannot be directly modified while the normal system interrupt sequence is active because a step in the screen editor IRQ routine [$C194] sets this bit according to the screen mode flag (location 216/$D8). To change the setting of this bit for bitmapped mode, you can either store the appropriate value in the flag location, or you can disable the screen-setup portion of the IRQ routine and change this bit directly. To use the flag location, set bit 7 of location 216/$D8 to the desired setting (%0 or %1) for the register bit. To turn off the screensetup portion of the interrupt routine, store the value 255/$FF in location 216/$D8.

To select multicolor character mode, you must use the option to disable the screen setup, since the text mode-setup subroutine always sets this bit to %0.

Bit 5: this bit is referred to in Commodore literature as the reset bit, but its intended usage is unclear. The value here has no apparent affect on any VIC operations.

Bits 6-7: these bits are unused. Writing to them has no effect, and they always return %1 when read.

53271 $D017 Sprite vertical expansion register

Each bit in this register controls the vertical expansion feature for one of the eight sprites. The relationship of sprites to register bits is the same as for the sprite enable register (53269/$D015). Setting a bit here to %1 will double the vertical height of the corresponding sprite. Each sprite can be expanded independently, with regard for the background screen on which the sprite is displayed. The resolution of the sprite is not increased-it will still be 21 pixels tall-but the height of the pixels will be doubled. Vertical expansion can be selected in conjunction with horizontal expansion to double the size of a sprite. Horizontal expansion is controlled by the register at 53277/$D01D. The default value in this register, established by the IOINIT routine $E109, is 0/$00, so no sprites are initially expanded.

53272 $D018 Screen and character base address register

The value in this register determines the location within the current 16K VIC video bank of the two movable components of video memory: the screen memory/video matrix and character memory/bitmap areas. There is no provision for moving color memory; that area always appears at 55296-56319/$D800-$DBFF.

The contents of this register cannot be changed directly while the normal system IRQ interrupt sequence is in use. The screen editor IRQ routine [$C194] copies the contents of a shadow location into this register during each interrupt. The shadow location depends on the screen mode in use. For text mode, or for the text portion of a split screen, the contents of location 2604/$0A2C will be copied here. For bitmapped modes, the value in location 2605/$0A2D will be copied into the register. You have two choices for changing the value in this register. You can either store the desired value in the appropriate shadow location, or you can turn off the screen setup portion of the screen editor IRQ routine to gain direct access to the register. To disable the screen-setup step, store the value 255/$FF in location 216/$D8.

Bit 0: this bit is unused. Writing to it has no effect, and it always returns %1 when read. Thus, the value read from this register will always be odd.

Bits 1-3: the value in these bits determines the location of character memory (for character mode) or of the bitmap (for bitmapped modes). For character mode, a complete 256-character set requires 2048 (2K) bytes, and the character set must start on an even 2K memory address boundary. Possible selections are as follows:

Bits 3-2-1 Offset for character set
0 0 0 0/$00
0 0 1 2048/$0800
0 1 0 4096/$1000
0 1 1 6144/$1800
1 0 0 8192/$2000
1 0 1 10240/$2800
1 1 0 12288/$3000
1 1 1 14336/$3800

These bits do not determine the absolute address of the character set, but rather the offset from the starting address of the current video bank. For example, video bank 2 begins at address 32768/$8000, so a bit setting of %100 in that case would place the character set at 32768 + 8192 = 40960/$A000. However, the default video bank (bank 0) begins at location 0/$0000, so in that case the offset is equal to the actual address. The 128 normally provides a pair of character sets and allows you to switch between them by pressing the SHIFT - Commodore key combination. If you are setting up a single custom character set, you should disable this character set-switching feature by setting bit 7 of location 247/$F7 to %1. If you wish to retain the character set-switching feature, you must provide two character sets, one at an “even” position (one for which bit 1 of this register is %0), and the other at the next higher (“odd”) position. The CINT screen editor initialization routine $C07B sets bits 1-3 to %010 in location 2604/$0A2C, the shadow for this register in text mode. This places the default character memory at an offset of 4096/$1000 from the starting address of the video bank (and implies that the alternate character set will be located at an offset of 6144/$1800), This may seem strange, since there is certainly no character pattern data stored in RAM at addresses 4096-8191/$1000-$1FFF/ and since the 128’s memory map shows that the character ROM is actually located at addresses 53248-57343/$D000-$DFFF.

However, the 128 has the capability to make the VIC chip see character ROM at addresses 4096-6143/$1000-$17FF (for the uppercase/ graphics set) and addresses 6144-8191/$1800-$1FFF (for the lowercase/uppercase set) in any video bank. Note that this is a change from the Commodore 64, which could only see character ROM in video banks 0 and 2.

Only the VIC will see the character ROM at those addresses. To the processor, those locations will still be RAM. This feature is controlled by bit 2 of the 8502’s built-in I/O port, at location 1/$01. When bit 2 of the register at 1/$01 is %0, the VIC chip will see character ROM in the character memory areas beginning at addresses 4096/$1000 and 6144/$1800. No other character memory slots are affected.

When the I/O port bit is set to %1, the VIC will instead see the true contents of RAM at those addresses rather than images of the character ROM. Like other screen control locations, the I/O port bit has a shadow location. Bit 2 of location 217/$D9 is copied into bit 2 of location 1/$01 during each pass through the text screen-setup portion of the screen editor IRQ routine. To switch out character ROM, you must set bit 2 of the shadow location to %1 (store the value 4/$04 in location 217/$D9). Alternatively, you can disable the screen-setup portion of the screen editor IRQ routine by storing the value 255/$FF in location 216/$D8; then you change bit 2 of location 1/$01 directly. Finding free space for a custom character set can be a challenge. If you are using machine language exclusively, any of the character set slots above address 4864/$1300 can be used, but none of the address slots are completely free in the standard configuration with BASIC. If you disable character ROM, there is free memory at 6144-7167/$1800-$1BFF for half a character set (128 character patterns). If your program doesn’t use a bitmapped screen, you can allocate a bitmap area and then use the reserved space for custom character sets. For example, if your BASIC program includes the statements GRAPHIC 1:GRAPHIC 0, the area from 7168-16383/$1C00-$3FFF will be protected from BASIC, and any character memory slot in that area can be used to hold the new character set. Since the bitmap for a high-resolution display requires 8000 bytes of memory and must begin at an even 8K memory address boundary, there are only two possible positions for the bitmap within the 16K video bank. When you are specifying the location of the bitmap, only the setting of bit 3 is significant. When that bit is %0, the bitmap will begin at an offset of 0/$0000 from the start of the video bank. When bit 3 is %1, the bitmap begins at an offset of 8192/$2000 from the start of the video bank. The CINT screen editor initialization routine $C07B sets bits 1-3 to %100 in location 2605/$0A2D, the shadow for this register in bitmapped mode, so the default location of the bitmap is 8192/$2000 bytes beyond the start of the video bank (address 8192/$2000 for the default video bank).

Bits 4-7: these bits determine the location of the video matrix area, which is used as screen memory in character mode and to hold color information in bitmapped mode. The video matrix requires 1000 bytes of memory and must start on an even IK address boundary. Possible selections are as follows:

Bits 7-6-5-4 Offset for video matrix
0 0 0 0 0/$0000
0 0 0 1 1024/$0400
0 0 1 0 2048/$0800
0 0 1 1 3072/$0C00
0 1 0 0 4096/$1000
0 1 0 1 5120/$1400
0 1 1 0 6144/$1800
0 1 1 1 7168/$1C00
1 0 0 0 8192/$2000
1 0 0 1 9216/$2400
1 0 1 0 10240/$2800
1 0 1 1 11264/$2C00
1 1 0 0 12288/$3000
1 1 0 1 13312/$3400
1 1 1 0 14336/$3800
1 1 1 1 15360/$3C00

These bits do not determine the absolute address of the video matrix, but rather the offset from the starting address of the current video bank. For example, video bank 3 begins at address 49152/$C000, so a bit setting of %0010 in that case would place the character set at 49152 + 2048 = 51200/$C800.

However, the default video bank (bank 0) begins at location 0/$0000, so in that case the offset is equal to the actual address.

The CINT screen editor initialization routine $C07B sets bits 4-7 to %0001 in location 2604/$0A2C, the shadow for this register in text mode. This places the default character memory at an offset of 1024/$0400 from the starting address of the video bank. You can’t change this register directly while the normal system interrupt sequence is active. To move the video matrix for the text screen, you can either change the value in location 2604/$0A2C, or you can turn off the screensetup portion of the interrupt sequence by storing the value 255/$FF in location 216/$D8. After that, you can change the register directly. Even if you change the value in this register, all printed characters will continue to go to the former screen memory range until you change the value in location 2619/$0A3B to reflect the new starting page for screen memory.

Because the bitmap for a high-resolution display requires half of the memory available in a 16K video bank, only half of the possible addresses are really useful. When setting up a bitmapped display, you should select a video matrix area in the portion of the video bank not occupied by the bitmap. The CINT screen editor initialization routine $C07B sets bits 4-7 to %0111 in location 2605/$0A2D, the shadow for this register in bitmapped mode, so the default location of the video matrix in that mode is 7168/$1C00 bytes from the start of the video bank (address 7168/$1C00 for the default video bank). Thus, the bitmapped mode video matrix will not disturb character mode screen memory.

To move the video matrix for the bitmapped screen, you can either change the value in location 2605/$0A2D, or you can turn off the screen-setup portion of the interrupt sequence by storing the value 255/$FF in location 216/$D8. After that, you can change the register directly.

53273 $D019 VICIRQ

Interrupt register

This register is read-only; writing to this location has no effect. Bits 0-3 indicate the status of the four interrupt sources for the VIC chip. These bits will always reflect the status of their corresponding events, regardless of whether or not register $D01A has been set to trigger an external interrupt request for the event. Once a bit here is set to %1, it will retain that value until the register is read, at which time all functional bits are reset to %0.

Bit 0: This bit will be set to %1 whenever the raster scan-line count equals the value in the raster compare register $D012 (plus bit 7 of $D011).

Bit 1: This bit will be set to %1 whenever a nontransparent portion of a sprite overlaps any screen foreground pixels. (Remember, however, that for multicolor character or multicolor bitmapped screens, no collision can be detected between sprites and foreground pixels represented by %01 bit patterns.) The register at $D01F records which sprites are involved in collisions with foreground data.

Bit 2: This bit will be set to %1 whenever two or more sprites overlap. Collisions can only be detected between the foreground portion of the sprites, those pixels represented by nonzero bit patterns. No collision is detected when the overlapping portions of the sprites are transparent (when the pixels are represented by %0 or %00 bit patterns). The register at location $D01E records which sprites are involved in collisions with other sprites.

Bit 3: This bit will be set to %1 whenever a new value is latched into the light pen registers at $D013-$D014.

Bits 4-6: The bits are not used, and always return %1 when read.

Bit 7: Whenever any internal interrupt source sets one of the other bits in this register to %1, this bit will also be set to %1 to indicate that an internal interrupt has been recorded. Thus, you need to test only this bit to determine whether an internal interrupt has occurred. Note that this register is automatically cleared after it is read, so you’ll need to save the register value before testing this bit if you want to be able to subsequently read any of the other bits.

53274 $D01A IRQMSK

Interrupt enable register

Certain events such as sprite-sprite collisions always generate internal VIC interrupts, recorded in the register at $D019. The VIC chip has the capability to generate an external interrupt request to the processor as a result of any of these conditions. In the 128, the VIC’s interrupt request output line is connected to the processor’s IRQ line, so internal VIC events can trigger processor IRQ interrupts. See Appendix A for more information on IRQ interrupts.

Bit 0: Setting this bit to %1 enables an external interrupt request when the raster count match is recorded in the flag at bit 0 of the register at $D019. Because raster interrupts are the normal source of the system jiffy interrupt that drives keyboard scanning and other important housekeeping features, this bit is initialized to %1 by the Kernal IOINIT routine $E109. Changing this bit to %0 will completely disable the system interrupt.

Bit 1: Setting this bit to %1 enables an external interrupt request when a sprite-foreground collision is recorded in the flag at bit 1 of the register at $D019, as when a sprite passes over a character on the text screen.

Bit 2: Setting this bit to %1 enables an external interrupt request when a sprite-sprite collision is recorded in the flag at bit 2 of the register at $D019.

Bit 3: Setting this bit to %1 enables an external interrupt request when a new value is recorded in the flag at bit 3 of the register at $D019. It is risky to use this interrupt source, because a number of events other than the light pen can trigger the latching of values into these registers. See the entry for the light pen registers for details.

Bits 4-7: These bits are unused; writing to them has no effect, and they always return %1 when read. Thus, the value seen when this register is read will always be at least 240/$F0. To mask off these unused bits and see the valid interrupt settings, use AND 15 in BASIC or AND #$0F in machine language.

53275 $D01B SPBGPR

Sprite-to-foreground priority register

Each bit in this register controls the sprite-to-foreground priority for one of the eight sprites. The relationship of sprites to bits is the same as for the sprite enable register ($D015). While a bit here is %0, the corresponding sprite will have higher priority than the screen foreground, and will thus appear to pass in front of anything displayed in the foreground color on the text or bitmapped screens. When a bit here is set to %1 , the corresponding sprite will have lower priority than the screen foreground, and will thus appear to pass behind anything displayed in the foreground color. For multicolor character or multicolor bitmapped screen modes, the low-priority sprite will appear to pass behind screen pixels represented by %10 and %11 bit patterns, but will still pass in front of pixels represented by %01 bit patterns. (The sprite always appears in front of pixels with the %00 background bit pattern.) The default value for this register, established by the IOINIT routine $E109, is 0/$00, so all sprites initially have higher priority than the screen foreground.

53276 $D01C SPMC

Sprite multicolor mode register

Each bit in this register controls the multicolor feature for one of the eight sprites. The relationship of sprites to register bits is the same as for the sprite enable register ($D015). Setting a bit here to %1 selects multicolor mode for the corresponding sprite. Multicolor mode can be selected independently for each sprite, and standard and multicolor sprites can be mixed freely on the same screen. Multicolor sprites are not restricted to multicolor screen modes; they can be used freely in standard screen modes as well. The default value for this register, established during the IOINIT routine $E109, is 0/$00, so no sprites are initially in multicolor mode.

Selecting multicolor mode for a sprite reduces the number of horizontal pixels for the sprite from 24 to 12. However, the sprite remains the same size; the multicolor sprite pixels are twice as wide. Two bits of the pattern definition are required for each pixel. All pixels represented by %00 are transparent; whatever is behind the sprite will show through. Pixels with %01 and %11 bit patterns take their color values from the registers at $D025 and $D026, respectively, which are common to all multicolor sprites. Pixels with %10 bit patterns take the color specified in the color register for the particular sprite ($D027-$D02E).

53277 $D01D XXPAND

Sprite horizontal expansion register

Each bit in this register controls the horizontal expansion feature for one of the eight sprites. The relationship of sprites to register bits is the same as for the sprite enable register ($D015). Setting a bit here to %1 will double the horizontal width of the corresponding sprite. Each sprite can be expanded independently, without regard for the background screen on which the sprite is displayed. The resolution of the sprite is not increased (it will still be 24 pixels wide) but the width of the pixels will be doubled. Horizontal expansion can be selected in conjunction with vertical expansion to double the size of a sprite. (Vertical expansion is controlled by the register at $D017.) The default value in this register, established by the IOINIT routine $E109, is 0/$00, so no sprites are initially expanded.

53278 $D01E SPSPCL

Sprite-to-sprite collision register

This register records collisions between two or more sprites. This register is read-only; storing values here has no effect. A collision occurs whenever any nontransparent portions of the sprites overlap. Transparent pixels (pixels with bit patterns of %0 or %00) are not involved in collisions. When sprites collide, the bits in this register corresponding to those sprites are set to %1 (the correspondence between sprites and bits is the same as for the sprite enable register). Since a minimum of two sprites are involved in any sprite-sprite collision, at least two bits will be set. The register is automatically cleared to 0/$00 after each time it is read, so you’ll need to store the value you read if you wish to perform multiple tests. Bit 2 of the interrupt register at $D019 will also be set to %1 whenever any sprite-sprite collision occurs.

This register indicates only that sprites have collided. It does not necessarily tell you which sprites are involved in a particular collision. If only two bits are set, then those sprites obviously must have hit each other. However, if you find that three or more bits are set, you must read the horizontal and vertical position registers for the involved sprites and determine which sprites are in contact with each other. Remember that the sprite position registers return the position of the upper left corner of the sprite, which may not be the point of the sprite that is colliding with the foreground.

One thing to beware of when reading this register is that after a sprite overlaps a foreground object, the register will continue to record collisions until the sprite is moved away from the object. Also, sprite-sprite collisions can occur even when the sprites are located completely outside the visible screen area.

53279 $D01F SPFGCL

Sprite-foreground collision register

This register records collisions between sprites and the screen foreground. This register is read-only; storing values here has no effect. A collision occurs whenever any pixel in a sprite represented by a nonzero bit pattern overlaps any foreground pixel on the screen, as when a sprite passes over a character on the text screen. Background or transparent pixels are not involved in collisions. For the purposes of collision detection, multicolor screen pixels represented by %01 bit patterns are not considered foreground, and no collision will be detected when a sprite pixel overlaps a multicolor screen %01 pixel. When a sprite collides with a foreground pixel, the bit in this register corresponding to that sprite is set to %1 (the correspondence between sprites and bits is the same as for the sprite enable register). The register is automatically cleared to 0/$00 after each time it is read, so you’ll need to store the value you read if you wish to perform multiple tests. Bit 1 of the interrupt register at $D019 will also be set to %1 whenever any sprite-foreground collision occurs.

This register indicates only that a sprite has collided with some portion of the screen foreground. It does not tell you exactly what the sprite is overlapping. To determine that, you must determine which sprite or sprites are involved in collisions, then read the horizontal and vertical position registers for the involved sprites and determine what screen-foreground object is located in that vicinity. Remember that the sprite position registers return the position of the upper left corner of the sprite, which may not be the point of the sprite that is colliding with the foreground.

One thing to beware of when reading this register is that after a sprite overlaps a foreground object, the register will continue to record collisions until the sprite is moved away from the object.

53280 $D020 EXTCOL

Border color register

The value in this register determines the color of the screen border, the area of the screen surrounding the active portion of the display. When the screen is blanked by setting bit 4 of the register at $D011 to %0, the entire display area will be filled with the color specified here. Since the VIC can produce only 16 different colors, only four bits are required to hold all possible color values. Thus, only bits 0-3 of this location hold meaningful values. Bits 4-7 are unused; writing to those bits has no effect, and the bits always return % 1 when read. Thus, the value in this register will always be at least 240/$F0. To mask off these bits and read the true color value you should use AND 15 in BASIC or AND #$0F in machine language. See Table 8-1 for a list of standard VIC color values. The default setting for this register, established by the IOINIT routine $E109, is 13/$0D (light green). From BASIC, the value here can be changed using the statement COLOR 4,rc (where n is the desired BASIC color number; BASIC color numbers are equal to VIC color values plus one).

53281 $D021 BGCOL0

Background color register 0

In standard character mode, the value here determines the color of all pixels in a screen position which are represented by %0 bits in the character pattern. This background color is common to all screen positions. Clearing the screen fills all positions with the screen code for the space character, which has a pattern that is all %0 bits. Thus, a cleared screen will be filled with the color specified here. The color of pixels with %1 bits in the character pattern (the foreground color) is determined by the value in the color memory location for the position.

This register is also used in both of the other character modes. In multicolor character mode, the value here determines the color of all pixels in all screen positions represented by %00 bit pairs in the character pattern. In extended background color mode, the value here determines the background color in any screen positions for which bits 6-7 of the screen code in the corresponding screen memory location are %00. This register is unused in standard bitmapped mode, but for multicolor bitmapped mode the value here determines the color for all pixels represented in the bitmap by %00 bit pairs.

Since the VIC can produce only 16 different colors, only four bits are required to hold all possible color values. Thus, only bits 0-3 of this location hold meaningful values. Bits 4-7 are unused; writing to those bits has no effect, and the bits always return %1 when read. Thus, the value in this register will always be at least 240/$F0. To mask off these bits and read the true color value you should use AND 15 in BASIC or AND #$0F in machine language. See Table 8-1 for a list of standard VIC color values. This register is initialized to 11/$0B (dark gray) by the IOINIT routine $E109, part of both the reset and RUN/STOP-RESTORE sequences. From BASIC, the value here can be changed using the statement COLOR 0,n (where n is the desired BASIC color number; BASIC color numbers are equal to VIC color values plus one.)

53282 $D022 BGCOL1

53283 $D023 BGCOL2

53284 $D024 BGCOL3

Background color registers 1-3

These three registers are used only when multicolor character mode or extended background color mode is enabled. For multicolor character mode, the value in 53282/$D022 determines the color of any pixels in a screen position represented by %01 bit pairs in the character pattern, and the value in 53283/$D023 determines the color of all pixels with %10 pairs. Since there is only one set of registers for all screen positions, the colors of pixels with %01 and %10 bit pairs will be common to all characters on the screen. The color of pixels with %00 bit pairs is determined by the value in $D021, and the color of pixels with %11 bit pairs is selected individually for each character position by the value in the corresponding color memory location (55296-56319/$D800-$DBFF). The register at 53284/$D024 is unused in multicolor character mode.

For extended background color mode, these registers determine the background color for the character position for the character, depending on the setting of bits 6-7 of the screen code in the screen memory location for the position. The selections are as follows:

Bits 7-6 Background color source register
0 0 53281/$D021
0 1 53282/$D022
1 0 53283/$D023
1 1 53284/$D024

Since the VIC can produce only 16 different colors, only four bits are required to hold all possible color values. Thus, only bits 0-3 of these locations hold meaningful values. Bits 4-7 in any of these locations are unused. Writing to those bits has no effect, and the bits always return %1 when read. Thus, the value in any of these locations will always be at least 240/$F0. To mask off these bits and read the true color value you should use AND 15 in BASIC or AND #$0F in machine language. These registers are initialized during the IOINIT routine $E019, part of the reset and RUN/STOP-RESTORE sequences. The default values are 1 (white) for 53282/$D022, 2 (red) for 53283/$D023, and 3 (cyan) for 53284/$D024. There is no BASIC statement specifically for changing the settings of these registers.

53285 $D025 SPMC0

53286 $D026 SPMC1

Sprite multicolor registers

The values in these registers determine two of the colors for multicolor sprites. A sprite can be switched to multicolor mode by setting the appropriate bit in the register at $D01C. The value in the register at 53285/$D025 determines the color for all pixels in the sprite represented by %01 bit pairs in the pattern. The value in 53286/$D026 determines the color for all pixels represented by %11 bit pairs. Since there are only these two registers for all eight sprites, the colors of pixels with %01 and %11 bit pairs will be common to all sprites. The color of pixels represented by %10 bit pairs can be selected individually for each sprite using the registers at $D027-$D02E. Pixels with %00 bit pairs in the pattern will be transparent.

Since the VIC can produce only 16 different colors, only four bits are required to hold all possible color values. Thus, only bits 0-3 of these locations hold meaningful values. Bits 4-7 in any of these locations are unused. Writing to those bits has no effect, and the bits always return %1 when read. Thus, the value in any of these locations will always be at least 240/$F0. To mask off these bits and read the true color value you should use AND 15 in BASIC or AND #$0F in machine language. See Table 8-1 for a list of standard VIC color values. The default settings of these registers, established by the IOINIT routine $E109, are 1 (white) for 53285/$D025 and 2 (red) for 53286/$D026. From BASIC, these settings can be changed using the SPRCOLOR statement.

53287 $D027 SP0COL

53288 $D028 SP1COL

53289 $D029 SP2COL

53290 $D02A SP3COL

53291 $D02B SP4COL

53292 $D02C SP5COL

53293 $D02D SP6COL

53294 $D02E SP7COL

Sprite color registers

Each of these registers holds color information for one of the eight sprites. For standard sprites, the value here determines the color of all %1 bits in the sprite pattern (%0 bit positions will be transparent). For multicolor sprites, the value here determines the color of all %10 bit groups in the pattern.

Since the VIC can produce only 16 different colors, only four bits are required to hold all possible color values. Thus, only bits 0-3 of these locations hold meaningful values. Bits 4-7 in any of these locations are unused. Writing to those bits has no effect, and the bits always return %1 when read. Thus, the value in any of these locations will always be at least 240/$F0. To mask off these bits and read the true color value you should use AND 15 in BASIC or AND #$0F in machine language. See Table 8-1 for a list of standard VIC color values. The following table shows the default colors for each sprite, established by the IOINIT routine $E109, part of both the reset and RUN/STOP-RESTORE sequences.

Register Sprite Default color
53287/$D027 0 0 (black)
53288/$D028 1 1 (white)
53289/$D029 2 2 (red)
53290/$D02A 3 3 (cyan)
53291/$D02B 4 4 (purple)
53292/$D02C 5 5 (green)
53293/$D02D 6 6 (blue)
53294/$D02E 7 7 (yellow)

53295 $D02F XSCAN

Extended keyboard scan-line control register

Bits 0-2: Each of these bits controls the state of one of the three output lines from the VIC chip, K0-K2. Setting a register bit to %0 causes the corresponding output line to go to a low (0 volts) state, while setting a register bit to %1 causes the output line to go to a high (+ 5 volts) state. Reading these bits returns the current state of the corresponding output lines. In the 128, the three output lines are used to scan the three keyboard columns containing the 24 keys in the numeric keypad and top row of control keys. See Figure 7-1 and the discussion of the keyboard scanning routine $C55D in Chapter 7 for more information.

Unless you are writing a custom keyboard scanning routine, there’s rarely a need to tinker with this register. The output lines are connected only to the keyboard, and are not available externally.

Bits 3-7: These bits are unused. Writing to them has no effect, and they always return %1 when read. Thus, the value in this location will always be at least 248/$F8. To mask off these irrelevant bits, use AND 7 in BASIC or AND #$07 in machine language.

53296 $D030 CLKRATE

Processor clock rate control register

Bit 0: This bit controls the processor clock speed. (Remember, the VIC chip is the source of most of the system’s timing signals.) When the bit is set to %0, the processor operates at its normal 1-MHz rate. To be precise, the clock frequency is 1.02273 MHz for NTSC (North American) systems and 0.98525 MHz for PAL (European) systems. Setting this bit to %1 doubles the clock rate, providing what is commonly referred to as 2-megahertz (MHz) mode. This is also known as fast mode, the old standard speed being disparagingly referred to as slow mode. During the reset and RUN/STOP-RESTORE sequences, the IOINIT routine $E109 sets this bit to %0 for slow mode.

Fast mode does have a few limitations. While the 8502 microprocessor and the VDC 80-column video chip have no problems operating at the higher clock rate, most of the other I/O chips cannot keep up at this speed. The VIC chip itself cannot maintain its video display at this speed-the 40-column screen becomes a colorful pattern of rapidly flashing squares. It is common practice to set bit 4 of the VIC register at $D011 to %0 to blank the 40-column screen display while operating in 2-MHz mode. For example, the BASIC routine for the FAST statement [$77B3] includes this step. The VDC provides an alternative to the VIC for fast mode, but other I/O chips have no substitutes. In these cases, the system employs an elaborate technique known as clock stretching, where the clock period is extended to create an effective 1-MHz rate for the portion of the clock cycle when the I/O chip is being accessed.

Because some serial bus and tape communications routines depend on software loops for timing functions, the system is usually switched to the slower clock frequency when serial bus or tape operations are being performed. The contents of this register are stored in location 2615/$0A37 during the operation, and restored to the register when the operation is completed. You can prevent this by setting bit 7 of the custom mode flag (location 2618/$0A3A) to %1. In this case, the clock rate will not be changed during tape and serial operations.

Bit 1: This bit is described in Commodore literature as a test bit. The IOINIT routine $E019 sets the bit to %0, and no other 128 ROM routine changes that setting. Some programmers have discovered that setting this bit to %1 will blank the 40-column screen display, and have even used this as an alternative to clearing bit 4 of location $D011 when switching the processor to fast mode. While this does appear to work without side effects, such undocumented “features” are best avoided.

Bits 2-7: These bits are unused. Writing to them has no effect, and they always return %1 when read. Thus, the value in this register will always be at least 252/$FC. To mask off these bits, use AND 3 in BASIC or AND #$03 in machine language.

See also