Write up on Tech Geek HISTORY: Commodore 64 Sprite & Memory Management

Literature Review

Summary
The Commodore 64 microcomputer consists of a 6510 microprocessor, ROM, R/W memory, and various I/O devices. These are interconnected by the address bus, the databus, and the control bus. Each of the65,536 memory 22 1 D The Commodore 64 Microcomputer System locations is identified by its address. Each memory location stores eight bits of information, called an eight-bit code, an eight-bit number, or a byte. Memory is used to store both data and machine-language programs. The microprocessor can read a code stored in memory, operate on it, or store (write) a code in memory under the direction of a machine-language program. A program is an ordered set of instructions stored sequentially in memory. Instructions consist of eight-bit codes that the microprocessor reads, interprets, and executes. In order to be understood by human beings, the instruc tions are described by a mnemonic and an English language description. The instruction set of the 6510 consists of 56 different instructions. Six registers inside the 6510 are involved in the execution of these instructions. These registers are the accumulator, X register, Y register, program counter, processor status register, and the stack pointer.

INSTRUCTION TYPES
There are 4 classes of instructions in the 6510. These are:

  • Data movement
  • Arithmetic
  • Thsting
  • Flow of control
    13 Data movement instructions are instructions that cause a value to be loaded from memory, stored into memory, or transferred from one register to another. There are a number of options as to how the address of the byte to be loaded will be determined. In the load accumulator instruction, LOA, there are eight different addressing modes that can be used to determine which byte to load. The different addressing modes are explained in the following section. Arithmetic instructions are used to modify data in some way. This class of instruction includes logical operations, such as the ANO and ORA instructions. There are instructions that allow a byte to be rotated as well as addition and subtraction commands. As with the data movement instructions, most of the available addressing modes can be used by the arithmetic instructions.
    7 testing instructions allow a nondestructive test of data in the microprocessor. For instance, when a CMP instruction is used to check a value in the ACCUMULATOR, the data in the ACCUMULATOR will not be changed in any way. The bits in the STATUS register will be changed in the same way as if the data to be compared was subtracted from the ACCUMULATOR.
    These instructions are generally used to modify the STATUS register prior to executing a branch instruction. Flow of control instructions are the branching and jump instructions. These are used to change the order in which different sections of code are executed. The branch instructions are all conditional branching instructions. That is, each instruction checks one of the bits in the status register and, depending on its value, will either branch to the instruction pointed to in the operand or execute the next instruction in line. Jump and jump to subroutine instructions also fall into the flow of control category. These are known as absolute commands because they do not check any conditions before performing a jump
    Sprites, Bitmaps and Vectors
    In the beginning there were essentially two different ways of making computer graphics. Sprites/Bitmaps and Vectors.
    Vector graphics represented images as a series of mathematical equations, allowing for smooth lines and curves. The most notable example of vector graphics during this time was Atari’s arcade game “Asteroids,” which featured wireframe graphics. The game was widely cloned and arrived on all the 8 bit home computer systems in one form or another during the early 80s.
    https://www.cadasio.com/post/8-bit-sprites-to-webgl-how-computer-graphics-have-changed-the-world
    The Commodore 64 has the ability to generate sprite graphics over a character background. When this data area is created and a sprite is moving over the background, that data will not be erased. This is because the sprites are located in a different area of memory that do not conflict with the screen data. This independence gives it a great advantage when creating games. Any data or graphics remains in its own independent space.
    A sprite is drawn as 24 x 21 (503 bits) or 63 bytes of memory. So a sprite can be 24 bits wide, and 21 bits high. This area is also known as an MOB (Moveable Object Block). Up to 8 sprites can be displayed, animated, and moved on the screen. However, using a technique known as sprite multiplexing, even more sprites can be occupied with raster line timing. Basic is too slow to move sprites effectively, so assembly language is the best bet when trying to create smooth movement.
    The bytes are separated into individual bits for each row (ranging from 0-7), with the 0 bit being on the right. The values for each section (in an 7 bit layer) is displayed as 128,64,32,16,8,4,2, and 1. The total sum of these values in 255 which would draw a complete line across the width of the sprite.
    Multicolor Sprites
    Sprites can be in one color or in multiple colors, when a special mode known as multicolor is activated using memory locations ($D025 – $D02E), which is listed as 53287-53294 in Basic decimal mode. These multicolors are displayed when the sprites are grouped in pairs. As a result this expands a pixel to twice the width of a high resolution pixel. When lining up these bits during the design phase, a sprite can contain up to 4 colors (0-4). The bit pair of 00 will be transparent. The bit pair of 01 will be linked to the color in $D025 (53285). The bit pair of 11 will be linked to address $D026 (53286). Finally the bit pair of 10 will take on the color of a sprite in memory locations $D025-$D02E (53287-53294).
    It is quite tedious to create a sprite on graph paper, but it can be accomplished. Essentially you will divide each area into 3 rows that occupy 8 bytes each and the height will designed the same way. Most people prefer using a Sprite Editor to accomplish this. Windows has made room for a popular editor known as SpritePad. By using this tool, you can quickly create a whole slew of sprites, add their multicolors, and even animate them.
    Sprite Positions
    Commodore 64 Sprites are positioned horizontally and vertically using the registers $D000-$D00F (53248-53263). So for example Sprite 0 could be positioned on the screen in a position ranging from left to right by using memory location $D000. However, there is a limit to the horizontal position up to byte 255. The vertical position of Sprite 0 can be placed using memory location $D001.
    As mentioned earlier, sprites have a limited (due to their width range) area that can be placed on the screen and require another memory location to reset the horizontal position of a sprite’s high byte. The memory location that handles this is $D010 (53264). By passing in a bit from 0-7 here you can set that sprite’s appropriate horizontal most significant bit at that position.
    Each of the Commodore 64 Sprites require the ability to have it turned on or off. The memory location that handles this is $D015. This is accomplished by setting a bit from 0-7 for the appropriate sprite once again. A zero contained here turns that sprite off and a 1 activates it so it displays on the screen.
    A sprite can be expanded to double it’s height with memory location $D017 (53271). The expansion is controlled by setting a bit with a 0 or 1. As identical to the sprite enable function, setting a zero here turns off the expansion, and placing a 1 here will activate the sprite vertical expansion. Often in games, this could be used to create a boss character since they tend to be larger.
    The Foreground Display Priority Register at memory location $D01B (53275) controls when a sprite will exist in front of a foreground or behind it. This is done again, by setting it to bit 0 or 1. If a game contains a multicolor graphics mode, the sprite will be shown behind other sprite graphics even though the priority is set here for the foreground graphics, due to the 01 bit pair being set.
    Sprite Bit Pairs
    A sprite can contain multiple colors within it’s bit pairs using memory location $D01C (53276). To activate this, set bit 1 here, and turn it off by replacing with bit 0. When it is turned on, the sprite shape data is gathered into pairs. Each pair controls a double wide pixel of the sprite display. Since the sprite has had the horizontal resolution reduced, it is now only 12 dots wide. This now allows the ability for using two new colors. According to Mapping the Commodore 64 the four possible combinations affecting these bit pairs get their color from the data below.
    00 Background Color Register 0 (transparent)
    01 Sprite Multicolor Register 0 (53285, $D025)
    10 Sprite Color Registers (53287, $D027-E)
    11 Sprite Multicolor Register 1 (53286, $D026)
    Each sprite also contains the ability to have three foreground colors, which that color being unique to that sprite.
    Sprite to Sprite Collision
    The collision of a sprite is stored in registers ($D01E-$D01F) or 53278-53279 memory registers. There is some conflict when using this register however. Although a sprite can confirm with sprites overlapped each other (bit 1 is set), it is unable to accurately determine a collision when Commodore 64 Sprites are stacked up in a row. When that occurs, this register would still trigger a collision even if they are not touching each other. A collision is tracked when a bit (dot) of a sprite’s data moves over another dot that does not contain zero data in that area. Sprites that utilize this memory area, can also detect a collision even when it climbs behind the border or off the screen. Likewise setting a zero here will usually clear the collision, if multiple sprites are not conflicting with each other.
    Sprite Foreground Collision
    Just like it’s counterpart, memory location $D01F (53279) has the ability to see when Commodore 64 Sprites have collided with the foreground. By checking to see if a bit 0 or 1 is contained here, it can act on that information. Yet there are still conflicts that can occur so use it wisely, ensuring that sprite bits are not crossing over each other.
    A sprite’s multicolor is set within memory locations $D025- $D026 as discussed earlier. It is necessary for the system to find a zero or 1 here so that sprite’s data can be set accordingly. The default color set for $D025 on power up is purple, and $D026 will contain the color black.
    A standard Commodore 64 Sprites color is set and turned off using locations $D027-$D02E (53287-53294) in memory. Each corresponding sprite once again contains a default color when the computer is first turned on, but they can be changed here.
    Sprite Shape Data and Animation
    Memory locations $07F8-$07FF (2040-2047) contain an area that reserves sprite data. This is useful for animation. The data is contained here for each pointer to match the appropriate shape in memory. Each of the Commodore 64 Sprites, ranging from 0-7 occupy it’s own data containment in these memory addresses. The pointer value is multiplied by 64, which is equal to the starting location of that sprite’s data table. A simple calculation as found in Mapping the Commodore 64 is using Sprite 0 at memory address 704 (11*64=704) to point to the appropriate area of memory. This then leaves room for 63 bytes up to memory address 767. By cycling through data contained in these registers, simple animation is quite possible with your sprites.

