Some simple code examples for C64 BASIC

Posted on: Posted on

The Commodore 64’s BASIC is a great way to start programming, as it’s immediate and gives you direct control over the hardware. Here are some simple code examples, starting with the very basics and moving into some fun C64-specific features like colors and sound.

To enter these, simply type the line number, then the command, and press ENTER. When you’re done, type RUN and press ENTER to execute. To see your code again, type LIST. To clear memory, type NEW.


1. Hello World! (The Absolute Basic)

This program prints “HELLO C64!” to the screen.

10 REM HELLO WORLD PROGRAM
20 PRINT "HELLO C64!"
30 GOTO 30 : REM Keep the program running so you can see the output
  • REM: Remark (comment). The C64 ignores this line.
  • PRINT: Displays text or variable values on the screen.
  • GOTO 30: Creates an infinite loop, effectively pausing the program so the output stays visible. Without this, the program would run and then end immediately, sometimes clearing the screen.

2. User Input & Variables

Ask the user for their name and then greet them.

10 REM USER INPUT EXAMPLE
20 PRINT "WHAT IS YOUR NAME?"
30 INPUT N$
40 PRINT "HELLO "; N$; "!"
50 GOTO 50
  • INPUT N$: Waits for the user to type something and press ENTER. The input is stored in the string variable N$. (String variables end with $).
  • Variables: N$ holds text. Numeric variables (like X or SCORE) hold numbers.

3. Simple Loop (FOR…NEXT)

Count from 1 to 10 and print each number.

10 REM COUNTING LOOP
20 FOR I = 1 TO 10
30   PRINT "COUNT: "; I
40 NEXT I
50 PRINT "DONE COUNTING!"
60 GOTO 60
  • FOR I = 1 TO 10: Starts a loop where I goes from 1 to 10.
  • NEXT I: Increments I and goes back to the FOR line if I hasn’t reached 10 yet.

4. Screen Colors & Clear Screen

Change the screen colors and clear the screen.

10 REM SCREEN COLORS
20 REM POKE 53280 = BORDER COLOR
30 REM POKE 53281 = BACKGROUND COLOR
40 POKE 53280, 0   : REM Black Border (0-15)
50 POKE 53281, 6   : REM Blue Background (0-15)
60 PRINT CHR$(147) : REM Clear the screen
70 PRINT "LOOK, NEW COLORS!"
80 GOTO 80
  • POKE address, value: Writes a value (0-255) to a specific memory address. This is how you directly control hardware registers on the C64.
  • 53280: Memory address for the border color.
  • 53281: Memory address for the background color.
  • C64 Color Codes (0-15):
    • 0: Black, 1: White, 2: Red, 3: Cyan
    • 4: Purple, 5: Green, 6: Blue, 7: Yellow
    • 8: Orange, 9: Brown, 10: Light Red, 11: Dark Grey
    • 12: Medium Grey, 13: Light Green, 14: Light Blue, 15: Light Grey
  • CHR$(147): The ASCII character code 147 is the “Clear Screen” command on the C64. PRINT CHR$(...) is used to send control codes.

5. Text Positioning

Place text at specific locations on the screen using TAB and POKE.

10 REM TEXT POSITIONING
20 PRINT CHR$(147) : REM Clear screen
30 PRINT "START HERE"
40 PRINT TAB(10)"INDENTED TEXT"
50 PRINT : PRINT : PRINT "THREE LINES DOWN" : REM Prints empty lines
60 REM POKE directly into screen memory (1024-2023)
70 REM Char 'A' is screen code 1 (or 65 ASCII)
80 POKE 1024 + (5 * 40) + 15, 1 : REM Puts "A" at row 5, col 15 (0-indexed)
90 POKE 55296 + (5 * 40) + 15, 2 : REM Sets "A" to Red color (0-15)
100 GOTO 100
  • TAB(column): Moves the cursor to the specified column. (C64 screen is 40 columns wide, 0-39).
  • POKE 1024 + (ROW * 40) + COLUMN, CHARACTER_CODE: This is how you draw characters directly to the screen.
    • 1024: Start of screen memory.
    • ROW * 40: Calculates the starting address for the desired row.
    • COLUMN: Offset within the row.
    • CHARACTER_CODE: The C64’s internal character code (e.g., 1 for ‘A’, 2 for ‘B’, etc. for uppercase. Shifted graphics chars have different codes). ASCII 65 for ‘A’ works too for standard characters.
  • 55296: Start of Color RAM, which corresponds to screen memory. Each location here stores the color of the character at the equivalent screen memory address.

