6502 Assembly programming for the Vic 20

The predecessor to the C64, the Vic-20 is an early 8 bit system, based around character graphics, it's far more limited than the C64, but still capable of some decent results, and is far better than the ZX-81 of the time.

Due to it's memory limitations, we won't be using the Vic-20 as much as some other systems, but there's still plenty of impressive stuff this early machine can do!

Cpu 1 mhz 6502
Ram 5k 
Resolution 176*184 max  (22*23 chars)
Sound 3 tone + 1 noise

Useful Documents

Programmers Reference Guide

Rom Disassembly

ChibiAkumas Tutorials

Lesson P8 - Bitmap Functions on the VIC-20

Lesson P16 - Joystick Reading on the VIC-20

Vic 20 - ASM PSET and POINT for Pixel Plotting - 6502 Lesson Photon7

Lesson S22 - Sprite Clipping on the VIC-20

Lesson P29 - Sound on the on the VIC-20

Lesson P50 - Sound on the VIC-20 (ChibiSound Pro)

Memory Map

Address   Purpose
$0000-$01FF   ZeroPage/Stack etc
$0200-$03FF OS memory
$0400-$0FFF 3K RAM Upgrade
$1000-$1DFF User Memory (screen memory with extra ram)
$1E00-$1FFF Screen Memory
$2000-$7FFF Rom area
$8000-$8FFF Character Rom
$9000-$900F VIC Registers
$9110-$911F VIA 1 (Timer 1 causes NMI)
$9120-$912F VIA 2 (Timer 1 causes IRQ)
$9400-$95FF (Character colors with extra ram)
$9600-$97FF Character Colors
$A000-$BFFF Cartridge ROM
$C000-$DFFF Basic ROM
$E000-$FFFF Kernel ROM

Text Graphics

The characters shown onscreen are selected by the bytes in the memory range $1E00-$1FFF,  the colors of the tiles are selected per 8x8 square, from the registers at $9600-$97FF

Character Map
The VIC does NOT use Ascii... as we don't have enough ram for a custom font, we're going to have to learn how to convert the charmap...
if we set the Character memory to $1C00 the Ascii set is offset by 128, and the inverted characters are lost... the result is the @ symbol is now character 128, and 0-127 are the custom characters

VIdeo Registers
The VIC20 has a range of video registers to set up it's screen
Address   Suggested  Value Meaning
$9000 $0C horizontal centering
$9001 $26 vertical centering
$9002 $96 ($16)* set # of columns, bit 7 is part of screen address
$9003 $AE set # of rows
$9004 $7A TV raster beam line
$9005 $FF ($CF)* bits 0-3 start of character memory / bits 4-7 is rest of video address
$9006 $57 horizontal position of light pen
$9007 $EA vertical position of light pen
$9008 $FF Digitized value of paddle X
$9009 $FF Digitized value of paddle Y
$900A $00 Frequency for oscillator 1 (low)
$900B $00 Frequency for oscillator 2 (medium)
$900C $00 Frequency for oscillator 3 (high)
$900D $00 Frequency of noise source
$900E $00 bit 0-3 sets volume of all sound / bits 4-7 are auxiliary color information
$900F $66+8 Screen and border color register
* Alternate settings to position screen base at $1000 and color base to $9400

Screen Colors
border and background color are set by memory address $900F... it's format is BBBISSS
Bits 0-2 (S) set the Screen background
Bit 3 sets Inverted or Normal mode - effectively this is usually on (so add 8 to all values)

Colors are defined as 0-7, as shown in the chart below... note, only color 0-7 can be used for background and border colors

  0     1     2     3     4     5     6     7  

In multicolor mode, the 'Auxilary' color is defined by the top 4 bits of  $900E

Background colors
border and background color are set by memory address $900F... it's format is BBBISSS
Bits 0-2 (S) set the Screen background
Bit 3 sets Inverted or Normal mode - effectively this is usually on (so add 8 to all values)
Bits 4-7 set background color