SPRITES
A sprite is a small moveable object block that can move independently of the background graphics. The VIC chip can display eight sprites on the screen at anyone time. Sprites can be displayed on anyone of the display modes, and they will look the same in all of them. You can have up to 256 different sprites defined at anyone time, but only eight can be displayed at the same time. The sprite to be displayed can be changed by changing a one byte pointer, so animation can be easily performed by quickly switching through a few different sprite patterns. Sprites can be moved very smoothly by simply giving the VIC chip the X and Y coordinates of the upper left comer of the sprite. Sprites have different display priorities. That means that the sprite with a higher priority will ap pear to move in front of a sprite with a lower priori ty. This can be used to give the illusion of three dimensional movement. The priority of a sprite to the background graphics is individually selected for each sprite. If the background is given priority, the sprite will appear to move behind the background graphics.
For instance, if a tree was being displayed in the bit mapped graphics mode, and a sprite in the shape of a dog was to move past the tree, the dog would appear to be moving behind the tree. Each sprite is a block 24 pixels horizontally by 21 pixels vertically. The pixels that are set to one use 1 of the 16 available colors.
The pixels that are set to zero allow the background color to show through (are transparent). Like the other graphics modes, a sprite can be selected to be in the multicolor mode, giving it a resolution of 12 by 21 in three colors plus transparent. Wherever a sprite is transparent, whatever is behind the sprite will show through. For those times when a larger sprite is necessary, the VIC chip has the option of doubling the horizontal size, the vertical size, or both. You will not increase the detail available in your sprite by using one of the multiply options, only the size.
When a sprite is expanded, each of the pixels is twice the size of the pixels in a normal sprite. Sprite Pointers Once a sprite has been defined, the VIC chip needs to be told where to find the pattern. The sprite definition must be in the currently selected bank of memory for it to be displayed. Since each sprite definition takes up 64 bytes, a sprite definition will always start on a $0040 boundary in memory. A 16K bank of memory can hold 256 sprite definitions, so it will only require one byte to tell the VIC chip which sprite to display. The sprite pointer is a number which, when multiplied by 64, will give the starting address of the sprite definition.
Sprite definitions may not be placed in a section of memory where the VIC chip sees an image of the character generator ROM. The VIC chip will read the eight sprite pointers from the last eight bytes of the lK of text memory, 30 an offset of $03F8 from the text base address. Since only 1000 out of 1024 bytes of text memory are used to display characters on the screen, the sprite pointers will not interfere with screen graphics. For example, since the default setting of the text memory is at $0400, the first sprite pointer will be $07F8. Sprite Controls For most of the sprite control registers, each bit in the register corresponds to one of the sprites. For example, bit 0 represents sprite 0, bit 1 represents sprite 1, and so on. The rest of the sprite controls require a value (such as a vertical location), so there is one register for each sprite. Enabling a sprite. Before a sprite can be seen, it must be enabled.
The register SPREN ($DOI5), has an enable bit for each sprite. If the bit is set, the sprite will be enabled. The sprite will only be seen if the X and Y positions are set to the visi ble portion of the screen. A sprite can be disabled by clearing the appropriate bit. Setting the sprite color. There are eight registers that are used to hold color information, one for each sprite. Any of the 16 available colors may be selected for each sprite. Each bit that is set in the sprite definition will cause a pixel to be displayed in the sprite color. If the bit is clear, the pixel will be transparent. The sprite color registers are: Name SPRCLO SPRCLl SPRCL2 SPRCL3 SPRCL4 SPRCL5 SPRCL6 SPRCL7 Address $D027 $D028 $D029 $D02A $D02B $D02C $D02D $D02E Setting the multicolor mode.
The multicolor mode can be individually selected for each ($DOlC)/sprite by setting the appropriate bit in the MLTSP ($DOlC) register. Setting a bit will enable the multicolor mode, clearing the bit will disable the multicolor mode. When the multicolor mode is enabled, the horizontal resolution drops from 24 pixels across to 12 pixels. Each pair of bits in the sprite definition is treated as a bit pair, whose value determines which of the four colors will be selected for the pixel

