Skip to main content

Commodore 64 Programming

caution

This page is still a Work in progress

Setup your environment​

The best environment is based on the VICE, the emulator of all Commodore 8 bit computers. The last version relased in 2021 is V3.6. It is pretty stable and improve steadly every year even now.

VICE provide an "accurate" C/64 emulator, called β€˜x64sc’. This emulator features a cycle-based and pixel-accurate VIC-II emulation. This requires a much faster machine than the old β€˜x64’ but helps to understand better some examples below.

So we suggest to install also a C compiler like the cc65 because it suggests you how to use with VICE and also supports modern machine like the upcoming CommanderX16.

Introduction to timing​

Comodore 8 bit computer clocks are strongly linked to video frequency needed to draw on the TV screen. On US the standard is called NTSC and on Europe is called PAL. These standard have different resolutions, so the C/64 board has a special clock called "Dot Clock" which defines how many pixels can be drawn on the screen per each refresh.

The properties of the C64 screen and the respective color standards lead to the required Dot Clock rate:

    PAL: 50.125Hz (refresh rate) * 504 Pixels * 312 Lines = 7.88MHz
NTSC: 59.826Hz (refresh rate) * 520 Pixels * 263 Lines = 8.18MHz

Internally the C/64 chips run at multiple of these frequencies. The 6510 CPU has a max clock frequency of around 1Mhz, so the Dot Clock is divided by 8 in order to get it as close to the 1Mhz while still in sync with the dot clock:

   PAL: 7.88MHz / 8 = 0.985Mhz
NTSC: 8.18MHz / 8 = 1.023MHz

So C/64 CPU is a little slower on PAL and a little faster on NTSC.

For this reason you cannot "overclock" a C/64 in a simple way: you cannot mess with display timing.

Bad Lines​

The VIC II and the C/64 share the same static RAM. The access to the RAM is "mediated" by the VIC-II chip, which has priority over the main CPU (also Amiga CHIP RAM had the same logic). During the rendering of the screen, every eight lines, VIC-II need a bit more time to access to character MAP and so "forbids" 6510 to access to RAM:

The VIC scans out the video frame line-by-line. Each line takes exactly 63 clock cycles. On normal lines, all these 63 cycles are available to the CPU. However, on every 8th pixel row (=start of a new character row), the VIC needs an extra 40 cycles to fetch a line of character codes from memory. When these fetches start, the CPU is β€œstunned”, meaning it won’t execute for about 40-43 clock cycles. These lines are called Bad Lines. On these lines, you have only 20-23 clock cycles to spend on your raster magic. With sprites, even less.
...
Here’s a simplified formula for evaluating how many cycles you can spend on a bad line with sprites:

num_cycles = 23 βˆ’ (3 + 2 * num_sprites)

From https://nurpax.github.io/posts/2018-06-19-bintris-on-c64-part-5.html

Thee lines are called "Bad Lines" and are the reason your screen is disabled (= is blank) when C/64 needs precise timing (like tape access). The blank screen was unecessary on VIC20 because its VIC-I chip has not this issue.

For this reason is not plan and easy to create a IRQ sync with a raster lines without flickering, and some technics have been developed.

Having a routine synced with raster is very useful because enable you to do very nice effect, like mix text mode with graphic mode.

We will show you a double IRQ example, adapted to work with the cc65 toolchain.

You can find the original example here https://codebase64.org/doku.php?id=base:double_irq_explained In Italian you can look at this article https://ready64.org/articoli/leggi/idart/112/lo-schermo-del-c64-e-il-raster


<still chosing the best code here>

Copy BASIC to RAM and enjoy (WIP)​

A first simple example can be found in http://www.zimmers.net/anonftp/pub/cbm/c64/manuals/mapping-c64.txt and it is a good start to undestand bank switching.

Byte $00 and $01 control the I/O lines of the C/64. It is a complex subject, so we will start with an example.

First of all the bits...

Pratical example: we will copy the Basic ROM inside

FOR I=40960 TO 49151:POKE I,PEEK(I):NEXT

Though it appears that such a program would not do anything, it in fact copies bytes from ROM to RAM. This is because any data which is written to a ROM location is stored in the RAM which resides at the same address. So while you are PEEKing ROM, you are POKEing RAM. To switch to your RAM copy of BASIC, type in: POKE 1,PEEK(1) AND 254.

Now you are ready to make modifications. Examples of simple modifications include changing the text which the interpreter prints, such as the READY prompt, the power-up message, or the keyword table.

[...]

you could change the prompt that INPUT issues to a colon, rather than a question mark:

POKE 43846,58

[...]

When you want to switch back to the ROM BASIC, enter POKE 1,PEEK(1) OR 1.

See http://www.zimmers.net/anonftp/pub/cbm/c64/manuals/mapping-c64.txt

Raster interrupts​

Sprite multiplexing​

Fast scrolling​

Think different: other develpment environments​

Turbo Rascal​

Turbo Rascal Pros:

  • Use a Pascal-like syntax
  • A huge set of example (250+) and very good examples even on tiny computers
  • A very broad support: not only Commodors 8bit computers, but also NES, Gameboy, Amiga, Atari ST, ZX Spectrum, Atari 2600, DOS and more, even some mega65 examples (!)
  • Supports VICE as emulators, one of the best for Commodore Computers
  • A very good list of support library, mostly for C/64 like code compressors, ray tracers and so on).

The Quick and Dirty​

We liked a lot the the 8Bit Workshop which is great for NES programming and has a decent C/64 emulator: for simple examples could be enough.