The effective options are:

 Background    Black     White     Red     Cyan     Purple     Green     Blue     Yellow  
Black 08 09 0A 0B 0C 0D 0E 0F
White 18 19 1A 1B 1C 1D 1E 1F
Red 28 29 2A 2B 2C 2D 2E 2F
Cyan 38 39 3A 3B 3C 3D 3E 3F
Purple 48 49 4A 4B 4C 4D 4E 4F
Green 58 59 5A 5B 5C 5D 5E 5F
Blue 68 69 6A 6B 6C 6D 6E 6F
Yellow 78 79 7A 7B 7C 7D 7E 7F
Orange 88 89 8A 8B 8C 8D 8E 8F
Light Orange 98 99 9A 9B 9C 9D 9E 9F
Light Cyan B8 B9 BA BB BC BD BE BF
Light Purple C8 C9 CA CB CC CD CE CF
Light Green D8 D9 DA DB DC DD DE DF
Light Blue E8 E9 EA EB EC ED EE EF
Light Yellow F8 F9 FA FB FC FD FE FF

Bitmap Graphics
The Vic-20 has no bitmap graphics! however it can use a custom character set, so we can effectively fake 8x8 'tiles' using this option
the low nibble of $9005 defines the position of the characters, though some options are unusable, here are the options, and where in memory the characters will be read.
the high nibble is used to define the video address, so should not be altered... it's default value is $F , but you can read it in, and OR in your new character source

The best position for it is at $1C00... and example of how to do this is shown to the right.

This will give you 128 definable characters between 0-127... the normal A-Z char map will start from character 128
    lda $9005
    and #$F0
    ora #$0F
    sta $9005    ;Set character Ram Location ----LLLL

$9005 Low Nibble value in bits Type Hex addr Dec Addr
0 0000 ROM $8000 32768
1 0001 ROM $8400 33792
2 0010 ROM $8800 34816
3 0011 ROM $8C00 35840
8 1000 RAM $0000 0
9 1001 N/A xxxx xxxx
A 1010 N/A xxxx xxxx
B 1011 N/A xxxx xxxx
C 1100 RAM $1000 4096
D 1101 RAM $1400 5120
E 1110 RAM $1800 6144
F 1111 RAM $1C00 7168

Color Map
The color map contains one byte per character, and defines the foreground color... the character colors is defined from $9600 onwards

Multicolor mode
Multicolor mode can be enabled for a screen character by adding 8 to its color number in the memory area $9600+
in multicolor mode, horizontal resolution is halved, and the color of the tile will be defined depending on it's bitpair...

The source of the color depends on the bit combination - 3 of the colors are screen-wide... only one is 'per tile'

 Bits Source Address
00 Screen Color  $900F  CCCC----
01 Border Color  $900F  ----CCCC
10 Character color  $9600 - $97FF
11 AuxColor  $900F  CCCC----

Interrupt Vectors

The standard 6502 interrupt vectors from $FFFA+ are ROM, however these jump to vectors in low memory addresses. IRQ and BRK interrupts push A,X and Y onto the stack in that order.

Note: It seems there is no VBLANK interrupt on the VIC20!

From To Function 
Registers Pushed
$0316 $0317 BRK A X Y
$0318 $0319 NMI


There are 3 sound channels for the 3 different frequencies, one for random noise, and a volume setting...
As well as volume The top 4 bits of the $900E also handles color

Address Meaning Bits Details
$900A Frequency for oscillator 1 (Bass) OFFFFFFF O=On F=Frequency
$900B Frequency for oscillator 2 (medium) OFFFFFFF O=On F=Frequency
$900C Frequency for oscillator 3 (high freq) OFFFFFFF O=On F=Frequency
$900D Frequency of noise source OFFFFFFF O=On F=Frequency
$900E Volume of all sound / Auxiliary color information CCCCVVVV V=Volume C=Aux color

File Header

If we're creating a PRG file which we're going to run on the VIC, we need a 'basic header',

