Programming the C64

Introduction
VIC-II Colour codes
Image-Application formats
Hardware Keyboard Matrix and Digital Joystick Scanning
GCR - Group Coded Recording
Comments to nonC64 assembler programmers

 

Introduction

This section is intended for programmers of the C64 (Mainly Assembler coders), or other programmers who need information about the programming of the C64. It contains some practical information and it is not the intention to give you an course in assembler programming here.

 

 

VIC-II Colour codes and Luminance intensity

Dec

Hex

Colour

Brightness

Vice Palette
R,G,B

CCSC64 palette
R,G,B

0

0

Black

0/0

00, 00, 00

10, 10, 10

1

1

White

4/8

FF, FF, FF

FF, FF, FF

2

2

Red

1/2

68, 37, 2B

E0, 40, 40

3

3

Cyan

3/6

70, A4, B2

60, FF, FF

4

4

Purple

2/3

6F, 3D, 86

E0, 60, E0

5

5

Green

2/5

58, 8D, 43

40, E0, 40

6

6

Blue

1/1

35, 28, 79

40, 40, E0

7

7

Yellow

3/7

B8, C7, 6F

FF, FF, 40

8

8

Orange

2/3

6F, 4F, 25

E0, A0, 40

9

9

Brown

1/1

43, 39, 00

9C, 74, 48

10

A

Light Red

2/5

9A, 67, 59

FF, A0, A0

11

B

Dark Gray (1)

1/2

44, 44, 44

54, 54, 54

12

C

Medium Gray (2)

2/4

6C, 6C, 6C

88, 88, 88

13

D

Light Green

3/7

9A, D2, 84

A0, FF, A0

14

E

Light Blue

2/4

6C, 5E, B5

A0, A0, FF

15

F

Light Gray (3)

3/6

95, 95, 95

C0, C0, C0

Note: Brightness is on a 0-4 scale on the original C64, and a 0-8 scale on C64C & C128(D)

 

 

 

Image-Application formats

 

Formats for application image types:

Start addr.

Start address/Load address (first two bytes of the file)

Length

File length in bytes (including load address bytes)

Bitmap

Bitmap offset (8000 bytes)

Colour

Colour data offset (1000 bytes). In Multicolour mode,  Copy (25*40) 1000 bytes to the area $D800 and upward.

Background

Background colour (1 byte), stored in lower nybble of $D021

 

Common file formats for Hires raw-images on the C64

Name (Hires)

Start Addr.

Length
(Bytes)

Bitmap
Offset Addr.

Screen
Offset Addr.

Colour Nybbles
Offset Addr.

Background
Offset Addr.

Art Studio

$2000

9009

0

8000

 
Not used

 

Doodle

$5C00

9218

1024

0

Image System (Hi)

$4000

9194

0

8192

The upper 4 bits of screen memory becomes the colour of any bits that is set (to 1) in the 8*8 pixels attribute controlled by the screen memory. The lower 4 bits is the colour of any pixels cleared (0).

 

 

Common file formats for multicolour bitmap raw-images on the C64

Name (Multicolour)

Start Addr.

Length
(Bytes)

Bitmap
Offset Addr.

Screen
Offset Addr.

Colour Nybbles
Offset Addr.

Background
Offset Addr.

Artist 64

$4000

10242

0

8192

9216

10239

Adv. Art Studio

$2000

10018

0

8000

9016

9001

Amica Paint (*)

$4000

10257

0

8000

9000

10000

Blazing Paddles

$A000

10242

0

8192

9216

8064

Koala Painter

$6000

10003

0

8000

9000

10000

Image System (MC)

$3C00

10218

1024

9216

0

9215

Vidcom 64

$5800

10050

2048

1024

0

2024

CDU Paint

$7EEF

10277

273

8273

9273

10273

(*) Amica Paint can save in packed format, using control-codes ($C2) for loops etc. For depacking : $C2 00 marks end of picture, $C2 xx yy means copy byte yy xx-times. Other bytes combinations must just be stored as they are. Furthermore, Amica Paint has an extra feature included in the file; The colour-Rotation-Table at offset Addr. 10000 with a total of 256 bytes.

 

 

