Tutorial game: Let’s character map (part 4)

Note: The source code for this tutorial is available in the tutorials/TutorialGame_Introduction/part4.ras (in the TRSE  framework), together with all resources mentioned in these texts.

The commodore 64 has two kinds of graphics types: 8 free sprites and a 40×25 grid of 8×8 pixel characters (or bitmap mode, which will not be covered here). The 40×25 grid is located default on memory address $0400 (and $4400, $8400 etc on the various banks dependent on the value you set for the VIC_DATA_LOC variable), and takes up 40×25 = 1000 = $3E8 bytes. Each byte thus represents an individual character from a pre-defined set of 256 8×8 pixel characters.

One of the major strengths of the commodore 64 is the ability to create custom character sets. Instead of using the default “font“, you can create your own, and point to the memory address where it resides. Everything on the screen will then be of your own design.

The C64 can display several kinds of character sets. The two we’ll be talking about here (as always) are hires and multicolor. Hires (the default mode when you boot up the c64) has 256  8×8 single color pixels = 8 byte per characters. Here, a pixel can mean either on or off. In order to define the color of a character, you must set the corresponding color position of $D800 for the char as well. Luckily, this is easy to do within the TRSE framework:


moveto(0,y,$04); // Move y lines down in screen memory
screenmemory[x]:=3; // some random character at position x
moveto(0,y,$D8); // Move y lines down in color memory
screenmemory[x]:=RED; // set character red

 

Multicolor charset

Both hires and multicolor charsets take up 8*256 = $800 bytes of memory. While hires only supports background + foreground = 2 colors, multicolor supports in total 4. However, as in the case with multicolor sprites, the x-resolution is unfortunately halved, so each character has to be 4×8 pixels. Another drawback is the fact that you need to share the two extra multicolor colors with all characters on the screen, as they are set globally.

There is also something called extended multicolor mode, but for now we’ll ignore that one.

Let’s start by creating a multicolor charset that will represent the background of a game!

In the TRSE project, click on the menu New file -> Image/Charset/Sprite, and select “C64 Multicolor Charmap“. As soon as you created it, save the empty file (ctrl+s) in a new subfolder as “charsets/charset1.flf”.

The charset editor supports several modes of drawing, where all are selected within the “Charset”-tab. They are:

  • Full character set: Just like a regular image, you can full access to all the pixels.
  • 1×1 character, for editing a single 8×8 (or 4×8 in multicolor char)
  • 2×2 character, for editing four 4x8x8 (or 4x4x8 in multicolor)
  • 2×2 character repeat, same as above but useful when creating repeating tiles

First, we need to choose the colors. With multicolor, the background + two of the multicolor colors are common for all character, while the remaining color is defined individually for each character. All colors can be selected in the “colors” tab.

An important note: There are unfortunately even more restrictions on the C64. While the background + two multicolors can be selected from the 16 color palette, the remaining free color is restricted to be between colors 0-7, meaning that it is not possible to use colors such as light gray or light blue.

For now, choose two neutral and complementing colors: gray and dark brown. Or whatever floats your boat.

Let’s draw some tiles using the 2×2 repeat charset mode! You can navigate between the characters by pressing W/A/S/D, and view the entire character set by clicking the charsets/full charset. When drawing, all regular image manipulation tools are also available in the charset editor:

  • Mouse wheel to change size of brush
  • Right click to draw background

When we use 2×2 characters, we effectively need 1/4h the memory of filling a screen with individual characters. This is very useful when  we wish to have several kinds of levels. It is therefore possible to have 256/4 = 64 unique 2×2 tiles for a given character map.

We’ll stop at three. Here’s what I drew:

Three types of tiles: a repeating brown brick, a earth-ground level and a grey earth.

When done, save the image and click the “Toolbox/export bin” button. In the export parameters section, make sure to set the “include colors” to 1, as we wish to .. well, include colors.

Let’s create a small sample program that loads this character set and displays some random chars!

Using character sets

Create a new source file (file->new ras source file). Let’s define some variables and include the charset at a certain position:


program part4_charsets;
var  
   	charset1: incbin("charsets/charset1.bin", $2000);
	colors : pointer; 
	i,j:byte;

I and J are just counting variables, while colors is a pointer that will later be pointing to the location of the color data ($2000+$800).

We include the binary exported file ($800 bytes of character data + 1000 bytes of colors) at posision $2000. This puts the character set within VIC bank 0 (between $0 and $4000), and we need to tell the VIC chip to use this address for displaying characters. This is simply done by calling SetCharacterLocation($2000). Keep in mind that if you use VIC bank 0 or 2 that $1000-$1FFF and $9000-$9FFF are reserved for the original C64 charset.
Here’s the main bulk of the program:


	clearscreen(LIGHT_BLUE, $D800);
	clearscreen($20, $0400);
	SCREEN_BG_COL:=BLACK;
	SCREEN_FG_COL:=BLACK;

	colors:=$2800;

	MULTICOLOR_CHAR_COL[1]:=GREY;
	MULTICOLOR_CHAR_COL[2]:=BROWN;

	setmulticolormode();

	SetCharacterLocation($2000);

Here, we first clear the screen & color ram. afterwards, we set border and background to black, before assigning color to point to the location of the character color data ( which was exported since we chose to include colors ). Afterwards, the two fixed multicolor colors are chosen : grey and brown in this case. Then multicolor mode is enabled, before we let the VIC chip know where the character set is located ($2000).

All we need to do now is print us some 2×2 blocks. Here’s a rouine that does exactly that :


procedure print2x2block(x,y,c:byte);
begin
	moveto(x,y,$04);
	screenmemory[0]:=c;
	screenmemory[1]:=c+1;
	screenmemory[40]:=c+40;
	screenmemory[41]:=c+41;

	moveto(x,y,$D8);
	screenmemory[0]:=colors[c];
	screenmemory[1]:=colors[c+1];
	screenmemory[40]:=colors[c+40];;
	screenmemory[41]:=colors[c+41];;

end;

This procedure takes in x and y coordinates together with a character value c. First, it uses the moveto method to point the built-in screenmemory pointer to screen memory (at $0400). We then set the values c at the current position. Since the TRSE character editor made sure that each row is 40 characters wide, we can just add 1, 40 and 41 to these values to get our 2×2 block.

Afterwards, we point the screenmemory pointer to color ram at $D800 and look up the corresponding color values from the color pointer that now points to the exported charset color data.

Finally, let’s use this method to draw some straight lines of blocks. At the end of the main begin/end block, we type:


	for 	i:=0 to 18 do
		print2x2block(3 + i*2,2,0);

	for 	i:=0 to 18 do begin
		print2x2block(3 + i*2,20,2);
		print2x2block(3 + i*2,22,4);
	end;
	Loop();

end.

Basically, we’re drawing a line of block 0, then a line of block 2 and then 4. The result should look something like this:

Wait… this is starting to look like a level! Which is exactly what it is.

Instead of manually “painting” the screen with for loops and hand-operated placement, we will instead be using the built-in TRSE level editor to create levels and render them using a method such as the print2x2block procedure, which is the topic of the next tutorial!