Commodore 64 (C64)¶
Open 8bitworkshop IDE
C64 Specifications¶
- Lifespan
1982-1994
- Media
Floppy disk, cassette tape, ROM cartridge
- CPU 8-bit
MOS Technology 6510 (6502-compatible) @ 1.023 MHz (NTSC) / 0.985 MHz (PAL)
- Memory
64 KB dynamic RAM, 1024 x 4 static color RAM
- Controllers
Joystick, mouse, paddles
- Best-selling games
The Last Ninja, Ghostbusters
History¶
In 1981, MOS Technology (Commodore’s integrated circuit design subsidiary) designed graphic and audio chips for a next-generation video game console called the Ultimax, destined for release in Japan. Commodore engineers pitched Commodore CEO Jack Tramiel on a new home computer using the new chips.
Tramiel dictated that the machine should have 64 KB of random-access memory. Although 64-Kbit dynamic random-access memory chips cost over US$100 at the time, he knew that 64K DRAM prices were falling and would drop to an acceptable level before full production was reached. The product was code named the VIC-40 as the successor to the popular VIC-20. The machine used the same case, same-sized motherboard, and same Commodore BASIC 2.0 in ROM as the VIC-20.
With the help of Commodore’s underutilized chip fab, the chips were completed by the end of the year. The VIC-40 product was renamed C64, and it debuted at the 1982 CES at $595. Thanks to aggressive pricing and wide distribution, it went on to sell more than 12 million units through its lifespan.
It was primarily known as a game machine, since the 1541 disk drive’s slow performance limited its use in business and productivity applications. Few cartridge-based games were released, but low-priced cassette games were popular in Europe.
The C64 had a Microsoft-licensed BASIC built-in, but any graphics or sound operations required unfriendly PEEK and POKE commands. Commodore offered developers an SDK consisting of an assembler/monitor, sound editor (SIDMON), sprite editor (SPED), and character graphics editor (CHRED) as well as programming documentation. A market quickly developed for third-party tools such as BASIC compilers, assemblers/linkers, and programming languages.
Nowadays, homebrew C64 developers usually write games in either assembler or C, the latter using the cc65 compiler toolchain. Writing in C gives you more functionality per line of code. While it has lower performance and greater code size than a well-written assembly program, you can still write a pretty good game in C.
Memory Map¶
Start |
End |
Description |
Alternate Use |
---|---|---|---|
|
|
RAM, zero-page |
|
|
|
RAM, CPU stack |
|
|
|
RAM |
|
|
|
RAM |
Cartridge ROM |
|
|
RAM |
BASIC ROM |
|
|
RAM |
|
|
|
RAM |
VIC-II |
|
|
RAM |
SID |
|
|
RAM |
Color RAM |
|
|
RAM |
CIA 1 |
|
|
RAM |
CIA 2 |
|
|
RAM |
I/O 1 |
|
|
RAM |
I/O 2 |
|
|
RAM |
Kernal ROM |
CC65 Header Files¶
C64¶
/* Color defines */
#define COLOR_BLACK 0x00
#define COLOR_WHITE 0x01
#define COLOR_RED 0x02
#define COLOR_CYAN 0x03
#define COLOR_PURPLE 0x04
#define COLOR_GREEN 0x05
#define COLOR_BLUE 0x06
#define COLOR_YELLOW 0x07
#define COLOR_ORANGE 0x08
#define COLOR_BROWN 0x09
#define COLOR_LIGHTRED 0x0A
#define COLOR_GRAY1 0x0B
#define COLOR_GRAY2 0x0C
#define COLOR_LIGHTGREEN 0x0D
#define COLOR_LIGHTBLUE 0x0E
#define COLOR_GRAY3 0x0F
/* Masks for joy_read */
#define JOY_UP_MASK 0x01
#define JOY_DOWN_MASK 0x02
#define JOY_LEFT_MASK 0x04
#define JOY_RIGHT_MASK 0x08
#define JOY_BTN_1_MASK 0x10
/* Define hardware */
#include <_vic2.h>
#define VIC (*(struct __vic2*)0xD000)
#include <_sid.h>
#define SID (*(struct __sid*)0xD400)
#include <_6526.h>
#define CIA1 (*(struct __6526*)0xDC00)
#define CIA2 (*(struct __6526*)0xDD00)
/* Define special memory areas */
#define COLOR_RAM ((unsigned char*)0xD800)
VIC-II¶
/* 6567/8562/8564 (NTSC) 6569/8565/8566 (PAL) */
struct __vic2 {
union {
struct {
unsigned char spr0_x; /* Sprite 0, X coordinate */
unsigned char spr0_y; /* Sprite 0, Y coordinate */
unsigned char spr1_x; /* Sprite 1, X coordinate */
unsigned char spr1_y; /* Sprite 1, Y coordinate */
unsigned char spr2_x; /* Sprite 2, X coordinate */
unsigned char spr2_y; /* Sprite 2, Y coordinate */
unsigned char spr3_x; /* Sprite 3, X coordinate */
unsigned char spr3_y; /* Sprite 3, Y coordinate */
unsigned char spr4_x; /* Sprite 4, X coordinate */
unsigned char spr4_y; /* Sprite 4, Y coordinate */
unsigned char spr5_x; /* Sprite 5, X coordinate */
unsigned char spr5_y; /* Sprite 5, Y coordinate */
unsigned char spr6_x; /* Sprite 6, X coordinate */
unsigned char spr6_y; /* Sprite 6, Y coordinate */
unsigned char spr7_x; /* Sprite 7, X coordinate */
unsigned char spr7_y; /* Sprite 7, Y coordinate */
};
struct {
unsigned char x; /* X coordinate */
unsigned char y; /* Y coordinate */
} spr_pos[8];
};
unsigned char spr_hi_x; /* High bits of X coordinate */
unsigned char ctrl1; /* Control register 1 */
unsigned char rasterline; /* Current raster line */
union {
struct {
unsigned char strobe_x; /* Light pen, X position */
unsigned char strobe_y; /* Light pen, Y position */
};
struct {
unsigned char x; /* Light pen, X position */
unsigned char y; /* Light pen, Y position */
} strobe;
};
unsigned char spr_ena; /* Enable sprites */
unsigned char ctrl2; /* Control register 2 */
unsigned char spr_exp_y; /* Expand sprites in Y dir */
unsigned char addr; /* Address of chargen and video ram */
unsigned char irr; /* Interrupt request register */
unsigned char imr; /* Interrupt mask register */
unsigned char spr_bg_prio; /* Priority to background */
unsigned char spr_mcolor; /* Sprite multicolor bits */
unsigned char spr_exp_x; /* Expand sprites in X dir */
unsigned char spr_coll; /* Sprite/sprite collision reg */
unsigned char spr_bg_coll; /* Sprite/background collision reg */
unsigned char bordercolor; /* Border color */
union {
struct {
unsigned char bgcolor0; /* Background color 0 */
unsigned char bgcolor1; /* Background color 1 */
unsigned char bgcolor2; /* Background color 2 */
unsigned char bgcolor3; /* Background color 3 */
};
unsigned char bgcolor[4]; /* Background colors */
};
union {
struct {
unsigned char spr_mcolor0; /* Color 0 for multicolor sprites */
unsigned char spr_mcolor1; /* Color 1 for multicolor sprites */
};
/* spr_color is already used ... */
unsigned char spr_mcolors[2]; /* Color for multicolor sprites */
};
union {
struct {
unsigned char spr0_color; /* Color sprite 0 */
unsigned char spr1_color; /* Color sprite 1 */
unsigned char spr2_color; /* Color sprite 2 */
unsigned char spr3_color; /* Color sprite 3 */
unsigned char spr4_color; /* Color sprite 4 */
unsigned char spr5_color; /* Color sprite 5 */
unsigned char spr6_color; /* Color sprite 6 */
unsigned char spr7_color; /* Color sprite 7 */
};
unsigned char spr_color[8]; /* Colors for the sprites */
};
/* The following ones are only valid in the C128: */
unsigned char x_kbd; /* Additional keyboard lines */
unsigned char clock; /* Clock switch bit */
};
SID¶
/* 6581/8580 SID chip */
struct __sid_voice {
unsigned freq; /* Frequency */
unsigned pw; /* Pulse width */
unsigned char ctrl; /* Control register */
unsigned char ad; /* Attack/decay */
unsigned char sr; /* Sustain/release */
};
struct __sid {
struct __sid_voice v1; /* Voice 1 */
struct __sid_voice v2; /* Voice 2 */
struct __sid_voice v3; /* Voice 3 */
unsigned flt_freq; /* Filter frequency */
unsigned char flt_ctrl; /* Filter control register */
unsigned char amp; /* Amplitude */
unsigned char ad1; /* A/D converter 1 */
unsigned char ad2; /* A/D converter 2 */
unsigned char noise; /* Noise generator */
unsigned char read3; /* Value of voice 3 */
};
CIA¶
/* 6526 CIA chip */
struct __6526 {
unsigned char pra; /* Port register A */
unsigned char prb; /* Port register B */
unsigned char ddra; /* Data direction register A */
unsigned char ddrb; /* Data direction register B */
unsigned char ta_lo; /* Timer A, low byte */
unsigned char ta_hi; /* Timer A, high byte */
unsigned char tb_lo; /* Timer B, low byte */
unsigned char tb_hi; /* Timer B, high byte */
unsigned char tod_10; /* TOD, 1/10 sec. */
unsigned char tod_sec; /* TOD, seconds */
unsigned char tod_min; /* TOD, minutes */
unsigned char tod_hour; /* TOD, hours */
unsigned char sdr; /* Serial data register */
unsigned char icr; /* Interrupt control register */
unsigned char cra; /* Control register A */
unsigned char crb; /* Control register B */
};