Commodore 64 Assembly Sprite
In this lesson, we provided building block steps that will teach you how to get a Commodore 64 assembly sprite up on the screen and moving. This C64 Assembly Sprite Tutorial was developed with the beginner in mind. It will be helpful if you do have a minor grasp on Basic as a lot of those techniques can be applied here.
For the first part we access the register $d020 (53280) in order to control the border color. The Commodore 64 utilizes memory “registers” to access specific functions that can be used within a program. The hardware chip that manages the border color is known as VIC II (Video Interface Controller).
The Border color has the ability to produce colors from 1-16. These colors are set and cannot be changed. The first set from 0-8 is known as standard colors and the remaining 9-16 are the multi colors. The color palette is defined below for our Commodore 64 Assembly Sprite project.
Note: The sprite tutorial is brief currently and will eventually be updated with more content. Let me know if you need more explanation of the code below. I’m always happy to further elaborate the tutorial to make things more clear.
VIC-II Memory
The Commodore 64 allows you to produce up to 8 sprites in memory and display them on the screen. The registers below dictate what they control. A specific microprocessor chip known as VIC (Video Interface Controller) contains 4K of memory between registers 53248-53294 ($D000 – $D02E). The VIC chip (or “VIC II”) is primarily responsible for the graphics and sprites that can be displayed on your system. The video display memory must be contained in a 16K that makes up display memory, character dot data and sprite shapes.
Mapping the Commodore 64
Feel free to view the Compute! PDF book “Mapping the Commodore 64” to explore more about these registers in detail. You can learn so much about your Commodore 64 just by consuming this book. It’s an excellent resource!
Sprite X Horizontal | Sprite Y Vertical |
---|---|
53248 ($D000) | 53249 ($D001) |
53250 ($D002) | 53251 ($D003) |
53252 ($D004) | 53253 ($D005) |
53254 ($D006) | 53255 ($D007) |
53256 ($D008) | 53257 ($D009) |
53258 ($D00A) | 53259 ($D00B) |
53260 ($D00C) | 53261 ($D00D) |
53262 ($D00E) | 53263 ($D00F) |
Below is a listing of the program in PDF format
[wonderplugin_pdf src=”https://www.c64brain.com/wp-content/uploads/2021/05/C64-Assembly-Sprite-Tutorial.pdf” width=”100%” height=”600px” style=”border:0;”]
Color 0 = Black
Color 1 = White
Color 2 = Red
Color 3 = Cyan (Blue/Green)
Color 4 = Purple
Color 5 = Green
Color 6 = Blue<
Color 7 = Yellow
Color 8 = Orange
Color 9 = Brown
Color 10 = Light Red
Color 11 = Dark Grey
Color 12 = Medium Grey
Color 13 = Light Green
Color 14 = Light Blue
Color 15 = Light Grey
The program starts off by setting the Commodore 64 border color.
Then we turn on the sprite, set the multi colors, sprite colors, background color, sprite x/y position, and set the sprite on the screen by setting the sprite shape pointer.
Note: Not all the registers will be seen here, but only the ones we need to first setup our sprite and others of importance.
Sprite Registers | Description |
---|---|
53264 ($D010) | Most Significant Bit of Sprites 0-7 Horizontal Positions |
53269 ($D015) | Sprite Enable Registers (Bit 0=Off, Bit 1=On): Makes sprites visible |
53271 ($D017) | Sprite Vertical Expansion Register (Bit =0 – Normal Height, Bit = 1 – Double Height: Sprite Y Size |
53275 ($D01B) | Sprite to Foreground Display Priority Register (Bit = 0 – Sprite in front, Bit = 1 Sprite in back |
53276 ($D01C) | Sprite Multicolor Registers (Bit 0=Off, Bit 1= On: Controls individual colors in bit pairs |
53277 ($D01D) | Sprite Horizontal Expansion Register (Bit 0 = Normal width, Bit 1 = Double Width): Sprite X Size |
53278 ($D01E) | Sprite to Sprite Collision Register (Bits 0-7: Determines if a sprite collided (Bit = 1 – collision occurred) |
53279 ($D01F) | Sprite to Foreground Collision Register (Bits 0-7) – Bit = Off – no collision, Bit = On – collision occurred |
* = $8000
; Found on Youtube
; Title: Commodore 128D: Episode 3: Hardware Sprites
; Channel: Nybbles and Bytes
lda #13
sta $d020 ; set the border color
jsr $e544 ; clear the screen (using a kernal call)
Sprite Color Registers
The table below sets the Sprite Color Registers. The sprites color are from 0-15 and we can use any colors from the standard color set.
Sprite Number | Sprite Register for Color |
---|---|
Sprite 0 | 53287 ($D027) |
Sprite 1 | 53288 ($D028) |
Sprite 2 | 53289 ($D029) |
Sprite 3 | 53290 ($D02A) |
Sprite 4 | 53291 ($D02B) |
Sprite 5 | 53292 ($D02C) |
Sprite 6 | 53293: ($D02D) |
Sprite 7 | 53294 ($D02E) |
The following lines set the multi-color for our sprites, background color, and position the sprites at a starting area on the screen.
lda #7
sta $d015 ; enable sprite
lda #7
sta $d01c ; activate multicolor bits
lda #$f4
sta $d025 ; sprite multicolor reg #1
lda #$f9
sta $d026 ; sprite color #0
lda #$05
sta $d027 ; sprite color #1
lda #0
sta $d021 ; background color
lda #24
sta $d000 ;sprite horizontal(x) position
sta $fb
sta $fc
lda #$90
sta $d001 ;sprite vertical(y) position
Sprite Shape Data
As usual, examining another table should help to simply a few things. The data will not be in a particular order, just in ascending order as seen in the code below so we can stay on course with this tutorial.
Each sprite (0-7) is defined by a pattern that ranges from 24 (across) and 21 (down). They occupy a total of 63 bytes for the shape patterns. The register locations 2040-2047 ($7F8 – $7FF) below setup a pointer in memory where that sprite data exists and can be displayed.
Sprite Shape Data Pointer | Description |
---|---|
2040 ($7F8) | Sprite Shape Data 1 |
2041 ($7F9) | Sprite Shape Data 2 |
2042 ($7FA) | Sprite Shape Data 3 |
2043 ($7FB) | Sprite Shape Data 4 |
2044 ($7FC) | Sprite Shape Data 5 |
2045 ($7FD) | Sprite Shape Data 6 |
2046 ($7FE) | Sprite Shape Data 7 |
2047 ($7FF) | Sprite Shape Data 8 |
In this area we set the shape pointer for sprite 0 that will be running across the screen from left to right.
lda #$c0
sta $7f8 ; sprite shape pointer
Position upper left Sprite
The next section will position the example sprite to be visible in the upper left corner. Try changing the x and y coordinate values to see it move around the screen.
Note: Be sure to refer back to the table above if you need to review the sprite registers again.
; show sprite 1 in corner
lda #24
sta $d002 ;sprite 1 X coordinate
lda #50
sta $d003 ;sprite 1 Y coordinate
Below is the colors for sprite 1 (stored in $D028) and we set the shape pointer here also. This is the sprite that appears in the upper left corner (used here for demonstration of having multiple sprites on a single screen).
lda #7
sta $d028 ; sprite 1 color reg
lda #$c4 ; sprite 1 shape data pointer
sta $7f9
Drawing the Floor
Registers 1024-2023 ($400-$7E7) contain the “Video Screen Memory Area” (resides in 1k of memory). Essentially this is the display you see when you boot up your computer or the VICE C64 Emulator. Each row (across) goes from 0-39 and 0-24 (down). So each character positions is reading a value from one of the registers here depending on which line the screen character has been typed on. You can peek into memory here in Basic to learn more about the data the exists here. It can read any character value from 0-255 (in the PET ASCII character set).
Screen Memory Registers | Description |
---|---|
1024-1063 ($0400-$0427): Line 1 | Screen Memory Data for Line 1 |
1064-1103 ($0428-$044F): Line 2 | Screen Memory Data for Line 2 |
1104-1143 ($0450-$0477): Line 3 | Screen Memory Data for Line 3 |
1144-1183 ($0478-$049F): Line 4 | Screen Memory Data for Line 4 |
1184-1223 ($04A0-$04C7): Line 5 | Screen Memory Data for Line 5 |
1224-1263 ($04C8-$04EF): Line 6 | Screen Memory Data for Line 6 |
1264-1303 ($04F0-$0517): Line 7 | Screen Memory Data for Line 7 |
1304-1343 ($0518-$053F): Line 8 | Screen Memory Data for Line 8 |
1344-1383 ($0540-$0567): Line 9 | Screen Memory Data for Line 9 |
1384-1423 ($0568-$058F): Line 10 | Screen Memory Data for Line 10 |
1424-1463 ($0590-$05B7): Line 11 | Screen Memory Data for Line 11 |
1464-1503 ($05B8-$05DF): Line 12 | Screen Memory Data for Line 12 |
1504-1543 ($05E0-$0607): Line 13 | Screen Memory Data for Line 13 |
1544-1583 ($0608-$062F): Line 14 | Screen Memory Data for Line 14 |
1584-1623 ($0630-$0657): Line 15 | Screen Memory Data for Line 15 |
1624-1663 ($0658-$067F): Line 16 | Screen Memory Data for Line 16 |
1664-1703 ($0680-$06A7): Line 17 | Screen Memory Data for Line 17 |
1704-1743 ($06A8-$06CF): Line 18 | Screen Memory Data for Line 18 |
1744-1783 ($6D0-$06F7): Line 19 | Screen Memory Data for Line 19 |
1784-1823 ($06F8-$071F): Line 20 | Screen Memory Data for Line 20 |
1824-1863 ($0720-$0747): Line 21 | Screen Memory Data for Line 21 |
1864-1903 ($0748-$076F): Line 22 | Screen Memory Data for Line 22 |
1904-1943 ($0770-$0797): Line 23 | Screen Memory Data for Line 23 |
1944-1983 ($0798-$07BF): Line 24 | Screen Memory Data for Line 24 |
Screen Display Codes
The Commodore 64 retains a character set in memory that can be written to the screen in the area of 1024-2023. The example program here draws an area under the sprite serving as a floor he can walk on. The screen reads in 40 bytes of data and draws one line after the other.
Click on the button to view the screen display codes (0-255). Therefore only values of 0-255 can be placed into screen memory.
Floor placed below the sprite
Here is the code that displays the ground under our animated sprite. Again looking at the Screen Display Codes PDF will help clarify the data that is being written to the screen.
ldx #$28
|
lda #78
|
---|---|
lda #77
|
dex
|
Color Memory Map
On the flip side of drawing the screen, we also have to take time to consider the coloring of the background text characters on the screen. This resides in an area known as Color Ram reserved between registers 55296-56295 ($D800-$DBE7). One important thing to remember is that color memory never changes, so you don’t have to copy it anywhere else even if you decide later you need more room (such as for a massive map environment).
Color Memory Registers | Description |
---|---|
55296-55335 ($D800-$D827) | Color Memory Data for Line 1 |
55336-55375 ($D828-$D84F) | Color Memory Data for Line 2 |
55376-55415 ($D84F-$D877) | Color Memory Data for Line 3 |
55416-55455 ($D878-$D89F) | Color Memory Data for Line 4 |
55456-55495 ($D8A0-$D8C7) | Color Memory Data for Line 5 |
55496-55495 ($D8C8-$D8EF) | Color Memory Data for Line 6 |
55536-55575 ($D8F0-$D917) | Color Memory Data for Line 7 |
55576-55615 ($D918-$D93F) | Color Memory Data for Line 8 |
55616-55657 ($D940-$D969) | Color Memory Data for Line 9 |
55656-55697 ($D968-$D991) | Color Memory Data for Line 10 |
55696-55735 ($D990-$D9B7) | Color Memory Data for Line 11 |
55736-55775 ($D9B8-$D9DF) | Color Memory Data for Line 12 |
55776-55815 ($D9E0-$DA07) | Color Memory Data for Line 13 |
55816-55855 ($DA08-$DA2F) | Color Memory Data for Line 14 |
55856-55895 ($DA30-$DA57) | Color Memory Data for Line 15 |
55896-55935 ($DA58-$DA7F) | Color Memory Data for Line 16 |
55936-55975 ($DA80-$DAA7) | Color Memory Data for Line 17 |
55976-56015 ($DAA8-$DACF) | Color Memory Data for Line 18 |
56016-56055 ($DAD0-$DAF7) | Color Memory Data for Line 19 |
56056-56135 ($DAF8-$DB47) | Color Memory Data for Line 20 |
56136-56175 ($DB48-$DB6F) | Color Memory Data for Line 21 |
56176-56215 ($DB70-$DB97) | Color Memory Data for Line 22 |
56216-56255 ($DB98-$DBBF) | Color Memory Data for Line 23 |
56256-56295 ($DBC0-$DBE7) | Color Memory Data for Line 24 |
Reserve Sprite Memory Area
Now that the basic sprite setup is complete, the sprite shapes need to be drawn next. The Commodore 64 registers 2048-40959 ($0800-$9FFF) contain an area of memory dedicated to Basic programming, while the memory area starting at 12288 ($3000) can hold up to 8 sprites.
When you get into more advance techniques later you can move the sprite memory to another area that will allow for the design of
many more sprite shapes. Examine the code below and you will see that is where we begin reading from.
Recall again that each sprite can occupy 63 bytes in that reserved memory area. So for example our sprite memory looks like this:
Sprite Number | Sprite Memory Area |
---|---|
Sprite 0 | 12288-12350 ($3000-$303E) |
Sprite 1 | 12352-12414 ($3040-$307E) |
Sprite 2 | 12416-12478 ($3080-$30BE) |
Sprite 3 | 12480-12542 ($30C0-$30FE) |
Sprite 4 | 12544-12606 ($3100-$313E) |
Sprite 5 | 12608-12670 ($3140-$317E) |
Sprite 6 | 12672-12734 ($3180-$31BE) |
Sprite 7 | 12736-12798 ($31C0-$31FE) |