Pair Description 00 01 10 11 TRANSPARENT, SCREEN COLOR SPRITE MULTICOLOR REGISTER #0 ($0025) SPRITE COLOR REGISTER SPRITE MULTICOLOR REGISTER #1 ($0026) Using the sprite multipliers. Each of the sprites can be expanded in either the X or Y direc tion. When a sprite is expanded, each pixel is displayed as twice the normal size in the direction of the expansion. The resolution of the sprite does not increase, only the size. To expand a sprite in the X direction, the ap propriate bit must be set in the SPRXSZ ($DOID) register. To return the sprite to its normal size, clear and bit. The expansion of a sprite in the Y direction is done in the same way as the X expansion. You must set the appropriate bit in the SPRYSZ ($DOI7) register to expand the sprite. The sprite can be returned to its normal size by clearing its bit in the . SPRYSZ register.
The sprite can also be expanded in both the X and Y directions by setting its bit in both registers. Positioning sprites. Each sprite can be posi tioned independently anywhere on the visible screen and off the visible screen in any direction. Since the screen is 320 pixels wide, it takes more than one byte to specify a horizontal position.
Each sprite has its own X position register and Y position register, and a bit in an extra most significant bit register.
The location specified by the registers is the position where the upper left comer of the sprite will appear.
For an unexpanded sprite to be completely visible, the Y value must be between $32 and $E9. Any other values will place the sprite partially off the screen. Whatever value is placed in the X position register is the least significant 8 bits of a 9 bit value. Each sprite has a ninth bit in the XMSB ($DOlO) register. An unexpanded sprite will be completely visible if the 9 bit X value is greater than $18 and less than $140. The HINC and HDEC macros can be used to perform 9 bit increments and decrements of the X position. Table 7-6 shows the screen coordinates for expanded and unexpanded sprites to be fully visible on the screen. Any sprite positions outside of these limits will be partially or fully off of the screen. This provides an easy way to reveal a sprite gradually. Assigning sprite priorities.
As mentioned before, each sprite has a display priority with respect to the other sprites and to the background. You can create a three dimensional effect by allow ing different sprites to pass in front of each other. The priority of one sprite to another is predeter mined by the VIC chip. Sprite 0 has the highest priority, meaning that it will appear to be in front of all other sprites. Sprite 7 has the lowest priority of all the sprites. Each sprite can be individually selected to either have a higher priority than the background or a lower priority. If the sprite’s bit in the BPRIOR ($D01B) register is clear, the sprite will appear to pass in front of the background. When the bit for the sprite is set in the BPRIOR register, the sprite will appear to move behind the background image and in front of the background color. Because sprites can have transparent as one of their colors, any sprite that passes behind a higher priority sprite with transparent in it will show through in the transparent areas.