Common formats for FLI raw-images on the C64

Application
(Format)

Background
*=Rasterbars

Colour
Nybbles

Colour Screens
(steps of $0400)

Bitmap

Notes

Saga FLI *

$3B01-$3BC8

$3C00-$3FFF

$4000-$5FFF

$6000-$7F3F

$3B00?

Interpaint (*)

$3B00-$3BFF

$3C00-$3FE7

$4000-$5FFF

$6000-$7FFF

*Options

* Rasterbars is an EXTENSION to the FLI concept.

 

 

Hardware Keyboard Matrix and Digital Joystick Scanning

The keyboard is read as a matix of 8 rows by 8 columns. The row is selected by clearing (set to 0) the corresponding bit in the CIA1 port A ($DC00). The column data bits are then read from the CIA1 port B ($DC01), and a cleared bit indicates that the key is pressed at the time of scanning.

Row
Key

0

CRSR U/D

F5

F3

F1

F7

CRSR L/R

RETURN

INST/DEL

1

L-SHIFT

E

S

Z

4

A

W

3

2

X

T

F

C

6

D

R

5

3

V

U

H

B

8

G

Y

7

4

N

O

K

M

0

J

I

8

5

,<

@

:

.>

-

L

P

+

6

/?

 UP-ARROW

=

R-SHIFT

CLR/HOME

;

*

£

7

RUN/STOP

Q

C=

SPACE

2

CTRL

LEFT-ARROW

1

Column

7

6

5

4

3

2

1

0

Notice: A keypress is of course not buffered in hardware. If a key is pressed, the bits are cleared at that moment, not before or after. You can scan for more than one key at a time if you want, withing the limits of course. For a buffering input stream, you should write your own routines or use kernal calls.

 

For scanning Joystisk 0 and 1 (Port A and B) you use the same registers, only this time you read from Port A also if you want to scan Joystick 0 in Port A.

   X   

    X   

   X   

   FIRE   

   RIGHT    

   LEFT   

   DOWN    

   UP    

Joystick 0 ($DC00) bits

7

6

5

4

3

2

1

0

Joystick 1 ($DC01) bits

7

6

5

4

3

2

1

0

X = Not important in connection with Joystisk

 

To give a simple example how keyboard scanning works, here is an example of how to wait for a press on the SPACE key.

LDA

$DC03

; Set Column 4 to Input

AND

#%11101111

STA

$DC03

 

 

LDA

$DC02

; Set Row 7 to Output

ORA

#%10000000

STA

$DC02

LDA

#%10000000

; Set Row 7 to High

STA  

$DC00

; (The rest to Low)

 

 

 

LDA  

#%00010000   

; Test Column 4  

testspace:

BIT  

$DC01

BNE  

testspace

spacedpressed:   

You can make versions which clean up the registers before and after use, or you can make quick and dirty versions for shorter code. It depends on what you need in your final code. This is just to give you an example.

 

 

GCR - Group Coded Recording

This is the disk encoding scheme of the Commodore 1541 (and similar) diskdrives , and does not take advantage of the index hole present on the disks (Some systems are Index-hole oriented) but is a SYNC-oriented format. It does however take advantage of the possibility of larger tracks towards the edge of the disk (Some systems don´t).

Each 1 bit on the magnetic media (disk) is represented by a fluxation in the magnetic field, either from North to South, or the other way. Each 0-bit is represented by a -nonchanged- magnetic field. A flux in the field generates a small current in the wires of the coil, this current is amplified and, in turn, interpreted as a High level (1) by the digital logic.

The disk is divided into tracks. Each track is divided into a number sectors. Each sector consists of a block-header and a datablock. In order to mark the beginning of a blockheader or datablock, a SYNC of ATLEAST 9 magnetic fluxations, e.g. (N)SNSNSNSNS (= 111111111) are written to disk. All this is in order to keep knowledge of where a sectors starts (without it, you would not be able to tell (in a simple way) which bits are what).

