C64 Workshop Part 2
Drawing Graphics with Characters and Colours
In Part 1, we created a number guessing game and learned about input, output, and program flow. Now we’ll explore how to create visual graphics on the C64 by placing characters directly into screen memory and controlling colours.
Objective
Create a program that draws a simple picture to the screen using PETSCII graphic characters and multiple colours.
Requirements
- The picture must use at least 3 different foreground colours
- The picture must set a custom background colour
- The picture must use at least 4 different PETSCII graphic characters
- The picture must be at least 10 lines tall
Bonus
- Add animation by using a loop to cycle colours or move elements
- Use cursor positioning with CHR$ codes to build your image line-by-line using PRINT statements instead of POKE (see Cursor Control in the reference table below)
- Create a border around your artwork
Understanding the C64 Screen
The C64 screen is 40 columns wide and 25 rows tall. Each position can hold one character. The screen has two colour controls: a single global background colour that fills the entire screen, and individual foreground colours for each character position.
Screen Memory (characters): starts at address 1024. POKE a character code here to display it.
Colour Memory (foreground): starts at address 55296. POKE a colour value (0-15) here to set the foreground colour of the character at that position.
Background Colour: controlled by the VIC-II chip register at address 53281. POKE a colour value (0-15) here to change the entire screen’s background colour.
Border Colour: controlled by address 53280. POKE a colour value (0-15) here to change the screen border.
Resources / Reference
POKE
Writes a value directly to a memory address. Essential for placing characters and colours on screen.
Example:
10 POKE 1024,81
Places character 81 at the top-left of the screen (address 1024).
PEEK
Reads a value from a memory address. Useful for checking what character or colour is at a location.
Example:
10 A=PEEK(1024)
20 PRINT A
Reads and prints the character code at the top-left screen position.
Screen Clear
Clears the screen. Use PRINT with CHR$(147) or press SHIFT+CLR/HOME.
Example:
10 PRINT CHR$(147)
Clears the entire screen.
FOR/NEXT
Creates a loop that repeats code a specified number of times.
Example:
10 FOR I=0 TO 9
20 PRINT I
30 NEXT I
Prints numbers 0 through 9.
Cursor Control
Move cursor using CHR$ codes:
- Home = CHR$(19)
- Down = CHR$(17)
- Right = CHR$(29)
- Up = CHR$(145)
- Left = CHR$(157)
Example:
10 PRINT CHR$(147)
20 PRINT CHR$(17);CHR$(17)
30 PRINT CHR$(29);CHR$(29);"X"
Clears screen, moves down 2, right 2, then prints X.
Screen Memory Quick Reference
| Memory Type | Address(es) | Purpose |
|---|---|---|
| Screen Memory | 1024 + (ROW × 40) + COL | Character codes (what to display) |
| Colour Memory | 55296 + (ROW × 40) + COL | Foreground colour for each character |
| Background Colour | 53281 | Single value sets entire screen background |
| Border Colour | 53280 | Single value sets screen border colour |
Rows are numbered 0-24 (top to bottom). Columns are numbered 0-39 (left to right).
Example Screen Positions
| Position | Screen Address | Colour Address |
|---|---|---|
| Top-left (row 0, col 0) | 1024 | 55296 |
| Top-right (row 0, col 39) | 1063 | 55335 |
| Center (row 12, col 20) | 1504 | 55776 |
| Bottom-left (row 24, col 0) | 1984 | 56256 |
Colour Values (0-15)
Use these values with POKE to set foreground colours (55296+), background (53281), or border (53280):
| Colour | Value | Colour | Value | Colour | Value | Colour | Value |
|---|---|---|---|---|---|---|---|
| Black | 0 | Purple | 4 | Orange | 8 | Grey 2 | 12 |
| White | 1 | Green | 5 | Brown | 9 | Lt Green | 13 |
| Red | 2 | Blue | 6 | Lt Red | 10 | Lt Blue | 14 |
| Cyan | 3 | Yellow | 7 | Grey 1 | 11 | Grey 3 | 15 |
Example: Colour Blending with Frame Flipping
This example places a filled circle in the center of the screen and rapidly alternates its colour between blue and light blue. On a CRT, these colours blend together to create a mid-blue that doesn’t exist in the C64’s 16-colour palette. Colours with similar brightness blend best.
10 PRINT CHR$(147): REM CLEAR SCREEN
20 REM SET BACKGROUND AND BORDER TO BLACK
30 POKE 53281,0: POKE 53280,0
40 REM CALCULATE CENTER POSITION (ROW 12, COL 20)
50 S=1024+12*40+20: REM SCREEN ADDRESS
60 C=S+54272: REM COLOUR ADDRESS (54272=55296-1024)
70 REM PLACE CHARACTER 81 (FILLED CIRCLE)
80 POKE S,81
90 REM FLIP BETWEEN BLUE AND LIGHT BLUE TO BLEND
100 POKE C,6: POKE C,14: GOTO 100
Tips for Success
- Plan your drawing on graph paper first - sketch out your design on a 40×25 grid
- Use variables for your base position to make the code easier to modify
- Test incrementally - run your program after adding each element to catch errors early
- Use FOR/NEXT loops to draw repeated patterns or lines efficiently
- To find PETSCII character codes, type characters on screen and use PEEK(1024) to read their values
- Use PRINT for fast character placement, then POKE colour memory (55296+) to set individual colours afterwards