Overview of System Memory Map
The System Memory Map plays a vital role in the operation of the computer. It is essentially a blueprint of the computer’s memory, showing the locations of the different memory regions and how they are used. By understanding the memory map, programmers and users can effectively use and manipulate the computer’s resources.
Compared to other Commodore computers, the C65’s memory map is unique. It features a larger address space of 24 bits, allowing for a maximum of 16MB of memory. This was a significant improvement over the 64KB limit of the popular Commodore 64. The C65’s memory map also includes a number of new memory regions, such as the SuperCPU and the burst mode, which were not present in earlier models.
The memory map is organized into different regions, each with a specific function. The first region, known as the Zero Page, contains important system variables and routines used by the computer’s operating system. The next region, the Stack, is used to store temporary data and addresses. The code area contains the main program code, and the data area is used to store program data.
The memory map also includes other regions, such as the I/O area, which is used to communicate with peripheral devices, and the ROM area, which contains read-only memory. By understanding the different regions and their functions, programmers and users can make better use of the computer’s resources and optimize their programs for maximum efficiency.
The System Memory Map is a crucial component of the Commodore C65. Its unique features and organization make it an important tool for programming and using the computer effectively. By gaining a deeper understanding of the memory map, users can unlock the full potential of the C65 and take their computing experience to new heights.
The C65 features a 128-kilobyte ROM that is organized into four regions: the system ROM, the BASIC ROM, the Kernal ROM, and the character ROM. The system ROM contains the C65’s boot code and the code that initializes its hardware, while the BASIC ROM contains the version of Commodore BASIC that was modified for the C65.
The Kernal ROM, on the other hand, contains the low-level routines that interact with the C65’s hardware, such as those used for reading and writing to disk drives and serial devices. The character ROM is responsible for storing the graphics and characters that the C65 can display.
The C65 features a 128-kilobyte ROM that is organized into four regions: the system ROM, the BASIC ROM, the Kernal ROM, and the character ROM. The system ROM contains the C65’s boot code and the code that initializes its hardware, while the BASIC ROM contains the version of Commodore BASIC that was modified for the C65.
The Kernal ROM, on the other hand, contains the low-level routines that interact with the C65’s hardware, such as those used for reading and writing to disk drives and serial devices. The character ROM is responsible for storing the graphics and characters that the C65 can display.
The system ROM is located at memory addresses $E00000-$E3FFFF, while the BASIC ROM is located at addresses $C00000-$C1FFFF. The Kernal ROM is located at addresses $E80000-$EBFFFF, and the character ROM is located at addresses $D00000-$D0FFFF.
When the C65 boots up, the system ROM is the first ROM region that is accessed. The boot code initializes the C65’s hardware and then loads the C65’s version of BASIC from the BASIC ROM into memory. The C65’s Kernal ROM is then used to interact with the hardware and perform low-level operations.
Understanding the organization and functions of each ROM region is essential for programming and effectively using the C65. By having a solid understanding of the C65’s ROM memory map, programmers can take full advantage of the capabilities of this unique and powerful computer.
https://philreichert.org/commodore-c65/system-memory-map.html
Memory-mapped I/O and interfacing To summarize what we have just explain, an input/output port (I/O port) is allocation in the memory map of the computer that can be used to transfer information either from an external device to the computer from the computer to an external device. The type of input/output operations that use sports in the memory map of the computer system is called memory mapped I/O. These ports maybe accessed with any of the instructions in the 6510instruction set that involve a read or write operation. The type of I/O in which from one to eight bits of information are transmitted simultaneously is called parallel I/O. If only one bit can be output at a time, then the I/O operations are described as serial I/O.

References:
https://philreichert.org/commodore-c65/system-memory-map.html
https://www.cadasio.com/post/8-bit-sprites-to-webgl-how-computer-graphics-have-changed-the-world
COMMODORE 64 ASSEMBLY LANGUAGE ARCADE GAME PROGRAMMING
STEVE BRESS
Copyright © 1985 by TAB BOOKS Inc.

Assembly Language Programming with the Commodore 64
Marvin L. De Jong The Scholte Ozarks Pt. Lookout, MO Brady Communications Company, Inc. A Prentice-Hall Publishing Company

Leave a Comment

Your email address will not be published. Required fields are marked *