this is effetively a 'launcher' for the program... our code immediately follows.
* = $1001
        ; BASIC program to boot the machine language code
        db $0b, $10, $0a, $00, $9e, $34, $31, $30, $39, $00, $00, $00
If we want to create a ROM cartridge, we can do this with a simple header... however there is a problem... the screen will not be set up, so we'll get a black screen until we set up the screen properly. * = $A000
        dw ProgramStart
        dw ProgramStart
        db $41,$30,$C3,$C2,$CD        ;ROM Header


View Options
Default Dark
Simple (Hide this menu)
Print Mode (white background)

Top Menu
***Main Menu***
Youtube channel
Email Newsletter
Merch Store
Amazon Affiliate Link
AkuSprite Editor
Dec/Bin/Hex/Oct/Ascii Table

Alt Tech
Please note: I wlll upload more content to these alt platforms based on the views they bring in

Z80 Content
***Z80 Tutorial List***
Learn Z80 Assembly (2021)
Learn Z80 Assembly (old)
Hello World
Advanced Series
Multiplatform Series
Platform Specific Series
ChibiAkumas Series
Grime Z80
Z80 Downloads
Z80 Cheatsheet
DevTools kit
Z80 Platforms
Amstrad CPC
Elan Enterprise
Gameboy & Gameboy Color
Master System & GameGear
Sam Coupe
ZX Spectrum
Spectrum NEXT
Camputers Lynx

6502 Content
***6502 Tutorial List***
Learn 6502 Assembly
Advanced Series
Platform Specific Series
Hello World Series
Grime 6502
6502 Cheatsheet
DevTools kit
6502 Platforms
Apple IIe
Atari 800 and 5200
Atari Lynx
BBC Micro
Commodore 64
Commodore PET
Commander x16
Super Nintendo (SNES)
Nintendo NES / Famicom
PC Engine (Turbografx-16)
Vic 20

68000 Content
***68000 Tutorial List***
Learn 68000 Assembly
Hello World Series
Platform Specific Series
Grime 68000
68000 Cheatsheet
DevTools kit
68000 Platforms
Amiga 500
Atari ST
Neo Geo
Sega Genesis / Mega Drive
Sinclair QL
X68000 (Sharp x68k)

8086 Content
Learn 8086 Assembly
Platform Specific Series
Hello World Series
8086 Cheatsheet
DevTools kit
8086 Platforms

ARM Content
Learn ARM Assembly
Learn ARM Thumb Assembly
Platform Specific Series
ARM Downloads
ARM Cheatsheet
DevTools kit
ARM Platforms
Gameboy Advance
Nintendo DS
Risc Os

Risc-V Content
Learn Risc-V Assembly
Risc-V Downloads
Risc-V Cheatsheet
DevTools kit

PDP-11 Content
Learn PDP-11 Assembly
PDP-11 Downloads
PDP-11 Cheatsheet
DevTools kit

TMS9900 Content
Learn TMS9900 Assembly
TMS9900 Downloads
TMS9900 Cheatsheet
DevTools kit
TMS9900 Platforms
Ti 99

6809 Content
Learn 6809 Assembly
6809/6309 Cheatsheet
DevTools kit
6809 Platforms
Dragon 32/Tandy Coco
Fujitsu FM7
TRS-80 Coco 3

65816 Content
Learn 65816 Assembly
65816 Cheatsheet
DevTools kit
65816 Platforms

eZ80 Content
Learn eZ80 Assembly
eZ80 Downloads
eZ80 Cheatsheet
DevTools kit
eZ80 Platforms

Work in Progress

Misc bits
Ruby programming

Buy my Assembly programming book
on Amazon in Print or Kindle!

Buy my Assembly programming book

Available worldwide!
Search 'ChibiAkumas' on
your local Amazon website!
Click here for more info!

Buy my Assembly programming book
on Amazon in Print or Kindle!

Buy my Assembly programming book

Available worldwide!
Search 'ChibiAkumas' on
your local Amazon website!
Click here for more info!