How to Move Sprites in C64 Assembly


One of the first things a C64 Game Programmer wants to know is how to move sprites in C64 Assembly. This article explains Sprite Movement in horizontal and vertical direction.

To move a sprite in C64 Assembly you have to change the X and Y Positions of the sprite that you want to move. Each of the 8 available Sprites has a Register for X and Y Position (located from memory address $D000 to $D00F) as well as an additional flag in Register $D010 for horizontal Positions above 255.

This article will give you some examples and explanations about how this works in detail.

Move Sprites

Now we will take a look at the steps that are necessary to move a sprite. This example will move the sprite to fixed positions. You will find the full source code at the end of this article.

Initializing the Program

As always we begin with our starting address and the call of our assembly language code. For more explanation on this you can read the C64 Hello World article (opens in new tab).

Next thing we do is defining some constants for convenience. We also clear the screen in order to operate from a blank space.

Short Primer on Sprite Memory

The SPRITE_0_POINTER is the address in memory, where the address of the sprite data is saved. There is one byte for each sprite and the pointers are always located at the end of the screen memory. The default screen memory starts at $0400 and the first sprite pointer has an offset from $03F8 (1016) to that.

Each sprite has a size of 64k. There are 256 available blocks where the data can be stored. In this example we use Block 13 which resolves in memory address $0340 as start address for the sprite data.

Initializing First Sprite

We use the first sprite (which is Sprite 0) for our example. The tasks at hand are enabling the first sprite (while disabling all the others), setting the Sprite color and loading the Sprite data.

Sprite Settings

We load the number 13 into Register A and write it to the address of SPRITE_POINTER_0. This is how we chose the Block 13 for the location of the sprite data.

Then we load the color code for green into Register A and write it into the address where VIC-II looks for the border color. The same thing is done with the color code for light green and the memory address for the background color.

In memory address $D015 is decided, which sprites are enabled (shown on screen) and which are not. Bit 0 of this Byte stands for Sprite 0, etc. So Bit 7 stands for Sprite 7, which is the eight Sprite. We set $D015 to 1, so all sprites are disabled except the first one.

Bit 7Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
00000001
Content of $D015 after Initialization

The last thing we do is setting the sprite color to black. We load the color code for black into Register A and wrtie it to the address where VIC-II looks for the color of Sprite 0.

Multicolor Sprites and Sprite Layering are not part of this article

Sprite Appearance

Now we have to load the Sprite data. First, we clear all Bytes in the Sprite 0 memory. Then, we load our Sprite data into the memory in order to see something on the screen.

Essentially two loops are created. The start of each loop is the address of SPRITE_0_DATA and it iterates 63 times until every memory position of the sprite is cleared and later set.

You may wonder where data comes from. With the ACME assembler we can declare a label called data at the end of the program and then put the data for the Sprite there. In this case the Sprite is simply a filled block.

For more Information about Sprite Layouts and Positions in Memory you can visit the C64-Wiki (opens in new Tab).

Don’t move too fast

There is one more thing to prepare. If we would just write into the x and y Registers of the Sprites than everything would happen so fast that we would not really see the sprite movement. So we write a subroutine that checks if the rasterline has reached a certain point and only returns if this is the case. By this we make the C64 wait for roughly one frame until it computes the next operations in line.

Move the Sprite

Finally we are ready to move the Sprite around. We first set the starting location by writing it into the Sprite x and y Position memory. Remember that the Border is always in front of the sprites (unless you do some tricks) so we have to set the location inside the screen in order to see our sprite at the beginning of the program. Otherwise the sprite would be hidden by the border. We randomly choose the Positions (x,y) = (100,70).

To move the Sprite down, we simply increase the y-Position. If the Position is 70 and we increase to 71, the sprite will be shown one pixel beneath its origin location. For the purpose of this example, we build a loop and move the sprite down until the y-Position 200 is reached.

Moving the sprite back up is the same thing in reverse. Instead of increasing, we decrease the y-Position in order to move the sprite up. We create a loop that moves the sprite back to its origin y-Position at 70.

Horizontal Fun

Moving in horizontal direction has one more thing that you have to look for. If we set the X-Byte of the sprite to $FF we are at screen position x=255. The Screen is 320 pixels wide. So there is another Register, $D010 where the upper bit (Bit 8) for each sprite is stored. Bit 0 is the upper Bit of Sprite 0, and so on. If Bit 0 is 1 and the Sprite X Register contains the value 4, the real X value is 256 (Bit 8=1) + 4 (Value of X-Register) = 260.

This means that when we increment the x-Position to move the Sprite right, we have to check if we go above 255 and if so, set the upper bit of Sprite 0 (while leaving the upper Bits of the other Sprites unchanged!).

To move back left we do the opposite again. We decrement the x-Position to move the Sprite left. If we are at x=0, we now switch Bit 8 of Sprite 0 back to 0 and then decrement the x-Position until we are back at our origin of 100.

If you wonder why we never reset x to 255 or to 0 keep in mind that if x is 255 and we increment, it overflows back to 0. If we decrement from 0, its value is then 255.

Result Snapshot

Let’s take a look at the result:

C64 move sprite: Final Location of the Sprite after the program execution finished
Final Location of the Sprite after the program execution finished

Full Source Code

Here is the full source code of our first example

Conclusion

This was a very brief explanation of how you can move sprites on a C64. There are some things to prepare upfront and you should watch out for the extra Bit when moving horizontally. Now you can try the program for yourself. You may even extend it. Read my article on Joystick Input and then make sprites move only if intended by Joystick Movement.

Marco Lieblang

Professional Programmer since 2003, passionate Programmer since the mid 90's. Developing in many languages from C/C++ to Java, C#, Python and some more. And I also may know a bit about Assembly Languages and Retro Systems.

Recent Posts