Loop data ($55 = %01010101) are part of Block-headers (10 * $55) and Data-blocks (X * $55, if needed).

The basics rules for recordings which are not Sync signals:

1. Not more eight 1-bits in sequence, recorded on the magnetic media.
2. Not more than two 0-bits in sequence, recorded on the magnetic media.

In order to achieve this, the each nybble is recorded as 5 bits-GCR code.

 

GCR conversion table

Dec

Hex

Binary

GCR value

Dec

Hex

Binary

GCR value

0

0

0000

01010

8

8

1000

01001

1

1

0001

01011

9

9

1001

11001

2

2

0010

10010

10

A

1010

11010

3

3

0011

10011

11

B

1011

11011

4

4

0100

01110

12

C

1100

01101

5

5

0101

01111

13

D

1101

11101

6

6

0110

10110

14

E

1110

11110

7

7

0111

10111

15

F

1111

10101

 

Example of GCR encoding

Four bytes plain data (in this case $12, $34, $AB and $CD) are converted into 5 bytes GCR format:

Bytes:              $12           $34           $AB           $CD
Binary: 00010010 00110100 10101011 11001101
Nibbles: 0001 0010 0011 0100 1010 1011 1100 1101
GCR codes: 01010 01011 10011 01110 11010 11011 01101 11101
Nibbles: 0101 0010 1110 0110 1110 1101 0110 1101 1011 1101
GCR bytes: 01010010 11100110 11101101 01101101 10111101
Converted: $52 $E6 $ED $6D $BD

 

 

As already mentioned, the scheme takes advantage of different track length. It simply adds more sectors to each track.

Sectors/Track on 1541 drives

Track

Sectors

1-17

21

18-24

19

25-30

18

31-35

17

Tracks 35-40 must be supported by an extra system (e.g trackloader or systems like Dolphin Dos.)

 

Examples of alternative disk encoding schemes, used on other systems:

MFM - Scheme used on many diskdrives for PC etc, also used on some drives of the C64/C128.

 

 

Comments to nonC64 assembler programmers

As I have coded in assembler on a wide range of microprocessors; the 6502, 8051, Motorola 68K, 56K (DSP), Intel 80X86, Pentium and ARM (Advanced Risc Machines) based processors, I know there is variation in the syntax of how to represent something in the assembler code, I feel the need for having a small section explaining the special signs and symbols used when it comes to coding the C64 in assembler.

 

A guide for common signs, symbols and terms used by C64 coders in the assembler syntax.

$

Hexadecimal number; Eg. $C000 (49152 decimal) same way as 0xC000 in C and some other systems. Used alone in an assembler instruction, it normally is a memory address (e.g. STA $D020 - Store the value from the accumulator to the memory location $D020 (In this case the VIC-II chip - Border colour).

%

Binary number. Is used similar to $ (Hexadecimal)

#

Numerical value. E.g. LDA #0 - Load accumulator with the value 0 (Not the value stored at address 0). Can be combined with the $ sign to represent a hexadecimal value, e.g. LDA #$0F will Load the accumulator with the numerical value 15 (Decimal). Similar syntax is common on many other platforms.

<

LSB, Least Significant Byte. E.g. LDA #<$ABCD will load #$CD into the accumulator. The final instruction will be LDA #$CD. Usefull with constants or to make the source easy to read.

>

MSB, Most Significant Byte. E.g. LDA #>$ABCD will load #$AB into the accumulator. See <

Nybble

4 bits (1 bytes = 2 nybbles. A nybble is either the uppermost or lower 4 bits)

 

 

Titles for reading:

General readings

Commodore 64 Programmers Reference Guide
- Published by Commodore Business Machines, Inc. and Howard W. Sams & Co., Inc.

Programming the 6502
- Rodnay Zaks, Sybex. (ISBN : 0-89588-046-6)

 

Advanced readings

The MOS 6567/6569 video controller (VIC-II) and its application in the Commodore 64
- Christian Baur