is undefined as its unshifted, shifted and CAPS LOCK values, and toggles the
display/nondisplay of the disk status window as its control value.
The key labelled CRSR with up and down arrows (bottom right on main keyboard) generates the hex value 17 (CONTROL-w) which causes the latest CP/M command line to be re-typed on the screen. The key next to this (CRSR with right and left arrows) allows you to move right (CONTROL-f) and left (CONTROL-a) (unshifted and shifted, respectively) through a command line to edit it.
The key labelled F1/F2 generates the two character string 'F1' in
the unshifted and CAPS LOCK modes and the string 'F2' in theshifted and control modes.
The key labelled F3/F4 generates the four character string 'dir RETURN' in the unshifted and CAPS LOCK modes and the string 'dir' in the shifted and control modes.
The key labelled F5/F6 generates the two character string 'F5' in the unshifted and CAPS LOCK modes and the
string 'F6' in the shifted and control modes.
The key labelled F7/F8 generates the two character string 'F7' in the unshifted and CAPS LOCK modes and a string
representing the date that the system files were assembled in the shifted and control modes (i.e. the date which is
displayed in the sing-on message).
The key labelled HELP generates the string 'Help' in all modes.
The Command Line
CP/M commands and transient programs are accessed from the system prompt by typing in a sequence of characters called a command line. A CP/M command line is composed of a command, an optional command tail,
and a carriage return. The command is the name or filename of a program to be executed. The optional command
tail can consist of a drive specification, one or more file specifications, and some options or parameters.
A>COMMAND {command tail} CR
Command Conventions
The following special symbols define the syntax of a normal command line.
{} surrounds an optional item.
| separates alternative items in a command line.
CR indicates a carriage return.
^ indicates the Control Key.
n substitute a number for n.
s substitute a string (group) of characters for s.
o substitute an option or option list for o.
[] type square brackets to enclose an option list.
() type parentheses to enclose a range of options within an option list.
RW Read-Write attribute - opposite of RO
RO Read-Only attribute - opposite of RW
SYS System attribute - opposite of DIR
DIR Directory attribute - opposite of SYS
... preceding element can be repeated as many times as desired.
* wildcard: replaces all or part of a filename and/or filetype
? wildcard: replaces any single character in the
same position of a filename and/or filetype.
Command Line Editing
The resident CP/M command interpreter (CCP) allows a certain degree of editing of the CP/M command line before
pressing the RETURN key. The editing keys are outlined below along with their usage. It should be noted that these
editing keys are totally independent from the control codes used by the terminal emulation for the video display.
Control Character Function
CTRL-A moves cursor one character to the left.
CTRL-B moves cursor from beginning to end of command line and back without affecting command.
CTRL-C stops executing program when entered at the system prompt or after CTRL-S.
CTRL-E forces a physical carriage return without sending command.
CTRL-F moves cursor one character to the right.
CTRL-G deletes character at current cursor position if in the middle of a line.
CTRL-H delete character to the left of cursor.
CTRL-I same as the TAB key.
CTRL-J moves cursor to the left of the command line and sends command to CP/M. Line feed, has
same effect as carriage return.
CTRL-K deletes character at cursor and all characters to the right.
CTRL-M same as carriage return.
CTRL-P echoes console output to the list device.
CTRL-CF: restarts screen scrolling after a CTRL-S.
CTRL-R retypes the characters to the left of the cursor on a new line; updates the command line buffer.
CTRL-S stops screen scrolling.
CTRL-U updates the command line buffer to contain the characters to the left of the cursor; deletes current
line.
CTRL-W recalls previous command line if current line is empty; otherwise moves cursor to end of line.
CTRL-J,-M,-R,-U and RETURN update the command line buffer for recall with CTRL- W.
CTRL-X deletes all characters to the left of the cursor.
Filespec
CP/M identifies every file by its unique file specification,= which can consist of four parts:
the drive specification,
the filename,
the filetype and
the password.
The term "filespec" indicates any valid combination of the four parts of a file specification, all separated by their
appropriate delimiters. A colon must follow a drive letter. A period must
precede a filetype. A semicolon must precede a password.
The general symbols and rules for the parts of a file specification follow:
d: drivespec optional single alpha character (A-P)
filename filename 1-8 letters and/or numbers
typ filetype optional 0-3 letters and/or numbers
password password optional 0-8 letters and/or numbers
If you do not include a drive specifier, CP/M automatically uses the default drive. Valid combinations of the elements
of a CP/M file specification are:
filename
d:filename
filename.typ
d:filename.typ
filename;password
d:filename;password
filename.typ;password
d:filename.typ;password
Some CP/M commands accept wildcard (* and ?) characters in the filename and/or filetype parts of the command
tail. A wildcard in the command line can in one command reference many matching files on the default or
specified user number and drive. This is sometimes referred to as an 'afn' or ambiguous filename. If no wildcards
are present, an 'ufn' or unambiguous filename results.
COMMODORE FREE
I would like to thank Herne and 'Herne Data Systems Ltd.' For granting the reprint permission of this text
From: Herne
Subject: Commodore Free magazine
To: Commodore Free Magazine
You have our permission to run the text. Pls be sure to send us a copy for our records when it appears.
regards, Mike
Herne Data Systems Ltd.
31 Adelaide St E, PO Box 357
Toronto, ON M5C 2J4
CANADA
Voice/FAX 416-364-9955
herne@herne.com
"Custom Software for DOS & Windows"
visit our award winning website-
http://www.herne.com
Other text about the CP/m and Commodore 128 can be found on Herne`s website, zipped up text versions can be
found here:
http://www.devili.iki.fi/Computers/Commodore/C128/CPM-tech/
JUMP Back To Contents
NEW BOXED AND FOR SALE ON EBAY
Of course by the time you read this the auctions will have ended but how many more of these warehouses' have
secret stashes of Commodore goodies, if the user is still selling you can see a list that is of course assuming seller and items are still for sale here http://shop.ebay.de/merchant/ibay10 the Commodore 16 was selling for EUR 1,50
CP/M – the Operating System for microcomputers of the 1980`s
By the end of the 1970`s and early 1980`s CP/M was the standard operating system for microcomputers. On top of
that, it was the first DISK Operating System (DOS), and therefore the basis for today's DOS, and in first place Microsoft?s DOS. MS-DOS itself derived from nothing more than a CP/M clone called QDOS (Quick and dirty
operating system) written by Tim Patterson. Microsoft bought QDOS from him to use with the first IBM PC. Many
former CP/M programs have been ported to DOS, first of all DBase and WordStar. CP/M itself on the other hand is
based on the Operating System for the DEC PDP-10, called "TOPS-10", at least as far as naming conventions for
files and devices and some commands are concerned. Surely, there are other influences, but they remain untold.
Many of the computing things that we take for granted today, have there roots back to the work of a single man, that
man was Gary Kildall, the developer of CP/M. Who has ever thought, why his my hard disk is called C: or where does
the DOS command DIR comes from?
Gary Kildall was born in 1942, and received a Ph.D. in Computer Science in 1972, soon he fulfilled a draft obligation
to the United States Navy by teaching at the Naval Postgraduate School in Monterey, California. When Gary
attended the introduction of the new Intel processor 8080 in 1973, he was so enthusiastic about it, that he suggested
to the Intel managers to write a compiler (i.e. a program that builds a ready-to-run program out of the program code)
for the language PL/1 (Programming Language Number 1). At this time, PL/1 was often used on mainframes, so that
the Intel people agreed immediately; the program was the called (= Programming Language for Microprocessors).
There was only a small problem: Gary didn?t own a computer that ran an 8080 CPU. He had access to a
Digital Equipment PDP-10 only, and so Gary built his PL/M compiler in FORTRAN on the PDP machine. when the
compiler was ready, he needed an 8080 computer for testing. He even managed to convince Shugart to donate him
a floppy drive. But, since cable, power supply and controller were missing; it didn?t help him very much.
Together with Gordon Eubanks (who later became CEO of Symantec) he built an 8080 based computer. For this
machine he wrote an operating system which he called CP/M (Control Program/Monitor). He offered a package
containing CP/M, PL/M, and a development system to Intel for 20.000 US$. Intel wasn?t interested in CP/M , but they
agreed to buy PL/M. So Gary at least had success with his compiler and decided to put CP/M on the market on his
own. Together with his wife, he established a company called "Intergalactic Digital Research Inc.", which later was renamed to "Digital Research Inc." ('DR').
Gary started to sell his CP/M through mail order in technical magazines. It should be mentioned that exactly at that
time many enthusiasts began to build computers on their own (e.g. Altair and IMSAI offered their now famous
assembly kits). What those computers were missing, was on operating system, so CP/M turned up in the right place
at the right time.
In 1979, DR published CP/M version 2.0, which soon was followed by CP/M 2.2. This version was the most popular
one and was used worldwide, as it offered high performance with only small amounts of memory usage. The next
version, 3.0, also called CP/M Plus, but wasn?t offered before 1982. Unfortunately, this was one year too late, since
in 1981 IBM started its triumph.
What was so special about CP/M?
You should be aware of the fact that microcomputers at that time were equipped quite badly and often had to be
programmed using switches (e.g. the Altair and IMSAI 8080 models). If ever, there was a programming language like
e.g. BASIC, which made it possible to write and save simple programs. An Operating System on the other hand
offered possibilities, that today we take for granted, but at this time were pure luxury. In first place, it had a
standardized user interface, which made it possible to run the same commands and programs on a couple of
different machines, so that the user didn?t need to care about the hardware any more. It was just the manufacturer
who had to adopt the CP/M to his hardware. But, since this was quite easy to be done, CP/M became very popular.
CP/M was based on three components:
1. The BIOS (Basic Input Output System): This was the part that controlled the basic communication between
hardware and software, and therefore was different with different hardware. It consisted of functions as e.g. reading
letters from the keyboard, show characters on the screen, or reading a sector from a floppy disk. A computer without
BIOS is unthinkable nowadays.
2. The BDOS (Basic Disk Operating System), the "brain" of the CP/M. It was the place where communication
between the command interpreter and the BIOS took place, i.e. the inputs and outputs were translated and forwarded
to the CCP.
3. The CCP, the command interpreter. This was a simple program that had some built-in commands (e.g. DIR to
show the directory listing) and could start other programs.
In 1981, CP/M did already run on about 300 different computer types. It even ran on machines without 8080 or z80
CPU. Microsoft sold the so-called "Softcard", which made it possible to run CP/M on an Apple computer. Believe it or
not, but at this time they had more income with CP/M than with their own software. As time passed, other CP/M
versions followed: those for the 16 bit CPU 68000 (CP/M-68000) and Intel 8086 (CP/M-86).
In 1980, the decisive turn in the history of Digital Research took place. IBM developed the PC, and of course they
needed an Operating System for it. CP/M seemed to be the ideal product, as enough software for all scopes was
available for it. By mistake they thought that Microsoft produced CP/M (as they sold the Softcard along with CP/M),
and they made an appointment with Bill Gates, just to learn that Digital Research was the right contact. Gates sent
the IBM managers to the nearby town of Monterey. When they arrive there, Gary wasn?t at home though. Nobody
knows exactly what happened at that time, but it seems that Dorothy McEwen, Gary?s wife, who managed the
company, didn't agree to IBM's terms and therefore cancelled the negotiations.
IBM's people addressed themselves to Bill Gates again, who realized the great chance and bound himself to provide an Operating System. When Gary came to know that PC-DOS was a plagiarism of CP/M (what he could even proof),
he filed a lawsuit against IBM. But shortly after that he abandoned it again, because IBM offered him a generous
compensatory payment. In the same course, they agreed to offer CP/M alternatively to DOS together with their PC.
What they didn't mention: they charged three times the price of DOS for the CP/M. Of course the available range of
software for CP/M was much larger, but because of the price most customers choose DOS. Anyway, during this
period many machines where offered that had both the 8086 and the z80 CPU, and even z80 cards for the IBM PC
where available, so that many customers could still use CP/M together with DOS. Some companies even kept on
offering CP/M and its successors with their x86 machines, e.g. Siemens.
Digital Research didn?t become inactive, though, and published a couple of innovative products in the following years.
An example was Concurrent CP/M, a real Multitasking System, which was efficient and easy to operate, because it
used the well known CP/M commands. Later on they issued DR-DOS, a MS-DOS compatible, but much more
comprehensive Operating System. In 1991, Gary Kildall sold Digital Research to Novell. After that, he was involved in
other developing projects, e.g. the file system for Multimedia CD ROMs. DR also brought out the graphics user
interface GEM, which wasn?t that popular for CP/M or DOS users, but then was licensed by Atari and became well-
known as the GUI of the ST series.
In any case, the choice of computers that ran CP/M was quite large at the beginning of the 1980ies. It can even be
said that in the Personal Computer sector the Digital Research Operating System was ruling the market. Software
was available for all kinds of applications. Freeware was offered in an extensive range so that CP/M computers
became affordable for almost everybody. There was only one disadvantage in CP/M: the mostly incompatible
hardware. I.e. an Osborne isn?t able to read floppies formatted on a Kaypro and vice versa. When you wanted to
exchange data between different computers, you had to use either a converter program or a serial connection
between the machines. On the other hand, at that time modems and acoustic couplers already existed, so that users
could connect to a mailbox and download programs and files.
Of course, at that period, files had completely other dimensions than those to which we are used today. You must
consider that a z80 based CP/M machine didn?t have more than 64 Kbyte of memory, and a floppy usually could save
not more than 360 Kbyte – imagine how memory thrifty programs had to be under these circumstances.
Comprehensive programs therefore used a modular structure, which made it possible to load only those parts into
memory that were currently needed.
Hard disks were rare and nearly priceless. Nevertheless, CP/M was able to manage partitions up to a size of 8
Mbytes. If somebody had to maintain a bigger project with higher amounts of data therefore had a distinct advantage
when using a hard disk instead of a higher quantity of floppy disks. An example of a CP/M machine with hard disk
was the Kaypro 10, which had a built-in 10 Mbyte hard disk.
One reason for the popularity of the CP/M successor DOS surely was (apart from the price) the similarity of its
structure and user interface. For somebody changing from CP/M to DOS, it was easy to become acquainted to the
new system. The only big difference was that DOS introduced sub-directories to the microcomputer world, where
CP/M used to work with User areas. Both solutions had their roots in mini and mainframe systems, though.
The most important CP/M commands were:
- DIR to show the directory listing
- STAT to show drive and media information and to change attributes
- PIP to copy
- ED line editor for text files
- SYSGEN for creating a system disk
Even other conventions were ported from CP/M to DOS, e.g. the 8.3 convention for file names (FILENAME.TXT), the
usage of the asterisk and question mark as wildcards and the extension .COM for executable files. A typical CP/M
command e.g. could be: DIR B:*.* or PIP B:=A:*.TXT, where in the latter example the copying direction is inverted in
comparison to DOS. This may result in the Assembler convention, a programming language many user were
acquainted to at this time.
It is justifiable to say that if history had developed slightly different, its possible that we might work with CP/M and
GEM (or their successors) instead of DOS and Windows today.
EDITOR
I would like to thank Gaby for contacting me regarding CP/m and offering this text, also I would like to thank
her for converting the text from German to English.
JUMP Back To Contents
Commodore Computer club Forum post = Clock Calendar 128
I've had the following email from Commodore128.org about a new 128 application:
"Clock-Calendar 128 (CC128) is now available for downloading. See the link at the end of this post and be sure to
read the documentation before trying it out. Also, if you wish to integrate CC128 with the C-128 80 Column Display
Manager (80CDM) you will need to download the latest 80CDM version, as the previous version is not compatible
with CC128.
Clock-Calendar 128 is a utility for the C-128 that provides date and time services that may be used by other
programs on an ad hoc basis. When started, CC128 is linked into the C-128's interrupt request (IRQ) processing
subsystem, causing the utility to run in the background until its services are needed. There are any number of uses to
which CC128 can be put, such as providing date and time services to BBS software, date and time stamping of
records in a database, date and time stamping of entries into a log, etc.
CC128's basic features are:
- 12 hour, AM/PM continuous time-of-day function. All CC128 timing functions are derived from the hardware TOD
clock in CIA #2. Unlike the TI$ software jiffy "clock" available in BASIC, the CIA's TOD clock is unaffected by
operating system activities and maintains excellent accuracy over long periods.
- Calendar with day of week, year, month and date. CC128 can maintain dates from January 1, 1753 to December
31, 9999, inclusive, with full leap year compensation.
- Audible alarm. At the alarm time, your C-128 will alert you with a pleasant gong tone. The alarm has the software
equivalent of a "snooze bar."
- Continuously updated date and time values. CC128 can export date and time data into any desired location in
RAM-0 for use by your software.
- Automatic detection of NTSC and PAL systems. Upon startup, CC128 will determine which video system is in use
and will program the TOD clock for the correct power line (mains) frequency.
- Presence signature. CC128 includes a "presence signature" that can be tested by other programs to determine if
CC128 has been loaded into memory and is intact..
-CC128 can interface with the C-128 80 Column Display Manager (80CDM) and offer the following extra services:
Timed "screen saver" function. CC128 can be configured to monitor the C-128's keyboard and turn off the 80 column
display after a programmable period of inactivity. Pressing almost any key will turn on the display. The inactivity
period can range from one to 32,767 seconds (more than nine hours).
-Continuous date and time display. If 80CDM's status line has been enabled, CC128 can be told to generate a
constantly-updating date and time display on the right-hand end of the status line (leaving plenty of room for user-
generated status line text).
-CC128 runs in RAM-0 underneath the kernel ROM and consumes less that 2 KB. Data is stored in normally unused
memory at the very top of RAM-0. When loaded and started, CC128 will adjust the top-of-BASIC pointers to protect
itself from outsized programs.
-CC128 is a low level operating system enhancement, and thus natively operates at the machine language level.
Access is through a jump table similar to the kernel ROM jump table, and date and time inputs and outputs are given
in compressed binary-coded decimal (BCD) format for easy manipulation and conversion in the M/L environment.
However, BASIC programmers have not been left out in the cold! I have also developed CC128CTL (CC128 control,
included in the CC128 distribution) to allow CC128 functions to be called from BASIC, using a simple SYS calling
syntax that even a trained monkey can understand. :
If you have any questions about the use of CC128 please peruse the documentation. If that doesn't help then feel
free to post here. If you are reporting what you think may be a bug, please be as specific as possible as to the
problem. Posts that lack adequate information or aren't germane to the topic will be ignored.
To unsubscribe from these announcements, login to the forum and uncheck "Receive forum announcements and
important notifications by email." in your profile.
You can view the full announcement by following this link:
http://landover.no-ip.com/forums/index.php?topic=2266.0
Regards,
The Commodore 128 Alive! Team."
Regards,
Shaun.
JUMP Back To Contents
WORLD'S GREATEST MENU
by Alan Reed
There are probably a million "menu" programs out there. If the menu is the first program on your disk, users can
LOAD"*",8:RUN and be presented with a list of programs on the disk.
I've always been fascinated by these programs -- I've humbly called my attempt "World's Greatest Menu." I think it
surpasses most of the old generic menus you've seen before in a few ways.
WGM is written entirely in DotBASIC plus and has the following features:
* Works with all drives/device numbers.
* Looks nice. Uses a custom character set, and is generic enough to be suitable for any collection of programs or
text.
* Uses a mouse in port 1, a joystick in port two, or CRSR keys and RETURN. Press 'Q' to QUIT if you are using the
keyboard only.
* If the selected file is of the Mr.Edstar persuasion (prefixed with a 'T.' the program will let you read and/or print the
text file.
* If you place a SID music file on your disk (prefixed with a 'M.') WGM will play the music. The SID must be less than
15 disk blocks long.
WGM is the natural evolution of the simple menu program I presented as a tutorial in the DotBASIC Plus manual.
The main differences are the addition of an FTS screen, a second clean character set for the text reader, and a few
lines of code to play the first SID file found on the disk.
There are lots of REM statements in the program listing detailing what WGM is doing. I invite you to take a look to
see how simple programming in DotBASIC Plus can be.
Enjoy!
http://8bitcentral.com/
JUMP Back To Contents
Alternative Programming Languages: C
Part 1 By Paul Davis
In the first article of this series we explored some of the capabilities of the Forth
language. Forth has many unusual characteristics that make it well suited to
programming on the Commodore, but it's a language that polarises opinion. Some
people love it, some hate it, and some just can't seem to wrap their head around it. So
this time we're going to look at a more mainstream language, C.
C is a compiled language. It's not like BASIC or Forth where there's an interpreter
you can type commands into and experiment with. Program code is entered into text
files which are then run through a compiler to translate the source code into an
executable program. This makes programming in C a bit more involved than you may
already be used to. Nevertheless, C is a very powerful and flexible language and is
well worth adding to your programming repertoire.
Although there are several implementations of C that run on the Commodore, the lack
of memory and poor disk drive performance makes writing programs a laborious
process. With that in mind, it provides a good opportunity to introduce the concept of
cross-development. That is, using a modern computer to edit and compile our
programs into a form that can be run either in an emulator or on a real Commodore
machine.
As was the case with the Forth article, this is not a complete tutorial. It's merely an
introduction to some of the features and programming style of the language to give
you an idea of how it can be used. I'm going to follow a similar format as before and
present some example programs with a brief commentary on how they work.
Getting started
We're going to be using a freeware C compiler called cc65 which is available in
executable form for Windows, and as source code that can be compiled for OS X and
Linux. The cc65 web site can be found at http://www.cc65.org/. We will also be using
the VICE emulator to test our programs. If you don't already have this, it can be
downloaded from http://www.viceteam.org/.
The first step is to download and install cc65. Point your browser or favourite FTP
client at the download area: ftp://ftp.musoftware.de/pub/uz/cc65/ then follow the
relevant instructions for your OS below.
Windows XP and Vista
Download the files called cc65-win32-2.12.0-1.zip and cc65-c64-2.12.0-1.zip. Next,
create a directory where you want to install the compiler. This can be anywhere you
like, although I would recommend avoiding the 'Program Files' directory (especially
on Vista) or directories with spaces in their name. This article will assume the
directory is C:\cc65. To install the program, extract the zip files you downloaded into
the cc65 directory you have just created.
Before we can use the compiler we need to set up our programming environment at
the command prompt. Open a command prompt window (hold down the Windows
key, press R then type 'cmd' and press Enter) and type the following commands:
path %path%;c:\cc65\bin
set CC65_INC=c:\cc65\include
set CC65_LIB=c:\cc65\lib
These instructions tell the command shell where to find the cc65 programs and tell
cc65 where to find various files that are needed to compile a program.
You will need to enter these commands each time you open a new command prompt
window. If you want the settings to be permanent, here's how to do it. Press Windows
+ Break (or right-click on 'My Computer' and choose 'Properties') to bring up the
System Properties dialog. On Vista select 'Advanced system settings' from the task
panel on the left and confirm the UAC dialog. In the System Properties dialog click
on the 'Advanced' tab, then on the 'Environment Variables' button. In the bottom panel
for system variables click on 'New' then enter 'CC65_INC' for the name and
'c:\cc65\include' for the value and click 'OK'. Do the same for the 'CC65_LIB'
variable with the value 'c:\cc65\lib'. Next, scroll down the list to find the entry for
'Path' and double click it. Click on the value field and move the cursor to the end of
the value then add ';c:\cc65\bin' to the end and click 'OK'. Click on the 'OK' button of
the Environment Variable and System Properties dialogs to complete the settings.
Finally, we need to create a directory within the cc65 directory to store the files we
will create during this tutorial.
cd c:\cc65
mkdir tut
cd tut
OS X and Linux
To keep these instructions as short as possible I'm going to describe the procedure for
OS X and assume Linux users will know how to deal with any differences.
First, to compile cc65 we need to install the Xcode developer tools. Insert the OS X
installation DVD that was shipped with your Mac and follow the links to install
Xcode.
Next, download the file called cc65-sources-2.12.0.tar.bz2 from the cc65 web site.
You will not need to download any of the other files. Assuming the file has been
saved to your 'Downloads' directory, open a new Finder window and navigate to that
directory. Double-click on the cc65-sources file and the Archive Utility will extract it,
creating a directory called 'cc65-2.12.0' in the Downloads directory.
Now we need to work at a command line, so navigate to Applications then Utilities
and double-click the Terminal program. Enter this command to change the current
directory to the cc65 directory in Downloads:
cd ~/Downloads/cc65-2.12.0
Now type this command to build the cc65 program suite:
make -f make/gcc.mak
This will take a minute or two to run. When the command prompt returns enter these
lines:
sudo mkdir /usr/local
sudo make -f make/gcc.mak install
You will probably need to enter the administrator password to run those commands.
They will install cc65 into /usr/local/lib/cc65 and the executables into /usr/local/bin.
At the end of the installation, there will be a message listing two variables that need to
be set up. We will do this in a minute, but first we need to create a work directory to
store the files that will be created during this tutorial. Enter these lines:
cd ~/Documents
mkdir cc65
cd cc65
To make setting up the environment variables a bit easier we will create a script to do
it for us. Enter this command:
xed -xc init.sh
The Xcode editor will start up and show a blank document. Enter the following lines
into the file:
export CC65_INC=/usr/local/lib/cc65/include
export CC65_LIB=/usr/local/lib/cc65/lib
alias edit='xed -xc'
Press Cmd+W and confirm the dialog to save the file. Finally, enter this command in
the terminal window to run our script:
. init.sh
That's a dot and a space before the init.sh. This command will need to be run in any
new terminal window when you want to use cc65.
Creating your first program
Because C is a compiled language, the program code is entered into plain text files.
These files should have a '.c' extension. The cc65 compiler is then used to translate the
source code file into an executable program.
To keep things as simple as possible we will use the standard tools provided by the
operating system. On Windows we will use Notepad for entering the source code. On
OS X we will be using the Xcode editor which you have already seen. If you are using
Linux replace 'notepad' or 'edit' in the instructions below with your favourite text file
editor. Windows users enter this command:
notepad first.c
Notepad will ask if you want to create a new file, answer yes. OS X users enter this
command:
edit first.c
Now type in (or copy and paste) the program below. To get the # on a Mac with a UK
keyboard press alt/option and 3.
// My first C program
#include <stdio.h>
void main(void)
{
puts("It works!");
}
Press Ctrl+S on Windows or Cmd+S on OS X to save the file. Now flip back to the
command prompt/terminal window. Windows users enter the command:
dir
OS X or Linux users enter the command:
ls -l
The directory should show our 'first.c' file. Now we need to compile this into a C64
program. To do this, enter the command:
cl65 first.c
If all goes well, the command prompt should return with no other output (cc65
follows the Unix philosophy of 'no news is good news'). If you get an error message,
swap back to the editor window, make any necessary corrections, save the file, then
enter the cl65 command again at the command prompt.
Once your program has compiled without errors, enter the 'dir' (or 'ls') command again
and you should see a couple of new files, 'first.o' and 'first'. The 'first.o' file is an
intermediary file created during the compilation. The file called 'first' is our C64
program.
Next, load up x64, the VICE C64 emulator. Select the option called 'Autostart' or
'Smart attach' in the 'File' menu. On Windows navigate to the c:\cc65\tut directory and
select 'All files (*.*)' as the file type filter. OS X users navigate to the
Documents/cc65 directory. Now double click on the file called 'first' and our program
should load and run, displaying 'It works!' on the screen.
That is, in a nutshell, the process for creating programs in C. This 'edit, compile, run'
sequence of actions will soon become second nature.
Okay, let's take a look at the program code in more detail. The first thing to notice is
that the code is written predominantly in lower case. C is case sensitive and all of its
built-in keywords must be entered in lower case. The first line in the program is a
comment line. The double slash characters mark the start of a comment and all text
after the // up to the end of the line is ignored. C also supports comments that span
multiple lines. All text between /* and */ markers will be ignored.
Skip past the #include line for now, we will come back to this in a moment.
C programs are broken down into separate named blocks of code called 'functions'.
Each function can take any number of parameters and can optionally return a single
value. The next line in the program creates a function called 'main'. The word 'void'
before the function name declares the type of the return value, in this case, void
because we are not going to return a value from the function. The parameters of a
function are listed after its name inside brackets. Again, 'void' here means the function
takes no parameters.
Typically, many programs follow the convention of using lower case for function
names, often with multiple words separated by underscores. For example, 'move', 'fire'
or 'show_high_scores'. Sometimes you may see programs or libraries that use mixed
case function names such as 'NewList' and 'AddListitem'. These are not enforced by
the compiler, they are just conventions used to make names consistent and readable.
The function called 'main' serves a special purpose in C. It's automatically called
when the program is run and therefore marks the starting point of the program. When
all the instructions in the main function have completed, the program will exit and
return back to BASIC. Every C program must have a 'main' function.
The body of a function is contained within curly braces. This is the way C groups
together lines of code into discrete blocks. Our 'main' function only contains one
instruction that calls another function named 'puts'. The brackets contain the
arguments passed to that function, in this example the string "It works!" delimited by
double quotes. The 'puts' function is one of many standard functions defined by the C
language and is used to print out a string. Notice that the instruction is followed by a
semi-colon. This must be used to mark the end of every separate instruction in C.
Before a function can be called, C needs to have been previously told about its name,
what parameters it takes and what type of value it returns. The C compiler uses this
information to check that the arguments you pass to the function match up with the
parameters it expects. C is quite strict in this regard. For example, it would not allow
you to pass a number to the 'puts' function which expects a string. So, how does the
compiler already know about 'puts' in our example program?
The answer lies with the #include line at the start of the program. This instruction
reads in another file containing declarations of functions that are in the standard
library, one of which is 'puts'. These files are called 'header' files and have the
extension '.h'. The one used here is 'stdio.h', short for 'standard input and output'. It
contains functions used to read and write data to files and other devices including the
screen.
The core C language itself is very simple, consisting only of a few keywords for
declaring functions and variables, testing conditions, looping and arithmetic
operations. The rest of the features are provided by libraries of functions. The
standard C language provides a good number of library functions for many purposes
including string, file and memory handling. The cc65 compiler provides some
additional libraries and you can also create your own libraries of often-used functions.
Variables
Now let's try using variables in C. Close the 'first.c' file and create a new file called 'var.c' at the command prompt:
notepad var.c
Enter the following program into this file:
#include <stdio.h>
void main(void)
{
int n = 1000;
char c = 'X';
char s[] = "Commodore";
int a[5] = { 1, 10, 100, 1000, 10000 };
int i;
printf("n = %d\n", n);
printf("c = %c\n", c);
printf("s = %s\n", s);
printf("a =\n");
for (i = 0; i < 5; ++i)
{
printf("%5d\n", a[i]);
}
}
Save the file and compile it at the command prompt using the cl65 command as
before:
cl65 var.c
When the program has compiled correctly, switch back to VICE. You could run the
program using the same auto-load method as before but, because VICE has now set
up device 8 to point to our tutorial directory during the last auto-load, you can also
enter the familiar load command directly into the C64 emulation:
LOAD "VAR",8
RUN
The program should display the values of the variables. 'n' is a number variable, 'c' is a
character, 's' is a string and 'a' is an array of numbers. These short variable names have
been chosen so the code fits in the narrow columns of the magazine. Normally,
variables would have longer, more descriptive names!
Variables declared inside a function must be positioned at the start of the code block,
that is, after the opening curly brace before any other instructions. These variables
will be 'local' to the function. In other words, they are only accessible by that function
and only exist temporarily while the function is running. You may also create global
variables in C by declaring them outside of any function. We will see an example of
global variables later.
Variable declarations follow this general format:
type name = value;
All variables in C must be declared to be a specific type. The type dictates what kind
of data can be stored, the limit on its values and how much memory the variable takes
up. The most commonly used types in cc65 are:
char - characters or whole numbers from -128 to 127
int - whole numbers from -32768 to 32767
long - whole numbers up to +/- 2,147,483,647
These are 'signed' types because they allow both positive and negative numbers. C
also supports 'unsigned' types that allow larger positive-only values:
unsigned char - numbers from 0 to 255
unsigned int - numbers from 0 to 65535
unsigned long - numbers up to 4,294,967,295
The variable name can be any combination of letters, numbers and underscores
(although it can't start with a number). Conventionally, variables have lower case
names, often with words separated by underscores. For example, 'level', 'score',
'high_score' etc.
A variable doesn't have to be assigned an initial value. Any variable without an
explicit value will contain random garbage. To avoid errors in your programs it's
usually a good idea to give variables an explicit initial value.
Arrays
C has no built-in type for strings, although it does allow a literal string to be created
by putting it in double quotes. In C, a string is simply considered to be an array of
characters.
Arrays are declared by putting the size of the array in square brackets after the
variable name. In the example program, the variable 's' is declared with empty
brackets so the array will be as long as it needs to be to fit the string. The variable 'a'
is declared as length 5 and has 5 values assigned to it. Notice the use of curly braces
again for grouping these values together.
To access an element in an array, the index number of that element is put in square
brackets after the variable name. Index numbers always start at zero and go up to the
array length - 1. In the example program, we could access the first element of the
array with a[0] and the last element with a[4]. Often, we would use some kind of loop
to iterate through all the elements in an array and use a variable as the index.
Formatted output
We have also introduced a new library function here, printf. The 'f' stands for
'formatted' and this function gives us greater control over the layout of the printed
text. The first parameter is a 'format string'. This is the text we want to print with
placeholders (marked by a % sign) for the values we want to display. These values are
passed as extra parameters to the printf function. The first printf instruction displays
the value of the 'n' variable. We use a %d placeholder to print the value of this
variable as a decimal number. The second printf displays the value of the 'c' variable
and uses the %c placeholder to display it as a character. The third printf uses the %s
placeholder to display the contents of the 's' variable as a string.
There is no special format placeholder for an entire array so we use a loop to print the
values one at a time. Notice this time we use %5d in the format. This causes the
numbers to be printed in a 5 character wide field. Any numbers shorter than 5 digits
will be padded with spaces on the left hand side to make them line up.
There are many other formatting options provided by the printf function. I will leave
it as an exercise for the reader to explore them in more detail. One important thing to
remember though is that 'printf' is a large, complex function and will add a
considerable amount to the size of your program. If you need to keep the size of your
program down you may prefer to use other library routines for generating output.
Finally, notice the '\n' at the end of each format string. This stands for 'new line' and
moves the cursor down to the start of the next line.
The for loop
The previous example also introduces C's for loop. The syntax looks strange at first
but it's not too complicated. The basic form is:
for (initialisation; condition; increment)
There are three sections in the brackets, separated by semi-colons. The first section
initialises the values of any variables needed during the loop, usually the loop counter.
In our example, we set the value of 'i', the loop index, to 0. The next section is the
condition. The loop will run as long as this condition is true. Note that the condition is
tested at the start of the loop so it's possible for the body of the loop to never run at all
if the condition is false the first time round. In our example, the condition is 'i < 5'.
The loop will keep running while 'i' is less than 5 and will terminate once 'i' is 5 or
more. The final section of a for loop is used to increment the loop variable. Here we
have used '++i' to increment (add 1 to) the value of 'i'. The for loop here is therefore
roughly equivalent to the following BASIC loop:
FOR I=0 TO 4:PRINT A(I):NEXT I
The console library
While the functions provided by the 'stdio' library are very useful, they are general
purpose routines designed for writing and reading streams of data to and from files.
The screen just happens to be one such type of data stream. The cc65 compiler
provides another library called 'conio' that is designed specifically for printing to the
screen and reading from the keyboard (collectively known as the 'console'). These
routines allow extra features such as moving the cursor to a specified location on the
screen, changing colours, waiting for a key press etc. They are also usually smaller
and faster than the equivalent 'stdio' routines. Let's write a program to demonstrate
some of this library's features.
Close the previous editor window and create a new file called 'console.c'. Enter the
following program into this file:
#include <conio.h>
void colors(int paper, int ink)
{
bgcolor(paper);
bordercolor(ink);
textcolor(ink);
clrscr();
}
void show_title_screen(void)
{
colors(COLOR_GRAY3, COLOR_GRAY1);
cputsxy(14, 12, "Welcome to C");
cgetc();
colors(COLOR_BLUE, COLOR_LIGHTBLUE);
}
void main(void)
{
show_title_screen();
}
Compile the program with 'cl65 console.c' and run it in VICE. The program will
change the screen colours to grey and display a message at the centre of the screen. It
then waits for a key to be pressed before restoring the default colour scheme.
This program introduces a few new concepts. Let's go through it. The #include line
reads the conio header file so we can call the functions in that library.
Next, we have created a function called 'colors' to change the colours on the screen (I
used the American spelling so the name is consistent with the names of the library
functions). The function takes two colour parameters and uses these to set the
background, border and text colours. It also clears the screen. Notice how the
parameters, just like variables, must be declared as a specific type.
The second function, 'show_title_screen', calls our 'colors' function to change the
screen to grey. We can use named constants for the colours rather than having to use
literal numbers which makes the program more readable. The convention for naming
constants is to use all upper case letters with words separated by underscores. This
makes it easy to differentiate them from variables.
The function 'cputsxy' is used to print the message at the centre of the screen. There
are many such functions in the conio library. Have a look through the 'conio.h' file (in
c:\cc65\include or /usr/local/lib/cc65/include) to see all the functions this library
provides.
The 'cgetc' function waits for a key to be pressed. It actually returns the ASCII code of
that key but we are ignoring the return value in this example. Once a key has been
pressed, the colours are restored to the familiar blue on blue.
Notice how the program has been organised. Each function performs a small well-
defined task, and the 'main' function does little more than call our other functions. It's
good practice to build programs up like this, rather than just dumping everything into
the 'main' function.
Also notice that the functions are defined before the point where they are first used.
Remember that C needs to know what parameters a function expects before it can call
it. One way to ensure this in your own program is to place the function definition
before any code that calls it. C also provides another, more flexible, way to do this
which we will look at next time.
It would be nice if our program could calculate the co-ordinates and centre the text for
us. Let's write a function to do this. First, we need to know the dimensions of the
screen. Okay, we know that the C64 screen is 25 lines of 40 columns, but if this
program were run on a C128 in 80 column mode that assumption wouldn't work. Let's
do it the proper way by asking the conio library for the dimensions of the screen.
First, add this line at the top of the file under #include <conio.h>:
#include <string.h>
We need to call a function that is in the string library so this line reads the header file
for that library. Now add the following lines above the 'colors' function:
typedef unsigned char byte;
byte scr_width, scr_height;
void init(void)
{
screensize(&scr_width, &scr_height);
}
void center(char text[], byte y)
{
cputsxy((scr_width - strlen(text)) / 2,
y, text);
}
Here we have introduced a number of new things. First is the 'typedef' line. We are
going to be using a lot of variables of type 'unsigned char' which is quite cumbersome
to type (and read). We can use 'typedef' to make a new type name that is equivalent to
some other type. Here, we are telling the compiler to allow us to use the word 'byte' to
mean 'unsigned char' which makes our program much neater.
Now, using our new 'byte' type, we create two global variables to hold the width and
height of the screen. The variables need to be global so that the other functions can
use them.
Next, we create a function that initialises these variables. using the 'screensize'
function in the conio library. The significance of the '&' will be explained in more
detail later when we look at pointers. For now, suffice it to say that the ampersands
allow the 'screensize' function to modify the variables passed as parameters.
Remember that a C function may only return a single value. This 'modifying the
parameters' approach is one way to get around that limitation.
The last new function is 'center' which takes a text string and a line number as
parameters. The function then uses 'cputsxy' to print the text as before, but this time
calculates the x co-ordinate using the length of the string (obtained using the 'strlen'
library function) and the screen width.
Now we need to change the line that prints the message to use our new center
function:
center("Welcome to C", scr_height / 2);
And finally, change 'main' to call the 'init' function at the start of the program so the
screen size is set up ready for the other functions to use:
void main(void)
{
init();
show_title_screen();
}
Save these changes, re-compile and run the new program. The result should be the
same as before, but now we have a general purpose function that can centre text on
any line of the screen.
The conio library also supports a limited form of line drawing using the Commodore's
graphical characters. Let's use these to put a box around the edge of the screen. Add
the following function above the 'colors' function:
void box(byte x, byte y, byte w, byte h)
{
cputcxy(x, y, CH_ULCORNER);
chline(w-2);
cputc(CH_URCORNER);
cvlinexy(x, y+1, h-2);
cputc(CH_LLCORNER);
chline(w-2);
cputc(CH_LRCORNER);
cvlinexy(x+w-1, y+1, h-2);
}
This function takes as parameters the co-ordinates of the top left corner of the box, its
width and its height. It uses a combination of 'cputc' to place individual corner
characters on the screen and 'chline' and 'cvline' for drawing horizontal and vertical
lines respectively.
Now change the start of the 'show_title_screen' function to use our new box drawing
capability:
colors(COLOR_GRAY3, COLOR_GRAY1);
box(0, 0, scr_width, scr_height);
box(9, 10, scr_width-18, scr_height-20);
Re-compile and run the console program again. Now the screen and message have a
box drawn around them. Try experimenting with these functions to create your own
title screen. How about changing the colours or having multiple lines of centred text?
Strings
In the previous program we touched briefly upon the string handling library. Let's
now look at strings in more detail. As mentioned earlier, a string is an array of
characters. We can create a string in C by enclosing it in double quotes and access the
characters in it through the array. For example, say we created a string like this:
char s[] = "String";
We can access the individual characters in the array through the 's' variable. The
expression s[0] would reference the first element in the array, the letter 'S', the
expression s[1] would reference the 't' and so on.
How do we know when we have reached the end of the string? C doesn't store the
length of a string, it uses a terminating 'null' character to mark the end of it instead.
Every function that manipulates strings needs to check for this 'null' character (ASCII
code 0).
C provides a library of string functions which we can access by including the 'string.h'
file in our programs. You have already seen one such function, called 'strlen' which
calculates the length of a string by counting the characters until it reaches the
terminating 'null' character.
One slightly awkward feature of the C language is that the normal assignment and
comparison operators don't work with strings. The expressions 'str1 = str2' or 'str1 <
str2', for example, don't work the way you might expect. Instead, library functions
must be used to copy and compare strings.
Let's create another program to demonstrate some of the standard string library
functions that you will use most often. Create a new file called 'string.c' and enter the
following code into the file:
#include <stdio.h>
#include <string.h>
void main(void)
{
char str[] = "Commodore";
char copy[20];
printf("str: %s\n", str);
printf("len: %d\n", strlen(str));
strcpy(copy, str);
printf("\ncopy: %s\n", copy);
printf("len: %d\n", strlen(copy));
printf("cmp: %d\n", strcmp(str, copy));
if (strcmp(str, copy) == 0)
{
puts("equal");
}
else
{
puts("not equal");
}
strcat(copy, " 64");
printf("\ncopy: %s\n", copy);
printf("len: %d\n", strlen(copy));
printf("cmp: %d\n", strcmp(str, copy));
if (strcmp(str, copy) == 0)
{
puts("equal");
}
else
{
puts("not equal");
}
}
As usual, save the file, compile it using 'cl65 string.c' and run it in VICE. The
program creates a string and a second array that is used to store a copy of that string.
The 'strlen' function is used to return the length the string. The 'strcpy' function copies
the original string into the 'copy' array.
The 'strcmp' function is used to compare two strings. It returns 0 if the strings are
equal, a number less than 0 if the first string is less than the second, or a number
greater than 0 if the first string is greater than the second. The 'if' statement compares
the two strings and displays 'equal' or 'not equal' depending on the result. Notice the
use of the '==' operator to check for equality. In C, the '=' operator is only used for
assigning values to variables.
Finally, the program uses the 'strcat' function to concatenate extra text to the end of
the copy string. See the difference this makes to the output of the 'strlen' and 'strcmp'
values.
POKE and PEEK
The cc65 compiler provides a neat way of performing POKE and PEEK operations.
Use #include <peekpoke.h> to get these features:
POKE(address, value);
PEEK(address);
Now, you may be thinking that we can use these for controlling the graphics and
sound capabilities of the C64. Indeed we could, but cc65 provides a better way to help
us program the custom chips by providing a named set of variables for their registers.
These features are found in the header file called 'c64.h'.
As an example, while we could change the border colour using a POKE such as this:
POKE(53280U, COLOR_BLACK);
A better way would be to use the following instruction:
VIC.bordercolor = COLOR_BLACK;
This is more readable and, perhaps surprisingly, is just as efficient as the equivalent
POKE.
VIC registers
To demonstrate some of these features, here's a short program that displays a sprite on
the screen. Create a new file called 'sprite.c' and enter the following program into it:
#include <string.h>
#include <peekpoke.h>
#include <c64.h>
#define SPRITE0_DATA 0x0340
#define SPRITE0_PTR 0x07f8
void main(void)
{
memset((void*)SPRITE0_DATA, 0xff, 64);
POKE(SPRITE0_PTR, SPRITE0_DATA / 64);
VIC.spr0_color = COLOR_WHITE;
VIC.spr_hi_x = 0;
VIC.spr0_x = 100;
VIC.spr0_y = 100;
VIC.spr_ena = 1;
}
After including all the required header files, this program uses #define to create two
constants that are used to tell the VIC chip where the sprite is stored in memory. The
'0x' prefix on the numbers tells C they are in hexadecimal.
The main function uses 'memset' to fill the sprite data memory with the value 0xff (a
byte with all bits turned on). This results in a solid block image. Next, the pointer for
sprite 0 is set to point to the sprite data using a POKE. Then we use the pre-defined
variables to set the VIC registers for sprite colour and position and finally, make it
visible.
Try experimenting a little with this program. How about using a 'for' loop to move the
sprite around the screen? If you're feeling adventurous, how about writing a function
that takes the x and y co-ordinates as parameters and moves the sprite to that position.
The function would have this type signature:
void move_sprite(int x, int y)
The tricky bit is dealing with x co-ordinates of 256 and above. If x is less than 256,
'VIC.spr_hi_x' should be 0 and 'VIC.spr0_x' should be x. But when x is 256 or more,
'VIC.spr_hi_x' should be 1 and 'VIC.spr0_x' should be 'x - 256'.
Next time
In the next article we will continue with the sprite theme and see how to build your
own library of sprite handling functions. We will also look at how to integrate
assembly language into your C programs for extra speed. See you then.
Article text and resources are now available at
http://sites.google.com/site/develocity/commodore/articles
JUMP Back To Contents