6. Simple Sound (Using the SID Chip)

Play a simple tone using the C64’s SID sound chip.

10 REM SIMPLE SOUND
20 REM SID CHIP REGISTERS START AT 54272
30 REM VOICE 1 FREQUENCY (LOW BYTE)
40 POKE 54272, 100 : REM Example frequency low byte
50 POKE 54273, 12  : REM Example frequency high byte
60 REM VOICE 1 CONTROL REGISTER (WAVEFORM & GATE)
70 POKE 54276, 17  : REM Triangle wave (16), GATE ON (1) -> 16+1=17
80 REM MASTER VOLUME
90 POKE 54296, 15  : REM Max volume (0-15)
100 REM DELAY
110 FOR T = 1 TO 500 : NEXT T
120 POKE 54276, 16 : REM GATE OFF (turn sound off by removing the "gate" bit)
130 POKE 54296, 0  : REM Turn volume off
140 GOTO 140
  • The SID chip has 3 voices, each with frequency, waveform, envelope (attack, decay, sustain, release), and control registers.
  • 54272, 54273: Frequency for Voice 1 (low and high bytes).
  • 54276: Control register for Voice 1. Bits here control waveform (triangle, sawtooth, pulse, noise), test, ring modulation, synchronization, and the “gate” bit to turn the sound on/off.
    • 1: GATE (on)
    • 2: Sync
    • 4: Ring Mod
    • 8: Test
    • 16: Triangle
    • 32: Sawtooth
    • 64: Pulse
    • 128: Noise
  • 54296: Master Volume register.

### 7. Random Numbers (Dice Roll)

Generate random numbers, like rolling a six-sided die.

10 REM RANDOM NUMBERS (DICE ROLL)
20 PRINT CHR$(147) : REM Clear screen
30 FOR I = 1 TO 5
40   PRINT "ROLL "; I; ": "; INT(RND(1) * 6) + 1
50 NEXT I
60 GOTO 60
  • RND(1): Generates a pseudo-random floating-point number between 0 (inclusive) and 1 (exclusive). The 1 (any positive number) seeds the random number generator, ensuring a different sequence each time you run. RND(0) would return the last random number. RND(-1) would re-seed with a fresh, system-time based seed.
  • * 6: Scales the random number to be between 0 and less than 6.
  • + 1: Shifts the range to be between 1 and less than 7.
  • INT(): Returns the integer part of a number, effectively rounding down. So INT(5.99) is 5. This gives us integers from 1 to 6.

8. Keyboard Input (GET)

Read a single keypress without waiting for ENTER.

10 REM GET KEYPRESS
20 PRINT CHR$(147) : REM Clear screen
30 PRINT "PRESS ANY KEY..."
40 GET K$ : REM Get a keypress
50 IF K$ = "" THEN GOTO 40 : REM Loop until a key is pressed
60 PRINT "YOU PRESSED: "; K$
70 GOTO 70
  • GET K$: Attempts to read a single character from the keyboard buffer. If no key has been pressed, K$ will be an empty string (""). If a key was pressed, K$ will contain that character.
  • This is useful for games or real-time interaction where you don’t want to wait for the user to press ENTER.

How to use these on a C64 or Emulator

  1. On a real C64:
    • Turn it on. You’ll see the blue BASIC screen.
    • Type NEW and press ENTER to clear any old programs.
    • Type in the lines of code one by one, pressing ENTER after each line.
    • Type RUN and press ENTER to execute.
    • Type LIST and press ENTER to see your code.
  2. On an Emulator (e.g., VICE):
    • Start the emulator. It will boot to the BASIC screen.
    • Follow the same steps as a real C64.
    • Emulators often let you paste text, which can be much faster. Look for a “Paste” option (often Ctrl+V or Shift+Insert, sometimes requiring a special emulator paste mode).

Have fun experimenting with these examples! The C64 is a fantastic machine to learn the basics of programming and hardware interaction.

Leave a Reply

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