Commodore 64 Graphics and Sound
Commodore 64 Graphics and Sound
Steve Money
GRANADA
London Toronto Sydney New York
Granada Technical Books Granada Publishing Ltd
8 Grafton Street, London WIX 3LA
First published in Great Britain by Granada Publishing 1984
Copyright © S. A. Money 1984
British Librar v Cataloguing in Publication Data Money, Steve A.
Commodore 64 graphics and sound.
I. Commodore 64 (Computer)-Programming
2. Computer sound processing 3. Computer graphics
I. Title
001.64' 43 QA 76.8.C64
ISBN 0-246-123427
Typeset by V & M Graphics Ltd, Aylesbury, Bucks Printed and bound in Great Britain by
Mackays of Chatham. Kent
All rights reserved. No part of this publication may be reproduced, stored in a retrieval system or transmitted, in any form, or by any means, electronic, mechanical, photocopying, recording or otherwise, without the prior permission of the publishers.
Contents
Important Note VI
Pre/ace Vll
Introduction
2 Character Graphics 14
3 High Resolution Graphics 31
4 Adding Colour 61
5 Setting Objects in Motion 82
6 Sprite Graphics 98
7 Graphs and Charts 117
8 Depth and Perspective 140
9 The Sound Generator 157
10 Making Music 178
Index 193 Important Note
In many program listings for the Commodore 64 computer the cursor, reverse video and colour control codes are included in text strings of PRINT statements. They appear on the listings as reverse video symbols but must be entered on the keyboard by using cursor keys or combinations of certain keys with the CTRL or LOGO keys. The method of keying in these codes is described in Chapters 2 and 4. Figs. 2.2, 2.7, 4. I and 4.2 show the listing symbols for these codes.
Control codes can also be entered using the CHR$(N) form where N is the ASCII code number. Since the listing symbols for these codes can sometimes be difficult to decipher in printed listings the CHR$ form has been used for most listings in this book, but some programs in Chapter 7 do use embedded control codes in text strings.
In Fig. 7.4 lines 4I~ and 46~, Fig. 7.6 line 44~, and Fig. 7.8 lines 44~ and 51 ~, the text string is produced by using the keys
[SPACE] [CRSR UP] [CRSR LEFT]
Preface
Modern home and personal computers usually have very good colour graphics and sound facilities, and the Commodore 64 is no exception in this respect. The graphics display capability of this machine is extremely good, and the sound generator is perhaps the most versatile available.
The primary graphics mode on the Commodore 64 makes use of character graphics, and is basically a development of the graphics provided on the earlier Commodore PET computer. The main difference is that the Commodore 64 has a colour display. In Chapter 2 we take a look at some of the techniques involved in using character graphics. To a large extent, using character graphics is like assembling a jigsaw puzzle. Once you have sketched out a rough outline of the picture to be produced, you simply choose suitable symbols from the available set, and then place them on the screen to build up the desired picture.
When the existing character set doesn't provide the symbol you want it is possible to create your own symbols. This is a fairly complicated process on the Commodore 64, but you will find a full description of how to do it in Chapter 2.
High resolution graphics (where individual dots on the screen can be controlled) were not available on the earlier PET and VIC 20 computers, but have been provided on the Commodore 64. This makes use of what is called the 'bit mapped graphics' mode. The BASIC language of the Commodore 64 does not provide any drawing commands for the high resolution graphics, so points and lines have to be set up on the screen by POKEing data directly into the graphics display memory. Some of the techniques involved in drawing on the high resolution screen are described in Chapter 3. However, drawing using BASIC is rather a slow process, and for serious work in this mode programs written in machine code will usually be required.
Chapter 4 looks at the colour capabilities of the Commodore 64, both in the text and character graphics mode and in the high
viii Preface
resolution mode. Sixteen colours are available, and by using the multicolour mode it is possible to produce multicoloured symbols.
For most games programs, animation of objects on the screen is an important factor. The basic principles involved in animating simple objects and detecting collisions are explained in Chapter 5. An important variation of animation makes use of scrolling, where the entire picture is moved up or down or from side to side. Typical applications of this technique are in 'road race' games and those of the Defender type, w here a landscape moves across the bottom of the screen. Scrolling requires the use of machine code routines since BASIC is far too slow for this type of operation. Three machine code routines are included which can be loaded and called by BASIC and provide downward and side-to-side scrolling actions.
One very important feature of the Commodore 64 is its sprite graphics. In Chapter 6 we look at how sprites are created, controlled and positioned on the screen. The chapter goes on to look at animation using sprites. For applications involving animation the sprite graphics are far superior, and more flexible in use than conventional character graphics.
An important application of the graphics capabilities of any computer is graphs, charts and other similar displays. In Chapter 7 the principles of displaying gauges and meters are discussed, and the chapter goes on to show how bar charts and scientific graphs can be produced.
Chapter 8 introduces 'three-dimensional' displays with three-axis bar charts and circular graph plots which give an illusion of depth. The chapter goes on to look at the principles involved in producing perspective views.
In Chapter 9 the versatile sound generator of the Commodore 64 is explored. There are many features in the special sound chip used in this machine, and many useful hours can be spent trying out the different possibilities. The principles of setting up sound frequencies and waveforms are explained. The chip has a comprehensive ability to tailor the 'envelope' of sounds, and the techniques involved in producing some common sound effects are explained.
The sound chip can, of course, be persuaded to produce music, and in Chapter 10 the basic principles of music and the techniques for translating written music into data for playing a tune are explained. Later in the chapter a program is developed which allows the Commodore 64 to be used as a musical instrument that can be played directly on the keyboard.
Steve Money
Chapter One Introduction
One of the attractions of the modern personal or home computer is its ability to provide highly detailed graphics displays, usually in colour, and to produce a wide range of sounds. These facilities are, of course, very important for one of the main uses of home computers: playing various types of video game. The graphics capabilities, however, are not limited to use for games. They can also provide diagrams and displays for business and educational use. It is also possible to turn the computer into a form of automated drawing board, and (if a suitable printer or plotter is available) to produce quite acceptable drawings or diagrams on paper. Finally, of course, computer graphics displays may be used purely as an art form.
The Commodore 64 computer provides an excellent graphics display which can produce both low and high resolution pictures in colour. One disadvantage, however, is that the BASIC language provided as standard on this machine has virtually no commands to handle the high resolution graphics and sound facilities. This can mean that programming graphics may at first seem to be a complicated process. The techniques are not, however, all that difficult to master.
The actual graphics displays are controlled by a special display chip known as the VICII Video Interface Chip (which may also be referred to by the chip type number 6566 or 6567), and its functions are controlled by inserting appropriate data into its internal registers using the BASIC POKE and PEEK instructions. This is a very complex device, and has a total of 47 internal registers to control its various operating modes.
Video displays
Before going on to explore the display capabilities of the
2 Commodore 64 Graphics & Sound
Commodore 64, it might be as well to look at the basic techniques involved in producing computer displays.
All current home or personal computers make use of a televisiontype display to present text and graphics outputs. In most cases a domestic television receiver is used, and the signal from the computer is fed into the aerial input of the TV receiver. As far as the television set is concerned the signals from the computer appear to be just another television channel. Usually the output of the computer is set to an unused channel, generally channel 35, and the TV is tuned to this using one of the spare channel selector buttons.
Passing the computer video signal through the complete television receiver can cause some loss of sharpness on high resolution graphics displays, especially when they are in colour. An alternative arrangement, which can produce greatly improved results, makes use of a television monitor unit. Here the video signals from the computer are not converted into a broadcast-type television signal but are fed directly to the television display circuits. The special television monitor units usually employ much highergrade display tubes and circuits, which themselves allow a much sharper and more steady picture to be produced.
In a television receiver the picture on the screen is built up by sweeping a single dot of light across and down the screen. The dot moves rapidly from left to right, tracing out a series of horizontal lines across the screen. At the end of each sweep the spot moves almost instantaneously back to the left-hand side ready to trace out the next line. At the same time as it is moving across the screen the dot also moves slowly down the screen, so that each successive line is drawn just below the previous one. Every 1/ 25th second (1/ 30th second in America and Japan) the spot traces over the complete area of the screen.
The complete picture is traced out 25 (or 30) times per second.
This could cause a flickering effect, since the eye can just about detect changes in a scene occurring at this rate. To avoid such problems a system known as interlaced scanning is generally used. In this scheme the dot is scanned down the screen in 1/ 50th (1/ 60th) second but only traces out alternate scan lines. So on the first scan the dot might trace out all of the odd numbered lines of the complete picture, and on the next all the even lines, filling in the gaps between the lines of the first scan. The effect of this, as far as the viewer is concerned, is to increase the flicker rate to 50 (or 60) per second, making it undetectable; but the rate at which complete pictures are presented is still 25 (or 30) per second.
Introduction 3
If the brightness of the spot is varied as it traces over the screen then a picture made up of light and shaded areas is built up on the screen each time the spot completes a scan. In a colour television display three separate spots oflight are scanned simultaneously over the screen. One spot is red, and the others are green and blue respectively. On the screen the three dots are kept very close together so that, to the viewer, they appear to be a single point of light. The red, green and blue light from the three dots is effectively combined, so that the viewer sees a white dot if the three separate dots are lit simultaneously. By varying the relative brightness of the red, green and blue dots any desired colour of light may be produced at each point as the group of dots scans over the screen.
Text displays
Much of the output from a computer will consist of printed text displayed on the TV screen. For our computer display we can conveniently divide the screen up into a series of small rectangular areas, called symbol spaces, and in each of these rectangles we can arrange to display a single text symbol. The Commodore 64 screen display allows 25 rows of text to be displayed with 40 symbol spaces in each row. This allows a total of 1000 text characters, or roughly 150 words of text, to be displayed on the screen at a time.
If you examine text symbols displayed on a broadcast television picture, for instance during programme credit titles, you will see that each symbol is actually built up from a pattern of short horizontal lines and dots. For a computer display the symbol space on the screen is divided up into a matrix of individual dots. If you look very closely at the text displayed by your Commodore 64 you will see that each letter is built up from a pattern of dots. In fact for each symbol space the Commodore 64 uses 8 rows of dots with 8 dots in each row. By selectively lighting some of the dots and leaving the others dark the outline of the required text symbol can be picked out as shown in Fig. 1.1.
In order to display text the computer needs to know the patterns of dots for each of the symbols it will be required to display. Typically there will be capital and lower case letters, numbers, and a selection of punctuation and other signs. A typical character set might contain about 96 different symbols.
The usual method of storing the dot patterns is to use a memory chip similar to those used for the computer's main memory. A
4 Commodore 64 Graphics & Sound
Fig. 1.1. Display of a text svrnbol using a dot matrix.
memory chip consists of thousands of tiny electronic cells, each of which can be turned on or off. Each cell stores one item of data which is called a 'bit'. Each of these bits has two possible states which are called' I', when the cell is turned 'on', and '0' when the cell is 'off. Each cell may equally be used to indicate if a dot on the screen has to be lit (I) or dark (0). With 64 dots in each character pattern, and assuming a set of 128 different characters, then a total of 8192 bits of memory are required to store the complete set of dot patterns. Typically the memory is arranged as groups of 8 bits, called bytes or words, so the dot-pattern memory would have 1024 bytes which can easily be fitted into a single memory chip.
We could, of course, use a piece of the main computer memory to store the character dot patterns, but the problem here is that when the computer is turned off the contents of the memory are lost. To overcome this problem a special type of memory device is used. This chip has the data pattern written permanently into it when it is made, and the pattern is retained even when the power is turned off. We can read data from the memory but cannot alter what is stored in it, so the device is called a Read Only Memory or ROM. When the ROM is used to hold the dot patterns for producing character displays it is generally called a 'character generator' ROM. The character generator fitted to the Commodore 64 is quite complex, and it contains the dot patterns for two complete character sets with 256 symbols in each set.
Introduction 5
The display memory
The television picture is scanned 25 (or 30) times a second to produce a continuous display on the screen. This means that we have to trace out the dot patterns repeatedly, so the display circuits will need rapid access to data telling them what symbols are to be displayed. This involves the use of some sort of memory to store the information to be displayed. We could of course store all of the dot patterns for the screenful of text; but this would use up a lot of memory, so it is normal to allocate a number code, or character code, to each character in the available set and then store just the character codes for the text to be displayed. Since a 'memory word' of8 bits can have 256 different combinations, a single memory word is sufficient to define each text symbol to be displayed.
The Commodore 64, with its 40 X 25 screen format, can display 1000 symbols on the screen and will need 1000 words of memory to store the character codes of the text to be displayed. This memory is, in fact, just a section of the computer's main memory, and is referred to as the screen memory. At switch-on the screen memory is automatically located at addresses 1024 to 2023, but it is possible to move the area reserved as screen memory to other addresses if desired.
To produce the display, the VICI I chip reads the sequence of character codes for a row of text as the dot scans across the screen. Each character code is in turn used to call up a row of dots from the corresponding character dot pattern, and the dot on the screen is switched on and off in sympathy with the dot patterns as it sweeps across the screen. Each row of text is scanned eight times, with a different row of dots from the character pattern being called up for each scan line.
The general arrangement of the text display system is shown in Fig. 1.2.
Character graphics
In the early days of computers the only form of output available, either on a display screen or printed on paper, was in the form of text. However, enterprising programmers soon discovered they could produce crude pictures, graphs and charts by using the text symbols. Some symbols, such as the M and W, will appear darker than others, such as I, so by careful choice of the pattern of symbols printed on a page a picture can be built up. Ifviewed from a distance such a picture can look quite good!
6 Commodore 64 Graphics & Sound
Screen IWlIIOry
1 ••• bytes RRN
Colour
IWlIIOry
1 ... byte
RRM
Rddress 1 J Data Rddress
Sylilbol codes
VIC 11 Video chip
1 Dot data
~ Uideo out
Fig. 1.2. Display system for text and character graphics displays.
The next step in the development of graphics displays was the addition of special graphics symbols to the displayable character set. These symbols would consist of a selection of horizontal and vertical lines, shaded blocks and some specialised symbols such as the suit markers for playing cards. One of the early personal computers to use such a character set was the Commodore PET, and the Commodore 64 provides a similar set of graphics symbols. Some examples of these symbols are shown in Fig. 1.3.
h
Character generator RON
Fig. 1.3. Typical character graphics symbols on the Commodore 64.
The graphics symbols provide segments of lines which can be assembled together to produce remarkably effective displays, and they can be very useful in producing such things as bar charts. There are some inherent limitations to this method of producing graphics displays, since the special symbols can only be positioned in the standard matrix of character spaces on the screen, and some care is needed in designing the display layout.
Introduction 7
Mosaic graphics
With the normal text mode we can, by having the whole character space lit or dark, produce a graphics dot pattern which is 40 dots wide and 25 dots high. By selectively lighting the character spaces we could produce simple patterns. This is generally referred to as low resolution graphics. We talk of 'resolution' as a measure of the fineness of detail that can be produced in the picture, and it is quoted as the number of dots or picture elements that can be individually controlled across and down the screen. For the Commodore 64 text screen, using whole character spaces as picture elements, we would have a resolution of 40 dots across and 25 down which is usually abbreviated to 40 X 25.
One of the variations of character graphics, which is often used on home computers to provide low to medium resolution displays, is called mosaic graphics. Here the symbol space is divided up into a matrix of four or six blocks arranged in two columns. If the space is divided into four quarters, and each can be set on or off, then the original 40 X 25 text screen now becomes an 80 X 50 graphics matrix. Some typical mosaic symbols are shown in Fig. 1.4. The picture is built up in much the same way as when character graphics symbols are used ~ it's rather like assembling a jigsaw puzzle.
Fig. 1.4. Typical mosaic graphics symbols on the Commodore 64.
Using mosaic graphics symbols we can now selectively light 80 dots across the screen and 50 down the screen, which allows us to produce low to medium resolution graphics. Thus for mosaic graphics on the Commodore 64 the resolution would be 80 X 50.
Mosaic graphics provide greater flexibility in building up a picture when compared with the line and shape elements of the graphics character set. Within the limits of the 80 X 50 screen resolution any desired pattern can be produced, although the results will usually look rather crude compared with those that can be achieved by careful use of character graphics. The mosaic graphics symbols also provide a convenient method of filling in areas of colour on the screen.
8 Commodore 64 Graphics & Sound
Programmable characters
Normally the dot patterns for all the text and graphics symbols that can be displayed on the screen are held in a special character generator ROM. This device, however, is just a piece of memory as far as the computer is concerned. Therefore it should be possible for the VICII chip to display the data patterns stored in any part ofthe computer's working memory. Since we can write whatever we like into the working memory, we can produce customised characters by setting up the appropriate patterns of' I 's and 'O's in the memory and telling the VIC II chip to use them as character dot patterns.
The Commodore 64 does in fact allow us to use the computer memory and VICII chip in this way, so that any desired symbol pattern within an 8 X 8 character matrix can be set up in memory and displayed on the screen. When these user-defined symbols are being used by the VIC II chip, however, the normal character generator ROM is disabled. This means that if we want to use some of the standard symbols as well as the custom-designed ones, the required dot patterns have to be copied from the RO M into the main memory, or RAM as it is generally called. Now the standard character patterns will form part of the user-defined symbol set, and can be displayed on the screen. During this copying process we can, if we like, rearrange the order of the standard symbol set; or we might select characters from both standard and alternate character sets for use simultaneously.
The arrangement of the display system when user-defined graphics symbols are being used is as shown in Fig. 1.5.
Bit mapped graphics
The mosaic graphics scheme effectively provides us with a matrix of 80 X 50 dots over the screen on which we can build up a pattern. The text symbols themselves are built up from a matrix of8 X 8 dots, and if we could control each individual dot in every character space then much higher resolution displays become possible. This mode of graphics operation is available on the Commodore 64, and it is called bit mapped or high resolution graphics.
In the case of the Commodore 64 the number of dots across the screen will be 8 X 40 or 320 dots, since there are 40 symbol spaces each 8 dots wide. In the vertical direction we have 25 rows of symbols with 8 dots for each symbol, so the number of dots down the
Introduction 9
Colour IIII!lIIOry 1888 byte RAM
Address T
I Data
I -1.
Screen VIC 11
IIII!lIIOry Address Video ~
1888 bytes chip
RAM
'I Dot data
Character
patterns
Sylilbol codes in RAM Video out
Fig. 1.5. Display arrangement for user-defined text and graphics.
screen is 25 X 8 or 200. Thus for the high resolution mode the Commodore provides a graphics resolution of 320 X 200, which will allow quite detailed graphics displays to be produced.
In the character graphics mode an 8-bit code defines the symbol to be displayed, and 1000 bytes of memory are used to hold these codes. For high resolution graphics a different arrangement is required. Let us suppose that each dot on the 320 X 200 screen can be set either 'on' or 'off. We can store the state of the dot as a single data bit which may be either a 'I' or '0'. The screen itself contains 320 X 200 or 64000 dots altogether, so we are going to need rather a lot of memory to store the required information. Since there are 8 bits per word we can use each memory word to store the data for 8 adjacent dots on the screen. As a result, a total of 8000 words of memory are required to deal with the high resolution screen display.
To handle high resolution graphics the Commodore 64 switches from its normal text display to a different display mode called the Bit Mapped mode. In this mode the VIC II video chip calls up its display data from an 8000-word section of the RAM instead of from the normal IOOO-word screen memory area. In fact, this bit map area of memory is simply an extension of the memory area that would normally be used to store the dot patterns for user-defined symbols. The change in the display mode is controlled by changing the data in
10 Commodore 64 Graphics & Sound
two of the control registers of the video display chip, as we shall see in a later chapter.
One slight problem is that when the display mode is switched to high resolution graphics the computer will no longer display text symbols - in fact the normal text screen memory area is used for another purpose. We can, however, mix text with graphics by
~_~_--''-----_~~~~~~L_. _0 .cu.~_~ __ ..... J _
Introduction 11
To allow individual symbols to be set to any colour combination, a separate section of memory is used to hold the colour information for each character space on the text screen. This is known as the colour memory. It is the same size as the screen memory (1000 bytes) and laid out in the same way relative to the text display. The colour memory is located at a fixed position high in the memory address range. As each symbol code is written into the screen memory, a corresponding colour code goes into the colour memory and this determines the colour of the displayed symbol.
The border around the main display area on the screen can also be set to anyone of the sixteen colours, and this is controlled by one of the registers in the video chip. The background colour is also controlled by a register in the VIC II chip, and may be set to any of the sixteen available colours. For more colourful results it is possible to select another display mode which permits the use of four different background colours.
When we come to the high resolution mode the text screen memory is used to store the colour data. This means that the colour of all lit dots within a text character space will be the same, so the cotour resolution is only 40 X 25.
I n both high resolution and text modes we can select a multicolour mode which allows the use of four different colours within a symbol space. The penalty here is that the resolution is reduced to 160 X 200 but the advantage is much greater flexibility in the use of colour. This mode allows the production of multicoloured text or graphics symbols when the character graphics mode is in use.
Sprite graphics
A variation on the user-defined symbol is the 'sprite'. In some ways this is a bit like a larger version of the symbol, but with a dot array of 24 X 21. Like user-defined symbols, the dot patterns for sprites are held in the RAM, although not in the same area. Unlike symbols, the sprites are not placed on the screen by using PRINT or POKE commands, but are controlled directly by registers within the video chip. As a result a sprite can be placed anywhere on the screen.
The Commodore can handle up to eight different sprites and the video chip can detect when two sprites overlap, which can be useful for detecting hits and collisions in games programs. Sprites can also be arranged so that as one sprite passes another it will blank the other sprite, as if it were passing in front; alternatively it may be
12 Commodore 64 Graphics & Sound
blanked out by another sprite as if it had passed behind that sprite. These features can be particularly useful when producing graphics for arcade-style games, where several objects may be moving around the screen at the same time.
Like the text and graphics symbols, sprites can be multi-coloured, and can be turned on or off at will by placing appropriate data into the registers of the video display chip. In Chapter 6 we shall take a look at how sprites are created and controlled on the Commodore 64.
Sprites are entirely independent of the text and bit-mapped display systems, and are controlled by the VICII chip itself. The dot patterns making up a sprite are, however, stored in memory in much the same way as the dot patterns for user-defined symbols. It is possible to display sprites with either text or bit-mapped graphics displays with no difficulty.
The video display chip
The key to the Commodore 64 display capabilities is the VIC 11 video interface chip itself. This contains all the logic that controls the generation of the text and graphics displays. This chip works in parallel with the central processor chip in calling up data from the screen or bit map memories, and dot patterns from the character generator, and using them to produce the video signals needed to build up the picture on the TV screen. The computer itself has to put the required data into the screen, colour, and bit map memories, and then leaves the VICII chip to get on with producing the display on the screen. While the computer goes on executing the rest of its program, the VICII chip steals small amounts of time from the central processor when it needs access to the computer memory, but this has little effect on the execution of the computer's main program task.
The VI C II chip's addressing system limits its access to the main computer memory so that only one 16k byte bank of the main memory is seen by the VI C II chip at any time. Normally this will be the section of memory from address 0 up to address 16383. It is possible to alter the section of memory accessed by the video chip to anyone of the four possible 16k byte banks of memory available in the 64k main memory of the computer. For most purposes it is best to leave the VIC II chip with its normal access to the first 16k block of memory.
Introduction 13
Sound generation
The Commodore 64 has quite a versatile sound generating capability. This is also controlled by a special chip called the Sound Interface Device or SID chip, which is sometimes referred to by its type number 6581.
The sound chip provides three independent sound generator channels, and each of these can be controlled in frequency and amplitude. There are also envelope generators to shape the sound, and a filter system which allows even more complex sound processing.
In Chapters 9 and IO we shall explore some of the aspects of the sound chip and see how it can be used to produce sound effects and to play music.
Chapter Two
Character Graphics
Let us make a start by looking at the text and character graphics display mode of the Commodore 64. As we saw in Chapter 1 the basic text display mode provides 25 rows of text symbols with 40 symbols in a row, and this is the mode which will be selected when you switch on the computer.
The data for the text display is held in a screen memory area, which takes up 1000 words of the main computer memory. This character memory normally occupies memory locations 1024 to 2023, but it is possible to move it to any convenient location within the 16k memory block that is being accessed by the video display chip.
The 1000-word memory area used for text contains one word for each displayed symbol, and this memory word contains a character code, with a value from 0 to 255, corresponding to the character to be displayed on the screen. An important point to note here is that the character code stored in the screen memory is not the same as the ASCII character code used in a PRINT statement. The layout of the memory is arranged so that successive characters across a text row are stored in 40 sequential memory locations, and are followed by the codes for the symbols in the next display row. Thus the symbol at the top left corner of the screen has its code stored in memory location 1024, and the one at the top right is held in memory location 1063. The layout of the screen memory is as shown in Fig. 2.1.
Placing text on the screen
The Commodore 64 has a text cursor which indicates to the machine, and the user, where the next symbol is to be displayed on the screen. This is normally shown as a flashing block.
We can control the position of the cursor by using various keys on
Character Graphics 15
1824 1864 11114 1144 1184 1224 1264 13114 1344 1384 1424 1464 15114 1544 1584 1624 1664 17114 1744 1784 1824 1864 19114 1944 1984
Fig. 2.1. The layout of the screen memory in the Commodore 64.
the keyboard. If you press the key in the top row marked CLRI HOME the cursor will immediately move to the top left corner of the screen. This is the HOME operation. Note that the text already being displayed on the screen is unaffected. If you hold down the SHIFT key while you press the CLRI HOME key a different action occurs. Now any text that was being displayed is cleared off the screen, and the cursor once again moves to the top left corner. This is the CLR (screen clear) operation. A point to note here is that the statement CLR in BASIC has a different function, and should not be confused with screen clear.
At the bottom right of the keyboard are two adjacent keys with arrows on them. One has arrows pointing up and down, and it moves the cursor up and down the screen. The other has arrows pointing left and right, and it controls left I right movement of the cursor.
N ow if you press the cursor up I down key the cursor will move down the screen one row at a time. Pressing the left I right cursor key moves the cursor to the right. To move the cursor up the screen the SHIFT key must be held down while the cursor up I down key is pressed. Similarly using the SHIFT key with the left I right cursor key moves the cursor to the left.
At the start of a program it is useful if we clear the screen display and place the cursor at the top left corner. This can be achieved inside the program by using the CLRI HOME key as if it were a normal letter key, and the result is placed between quotes after a PRINT command as follows:
11163 11113 1143 1183 1223 1263 13113 1343 1383 1423 1463 15113 1543 1583 1623 1663 11113 1743 1183 1823 1863 19113 1943 1983 2823
16 Commodore 64 Graphics & Sound
l~~ PRINT "[SHIFT CLR]"
The required control code is keyed in by using the SHIFT and CLR keys together. Here the key names have been included between square brackets to indicate that these are the names of the keys to be pressed and not an ordinary text string.
If you just want to move the cursor to the top right corner, without clearing the screen, then the CLR/ HOME key must be used by itself as follows:
l~~ PRINT ''[HOME]''
The cursor can be moved up, down, left or right by using the cursor arrow keys, either with or without SHIFT, in a PRINT statement in the same way.
Each of the cursor control keys does in fact produce a symbol code, and this appears on screen between the quote symbols when you type in the PRINT statement. This symbol will also appear in the program listing; however, when the instruction is executed by the computer the cursor moves, but the special symbol is not displayed on the screen. These special symbols are important, however, because they show that there are cursor control codes in the character string. Thus the CLR key produces a heart-shaped symbol and the HOME key produces an S symbol in blue on a light blue background. The other cursor keys also produce unique symbols and these are shown in Fig. 2.2. A point to note is that the cursor control symbols are not written to the screen when the program is actually run, and they do not take up any space in the screen memory.
Each of the cursor control keys does in fact produce a particular character code and an alternative way of placing them in a PRINT statement is to use the form
l~~ PRINT CHR$(N)
where N is a number from 0 to 255 corresponding to the ASCII code for the cursor move that you want to execute. These ASCII code numbers for the various cursor control actions are listed in Fig. 2.2. Thus if you want to clear the screen you could use
1~~PRINT CHR$(l47)
To move the cursor to any desired position on the screen a series of cursor shift codes can simply be included in the PRINT statement before the text or graphics symbols, or even between them. It is usually best to start off with a CLR or HOME command at the start
Character Graphics 17
of the program so that you know where the cursor is before starting
to move it.
t<. e: 1::1 Sh i f t ASCII Lis· t
K e: 1::1 cClde: Sym b o L
CRSR 1:\ NCI 17 t!l
CR::·R IJ Y e: s· 145 0
CF::5R R No 29 I
C:R5R L '{ e: :E. 157 II
HO~1E NCI 19 IE]
CLF~ "{ e: ::. 147 C Fig. 2.2. The keys, character codes and listing symbols for cursor control on the Commodore 64.
Simulating PRINT AT operations
Some personal computers have a PRINT AT statement included in their BASIC language, but in the case of the Commodore 64 this very useful command is not available. We can, however, devise alternative schemes which will produce the same results as a PRINT AT command.
First let us see what PRINT AT does. The statement usually takes the form
PRINT AT R,C;"Text"
where Rand C are numbers which define the row and column position on the screen where printing is to start. Sometimes Rand C may be replaced by a single number which indicates the number of the character space starting from the top left corner and working across each row and down the screen. Ofthese forms the R,C version is probably easier to understand and use, although the version with a single variable N is easier to implement on the Commodore 64. In this book the R,C form of position co-ordinates will be used. The
18 Commodore 64 Graphics & Sound
range of Rand C and their relationship to the display area on the screen are shown in Fig. 2.3.
COLUMN
39
ROW
, I ' , I ' I , I I ' ! ! f I ' , I . I
r i : , , I i , f ' I I
, f ! I I i f , I I ,
I ' , , i f ,
i f 1 ' I f I , I
! I I I I I ! I I I I
I I i I I I i I
I ; 1 f
, I ; I I
, I I , I . i I
, ! f , I I
'j_ L1 ! ,
LL i [ i l . i I i I
I I I I I I! ! I I I I I !
I ! I ! I ! ! I I , I I I
! I ! ! ! , I I I ' I
, I , I I I
, , I I I I
I I I I
I i , I
f I i
i I , i
I I I I I I
I ' I I !
I I
L.L I I 24
Fig. 2.3. Screen layout for text displays showing the row and column numbering.
One simple approach to producing a PRINT AT operation is to start by using HOME to place the cursor at row 0 column O. To select the required column, a count loop is set up running from 1 to C, where C is the column number. On each pass through the loop, a single CRSR RIGHT code is printed, moving the cursor one space to the right. At the end of the loop the cursor is at the required column. A problem occurs if the required position is in column O. To deal with this a test for C=O is included before the loop and if C=O then the loop is bypassed and the program jumps to the statement number following the loop. A similar process is then used to set up the required row position. This gives a routine on the following lines:
5~~ IF C=~ THEN 53~ 51~ FOR 1=1 TO C
52~ PRINT CHR$(29);:NEXT 53~ IF R=~ THEN 56~
54~ FOR 1=1 TO R
55~ PRINT CHR$(17);:NEXT 56~ RETURN
Character Graphics 19
Here a subroutine has been used, and after C and R have been given values the cursor is positioned by using GOSUB5~~.
Although the Commodore 64 doesn't have a PRINT AT command it does keep track of the current position of the cursor on the screen. This information is stored in memory locations 209, 210 and 211.
The column number from 0 to 39 is held in location 211. If we want to know the current column position of the cursor this can be done by using
C = PEEK(211)
If we want to place the cursor at a particular column position across the screen this can be done by POKEing the column number into memory location 211 as follows:
POKE 211,C
where C is the column number from 0 to 39.
When we come to deal with the row number, things are a little more complicated. Here the Commodore 64 stores the memory address where the first character in the row will be stored in the screen memory. Since the screen memory starts at location 1024, the row address for the first row will be 1024, 1064 for the next row, and so on with each row adding 40 to the address. Thus the row address is given by
RI = 1024 + 40*R
where R is the row number from 0 to 24. This gives a number between 1024 and 1984, which is too big to fit into a single memory word, so the computer uses two words (209 and 210) to store this number. The storage in memory is in binary form, and one word (209) represents numbers up to 256 while the second, 210, represents the number of 256s. To find the number that goes into location 210 we take R I, divide by 256, and discard the fractional part as follows:
R2 = INT(R 1/256)
N ow to find the remainder that has to go into location 209 we can use the following:
R3 = RI - 256*R2
Thus to set the cursor locations in memory we can use the following little subroutine:
20 Commodore 64 Graphics & Sound
5~~ POKE211,C
510 Rl = SM + 40*R 52~ R2 = INT( R 1/256) 53~ POKE21~,R2
54~ POKE209,RI-256*R2 55~ RETURN
Here the variable S M (start of screen memory) has been included in case you have moved the position of the screen memory from its normal address of 1024.
If we want to read the cursor position this can be done by PEEKing the locations 209 to 211, and then calculating Rand Cas follows:
C=PEEK(211)
R=(256*PEEK(21~)+ PEEK(209)-1~24) / 4~
In this calculation 1024 could be replaced by SM if the screen memory start address was likely to be different from 1024.
Another way of setting Rand C
There is a useful machine code routine ill the Commodore 64 computer's own operating system which we can use to set up the cursor position on the screen. This accepts the row and column numbers, and then automatically sets up the cursor position data in locations 209 to 211.
This routine requires that we transfer data to the A, X, and Y registers of the processor and then call the machine code subroutine to set up the cursor position. The data is actually transferred into three memory locations as follows:
A register = location 780 X register = location 781 Y register = location 782
The data is transferred by simply POKEing the numbers into the appropriate memory locations as follows:
POKE 78~,~ POKE 781,R POKE 782,C SYS65520
Character Graphics 21
The SYS statement calls the machine code subroutine which starts at memory location 65520. When the cursor has been positioned, the BASIC program is resumed at the next line number. This routine has the advantage that it uses Rand C as direct inputs and automatically takes care ofthe actual address of the screen memory.
Drawing lines
For many graphics applications we shall want to draw lines on the screen, perhaps to separate the columns of a table of figures, or to make up simple diagrams. This can be done by using the graphics symbols containing line elements.
For horizontal lines there are eight basic symbols, each containing a horizontal line across the symbol space in one of the row positions, and these are shown in Fig. 2.4 together with their ASCII and screen memory codes. By using the appropriate symbol, and repeating it across a text row as required, we can draw a horizontal line at any desired position on the screen. The limitation is that the line must start and end at the edge of one of the character columns.
~5CII SCRN CODE COC~E
163
99
101
69
100
66
67
D U E]
8
~SCII SCRN CCIDE CODE
96
64
B g
b]
D
Fig. 2.4. The horizontal line segment symbols and their codes.
102
70
Vertical lines can be handled by another set of eight graphics, each with a line of dots running from top to bottom in one of the columns of the symbol matrix. Here we can draw vertical lines by PRINTing the symbols one above the other on the screen. This can be done by adding 'cursor left' and 'cursor down' control codes after each symbol to move the cursor to the correct position for the next
114
62
164
100
22 Commodore 64 Graphics & Sound
graphics symbol. These symbols, and their ASCII and screen codes,
are shown in Fig. 2.5.
FlSCII SCRN FlSCII SCRt-~
CODE CODE COC'E COC"IE
165 11211 D 125 93 rn
116 64- [] 11214- 72 OJ
11213 71 ITJ 121 69 0
96 66 ITJ 167 11213 D
Fig. 2.5. The vertical line segment symbols and their codes. When we come to sloping lines, things get a little more complicated. If you print the set of horizontal line symbols one after another, starting with the symbol with a line at the top of the symbols space, and with each successive line one row of dots lower, this will give a stepped line that slopes down the screen to the right. If you want the line to slope upwards, the symbols are simply printed in reverse order. After eight symbols have been printed, a 'cursor up or down' move is required, and then the sequence starts again to continue the sloping line. The same basic idea can also be applied using the vertical line segments to generate stepped lines that slope a little to the right or left of vertical. Here cursor moves are needed after each symbol, and an extra one is needed after every eight symbols.
Lines can be made to slope at steeper angles by using alternate symbols from the set of eight. Thus you might use the symbols with the line drawn in rows I, 3, 5 and 7. For extended lines the cursor shift to the next row or column will need to be made after only four symbols have been printed. The possible variations of this technique are numerous, and it is worthwhile experimenting to see the range of different lines that can be produced by just using the horizontal and vertical line segment symbols.
There are two symbols to deal with diagonal lines, and these are shown in Fig. 2.6. When drawing a line using these symbols, one or more cursor control codes will be needed after each graphics symbol
Character Graphics 23
~.SCII SCREEN SYMBOL
CODE CODE
109 77 [SJ
110 78 0
118 86 ~
Fig. 2.6. The diagonal line symbols and their codes. to place the cursor in the correct position for the next section ofline to be printed. A third symbol gives crossed lines.
Crossing lines and junctions present something of a problem.
There are four right-angle T junctions and eight corner shape symbols. These allow crossovers and junctions to be made at the corners or middle of character spaces. There are also some curved corner shapes.
The graphics symbols may be obtained from the keyboard by holding down either the SHIFT or LOGO keys while a letter key is pressed. The LOGO key is the one at the bottom right of the keyboard, with the Commodore trademark printed on it. The actual graphics symbols are printed on the front face of the key. You will note that there are two symbols on each key. To select the right-hand symbol use the letter key with the SHIFT key; for the left-hand symbol use the letter key with the LOGO key.
This set of line symbols can give remarkable flexibility in building up a diagram, but some care is needed in planning the layout of the diagram to ensure it will fit in with the available symbols. The basic technique involved in producing a picture on the screen is similar to that of building up a jigsaw puzzle.
Reverse video
You will have noticed that some of the symbols displayed when you type in a cursor control code are shown in reverse video. This means the dots that would normally be lit are dark, and those that would normally be dark are lit. Thus the HOME key produces an S symbol in dark blue on a light blue background.
24 Commodore 64 Graphics & Sound
Any symbol or set of symbols can be displayed in this fashion by using [CTRL 9] to select the RVS ON mode, where all symbols typed in will be displayed in reverse video form. To return to the normal display mode [CTRL ~] (RVS OFF) is used. Note that it is possible to have just one or two symbols in a string in reverse video by just switching R VS on for the selected symbols. At the end of a PRINT line the R VS ON mode is automatically turned off.
Reverse video is useful with the mosaic block symbols since several patterns do not appear to be available. If you examine the symbol pattern, however, you will see that the missing symbols can be generated by using R VS with those that are directly available from the keyboard. The ASCII codes and listing symbols for the RVS ON and RVS OFF commands are shown in Fig. 2.7.
Key:. used
Flction
Fl5CII
cOde
List
s y m bo L
CTRL 9 RI...J5 ON
16
CTRL 12' RI...J5 OFF
146
Fig. 2.7. Thekeys, character codes and listingsymbolsforswitchingtoandfrom the inverse video symbols.
Making new characters
So far we have produced drawings and pictures or text displays by using the character sets programmed into the character generator ROM built into the Commodore 64. For most purposes these may well be perfectly adequate, but there will be times when we may want to display some special symbols that are not available in the standard set. As an example, we might (in a mathematical program) want to introduce Greek letters or special signs, such as the integration and square root symbols.
For producing text displays in other languages we may require accented letters, or in the case of Russian we might use the Cyrillic alphabet. Once again, there is a need for some custom-designed symbols.
In graphics we have already seen that there are some limitations in using the standard set of graphics symbols. Here it might be useful to have some new graphics symbols to suit the needs of the particular
Character Graphics 25
type of diagram we want to produce. Examples here might be the inclusion of special symbols, such as those used in electrical and other types of engineering drawing.
If, instead of taking the character dot patterns from the character generator ROM, we could persuade the VIC11 chip to use dot patterns from the RAM area of memory, then we could write in our own dot patterns to define the shapes of the displayed symbols. In fact this facility for producing user-defined text and graphics symbols is provided on the Commodore 64.
The character generator ROM is actually located at addresses starting at 53248 in the memory address map of the computer. As far as the VICll chip is concerned, however, the ROM appears to be located at addresses 4096 to 6143 in memory. This is because the video chip only looks at a 16k byte block of memory at any time. If the alternative (lower case) character set is in use then the ROM appears at locations 6144 to 8191. In fact there is also a section of RAM at this address, but it is disabled when the video chip calls up dot patterns for a symbol, and the data is read from the ROM instead. The address that the VICll chip looks at for its dot pattern data can, however, be altered, and if this is done the dot patterns will actually be read from the RAM itself. The address looked at is controlled by one of the registers in the video chip, so by changing the data in this register we can pick up our own set of symbol dot patterns for display on the screen.
The character data address register in the video chip is at memory location 53272, and the lower four data bits of the word are used to select a 2k block of memory where the video chip will read data for its symbol patterns. The number we feed into this register is from 0 to 14, and is always even. In fact, this number is simply the number of 1 k bytes to the start of the character pattern memory, and will be either 0,2,4,6,8, 10, 12 or 14. Note that the video chip only looks at one 16k bank of memory at a time, so there is no need for addresses higher than 16k.
If we select blocks 4 or 6, the normal ROM will be used. Block 0 must be avoided, since this part of the memory is used by the computer itself to store system variables, and if overwritten will cause complete chaos. Similarly, block 2 should be avoided, since this is where the BASIC program starts. The safest place to start is at 12k (12288), and this can be done by POKEing 12 into location 53272. A point to watch is that the upper four bits of this register in (he VIC chip control the location of the screen memory, so you do not want to disturb them. The solution is to use the following
26 Commodore 64 Graphics & Sound
command:
POKE 53272, (PEEK(53272)ANDI5)OR A
where A is the dot pattern start address in k bytes. Here the AND operation sets all the lower four bits at 0 without affecting the upper four bits. Then the OR operation sets the lower four bits to their new value, again without affecting the upper four bits.
Copying the ROM character set
If we simply shift the location of the dot pattern memory being used by the video chip, and then PRINT characters to the screen, the result will be random patterns of dots. This is because the area of RAM that we have defined as the character generator contains random data: we haven't programmed any data into it. Now for most programs we shall still want to use some of the standard symbol set, so the first thing we need to do is to copy the character dot pattern data from the character generator ROM into the area of RAM we are going to use as a character generator.
Normally if we tried PEEKing the addresses at which the ROM
appears to the VIC chip we would simply get the contents of the RAM at these addresses. This is because the ROM is normally disabled unless the VIC chip is addressing it. To switch on the ROM so the CPU can read data from it we need to change a data bit in location I of the memory.
An important point, however, is that memory address locations 0 and I in the Commodore 64 do in fact call up two registers in the CPU itself. These registers are used in interrupt operations such as the one involved in scanning the keyboard. To avoid problems it is advisable to disable the keyboard and other interrupts while you are copying data from the character generator ROM. This can be done by using
3PP POKE 56334, PEEK(56334) AND 254
With the interrupt system disabled we can now use register I to switch on the character generator ROM. This is done by resetting bit 2 of the word, which has a value of 4, by using the POKE operation
31p POKE l,PEEK( I) AND 251
When the ROM is enabled, it will appear to the CPU at addresses from 53248 to 57343, and all we need to do at this stage is set up a
Character Graphics 27
simple loop operation to copy data words from the ROM addresses into the area of RAM we are going to use for our user-defined symbols. This can be done as follows:
32~ FORJ=~T04~95
33~ POKEJ+ 12288,PEEK(53248+ J) 34~ NEXT
After copying the dot data the ROM can be disabled by using 35~ POKE I,PEEK(l)OR 4
and then the interrupts reactivated by using 36~ POKE 56334,PEEK(56334) OR 1
At this stage we now have all the standard dot patterns in memory, starting at location 12288, and if we now switch the character memory address of the VICII chip to 12288 by using
37~ POKE 73272, (PEEK(53272)AND24~)ORI2
then the computer will appear to behave normally as we type in data or PRINT characters to the screen.
Like the other text characters, each of the user-defined symbols has eight rows with eight dots in each row, and each dot may be either 'on' or 'off. In the computer, each memory word has eight bits, each of which may be set as a 1 (on) or a 0 (off), so it is convenient to store one row of dots from the character pattern into one memory word. The eight rows of dots making up the character are then stored in eight successive memory words. If we want to create a new symbol then the new dot pattern must be written into a set of eight memory locations in the user-defined graphics area of the memory, replacing one of the standard dot patterns that we have just copied from ROM.
Of course we may just want to rearrange the existing set of symbols, and this can be done by copying the required dot patterns from the ROM into the RAM at a different position in the code table. We could also mix symbols from the two sets that are available in the ROM. The second set of symbols is located at addresses 2048 higher in the ROM, that is from 55296 upward.
Programming a new symbol
The first step in creating a new symbol is to work out the dot pattern
28 Commodore 64 Graphics & Sound
that is needed to build up the symbol. This can easily be done by drawing a grid with eight rows of squares and eight squares in each row, as shown in Fig. 2.8. Squares are then shaded in to pick out the shape of the desired symbol.
128 64 32 16 8 4 2 1 DATA BIT PATTERN DECIMAL
111111111 i27
II !I 1 II II II II 1 33
II II IJ 1 II II II II 16
IJ II II II 1 II II II 8
II II II 1 II II II II 16
II II 1 II II II IJ 1 33
II 1 1 1 1 1 1 1 127
II II II II II II II II II Fig. 2.8. Dot matrix and data coding for a user-defined symbol.
Once the dot pattern has been worked out, the next step is to work out the numbers that have to be stored in the memory. Figure 2.8 shows the layout of a typical user-defined graphics character. Here the pattern is of the Greek letter sigma. In the diagram, the black dots are in the foreground colour and will be represented by 'l's in the computer word, while the remaining dots are in background colour and will be 'O's. Each data bit in the word has a numerical value starting with I for the right-hand end bit, and working up in the sequence 2, 4, 8, 16 and so on for successive bits as we move to the left through the data word. The actual value of each bit is shown at the top of the diagram.
To find the decimal number that has to be fed into the computer, we can simply add together the numerical values for all the bits in the word that are set at '1'. This gives a number in the range 0 to 255.
To set up the dot pattern in memory we now have to write the sequence of eight numbers into eight successive memory locations, and this can easily be done by using a series of POKE commands as follows:
5~~ FOR K = ~ TO 7 51~ POKE A+K,D(K) 52~ NEXT K
where A is the starting address in the computer memory for the dot
Character Graphics 29
pattern of the character we are creating, and 0 is an array of eight numbers representing the dot pattern.
All we have to do now is put the data words into the right place in memory. The first step here is to decide what screen code you want the new symbol to have. Let us say that this is some variable C. Now we have to pick up the memory address C*8 words up from the start of the character RAM area, and we write our eight data words into the next eight successive memory locations. Suppose we wanted to replace the standard character 'C. This has a screen code of 3, so the dot data words would go into memory starting at location 12288+(3*8) = 12312, and going up to location 12319.
100 REM CREATING A NEW SYMBOL
105 REM SELECT UPPER CASE SYMBOLS 110 PRINT CHR$(142)
115 REM PROTECT NEW CHARACTER MEMORY 120 POKE52,48:POKE56,48
130 UG=1228S:CG=53248
135 REM TURN OFF KEYBOARD INTERRUPT 140 POKE56334,PEEK(56334)AND254
145 REM ENABLE CHARACTER ROM
150 POKE1,PEEK(1)AND251
155 REM COpy CHARACTER SET
160 FORK=0 TO 2047
170 POKE UG+K,PEEK(CG+K)
1:30 HE;:-::T
185 REM DISABLE CHARACTER ROM 190 POKE1,PEEK(1)OR4
195 REM RESTORE KEYBOARD INTERRUPT 200 POKE56334,PEEK(56334)ORl
205 REM SELECT USER GRAPHICS RAM
218 POKE53272.(PEEK(53272)AND240)+12 220 CC==l
225 REM LOAD NEW SYMBOL DOT PATTERN 2:30 FOF. ..T::::>:I TO 7
240 READ A:POKE UG+8*CC+],A 250 ~lE::<:T
260 DATA 127,33.16,8,16.33.127,0 270 PRINT CHR$(147)
280 FOR N=64 TO 80
290 PR rr-H CHF.::t un .;" ";
Fig. 2.9. Program demonstrating copying of the character set and creation of a user-defined symbol.
30 Commodore 64 Graphics & Sound
I n Fig. 2.8 the dot pattern for the Greek letter sigma is shown and alongside it are the required data words that will represent the dot pattern in RAM. The program listed in Fig. 2.9 demonstrates how this new character can be set up in the user graphics area and used on the display screen.
In line II ~ the upper case character set is selected. This is the normal symbol set with the graphics symbols. In line 12~ the character RAM area of memory is protected from BASIC by altering the top address available to BASIC programs. Lines 14~ and l5~ turn off keyboard interrupts and enable the character generator ROM so that we can copy its dot patterns. The complete set of character dot patterns is then copied into the user-defined character RAM area of memory. Next the ROM is disabled and the interru pt restored.
Line 21~ now selects the user graphics RAM dot patterns for use by the display. The new pattern for the sigma symbol is then POKEd into the character RAM in place of the dot pattern for the A symbol. Finally the screen is cleared and the set of letter symbols is printed out. You will notice that the A is now displayed as a sigma. When the program completes, the word READY will also contain the sigma symbol instead of an A and in fact all As will be displayed as sigmas while the user graphics RAM is selected. The new dot pattern will remain in the user-defined graphics set as long as the computer remains switched on. Of course you can define as many new symbols as you like, and use them to replace any of the existing sym bois in the standard character set.
Chapter Three
High Resolution
Graphics
So far the pictures on the screen have been produced by printing patterns of graphics symbols. As we have seen, there are limitations in using the standard set of graphics symbols, but these can often be overcome by creating user-defined symbols. The lack of flexibility of character graphics becomes important when we want to draw shapes such as circles. Much greater flexilibity in drawing shapes is possible by making use of the high resolution bit-mapped graphics mode provided on the Commodore 64. This gives a screen resolution of 320 by 200 dots and permits the state of each dot to be individually controlled.
One penalty that has to be paid for this extra flexibility is loss of memory space: the bit map display mode uses up an 8000-word area of memory compared with only 1000 words for the character graphics mode. With some 30k of memory available, this need not be a serious problem. Another and perhaps more significant disadvantage is that the normal PRINT command no longer produces a text display when bit-mapped graphics are selected. As a result, the combination of text and graphics on the high resolution displays becomes a more complex operation than it is with the simple character graphics display.
Memory allocation
When the bit map graphics mode of the Commodore 64 is selected it uses an 8000-word section of memory, which starts at the same address as the user graphics memory. As with the user-defined graphics memory, the start address of the memory used in the bit map mode has to be set up in the VIC 11 chip. Here the start address must be chosen to avoid conflict with memory used by the processor itself, or by the BASIC interpreter. One possible start address for the
32 Commodore 64 Graphics & Sound
bit mapped display memory is at a point 8k (8192) bytes up from the start of memory.
The choice of memory position is rather more limited than for the user-defined symbol set, because now we have to fit in an 8000-word block of memory which must fall within the 16k bank of memory being accessed by the VIC II chip. If you set the bit map at an address between 8k and 16k then part of the map will fall outside this 16k block, and will not be displayed. The section of memory used for the bit map mode is governed by register 24 in the VI C 11 chip. This is in fact the same register that specified the start of the user-defined character patterns in memory, and the start address may be set in steps of 2k bytes at a time.
To set the bit map memory to the required position we need to POKE a new number into register 24 of the video chip, which is at memory address 53272. This register has only 3 bits (bits 1,2 and 3) allocated for setting the bit map address; the remaining bits control other functions. A point to note is that the least significant bit of the register is not used; this is why the selected memory start address increases in steps of 2k bytes. At switch-on the bit map address bits are usually set at O. To avoid altering the other bits in the register it is best to PEEK the contents, then add in the memory address bits and POKE the result back into the register. This can be done by using
POKE53272,PEEK(53272) OR MS
where M S is the bit map start address in kilobytes. So to place the bit map at address 8192 (8k), MS would have the value 8. If the address in the register might have altered from 0, perhaps because you have been using custom symbols, then it is as well to AND the result of the PEEK with 240 before adding in the bit map address. This will set the lower four bits of the register to O.
It is a good idea to protect the bit map area of memory from BASIC. This can be done by the following two POKE operations:
POKE 52,32 POKE 56, 32
These may be included as the first instructions of your BASIC program, or they may be carried out directly by just typing them in without line numbers. The data to be POKEd into locations 52 and 56 will be the top address you want BASIC to use in kilobytes, multiplied by 4. If the number POKEd into these locations is 32, BASIC will 'think' that the top of the available memory is at 8192, which will leave you about 6000 bytes of memory for your BASIC program and its variables.
High Resolution Graphics 33
Setting the bit map mode
Once you have placed the display memory in an appropriate position, the next step in achieving bit-mapped high-resolution graphics is to select the bit map mode. This is done by setting a control bit in register 17 of the video display chip. This register is located at memory address 53265, and the particular bit we need to set is bit 5, which has a numerical value of 32.
The control register which governs the bit map mode also controls other functions within the video display chip, so we want to alter the state of bit 5 without altering any of the other bits in the register. To discover what is already in the register we can use PEEK(53265). If we want to set bit 5, the simplest approach is to OR the contents of the register with the number 32. For the number 32 the only bit which is at I will be bit 5, and this is the only bit that will be affected by the OR function. So to select the bit map mode we can use the statement
POKE 53265,PEEK(53265) OR 32
If we want to switch off the bit-mapped display mode and return to normal text displays then we need to reset bit 5 of the control register to O. This can be done by using the AND function. In this case the contents of the register are ANDed with a mask pattern word where all bits except bit 5 are set at '1'. This pattern is produced by the number 255-32, or 223, and the required statement becomes
POKE 53265,PEEK(53265) AND 223
This is how the mode would be switched during a program. Another and perhaps easier way of restoring the normal display mode after the program has stopped is to hold down the RUN / STOP key and press the RESTORE key. If you want to switch back and forth in a program, however, the POKE commands must be used.
Clearing the screen
When the bit map mode has been selected the normal 'screen clear' function of the text mode no longer operates, so a different technique for clearing the display has to be used. Remember that in the bit map mode the state of the individual bits in the words of the display memory determines whether the dots are turned on or not. To clear the screen we simply have to set all the words in the bit map
34 Commodore 64 Graphics & Sound
memory to zero. This can be done in BASIC by using a simple loop which POKEs zero successively into each location of the bit map display memory. This might be done as follows:
l~~ BM = 8192
11~ FOR N=BM TO BM+8~~~ 12~ POKE N,~
13~ NEXT
Here the loop starts at the start address of the bit map (BM) and steps through the next 8000 memory locations placing 0 into each one.
When you have cleared the display memory there will still be a random selection of coloured blocks on the screen. This is because when the bit map mode is selected the text display screen memory is used to control the colour of the dots on the bit-mapped screen. We shall be looking at colour more closely in the next chapter. For the moment we shall set the background colour to blue and the foreground colour to white. To do this we simply have to POKE the number 22 into every location of the text screen memory.
Setting individual dots
To draw effectively on the high resolution screen the first thing we need to be able to do is to set individual dots 'on' or 'off as required. To do this we need to POKE a 1 into the appropriate bit of one of the words in the display memory. The problem here is to convert from a set of X and Y co-ordinates to a word address and a bit pattern to go into that word.
It is convenient to arrange the X and Y co-ordinate system as shown in Fig. 3.1. Here the value of X increases from 0 at the left edge of the screen to 319 at the right edge; Y starts at 0 at the top of the screen and increases to 199 at the bottom of the screen.
The bit map memory is arranged in what seems at first to be a rather strange layout. One might expect the words to be allocated along each row of dots on the screen, with each word representing eight successive dots along the line. In fact, the memory is arranged so that the eight rows of each character space are stored successively in memory, and these sets of eight rows of dots are taken in sequence across the screen as shown in Fig. 3.2.
The lines across the screen are effectively stacked in sets of 8, so that after the first 8 lines have been stored the next memory location
High Resolution Graphics 35
)(=8 Y=8
)1=319 Y=8
X=319 \'=199
X=8 '1'=199
Fig. 3.1. Layout of the X and Y co-ordinates on the bit map screen.
is at the start of the next block of 8 lines. This arrangement is in fact the same as that used for the user-defined graphics patterns. There are some advantages to this arrangement when text has to be added to a bit-mapped picture, as we shall see later.
bvteO byte8 byte16 byte304 byte312
byte1 byte9 byte17 byte3€'5 byte~313
byte2 byte10 byte18 byte3€'6 byte314
b-yte3 byte11 byte19 byte307 byte315
byte4 byte12 byte2(' byte308 byte316
byte5 byte13 byte21 byte309 byte317
byte6 byte14 byte22 byte310 byte318
by'te7 byte15 byte23 byte311 byte319
byte32':J byte:328 byte336 byte624 byte632
byte321 byte329 byte337 byte625 byte633
byte322 byte330 byte338 byte626 byte634 Fig. 3.2. Layout of the bit map screen data in the computer memory.
Let us start with the X direction. Each successive word across a single line is spaced 8 locations on from the last, so we can find part of the address by dividing X by 8 and taking the integer value. Each group of 8 scan lines is equivalent to a row of text symbols, and the next step is to find out which row we are in. This can be done by simply dividing Y by 8 and then taking the integer to remove any fractional parts. Now in each row there are 8 scan lines with a total of
36 Commodore 64 Graphics & Sound
40 X 8 or 320 individual words. So the second block of 8 lines starts 320 memory locations from the start of memory. If we multiply the row number by 320 this gives the start address for the block of 320 memory locations that we want to access. The next step is to find out which scan line of the set of 8 the dot to be set is in. This is related to the Y position, and must be a number from 0 to 7. For this we can simply take the lowest part of the Y value by using Y AND 7, which selects out the three least signficant bits (value 0 to 7) of the Y number.
Assembling these steps together to find the particular word to be altered we get the equation
P=BM+32~*INT(Y/8)+8*INT(X/8)+(Y AND 7)
where BM is the start address of the bit map memory, and P is the address of the location we need to alter.
The next step is to set the required bit in the word. The bit number is obtained by taking the three least significant bits of the X number, which tells us which of the 8 bits is to be set. This is done by simply ANDing X with 7. Now in the display memory word each bit has a value which is 2 raised to a power from 0 to 7 according to the bit position in the word. So bit 0 (the right-hand one) has a value of 1 (20), the next bit is 2 (21), and so on to the left-hand bit which has the value 128 (27). The value of X, however, runs from 0 to 7, moving left to right through the word, so to set the required bit we have to calculate 21(7-(X AND 7)). The result of this calculation is ORed with the existing contents of the memory location at address P, and then the result is POKEd back into that memory location.
This process of setting a dot may seem rather complex, but in fact boils down to a simple three-line subroutine. Now all we have to do to plot a point is to set X and Y to the co-ordinates of the point on the screen, and then call the subroutine to light up the required dot. To reset a dot to its 'off' state we need to AND the contents of the required memory location with 255-DV, where DV is the value of the data bit representing the dot we want to reset.
The program listed in Fig. 3.3 sets up the bit map mode, clears the screen, and then plots a series of randomly-positioned dots all over the screen. The dot setting subroutine starts at line 2~~. A point to note here is that the screen clearing operation takes several seconds, during which time nothing much will appear to happen.
High Resolution Graphics 37
100 REt1 H I -RES RAt,lDor1 DOTS 185 REt1 CLEAR BIT t1AP AREA 110 t18=8192
120 PRHn"SETTH~G UP"
130 FOR M=t18 TO t18+8000: POKE t1 J 0 : t'4E:~:T 135 REM MOVE BIT MAP ADDRESS
140 PO~~E53272 J PEEK (53272) OR 8
145 REt1 SELECT BIT t1AP t10DE
150 POKE 53265,PEEK(53265) OR 32 155 REM SET COLOURS
160 FOR I=1024T02023:POKE I,22:NEXT 170 GOT01000
195 REt1 DOT SET ROUT mE
200 P=MS+320*INT(Y/8)+8*INT(X!S)+(YAND7) 210 POKE P,PEEK(P) ORC2t(7-(X AND 7») 220 RETURN
995 REM MAIN PROGRAM 1000 FOR N=l TO 200 1010 Y=200*RND(0) 1020 X=320*RND ': 0)
1 eJ30 (,OSUB200
1040 NE)C:T
1050 END
Fig. 3.3. Simple BASIC program to select the bit map mode and plot random dots.
Machine code screen clear
Waiting for the computer to clear the screen using a BASIC program is a rather tedious business, as you will just have discovered, The solution is to use a machine code routine to perform this task, and to call it from BASIC whenever the bit map screen needs to be cleared.
Figure 3.4 shows the list of assembly language instructions for a short machine code routine which will clear the bit map screen. The machine code itself is set up in the computer by using a short piece of BASIC program to POKE the data representing the machine code into the computer memory. This is shown in Fig. 3.5. Here we have placed the machine code in an area of memory starting at location 49152 by using a loop to read the required data numbers and POKE them into successive memory locations. This area of memory is above that used by BASIC, so it will not be overwritten by your
38 Commodore 64 Graphics & Sound
STAF:T
BLOCI< BYTE
LOA #(.) Start address
5TA 251
LOA #32 in 251/2
STA 252
LDX #32 No. of blocks
LOY #0
LDA #0
STA 251,Y Set byte to 0
DEY Next byte
BNE BYTE End of block?
INC 252 Update address
DEX to next block
BNE BLOCK All done?
F:TS F:eturn Fig. 3.4. Machine code program to clear the bit map screen.
106 REM BIT MAP CLEAR M/C ROUTINE
105 REM CLEARS 8000 BYTES FROM 8192 UP 110 REM CALL USING SYS49152
120 T=0:FOR N=49152 TO 49176
130 READ A:POKE N,A:T=T+R:NEXT
140 READR: 1FT OA THEf-l PR i iH" ERROF.:" : END 150 PRIt-lT"LOADED OK"
160 DATA 169,0,133,251,169,32.133,252 170 DATA 162,32,160,0,169,0,145,251 180 DATA 136,208,251,230,252,202,208 190 DATA 246.96,3887
Fig. 3.5. BASIC program to load machine code screen clear routine.
BAS I C programs or their data and variables. Once the data has been POKEd into the memory the machine code routine will remain available all the time the machine remains switched on. Typing NEW doesn't affect the machine code area, so you could use this short BASIC program to load the screen clear routine at the start of a computing session, then type NEW and load the BASIC programs that will use the routine.
Be very careful in entering the DATA items: an error here can cause unpredictable results when the machine code routine is executed, and will probably cause the computer to become totally locked-up. A simple checking routine has been built into the program which should pick up most data entry errors. This check adds up all of the DATA items and compares the result with a final check OAT A word. If the results match, the message 'LOADED
High Resolution Graphics 39
OK' is printed, but if a mismatch occurs the message 'DATA ERROR' is printed. This simple check is not totally infallible, since two errors in succession could cancel one another and give the correct check answer, but the machine code will still be in error.
100 REM RANDOM BIT MAPPED DOTS
105 REM SET BIT MAP ADDRESS TO 8192 110 BM::::8192
120 POKE53272~PEEK(53272)OR8 125 REM SELECT BIT MAP MODE 130 POKE53265~PEEK(53265)OR32 135 REM SET COLOURS
140 FOR I=1024T02023:POKEI)22:NEXT 145 REM USE CLEAR ROUTINE AT 49152 150 S'7'549152
160 GOT01000
195 REM DOT SETTING SUBROUTINE
200 P=BM+320*INT(Y/8)+8*INT(X/8)+(YAND7) 210 POKE P,PEEK(P)OR(2t(7-(XAND7»))
220 RETURt·~
995 REM MAIN PROGRAM 1000 FOR N=l TO 200 1010 X=320*RND(0) 1020 Y=200*RND(0) 1030 GOSUB200
1040 t·~E~:T
1050 END
Fig. 3.6. Random bit-mapped dots program using machine code screen clear routine.
The machine code screen clear operation is called from a BASIC program by using the instruction SYS49152 as a BASIC statement. In the program shown in Fig. 3.6 the screen is set to bit map mode, then cleared, and then the random dots are plotted as before. This time the process repeats 20 times, and you will notice that the screen clears almost instantly.
Drawing lines
Now that we can plot individual points on the screen, the next step is to draw lines. Suppose we want to draw a horizontal line across the screen from a point Xl, Y to another point X2, Y. Since the line is horizontal, all the points along it will have the same Y value. To
40 Commodore 64 Graphics & Sound
draw the line on the screen we have to set all the dots along the line from point X 1 to point X2 to the lit or '1' state. This can easily be done by using a simple loop operation where the X value is stepped from X I to X2 and a dot is set at each step as follows:
3~~ FOR X = Xl TO X2
31~ P=32~*INT(Y j 8)+8*INT(Xj 8)+(Y AND7) 32~ B=21(7-(XAND7))
33~ POKE BM+ P,PEEK(BM+ P) OR B 34~ NEXT
Here it is assumed that the bit map mode has been set up and values have been given to Xl, X2 and Y earlier in the program.
Drawing vertical lines on the screen follows a similar procedure to the drawing of horizontal lines, except that now the X co-ordinate of the points remains constant and the Y co-ordinate is stepped from Y 1 at one end of the line to Y2 at the other, with a point being plotted at each step.
A general line-drawing routine should be able to draw lines at an angle as well as horizontal and vertical lines. This requires a more complex routine, since both X and Y co-ordinates now have to be changed as the line is drawn.
If the line is to be a diagonal one, at 45 degrees, the X and Y changes are equal, and the direction of the line will simply be determined by the signs of the steps in X and Y. Thus if both X and Y increase by one for each successive dot the line is drawn diagonally downward and to the right. If X decreases by one and Y increases by one the line is drawn down and to the left. If Y decreases by one at each step then the line will be drawn up the screen and to left or right according to whether X decreases or increases.
If the line is not at 45 degrees then the steps in X and Y will be different from one another. The technique here is to choose the larger co-ordinate change from one end of the line to the other and make that the total number of steps to be plotted. Now some steps will need to be made diagonally, while between them there will be vertical or horizontal steps according to which direction has the greater change in position.
Let us consider an example. Suppose we want to draw a line from point XI, Y 1 = 50,50 to point X2, Y2 = 150,80. First we check whether X or Y has the largest change in value. In this case it is X which changes by 100 while Y changes by only 30. So here we make the total number of steps equal to 100.
In the program this can be done by using an IF statement to
High Resolution Graphics 41
compare ABS(X2-XI) with ABS(Y-YI). The absolute values must be used since either X2-XI or Y2-YI may be negative, and this would give the wrong answers. We are only interested here in the size of the difference in the X and Y co-ordinates of the line.
If X2 is larger than X I the line is drawn from left to right, whereas if X2 were smaller than X I the line would extend to the left and the X value would have to be reduced by one for each successive dot. The direction in which the steps have to be plotted is governed by the signs of the (X2-XI) and (Y2-YI) differences, and these are determined by using SGN(X2-XI) and SGN(Y2-YI). The results are held as variables SX and SY, which will have values of-I, 0 or +1.
To draw the line we shall now plot a total of 100 dots along the line. Since the change in Y is only 30 there will be 30 diagonal steps, and the remaining 70 steps are in the X direction only. To give a smooth line the diagonal steps must be spread out evenly along the line.
To do this we set up a running total NO which is initially set to the integer value of half the larger of the X or Y differences. In this case
NO = INT(NX)/2 = 5~
Now we set up a loop running from I to NX, in this case. If NY were greater it would determine the size of the count. On each pass through the loop the lower of the two differences (NY) is added to NO, and the result is compared to the larger difference (NX). Normally a horizontal or vertical step is made, but when the new total becomes larger (i.e. here NO> NX) a diagonal step is made. After the diagonal step the larger difference, in this case NX, is subtracted from NO. In the example, NO starts at 50 and we add NY (30) giving 80. This is less than NX, so the first step is horizontal. On the next pass NO becomes 110, so we make a diagonal step and reduce NO by NX to make it 10. The next three steps are horizontal, with NO at 40, 70 and 100, then another diagonal step is made, and so on along the line.
We can now produce a general line drawing routine as shown in Fig. 3.7. The program shown draws a series of lines of random length and with random angles all over the screen. The line drawing subroutine starts at line 3~~ and this calls a dot-setting routine at line 2~~. Now when the line is drawn it will have a stepped appearance depending upon its angle relative to the horizontal or vertical axis.
42 Commodore 64 Graphics & Sound
100 REM RANDOM HIGH RES LINES
105 REM SET BIT MAP ADDRESS TO 8192 i 10 Bt'l=8192
120 POKE53272,PEEK(53272)OR8 125 REM SELECT BIT MAP MODE 130 POKE53265.PEEK(53265)OR32 135 REM SET COLOURS
140 FOR I=1024T02023:POKEI.22:NEXT 145 REM USE CLEAR ROUTINE AT 49152 150 S',.'S49152
16~3 GOTO 1 066
195 REM DOT SETTING SUBROUTINE
200 P=BM+320*INT(Y!8)+8*INT(X/S)+(YAND7) 210 POKE P,PEEK(P)OR(2t(7-(XAND7»)
220 RETUR~l
295 REM LINE DRAWING SUBROUTINE 300 SX=SGN(X2-Xl):SY=SGN(Y2-Yl) 310 NX=ABSeX2-Xl):NY=ABS(Y2-Yl) 320 :-.:=>:: 1 : 'r'='t'l : GOSU:S266
330 IF NY)NX THEN390
340 I'm= I NT (N::-V2)
356 FORK=lTO NX:ND=ND+NY
360 IF ND<NX THEN X=X+SX:GOT0380 370 ND=ND-NX:X=X+SX:Y=Y+SY
380 GOSUB200:NEXT:GOT0440
390 ND=INT(NY/2)
460 FOR K=l TO NY:ND=ND+NX
410 IF ND(NY THEN Y=Y+SY:GOT0430 420 ND=ND-NY:X=X+SX:Y=Y+SY
430 GOSUB200:NEXT
440 RETURl'l
995 REM MAIN PROGRAM 1000 FOR N=l TO 15
1010 Xl=320*RND(0):Yl=200*RND(0) 1020 X2=320*RND(0):Y2=200*RND(0) 11030 GOSU:B300
11046 t·lEXT
1050 END
Fig. 3.7. General purpose line drawing routine for use with the bit map graphics mode.
Screen edge limiting
In the line drawing program of Fig. 3.7 the values of Xl, X2, Y I and
High Resolution Graphics 43
Y2 are calculated so that they are within the limits 0 to 319 (for X) and 0 to 199 (for V). In some programs where the line length and position are being calculated by the program it is possible that one or both ends of the line will fall outside the permitted range of values for X and Y, so we need some scheme which can deal with this situation.
If X or Y were negative, or greater than the screen limits, the data
for the points would be written into computer memory which is outside that allocated to the high resolution screen, and this could have disastrous effects on the program. In a computer program, however, it may be that the values calculated for the end point of a line are outside the screen area, so we need to build into our subroutine some checks for the screen edge. This can be done in the dot plotting subroutine by testing the values of X and Y before trying to plot the dot.
The simplest approach is to arrange that if X<O or X> 319 the dot plotting operation is skipped altogether and the subroutine returns to the main program. A second test for Y<O or Y> 199 also causes the dot plotting operation to be skipped. These two tests are placed at the start of the dot plotting subroutine. This scheme effectively clips off any part of the line that goes off the screen, and the new subroutine becomes
2~~ IF X<~ OR X>319 THEN 25~ 21~ IF Y<~ OR Y>199 THEN 25~
220 P=320*INT(Y/S)+S*INT (X/S)+(YAND7) 23~ B=2t(7-(XAND7»
24~ POKE BM+ P,PEEK(BM+ P)OR B 25~ RETURN
Here BM is the start address of the bit map memory, and B is the value of the bit that has to be set to light the particular dot being plotted.
Screen wraparound
An alternative approach to dealing with off-screen points is to apply screen wraparound. This treats the screen as if it were a sheet of paper wrapped around a cylinder so that the left and right edges of the paper touch. Now if we draw a line which runs off the right edge of the paper it continues by running in from the left edge of the paper. Thus on our screen a point moving off the right edge of the
44 Commodore 64 Graphics & Sound
screen will reappear at the left edge of the screen. A line running off the right side of the screen would have its off-screen segment drawn at the left of the screen. We can also apply vertical wraparound so that a line running off the bottom of the screen continues to be drawn running down from the top of the screen.
This wraparound effect can be achieved by successively adding or subtracting 320 to or from X until X falls within the screen limits. Similarly Y is changed by 200 at a time, until the Y value is on the screen. Of course if there are a lot of points off the screen this can be a slow process. The dot plotting routine could now be ,
2~~ IF X<~ THEN X=X+32~:GOT02~~
21~ IF X>319 THEN X=X-32~:GOT021~ 22~ IF Y<~ THEN Y=Y+2~~:GOTO 22~
23~ IF Y>199 THEN Y=Y-2~~:GOT023~ 24~ P=32~*INT(Y / 8)+8*INT(X/ 8)+(YAND7) 25~ B=21(7-(X AND 7))
26~ POKE BM+P,PEEK(BM+P) OR B 27~ RETURN
Here if X<O then 320 is added to X to bring X into the correct range, and the test is repeated in case X is still negative. If X> 319 then 320 is subtracted from X and the test is repeated. A similar series of tests is carried out on the Y values, and then the dot is set. Fig. 3.10 shows a program where the dot subroutine is arranged to give wraparound.
Drawing simple figures
So far we have looked at plotting dots and drawing lines, but for many purposes we may want to draw complete figures such as triangles, rectangles, polygons and circles. A sketching program could be used, but it is usually more convenient to let the computer draw the figures itself. We shall now look at some ofthe techniques involved in drawing shapes on the screen.
To draw a triangle the simplest approach is to draw three straight lines linking the corners of the triangle. A rectangle can also be drawn by working out the X, Y co-ordinates for each of its four corners, and then drawing four lines which link the points together to form the sides of the rectangle.
The program iisted in Fig. 3.8 draws a series of random-shaped triangles around the screen. Here the corner co-ordinates of the triangles are set up as variables XA, Y A, XB, YB and XC, YC, and
High Resolution Graphics 45
100 RH1 RA~mOM TR I A~mLES
105 REM SET BITMAP ADDRESS TO :3192 110 B~1=8192
120 POKE53272.PEEK(53272)OR8 12~ REM SELECT BIT MAP MODE 130 POKE53265.PEEK(53265)OR32 135 REM SET COLOURS
140 FOR I=1024T02023:POKEI.22:NEXT 145 REM USE CLEAR ROUTINE AT 49152 150 S',-IS49152
160 GOT010e0
195 REM DOT SETTING SUBROUTINE
21313 P=BM+320*INT(Y/8)+8*INT(X/8)+(YAND7) 210 POKE P.PEEK(p)ORe2t(7-(XAND7»)
220 RETURI'4
295 REM LINE DRAWING SUBROUTINE 3130 SX=SGNeX2-Xl):SY=SGN(Y2-Yl) 3113 NX=ABS(X2-Xl):NY=ABS(Y2-Yl) 3213 X=Xl:Y=Yl:GOSUB2e0
330 IF NY)NX THEN390
340 ND= I I'n ( t~:~/2)
350 FORK=lTO NX:ND=ND+NY
360 IF ND<NX THEN X=X+SX:GOT0380 370 ND=ND-NX:X=X+SX:Y=Y+SY
380 GOSUB20e:NEXT:GOT0440
390 ND:: I I'n (N',.' /2)
4130 FOR K=l TO NY:ND=ND+NX
410 IF ND<NY THEN Y=Y+SY:GOT0430 420 ND=ND-NY:X=X+SX:Y=Y+SY
430 GOSUB200:NEXT
4413 RETURt·j
995 REM MAIN PROGRAM 10130 FOR N=l TO 5
1005 REM SELECT CORNER POINTS 1010 XA=320*RND(e):YA=200*RNDC0) 11320 XB=320*RND(0):YB=200*RND(0) 1030 XC=320*RND(0):YC=200*RND(0) 1035 REM DRAW TRIANGLE
1040 Xl=XA:Yl=YA:X2=XB:Y2=YB:GOSUB300 1050 Xl=XB:Yl=YB:X2=XC:Y2=YC:GOSUB300 11360 Xl=XC:Yl=YC:X2=XA:Y2=YA:GOSUB300 1070 !'lEXT
11380 END
Fig. 3.8. Random triangle drawing program.
46 Commodore 64 Graphics & Sound
then lines are drawn linking these points. This program needs the machine code clear routine loaded into memory before it is used.
Drawing rectangles
We could draw a rectangle in the same way as a triangle by specifying the corner points and linking them with lines, but there is a simpler approach which can be used. Rectangles have a width W and a height H, and knowing these and the X, Y position of one corner we can let the computer calculate the X, Y co-ordinates for the other corners and draw in the lines. The values for the other corners are shown in Fig. 3.9.
X,Y
W
X+W,Y
H
X,Y+H
X+W,Y+H
Fig. 3.9. Diagram showing drawing co-ordinates for a rectangle based on width and height.
To dra w the rectangle we start by setting X I and Y I to the X and Y values for the top left corner. X2 will now be X 1+ H but Y2 is the same as Y I, since the line is horizontal. We can now call the line drawing subroutine to draw in the top side of the rectangle. Now Xl and Y I are set equal to X2 and Y2. For the right side of the rectangle a new value of Y2 equal to Y 1+ H is calculated, and another line drawn. For the third side W is subtracted from Xl to give the new value for X2, and on the final side H is subtracted from Y I to give the final value for Y2. This sequence is shown in the program listed in Fig. 3.10. Here the rectangle-drawing operation is set up as a subroutine, and random size rectangles are drawn at random points
High Resolution Graphics 47
100 REM RANDOM RECTANGLES
102 REM WITH SCREEN WRAPAROUND
105 REM SET BIT MAP ADDRESS TO 8192 110 Bt1=8192
120 POKE53272IPEEK(53272)OR8 125 REM SELECT BIT MAP MODE 130 POKE53265,PEEK(53265)OR32 135 REM SET COLOURS
140 FOR I=1024T02023:POKEI,22:NEXT 145 REM USE CLEAR ROUTINE AT 49152 150 8',-'549152
160 I]OT01000
195 REM DOT PLOT WITH SCREEN WRAPAROUND 200 X=INTeX):Y=INTCY)
210 IF X(0 THEN X=X+320:GOT0210 220 IF X)319 THEN X=X-320:I]OT0220 230 IF Y<0 THEN Y=Y+200:GOT0230 240 IF Y)199 THEN Y=Y-200:GOT0240
250 P=BM+320*INT(Y/8)+8*INT(X/8)+(YAND7) 260 POKE P;PEEK(p)ORe2t(7-(XAND7»)
270 RETUR~~
295 REM LINE DRAWING SUBROUTINE 3005X=5GN(X2-Xl):SY=SGN(Y2-Yl) 310 NX=ABS(X2-Xl):NY=ABS(Y2-Yl) 320 X=Xl:Y=Yl:G08UB200
330 IF NY)NX THEN390
340 ~m:: I NT (NK/2)
350 FORK=lTO NX:ND=ND+NY
360 IF ND(NX THEN X=X+SX:GOT0380 370 ND::ND-NX:X=X+5X:Y=¥+S¥
380 I]OSUB200:NEXT:GOT0440
:390 t·m=I~n(N'r/2)
400 FOR K=1 TO NY:ND=ND+NX
410 IF ND<NY THEN Y=Y+SY:GOT0430 420 ND=ND-NY:X=X+SX:Y=Y+SY
430 GOSUB200:NEXT
440 RETURN
495 REM RECTANGLE SUBROUTINE 500 X2=Xl+W:Y2=Yl:GOSUB300 510 Xl=X2:Y2=Yl+H:GOSUB300 520 X2=Xl-W:Yl=Y2:GOSUB300 530 Xl=X2:Y2=Yl-H:GOSUB300 540 RETUR~l
995 REM MAIN PROGRAM 1000 FOR N=l TO 10
48 Commodore 64 Graphics & Sound
10105 REM SELECT CORNER PO I I'n 11010 Xl=480*RND(0):Y1=300*RND(0)
1 020 l~=30+30*RI'm (0) : H=25+50*RND (e) 1025 REM DRAW RECTANGLE
1030 GOSUB500
1040 t'~E:"~T
110510 am
Fig. 3.10. Program to draw random rectangles with screen wraparound.
on the screen. The dot plotting routine used in this program features screen wraparound, so that when a rectangle is near the edge of the screen and part of it goes over the edge the overs pill will be drawn at the other side of the screen.
Drawing circles
One figure we shall often require is the circle. There are several methods for drawing circles. These build up the circle by plotting a large number of individual dots, or drawing a number of short lines to build up the circular figure. The positions of the dots or lines are calculated using one of the mathematical formulae for a circle.
c
R
B
Fig. 3.11. Derivation of the equations for a circle by the squares method.
Figure 3.11 shows a segment of a circle. Here point A is at the centre of the circle while points Band C are on the circle itself. The length of the line AB is equal to that of line AC, and is called the radius (R) of the circle. Let us now drop a vertical line down from point C to meet
High Resolution Graphics 49
side AB at point D. This produces a right-angled triangle ACD.
To place dots at points Band C we need to know the X and Y coordinates for each of those points. It is convenient to calculate these relative to point A which will therefore have co-ordinates X and Y both equal to O. If we move to point B, its X co-ordinate must be equal to R, the length of line AB. Since the line is horizontal the Y co-ordinate must be the same as that of point A, and is therefore O. When we look at point C, the X value is the length of side AD, and the Y value is equal to the length of side CD of the triangle ACD.
For a right-angled triangle the square of the length of the longest side is the sum of the squares of the lengths of the other two sides. We can write this down as follows:
(AC)*(AC) = (AD)*(AD) + (CD)*(CD)
Now AC = radius R while AD and CD are the Xand Yeo-ordinates for point C, so putting these in our equation we get
R * R = (X * X) + (Y * Y)
which can be rearranged to give us
Y * Y = (R * R) - (X * C)
from which we can get Y by simply taking the square root. The calculation for Y now becomes
Y = SQR«R * R) - (X * X))
The values of X and Y in this equation are measured with reference to the centre point of the circle. Note that for point B the equation for Y is still true, since in this case X=R, so the term on the right becomes zero and therefore Y=O.
To place the circle at some particular point on the screen we shall have to add in the X and Y co-ordinates for the point where the circle is to be drawn. To avoid confusion we shall call these co-ordinates XC and vc
In order to plot all the points around the circle we need to calculate values of Y for a series of values of X ranging from - R to + R, and the more points we calculate the better the circle will look.
When we take the square root of a number there are in fact two possible answers with the same numerical value, one being positive and the other negative. For each value of X we shall have two values for Y, and be able to plot a pair of points, one on the upper half of the circle, and the other on the lower half. To plot the first point the result of the square root calculation is added to the Y value for the
50 Commodore 64 Graphics & Sound
centre of the circle (YC) to give a point below the centre line ofthe circle. The second point has the square root subtracted from YC, and will lie above the centre line of the circle. This is because, on the bit map screen, Y increases as we move down the screen.
Since we are plotting single points, and the circumference of the circle is just over 6 times radius R, it is convenient to have a total number of points equal to 4 times R to make up the circle. Remember that we plot two points for each calculation, so a good value for the number of calculations is twice the value of radius R. This is easily achieved by taking all of the X values from X=- R to X=+ R. Thus a circle with a radius of 50 screen units would calculate 100 steps and plot a total of 200 points around the circle.
The program shown in Fig. 3.12 draws a circle of radius 50 units with its centre point at XC= 16~, YC= l~~, which is roughly at the centre of the screen. With this routine the number of calculations depends upon the size of the circle. By changing the values of XC,
100 REM CIRCLE DRAWING USING SQUARES 110 Bt1""t: 192
115 REM SET BIT MAP START
128 POKE53272,PEEK(53272)OR8 125 REM SELECT BIT MAP MODE 130 POKE53265JPEEK(53265)OR32
REM CLEAR SCREEN
134 REM NEEDS MIC ROUTINE AT 49152 14(1 Slr1:349152
145 REM SET COLOURS
150 FORI=1024T02023:POKEI,22:NEXT 160 GOTO 1 ~H3fl
195 REM DOT PLOT ROUTINE
200 P=BM+320tINT(Y/S)+8*INT(X!8)+(YAND7) 210 FOKEP,PEEKCP)OR(2t(7-(XAND7)))
22(1 ~:ETUPt'l
495 REM CIRCLE ROUTINE 500 FOR Xl=-R TO R
510 Yl=SQR(R*R-Xl*Xl)
520 X=XC+Xl:Y=YC+Yl:GOSUB200
530 Y=YC-Yl:GOSUB200:NEXT:RETURN 995 REM MAIN PROGRAM
1000 XC=i60:YC=100:R=50
1010 OOSUE500
1020 Et'4D
Fig. 3.12. Circle drawing program using squares method.
High Resolution Graphics 51
YC and R, other circles may be drawn, or you could draw a series of random-size circles all over the screen. It will be seen that the larger size circles take a noticeable time to draw. This is because the computer has quite a lot of calculations to carry out. The square root function itself is rather slow in BASIC. If we want to draw circles faster we will need to look at other ways of calculating the points around the circle.
You will note that at the right and left sides of the circle the first few points tend to be rather spread out, especially on the larger radius circles. This can be overcome by plotting more points - for instance by increasing X by steps of 0.5 instead of I - but the circle takes even longer to draw.
The trigonometric method
Instead of plotting a series of dots we can draw a series of short lines, which when joined together will form the outline of the circle. For the second method of drawing circles we need to get involved in some simple trigonometry.
c rxa .. Y2)
= R*5IN(TH)
R
va
6
D
Fig. 3.13. Derivation of equation for the trigonometric method of circle drawing.
Figure 3.13 shows a segment of the circle with two points Band C on the circle itself and point A at the centre. The angle at point A of the triangle is given the variable name TH which is a shortened version of THETA, the name of the Greek letter normally used for labelling angles. The co-ordinates X2, Y2 for point C can now be calculated using the radius R and the angle TH.
52 Commodore 64 Graphics & Sound
To find the length of side CD the function we need to use is SIN(TH). SIN(TH) is the ratio of the length of the side of the triangle opposite angle TH to the length of the hypotenuse (the side opposite the right angle), which is side AC. So in our triangle
SIN(TH) = CD / AC
We already know that AC = radius R. The length of side CD is the Y2 value for point C, assuming that at point A the value of Y=O. Substituting these new terms in the equation we get
SIN(TH) = Y2/ R
and if we multiply both sides by R the result becomes
Y2 = R * SIN(TH)
Having found Y2 we need to find a value for side AD, which is the X2 value for point C. Now it just happens that COS(TH) is the ratio of the length of the adjacent side (AD) of the triangle to the length of the hypotenuse (AC) so we get
COS(TH) = AD / AC
and substituting the values X2 and R gives X2 = R * COS(TH)
To find the co-ordinates for the next point we apply the same equations, but now the angle TH has a different value.
To draw the first segment of the circle we must draw a line from point B to point C. This line starts at point B, where TH=O and the required values for X I, Y I are
XI = XC + R YI = YC
where XC and YC are the co-ordinates for the centre of the circle.
The next step is to calculate the co-ordinates of point C, which will be
X2 = XC + R * SIN(TH) Y2 = YC + R * COS(TH)
and the line BC can be drawn from XI,YI to X2,Y2.
For the next line segment of the circle, the values of X I and YI are set equal to the values of X2 and Y2.. The angle TH is then increased, and new values are calculated for X2, Y2 using the new value for the angle TH. This process continues until the angle TH reaches 360
High Resolution Graphics 53
degrees, when a complete circle will have been drawn.
While angles in degrees are familiar to us, the computer doesn't work in degrees; it uses radians instead. All we need to know here is that there are 2*7T radians in 360 degrees. The number 7T (pronounced PI) is a constant whose value is approximately 3.14, and it is the ratio of the circumference of a circle to its diameter. We do not need to remember the value for 7T because the Commodore 64 has a special key which allows us to insert 7T into a program statement as required. This key is marked with the Greek letter 7T on its front face, and must be used with the shift key held down. It produces the number 3.14159265.
A convenient number of steps for drawing the circle is given by R, the radius in screen units. Drawing the circle involves using a simple loop to repeat the calculations and draw a short line segment R times. After each segment of the circle has been drawn, the value of the angle TH is increased by 2*7T / R radians, and the values of XI and Y 1 are updated to point to the end of the line that has just been drawn, ready for the next drawing step.
A program to draw random-sized circles is shown in Fig. 3.14.
100 REM CIRCLES USING TRIG METHOD 110 E:r'1:::::8 i 92
115 REM SET BIT MAP START 120 POKE53272JPEEK(53272)OR8
125 REM SELECT BIT MAP MODE
130 POKE53265JPEEK(53265)OR32
132 REM CLEAR SCREEN
134 REM NEEDS MIC ROUTINE AT 49152
14ti S;Jr'S49152
145 REM SET COLOURS
150 FORI=1024T02023:POKEI,22:NEXT i se GOrO 1 i2l12i0
195 REM DOT PLOT ROUTINE WITH CLIPPING 200 IF X<O OR X)319 THEN 240
210 IF Y{0 OR Y)199 THEN 240
220 P=BM+320*INT(Y!8)+8*INT(X!8)+(YAND7) 230 POKEP,PEEK(P)OR(2t(7-(XAND7»)
240 RETURt·i
295 REM LINE DRAWING ROUTINE
300 SX=SGN(X2-Xl):SY=SGN(Y2-Yl) 310 NX=ABS(X2-Xl):NY=ABS(Y2-Yl) 320 X=Xl:Y=Yl:GOSUB200
330 IF NY)NX THEN 380
54 Commodore 64 Graphics & Sound
340 ND=INT(NY!2):FORK=lTONX:ND=ND+NY 350 IF ND<NX THEN X=X+8X:GOT0370
370 GOSUB200:NEXT:GOT0420
380 ND=INT(NY!2):FORK=lTONY:ND=ND+NX 390 IFND<NY THEN Y=¥+SY:GOT0418
400 ND=ND-NY:X=X+SX:Y=¥+SY
410 GOSUB200:NEXT
42el ~:ETIJRt'l
495 F~Et1 c: I RCLE ~:OUT I 1··lE
500 DT=2*~!R:TH=0:Xl=XC+R:Yl=YC 510 FOR 1=1 TO R
520 TH=TH+DT:X2=XC+R*COS(TH) 530 'r'2='!'C+R:;:SHlnH): GOSUB3el0 540 Xl=X2:Yl=Y2:NEXT:RETURN 995 REM MAIN PROGRAM
1000 FOR t'l= 1 T08
1010 XC=INT(300*RND(0)+10 1020 YC=INT(170*RND<0)+10 1030 R=15+INT(15*RND(0» 1040 GOSUB500:NEXT
105(1 Er-ID
Fig. 3.14. Random circle program using the trigonometric method.
Fig. 3.15. Typical display of random circles.
High Resolution Graphics 55
This program gives a result similar to that shown in Fig. 3.15. The actual circle-drawing section is written as a subroutine starting at line 5~~. If several circles are to be drawn, it is best to use a subroutine for drawing the circle, and call it from the main program whenever it is needed. Before calling the subroutine, the values for R, XC and YC must be set up for the required circle.
This circle-drawing program uses a dot plotting routine which clips points at the edge of the screen. Thus any points falling outside the screen area are not plotted at all.
The rotation method
A variation of the trigonometric method for a circle bases the calculations upon the angle through which the radial line is rotated at each step. In this case the new values for X2 and Y2 are calculated from the values for the previous point (X I, Y I) rather than from the radius and the total angle.
X2 =X 1 *C05 (TH:I 'y'2 =X 1 *5 IN I:TH)
C (X21 'y'2)
Fig. 3.16. Equations for rotation of a point with Yl initially at O.
If we look at Fig. 3.16 the value of Y I is zero so that only the Xl value, which also happens to be equal to R, affects the results. Here we get
X2 = Xl * COS(TH) Y2 = Xl * SIN(TH)
Now consider the situation where the radial line is vertical and is moved through angle TH. This is shown in Fig. 3.17. Here the value
56 Commodore 64 Graphics & Sound
__ --:-.. - __ -...... _-
(" .,e::;.----1
'-' I~I
(~'~2,,\'2) "
\ \
"
"
\
"
"
'I
R \
, \
\',TH
-,
I,
~'::2 = -''(''1 *:5 It'" t:TH) \,
1\
Fig, 3.17. Equations for rotation of a point with X1 initially at O.
of X I is 0, and only the Y I value affects the results, In this case the value of X2 is negative, since the point has been shifted to the left of the line where Xl =0, Here we get the results
X2 = -YI * SIN(TH) Y2 = Y I * COS(TH)
If we combine these two results we can produce a general expression for calculating X2 and Y2 for any initial values of X I and Y I, The two new equations are
X2 = X I * COS(TH) - Y I * SIN(TH) Y2 = Xl * SIN(TH) + YI * COS(TH)
Now the big advantage of this approach is that the value of TH is constant, so we can work out the values of SIN(TH) and COS(TH) before entering the co-ordinate calculation and line drawing loop, This eliminates virtually all the trigonometric calculations, which tend to be slow, The program for drawing a circle now becomes as shown in the listing of Fig, 3,18, As for the trigonometric method, this program produces random circles with edge clipping,
100 REM CIRCLES USING ROTATION
115 REM SET BIT MAP START
120 POKE53272,PEEK(52272)ORS
125 REM SELECT BIT MAP MODE
High Resolution Graphics 57
130 POKE53265,PEEK(53265)OR32 132 REM CLEAR SCREEN
134 REM NEEDS M/C ROUTINE AT 49152
145 REM SET COLOURS
156 FORI=1024T0202S:POKEI,22:NEXT 160 OOTO 10~30
195 REM DOT PLOT ROUTINE WITH CLIPPING 200 IF X(0 OR X)319 THEN 240
21G IF Y(G OR Y)199 THEN 240
220 P=BM+320*INT(Y/8)~8*INT(X/8)+(YAND7) 230 POKEP,PEEK(P)OR(2t(7-(XAND7»)
24121 F.:ETUf.j··1
295 REM LINE DRAWING ROUTINE 300 SX=SGN(X2-Xl):SY=SGN(Y2-Yl) 310 ~~<=ABS(X2-Xl):NY=ABS(Y2-Yl' 328 X=Xl:Y=Yl:GOSUB200
330 IF NY)NX THEN 380
340 ND=INTCN¥!2):FORK=lTONX:ND=ND+NY 350 IF ND<NX THEN X=X+5X:GOT0370
360 ND=ND-NX:X=X+SX:Y=Y+SY
370 GOSUB200:NEXT:GOT0420
380 ND~INT(N~V2):FORK=lTONY:ND=ND+NX 390 IFND<NY THEN Y=¥+SY:GOT0410
406 ND=ND-NY:X~X+SX:Y=Y+5Y
410 GOSUB200:NEXT
42i2! F.:ETURH
495 REM CIRCLE ROUTINE
500 SN=SIN(2*«;R):CN~COS(2*fi!R) 510 Xl=R:Yl=0:FOR 1=1 TO R
520 X2=XC+Xl*CN-Yl*SN
530 Y2=~:+Xi*SN+Yl*CN
546 X1=XC+Xl:Yl=YC+Yl:GOSUB300 550 Xl=X2-XC:Yl=Y2-¥C:NEXT:RETURN 995 REM MAIN PROGRAM
1008 FOR 1"4= 1 T08
1 g 10 ::<;C:: I i-lT (300*~:r·m >: 0) ) + 10 1020 YC=INT(170*RND(0»)+10 1030 R=15+INT(15*RND(0)) 1040 GOSUB500:NEXT
1050 Et·m
Fig. 3.18. Program to draw circles using the rotation method.
58 Commodore 64 Graphics & Sound
Note here that although XC and YC are added in to give the coordinates for the line drawing they are subtracted from Xl,YI before calculating the new value of X2, Y2. This is important, since the Xl value used to calculate X2 must always be measured relative to the centre of the circle for correct results. If desired you could use another variable for the value of Xl, Yl, without the offset component XC, vc.
Drawing polygons
If we reduce the number of steps used in the circle drawing routine, the result will be a figure with a number of equal straight sides. Such a figure is called a regular polygon.
To make a general polygon drawing routine we could introduce a new parameter NS (number of sides) and then modify the program to make the required number of drawing steps. Thus the rotation angle TH will be given by
TH = 2*rr/NS
To see how this works try running the program shown in Fig. 3.19 which draws random sized regular polygons with from three to eight equal length sides. Figure 3.20 shows the sort of display produced by this program.
100 REM RANDOM POLYGONS 110 Bt1;::8192
115 REM SET BIT MAP START
120 POKE53272.PEE~(~3272)OR8 125 REM SELECT BIT MAF MODE 130 POKE53265.PEEK(53265)OR32 132 REM CLEAR SCREEN
134 REM NEEDS M/C ROUTINE AT 49152 140 SYS49152
145 REt1 ~;ET COLOURS
150 FORi=1024T02823:PGKEI,22:NEXT 160 G0101e.12I1Q
195 REM DOT PLOT ROUTINE WITH CLIPPING 200 IF X<0 OR X)319 THEN 240
210 IF Y<0 OR Y)199 THEN 240
220 F=BM+320*INT(Y!8)+8*INT(X!8)+ YAND7) 230 POKEP,PEEK(P)OR(2t(7-(XAND7»
2:40 R:ETUF.:r-·,
High Resolution Graphics 59
295 F:i:}'j L I t-~E DRA~'l I r'W F.:OUT I r'lE SA0 ~v=~n~{Y?-Y~J.):~Y=~GN{Y2-yj)
",. .... ....., 1 ._ _ I • "I I S'_ / I' . __ ... ._ "_', _ "
310 NX=ABS(X2-Xl):NY=ABS(Y2-Yl) 320 X=Xl:Y=Y1GOSUB200
330 IF NY)NX THEN 380
340 ND=INT(NY/2):FORK=lTONX:ND=ND+NY 350 IF ND<NX THEN X=X+SX:GOT0370
360 ND=ND-NX:X=X+8X:Y=Y+SY
370 GOSUB200:NEXT:GOT0420
380 ND=INT(NY!2):FORK=lTONY:ND=ND+~X 390 IFND<NY THEN Y=V+SY:GOT0410
400 ND=ND-NY:X=X+SX:Y=Y+SY
410 GOSUB200:NEXT
420 RETURt,~
495 REM POLYGON ROUTINE 500SH=SIN(2*«!NS):CN=COS(2*«!NS) 510 Xl=R:Yl=8:FOR 1=1 TO NS
520 X2=XC+Xl*CN-Yl*SN
530 Y2=VC+Xl*SN+Vl*CN
540 Xl=XC+Xl:Y1=YC+Yl:GOSUB300 550 Xl=X2~XC:Yl=Y2-YC:NEXT:RETURN 995 REi"1 MA! ~j PF.:OGRAM
10121121 FOR t'~=lT08
1010 XC=INT(300*RND(0»+10 1020 YC=INT(170*RNDC0»+10 1030 R=25+INT(25*RND(0» 1040 NS=3+INT(5*RND(0) 1050 GOSUB500:NEXT
1060 E~m
Fig. 3.19. Polygon drawing program using the rotation method.
60 Commodore 64 Graphics & Sound
Fig. 3.20. Typical random polygon display.
Chapter Four
Adding Colour
So far, the text and character graphics displays we have generated on the Commodore 64 have been in light blue on a blue background, which are the default display colours. In the bit map displays, however, the colours were changed to white on a blue background by POKEing numbers into the screen memory area. The computer is in fact able to present much more colourful displays, where the symbols may be set to anyone of sixteen different colours. The colours of the border around the display area, and of the background, can also be set to any of the sixteen available colours. In the bit mapped mode any pair of colours from the sixteen available may be chosen for the drawing and background colours.
More advanced techniques allow the creation of multi-coloured text or graphics symbols. In this chapter we shall look at the various ways in which the colours can be controlled.
Setting text colours
Let us start by experimenting with changes in the text colour. The computer normally starts up with the text symbols in a light blue colour on a blue background. The colour of the displayed text can be changed by making use of the CONTROL key (marked CTRL) at the upper left side of the keyboard.
If you press the CTRL and I keys together (we shall indicate this in the text as [CTRL I ]), you will notice that the colour of the flashing cursor changes to black. If you now type in some text or graphics symbols they will be displayed in black. Notice that only new symbols are affected: the text that was already on the screen remains unchanged. When using the CTRL key it is best to hold it down and then press the number key. The CTRL key works in much the same way as the SHIFT key to alter the function of other keys on the
62 Commodore 64 Graphics & Sound
keyboard, but doesn't by itself produce any effect on the screen.
Now try using CTRL with the 2 key. This time you will see that any new text is now displayed in white. The CTRL key can also be used with the other number keys from 3 to 8, and each of these causes the new text to be printed in a different colour, giving eight possible colours for the displayed text. Figure 4.1 shows the set of colours
Colou,- Ke ':I s ASCII List
used code Sym bo I_
BlacK CTRL :1. :1.44 ~
I.-_Ih i t.e CTRL 2 5 13
Red CTRL 3 28 m
C':I a n CTRL 4- :1.59 iJ
Pu ,-p te CTRL 5 :1.56 a
G,een CTRL 6 30 U
Blue CTRL 7 3:1. mil
___ v" e l I_ 0 I_tl CTRL 8 :1.58 m
Fig. 4.1. Colours produced by using the CTRL key, with their ASCII codes and
listing symbols. produced by using the CTRL key with the number keys from 1 to 8.
There are, as we have seen, sixteen possible colours available for text on the Commodore 64. So how do we manage to select the remaining eight? The answer lies in the use of the Commodore Logo key, which is at the left end of the bottom row of keys. This is the key that carries the 'C'-shaped trade mark (logo) of Commodore computers. We shall call it the LOGO key.
To select text colours the LOGO key is used with the number keys in the same way as we used the CTRL key. Now if you press the LOGO and 1 keys at the same time the colour of the flashing cursor will change to orange, and all new text symbols entered will also be orange. Like the CTRL key, the LOGO key can be used with the numbers 1 to 8 to produce eight different text colours. The eight colours produced by using the LOGO key are shown in Fig. 4.2.
Adding Colour 63
CCtlCtUI- 1-<:. e: ."" 50 ASCII List
use:d CCtde: Sym bCt l
Ol-ange: LOGO ::1. ::1.29 ~
BICtwn LOGO 2 ::1.49 1m
Lt Ie:d LOGCt 3 ::1.50 a
Gle:y ::1. LOGO 4 ::1.5::1. ID
Gle:y 2 LOGO 5 ::1.52 aa
Lt Gle:e:n LOGO 6 ::1.53 11
Lt Blue: LOGO 7 ::1.54 a
Lt G I e:'"" LOGO ;9 155 D
Fig. 4.2. Colours produced by using the LOGO key, with their ASCII codes and
listing symbols. The colour memory map
As we saw in Chapter I, a separate area of memory is set aside to hold the colour information for each of the text symbol positions on the screen. Within each symbol position all the lit dots will be displayed in the foreground colour, while the unlit dots are displayed in the background colour. If the foreground colour is changed, then all the lit dots change to the new colour.
The colour memory occupies the 1000 memory locations from 55296 to 55319, and these correspond to the screen memory locations 1024 to 2023. Thus the colour data for the symbol in location 1024 is held in location 55296, and so on.
In the colour memory each location specifies the colour for a particular symbol space on the screen. There are sixteen colours altogether, and these can be represented by the numbers 0 to 15. The computer stores binary numbers in its memory, and the numbers 0 to 15 can be represented by a four-bit binary data word. In the colour memory the lower four bits of the data word specify the text colour.
If a PEEK command is used to read the contents of a colour
64 Commodore 64 Graphics & Sound
memory location, the result will be a number between 240 and 255. This may seem odd since the numbers representing the colour only run from 0 to 15. The reason is that the upper four bits of the colour memory word are not used, and to the processor these four bits will all appear to be set at '1'. If you want to PRINT out the colour data for a particular symbol space, then the upper four bits need to be masked off by using an AND operation as follows:
PRINT PEEK(N) AND 15
where N is the location in the colour memory. The AND operation slices off the upper four data bits of the word to leave the colour number from 0 to 15.
The data we have to write into the colour memory is simply a number from 0 to 15 corresponding to the colour we want. The colour numbers and their associated colours are shown in Fig. 4.3. You will notice that although the colour sequence is the same, the numbers are different from those we used with the CTRL and LOGO keys.
For the first eight colours the number required is one less than the number of the key used with the CTRL key. For the other eight colours the number is seven greater than the number of the key used with the LOGO key.
Changing colour using PRINT
In a program we put the symbols on the screen by using a PRINT statement and enclosing the character string in quotes. We can also insert the [CTRL n] or [LOGO n] codes into a PRINT statement in the same way.
Try typing in the following lines:
PRINT "[CTRL3] RED TEXT" PRINT "[CTRL7] YELLOW TEXT"
When you hit the return key the message RED TEXT will be printed in red, and for the second line the message YELLOW TEXT is printed in yellow. The LOGO key together with a number can be inserted into a PRINT text string in the same way to switch to one of the other eight colours.
You will now notice when the [CTRL n] is inserted in a PRINT statement a strange graphics symbol appears on the screen where the colour control code was entered, but when the command is actually
Adding Colour 65
Display Colour memory ASCII
Colour POKE code CHR$ code
Black 0 144
White 1 5
Red 2 28
Cyan 3 159
Purple 4 156
Green 5 30
Blue 6 31
Yellow 7 158
Orange 8 129
Br own 9 149
Light Red 10 150
Dark Grey 11 151
Medium Grey 12 152
Light Green 13 153
Light Blue 14 154
Light Grey 15 155 Fig. 4.3. The set of available colours and their numbers as used for colour memory, bit map and background colour selection.
executed this symbol is not printed on the screen. The advantage of having a symbol shown in the PRINT command line is that we can see there is a control code in the test string. Figures 4.1 and 4.2 show the various symbols displayed to indicate these colour control codes.
In a program, the control codes are inserted into the text string in much the same way. The only difference is that the statement now has a line number at the start. When the program is LISTED, the
66 Commodore 64 Graphics & Sound
control codes will be displayed on the screen using their special symbols. If you have a Commodore printer the graphics symbols for these codes will also be presented on the printout.
Using CHR$ codes
All symbols and control codes can also be represented by an ASCII code, and this can be used in a PRINT statement by using the CHR$(n) form. One might have expected the codes for the colours to run in sequence, but in fact they are scattered through the complete set of codes between the groups of codes used for graphics and text. The codes corresponding to the sixteen colours available are listed in Figs. 4.1 and 4.2.
Now let us see how these colour control codes might be used.
Suppose we wanted to change the text colour to white while printing a text string. We could use the statement
PRINT CHR$(5);"WHITE TEXT'
and this would produce the same effect as including [CTRL 1] in the text string. Note here that a semicolon is included after the CHR$(N).
If we want to make several changes of colour it is best to set up an array variable to hold the complete set of codes. Suppose we use the variable TC (text colour) and set it with an array dimension of 8. Now we can set up a single loop to read in the set of colour codes. We can arrange that the sequence of colours is the same as that of the CTRL or LOGO sequence. Now to set a colour we merely have to set the value in the CHR$ term equal to TC(N) where N is the number that would have been used with the CTRL or LOGO key. This is shown in the following small program:
1~~ FOR N=l TO 8 11~ READ TC(N) 12~ NEXT
13~ DATA 144,5,28,159,156,3~,31,158 14~ PRINT CHR$(147);
15~ FOR N=l TO 8
16~ PRINT CHR$(TC(N»;"****"; 17~ NEXT
The other eight colours could equally well have been set up in the C array, or you could even have all sixteen colour codes set up in the
Adding Colour 67
18121 REM COLOURS USING CTRL KEY 119 DIM CC(B),C$(B)
12121 FOR ~l== 1 TOS
13121 READ CC(N),C$(N) 14121 ~lE~<:T
15121 DATA 144., "BLK", 5., "~JHI", 28. "RED" 16121 DATA 159, "C',.'N". 156. "PUR" .. 3121., "G~:~l" 1 7121 DATA 31.," BLU II , 158, II 'r'EL "
189 PRINT CHR$(147);
19121 FOR R==ITOI5
2121121 PRINT CHR$(lS);
219 FOR B=1T08
229 PRINT CHR$(CCCB»;" 239 t'~EXT: t·lE::.;T
24121 PRINT CHR$(146)
258 FOR N=lT08
26121 PRINT" ".; C$(N) i"".; 27121 ~lEXT
289 PRINT
299 FOR N==IT08 399 PRINT"CTRL "; 31121 NEXT
329 FOR t~:=l TO 8: PRINT STR$(~D.;" 339 t'lEXT
349 Et·m
11·
I
II'
I
Fig. 4.4. Colour bar program using the CTRL colours.
array. You can also allocate the colours in any sequence you like, since the colour selected by the number C(N) depends upon the data you choose to feed into the array at the start.
The program listing of Fig. 4.4 uses the CHR$ codes to produce a pattern of vertical coloured bars, using the eight colours produced by the CTRL key. The display also shows the corresponding CTRL numbers. The program listing of Fig. 4.5 produces a similar colour bar display but this time uses the set of eight LOGO key colours.
Changing the background colour
The Commodore 64 starts up with a blue background, cyan text and a cyan border around the display area. The background colour can be changed to anyone of the sixteen colours we can use for the text.
In most computers there is a BASIC command to set up the
68 Commodore 64 Graphics & Sound
100 REM COLOURS USING LOGO KEY 110 DIM CC(8),C$(8)
120 FOR t·l== 1 r08
130 READ CC(N',CSCN) 140 t·ln:r
150 DATA 129.," O~:G ".,149.," BF!:N 11 160 DATA 15€i, ilL. RD ".,151.. "GR',.'1 " 170 DATA 152,"GR'T'2 ",153., ilL. G~: II 180 DATA 154., "L. BL ".,155., "GRlr'3 " 190 PRINT CHR$(147);
200 FOR F.:= 1 TO 15
210 PRINT CHR$(18);
22el FOR B= 1 T08
230 F'R I NT CHRS':: CC ( B) ) .: II 240 t·lE:,,:r: t·lE::<:r
250 PRINT CHRS(146)
26(1 FOR rl= 1 T08
270 FF!:INT C$(t~).:
280 rlE:~T
290 PRItH
300 FOR rl= 1 T08 310 PRINT"LOGO ".: 320 rlE::':T
" . . '
330 FOR 1'4=1 TO 8: PRIi'H STR$(N).:" 340 i'lE:,.:r
350 Et·m
II' .'
Fig. 4.5. Colour bar program using the LOGO colours.
background colour of the display, but on the Commodore 64 this is done by setting up a register in the VICII chip. The VICll video display chip contains several registers which are used to control the various display modes, and also some of the colour features of the display. Figure 4.6 shows the registers used for colour and mode control together with their memory addresses.
Background colour is controlled by register 33 in the chip, and this is located at memory address 53281. The number that has to be POKEd into this register ranges from 0 to 15, and is the same as the corresponding text colour number shown in Fig. 4.3. As an example, if we want a red background then the instruction would be
POKE 53281,2
since 2 is the colour number for red. As with the colour memory, only the lower four bits of the register are used, with the upper 4 bits
Adding Colour 69
Register Address Function
17 53265 Extd. Background (Bit 6)
..... ? 53270 Multicolour mode (Bit 4)
..::.~
32 53280 Border colour
33 53281 Background colour 0
34 53282 Background colour 1
35 53283 Background colour 2
36 53284 Background colour 3 Fig. 4.6. The colour control registers of the VIC11 chip with their memory addresses and functions.
set at '1'. If you PEEK the register in a program remember that you need to AND the result with 15 to get the correct colour number.
Unlike the text colour, which can be different for each symbol space, the background colour all over the screen will change when the colour number in the background register of the VIC 11 chip is altered.
Setting the border colour
The border colour on the screen is controlled by register number 32 in the VICII chip, and this has the memory address 52380. As with the background colour, we can change the border colour by POKEing a number from 0 to 15 into this register. The colours produced are the same as those produced by the background register. The whole border area will change colour when a new number is placed in the border control register.
70 Commodore 64 Graphics & Sound
100 REM RANDOM COLOURED BLOCKS 110 DIM CC(6)
115 REt~ READ COLOUR CHR$ CODE DATA 120 FOR N=1TOI6: READ CCCN): NE:x:T 130 DATA 144,5,8,159.156,30,31.158
140 DATA 129,149.150.151.152,153,154.155 145 REM CLEAR SCREE~l
150 PRINT CHR$(147)
155 REt1 SET REVERSE V IDEO Ot4 160 PRINT CHR$(18);
170 FOR N=1 TO 2000
175 REM POSITION CURSOR 180 R :::: INT(24*RND(0» 190 C = INTC40*RND(0»
200 POKE780.0:POKE781,R:POKE782,C 210 SYS65520
215 REM SELECT RANDOM COLOUR 220 K=INT(16*RND(0»+1
230 PRWT CHR$(CC(K»;" "; 240 !-lEXT
Fig. 4.7. Program to display a pattern of random coloured blocks.
Colour patterns
The program listed in Fig. 4.7 uses random values of Rand C with the direct cursor positioning routine. It PRINTs solid blocks of different colours in a random pattern all over the screen. Here reverse video is used with a space symbol to produce the coloured blocks, and colours are selected at random from the whole set of sixteen colours and set up on the screen using the CHR$ colour codes.
Another type of pattern that can produce colourful displays makes use of mirror imaging. A program to produce this type of display is listed in Fig. 4.8. Here the screen is effectively divided into four quadrants around a centre point where R= 12 and C=2~. A random point is chosen in one quadrant and a coloured block is PRINTed at that point. Next the mirror images of that point are plotted in the other three quadrants and blocks of the same colour are PRINTed. As the dots increase, a symmetrical pattern will develop, similar to the pattern produced by a kaleidoscope.
Adding Colour 71
100 REM KALEIDOSCOPE PATTERN 110 DIt1 CC(6)
115 REM READ COLOUR CHR$ CODE DATA 120 FOR N=IT016:READ CC(N):NEXT 130 DATA 144,5,8,159,156,30,31,158
140 DATA 129,149,150.151,152,153,154,155 145 REM CLEAR SCREEN
150 PRINT CHR$(147)
155 REM SET REVERSE VIDEO ON 160 PRINT CHR'(18);
170 FOR N:l TO 2000
180 Y = INT(12*RND(0»
190 X = INT(20*RND(0»
195 REM SELECT COLOUR
200 K=INT(16*RND(0»+1
210 R=12+Y:C=20+X:GOSUB400 220 PRINT CHR$(CC(K».; 11 "; 230 R=12~Y:C=20+X:GOSUB400 240 PRHH CHR$(CCCK».; 11 ".; 250 R=12-Y:C=20-X:GOSUB40B 260 PRINT CHR$(CC(K».;" ".; 270 R=12+Y:C=20-X:GOSUB400 280 PRI~H CHR'(CCCK».;" ".; 290 I'~E)<:T
300 Et·m
395 REM CURSOR POSITION SUBROUTINE 400 POKE780,0:POKE781,R:POKE782,C 410 SYS65520:RETURN
Fig. 4.8. Program to produce kaleidoscope patterns using the mirror image technique.
Coloured wallpaper
To demonstrate the effect of changing colour on the character graphics display, we can now try a program which produces simple wallpaper-style patterns in a range of colours. The program is listed in Fig. 4.9.
In this program the computer generates a random string of five to twenty characters, and then repeatedly prints the string until the screen is filled with a pattern. Between each symbol in the string a random colour code is inserted, which selects one of the first eight colours for the following symbol. The length of the string is chosen so that it is not a submultiple of 40. As a result, the pattern is printed
72 Commodore 64 Graphics & Sound
100 REM COLOURED WALLPAPER 110 Dlt'i ((8>
115 REM SET UP COLOUR CODES
12121 FOr.: t'4;'M,:1 TO 8 130 PEAI! COD
i 40 1'··IE>·;1
158 DATA 3,28,30,31,144,156,158,159 160 FOR ..T "" 1 T05iZi
1_' .. ·,.
(' ~!
175
REM SET BACKGROUND
COL..out
lBG POKE 53281·8*RND(O)+8
IS:::; REM CHOOSE STRING LENGTH 190 NC=INT(15*RND(0)+5)
200 IF INT(40!NC)=40/NC THEN 190 210 A$"'''''
21~ REM SET UP TEXT STRING
225 REM SELECT GRAPHICS COLOUR 230 f(·";3:+:RI··m «(i) "r 1
240 A$=AS+CHRt(C(K»)
245 REM SELECT GRAPHICS SYMBOL 250 A$:A$+CHR$(~54*RND(0»+161) ':::6121 [··IE;<:T
265 REM DISPLAY PATTERN
270 FOR N=lT0100G-NC STEP NC 280 pr-;.~ I t'~T i1$;
290 t'4E~!~:T
300 FOR T=lT02000·NEXT
320 Et·m
Fig. 4.9. Program to produce coloured wallpaper patterns.
at a slightly shifted position on the next row of symbols, and this produces diagonal patterns on the screen.
Each pattern is held on the screen for a few seconds by using a simple counting loop, and then the screen is cleared and a new pattern is drawn. The program generates a set of 50 patterns, but would go on producing patterns almost indefinitely if the size ofthe main loop using the variable J were increased.
To provide more variety in the patterns the background colour is set to a random colour by POKEing a number between 8 and 15 into the address 53280. This sets up one of the second eight colours for the background. You could, of course, set the background to any colour between 0 and 15, which would produce more variations, and
Adding Colour 73
it would also be possible to use all sixteen colours for the graphics symbols. Remember that you will need to dimension the array C to 16 and add the other eight data codes to the D A T A statement as well as increasing the number of items read.
Using POKEs to display symbols
Instead of using the PRINT command to write text symbols to the screen we can adopt a different approach. You will remember that the character codes of the symbols being displayed are held in the screen memory, and their position in that area of memory is directly related to their position on the screen. Thus the code for the symbol at the top left corner position is in the first location in the screen memory. If we write the character code of the symbol we wish to display into the screen memory, it will be displayed on the screen. The position of the symbol on the screen now depends upon where we place it in the screen memory.
It is convenient to denote our symbol positions in terms of the row R of text that the symbol is in, and its column position C across that row starting from the left side of the screen. Since there are 25 rows we can number them from 0 to 24, and this will be the range of values for R. Similarly, with 40 characters per row the value ofthe column number, C, will range from Oto 39. The layout of the screen memory is shown in Fig. 4.10, and you will notice that memory locations are allocated in sequence working across the rows from left to right, and then row by row down the screen from top to bottom.
To find the required memory location in the screen memory, given a row and column position on the screen, we can use the calculation
M = 1~24 + 4~*R + C
Note here that the rows are numbered starting from the top of the screen.
Having found the memory location we can insert the required screen symbol code by using a POKE command as follows:
POKE N,SC
where SC is the screen symbol code for the character to be displayed, and should be in the form of a decimal number.
There is an important difference between POKEing a character to the screen and PRINTing it. The Commodore 64 does not use the normal ASCII character coding scheme when it stores data
74 Commodore 64 Graphics & Sound
representing the displayed symbols in its screen memory. For PRINTing to the screen using the CHR$(N) format the standard ASCII coding is used, but for POKEing symbols to the screen a different set of codes is used. These are Commodore 64 screen codes. In the screen codes there are no control codes, such as for colour setting or cursor movement, and some blocks of symbols have their codes changed from their normal ASCII values.
The screen codes 0 to 31 correspond to ASCII codes 64 to 95. The codes from 32 to 63 are the same for both ASCII and screen memory. Codes 64 to 95 on the screen are equivalent to ASCII codes 96 to 127, and the screen codes from 96 to 127 produce the symbols with ASCII codes from 160 to 191.
The screen codes from 128 to 255 produce reverse video versions of the characters with screen codes from Oto 127. Thus a space which has a code of 32 becomes a filled-in block when screen code 160 (128+ 32) is used. Reverse video on the screen is obtained by simply adding 128 to the basic screen code for the symbol. The particular set of symbols displayed will still depend on whether the upper or lower case symbol set has been selected. Normally upper case is selected at switch-on, and this provides the set of character graphics symbols.
When a PRINT command is used to put symbols on the screen the colour memory locations for those symbols are automatically set up to the current text colour. An important difference when POKEing symbols to the screen is that, unlike the PRINT command, a POKE does not set up the symbol colour. Thus POKEing a screen code into the screen memory may not always produce a visible symbol unless the corresponding colour memory location is set to the required display colour code. To deal with this situation, a colour code must be POKEd into the equivalent position in the colour memory. The simplest way to do this is to set up two variables SM and CM to give the start addresses of screen and colour memory areas. Normally these would be set up as S M= 1024 and CM= 55296. Now if the position in the memory P is calculated from
P=4~*R+C
then the symbol and colour can be dealt with using
POKE SM+ P,SC:POKE CM+ P,CC
where SC is the symbol's screen code, and CC is the colour code (0 to 15) for the colour you want the symbol to have.
Adding Colour 75
Extended background colour mode
In the normal text or character graphics display mode of the Commodore 64, we have seen that changing the background colour causes the background of all displayed symbols to change at the same time. More colourful results would be possible if we could select different background colours for some areas of the screen. This can be achieved by using the Extended Background mode.
In the extended background colour mode we can set up four different background colours, and it becomes possible to allocate anyone of the four colours as the background colour for each individual character on the screen.
The display chip needs to know which background colour to display in each character space, and to do this it uses two of the data bits in the character code that is stored in the screen memory. Here a trade-off has to be made, because normally all the bits in the screen memory word are used to define the symbol to be displayed. In the extended background mode, however, the upper two bits of the code are used to define the background colour, leaving only 6 bits for the character itself. The result is that we can only have 64 displayable characters when the extended background is selected. These sym bols will, in fact, be the ones with codes from 0 to 63. Remember that here we are talking about screen data codes and not ASCII codes. The same restriction will apply if you set up a table of userdefined symbols.
To select the extended background mode we need to set bit 6 of register 17 of the VICII chip to '1', and to return to normal operation that bit must bereset to its normal '0' state. To set up the mode we can use the command
POKE 53265,PEEK(53265)OR 64
and to reset the system to the normal character display mode we use
POKE 53265,PEEK(53265)AND 191
The PEEK is included here because register 17 also controls other functions, so the states of the other bits should be preserved when switching the extended background colour bit. Note that when you switch back to the normal mode, all kinds of odd characters are likely to be displayed, because now the bits used to select the extra background colours become part of the character code.
Using two data bits there are four possible combinations of' l' and '0' states, and these will give the four alternative background
76 Commodore 64 Graphics & Sound
MS bits of Screen Background
screen code codes colour
Bit7 Bit6 (reg. address)
0 0 0 63 No.0 (53281)
0 1 64 127 No.1 (53282)
1 0 128 191 No.2 (53283)
1 1 192 255 No.3 (53284) Extended background colour mode is selected by setting bit 6 to '1' in register 17 (53265) of the VIC11 chip.
Fig. 4.10. Colours selected by the most significant bit pair of the symbol code when extended background mode is used.
colours. When both bits are at '0' the normal background colour, which is referred to as Background No 0, will appear in the symbol space just as in a normal character display.
The other three combinations of bits call up Background No.1, Background No.2 and Background No.3 as shown in Figure 4.10.
Each of the four background colours is controlled by the contents of a register in the VICll chip, and each may be set to any of the sixteen colours by simply placing the required colour number into the appropriate background colour register.
To set up the background colour in a character space, all we have to do is set the corresponding combination in the two upper bits of the screen memory word for that character position on the screen.
This is done by firstly ANDing the data already in the memory with 63, which effectively sets the top two bits at '0'; then the result is ORed with the required background colour number multiplied by 64, as shown below.
POKE M,(PEEK(M)AND63)OR(BC*64)
When you use the CHR$(N) and PRINT operation to place characters on the screen, remember that you can only use the symbols with ASCII codes from 32 to 95, which correspond to screen codes 32 to 63 and 0 to 31. Any other displayable character
Adding Colour 77
100 REM EXTENDED BACKGROUND DEMO
105 REM CLEAR SCREEN AND POKE SYMBOLS
110 PRINT CHRS(147)
120 FOR 1=0 TO 255
130 POKE1024+!,r:POKE55296+I,7 140 ~lE~<T
145 ~~Et1 SELECT E::·::THmED E:ACYCFOUr·m t"!ODE 150 POKE53265,PEEV(53265)OR64
153 REM SET EXTENDED BACKGROUND COLOURS 16fJ PO~-::E532:32.\ 2
170 POI<E532:33., 4
180 POKE53284,:3
19121 Et·m
Fig. 4.11. Demonstration of the extended background mode.
codes will produce these same symbols, but with a different background colour.
The program listed in Fig. 4.11 demonstrates this mode. This program starts by POKEing the complete set of 256 character patterns on to the screen in light blue. At this point you will note that graphics and reverse video symbols are displayed. The extended background colours are then set up and the extended background colour mode is selected. At this point you will note that all of the graphics symbols disappear, and four different background colours are presented in the four groups of 64 characters. If you want to use extended background with graphics symbols, then the required sym bols should be set up as a user-defined character set, with screen codes running from 0 to 63. This is easily done by copying the required dot patterns from the ROM character generator.
Multicolour symbol mode
Another mode which can be used to produce more colourful displays is the Multicolour mode. This allows us to choose four different colours for the dots making up the symbol.
Once again, a trade-off has to be made in order to find somewhere to store the extra colour information. This time the dots in each row of the character space are grouped in pairs, so that the character dot matrix now becomes effectively four wide by eight high. Now the two bits representing each of the adjacent dot pairs are used to select the display colour for the pair of dots.
Two of the available colours are the text colour, as read from the
78 Commodore 64 Graphics & Sound
Bit pair Register
in dot Colour address
pattern
00 Background No. 0 53281
01 Background No. 1 53282
10 Background No. 2 53283
11 Foreground Colour RAM •
Note. Only colours 0 - 7 can be set in
colour RAM when this mode is used.
Fig. 4.12. Colours produced by character bit pairs in the multicolour mode.
colour memory, and the Background No. 0 colour. This is the normal overall screen background colour. The other two colours are the Background No.1 and Background No.2 colours specified by registers 22 (53282) and 23 (53283) in the VIC11 chip. These two colours can be set to any of the sixteen available colours by simply POKEing the required colour number into the registers.
The actual colours presented by a pair of dots in the symbol space is governed by the bit state combination of the pair of bits, and is shown in Fig. 4.12. Thus if the bits are set to the combination 01 they will both be displayed in Background colour No. 1.
A point to note is that in this mode only the first eight colour numbers can be used in the colour memory. Bit 3 of the colour memory is used for control purposes when this mode is selected. The program listed in Fig. 4.13 shows the effect on standard symbols when the multicolour mode is selected. Generally this mode will be used with user-defined symbols so that the dot patterns can be selected to pick out the desired colour combinations within the symbol space.
Multicolour bit map mode
Normally in the bit map mode we have only two colours, one for the dots and one for the background. As for the text mode, there is a multicolour version of the bit map display mode. This allows a
Adding Colour 79
100 REM DEMO OF MULTICOLOUR SYMBOLS 105 REM CLEAR SCREEN
110 PRINT CHR$(147)
115 REM SET GREY BACKGROUND 120 POKE 53281111
130 FOR 1=0 TO 900 STEP 2
140 POKE 1024+1190:POKE55296+II8 150 ~~E~:T
155 REM SELECT MULTICOLOUR MODE 160 POKE 53270,PEEK(53270)OR16 1;:'13 FOr:;: J:::: 1 TO 7
18~1 FOft: K=0 TO 7
185 REM SET MULTICOLOUR REGISTERS 190 POKE53282:,.J
200 POKE53283., r.:
210 FOR T=1TO 1500:NEXT 220 1··lEin
235 REM RESTORE NORMAL MODE
240 POKE 53270)PEEK(53270)AND239 250 POKE 53281;6
Fig. 4.13. Multicolour character mode demonstration program.
Bit pair Register
in dot Colour address
pattern
0~' Background No. 0 53281
(11 Upper 4 bits Screen RAM
if' Lower 4 bits Screen RAM
11 Lower 4 bits Colour RAM Note. This mode is selected by setting bit 5 0+ 53265 and bit 4 of 53270.
Fig. 4.14. Colours produced by bit pair combinations in the multicolour bitmapped mode.
80 Commodore 64 Graphics & Sound
choice of four colours on the screen at any time. To cater for this, the horizontal resolution is reduced to 160. The scheme here is that the dot positions across the screen are taken in pairs, and each pair of dot bits indicates the colour for the pair of dots.
The technique therefore works in much the same way as for multicolour characters. Selection of the multicolour bit map mode involves setting the multicolour mode bit (bit 4 in register 22, address 53270) and also setting the bit map mode bit (bit 5 in register 17, address 53265). Colours are set up in the screen memory, colour memory and background register, and appear as shown in Fig. 4.14. and background register, and appear as shown in Fig. 4.14.
The dot plotting routine must be changed slightly to cater for the multicolour bit map mode. This is shown in the program listing of Fig. 4.15. Here the value of X is made even, by first dividing X by 2, then taking the integer value to remove any fractional part, and then multiplying by 2 to restore X to its normal range of values.
When setting the dots a colour variable C is used with a value from o to 3. This is used as a multiplier when setting the dot pattern, and effectively sets a pair of dots to the required combination. The program shown here plots random dots in three different colours. The normal line drawing routine can also be modified, if desired, so that it plots only alternate dots along the X axis. The normal line routine should still work satisfactorily with the modified dot routine, but it will plot the same pair of dots twice as it moves in the X direction.
Adding Colour 81
100 REM MULTICOLOUR BIT MAP DOTS
105 REM NEEDS M!C SCREEN CLEAR ROUTINE 1 1121 B~1::::8192
115 REM BIT MAP AT 8192 IN MEMORY 120 POKE53272,PEEK(53272)OR8
130 POKE53265.PEEK(53265)OR32
140 FOR 1=1024 TO 2023:POKEI,37:NEXT 15>3 S',.'S49152
16(1 GOTO 1 0013
195 REM PLOT MULTICOLOR DOT 20(1 ;:·:;:::::2:+: I tH ex ... '2;,
210 P=BM+320*INT(Y!8)+8*INT(X!8)+(YAND7) 220 CP:::::C*2t(6-(XAND7»
230 POKE P,PEEK(P) OR CP
240 FETUF::t·l
1000 FORI:::::0T0999:POKE55296+!,7:NEXT 1005 REM SELECT MULTICOLOUR MODE 1010 POKE53270,PEEK(53270)OR16
1020 FOR N=l TO 200
1030 X=INT(318*RND(0»
1040 Y=INT(198*RND(0»
1050 C=i+INT(3*RND(0)
1060 GOSUB212JO
i tl70 'r'='1'+ 1
1 ~3:30 GOSUB20€1 1090 HE:'(T 110121 Ef-W
Fig. 4.15. Program to plot random coloured dots using the multicolour bit map mode.
Chapter Five
Setting Objects in Motion
For most computer games, particularly the arcade type, an important feature is the display of moving objects on screen. Computer displays of this type make use of the basic principles of the cartoon film. A sequence of pictures is produced, and the individual pictures or 'frames' are presented in rapid succession on the screen. The moving object is drawn in a slightly different position on each successive picture, and because the viewer's eyes retain each image for a short time after it has disappeared, successive pictures merge together and the object appears to move smoothly across the screen.
The television pictures producing the computer display are also being presented in rapid succession, so if an 0 bject on the screen is moved to a new and slightly different position on successive display scans then the object will appear to move over the screen. To achieve reasonably smooth movement, the changes between pictures are made at least once every 1/ 10 second. If the movement steps are small, the movement will appear to be smooth but slow. With larger steps between successive pictures the motion becomes faster but may tend to appear jerky.
In the simplest form of animation an object such as a ball, alien invader or spaceship is moved from one character position to the next either left, right, up, down or possibly diagonally. For more realistic results, the object on the screen may need to change shape as it moves. An example of this would be a man walking across the screen. If the image of the man remained constant he would appear to glide across the screen rather like an ice skater. To give the impression of walking or running the position of the legs, and perhaps the arms too, must be changed regularly. In effect a series of 'snapshots' of the action of walking are presented in rapid succession. Most actions such as walking are repetitive, so perhaps three or four different images may be used, and the sequence is
Setting Objects in Motion 83
simply repeated at different screen positions as the man moves across the display. When animating an object, and particularly a familiar real-life object, it is important to study how it moves carefully if you want to get realistic animation.
A simple moving ball
For many games-type programs a simple object such as a ball moves around the screen. This is fairly easy to achieve by using character graphics on the normal text display screen. On the Commodore 64 there is a convenient symbol which displays a circle giving a good representation of a ball. This has the display code 87, or 81 if you want the circle filled in with text colour.
Let us start by placing the ball somewhere near the middle of the screen, by POKEing its code into screen memory location 1524. Remember that screen memory runs from 1024 to 2023. Remember, too, that you need to POKE a colour number into the corresponding position in the colour memory. A variable P may be used to keep track of the position of the ball. It is convenient to let P run from 0 to 999 and add P as an offset to either the colour memory address (CM) or the screen memory start address (SM). These two variables are set to 1024 and 55296 at the start of the program.
To move the ball to the right we want to POKE it into memory location 1525. Having POKEd the symbol into the new position we must now erase the original symbol, otherwise we shall end up with a trail of balls across the screen. This is easily done by POKEing 32 (a space symbol) into location P. Now the value of P is updated by making it equal to PN so that it still points to the current ball position. This process is then repeated to make the ball move to the right across the screen. This can be done by using a routine such as the following:
5~~ PN=P+I
51~ POKE SM+PN,87:POKE CM+PN,7 52~ POKE SM+ P,32
53~ P=PN
54~ RETURN
Here the ball colour is 7 (yellow), which shows up well on the blue background. Each time the ball is to be moved we simply use a GOSUB5~~ statement in the main program. To move the ball to the
84 Commodore 64 Graphics & Sound
left we need to make PN equal to P-I when calculating the new position for the ball in line 5~~.
For vertical motion of the ball the calculations have to be a little different. In the screen memory each row of text takes up 40 memory locations. Now if we want to move the ball to the space immediately below its current position, P, we shall have to add 40 to P to get the required value for PN. Apart from this change the routine would be the same as for moving the ball horizontally. If we want to move to the position immediately above the current one then PN is obtained by subtracting 40 from P. As for the sideways motion, the ball is blanked from position P by POKEing 32 to that location before Pis updated to its new PN value, ready for the next move.
Moving diagonally is a little more complicated because we have a combination of left-right and up-down movements. To move up to the right we have a right move (+ I) and an up move (-40), so P needs to have 39 subtracted from it to get the new position. Figure 5.1
•
shows the change in the value of P required for making a single step
in each of the eight basic directions. This figure assumes that the ball is at location P, which would be at the centre point of the diagram.
P-41
P-48
P-39
P-1
P+1
P"39
P"48
P"41
Fig. 5.1. Required changes to the POKE address in the screen memory for one symbol space movement in the eight main directions of motion.
Setting Objects in Motion 85
Movement using PRINT and cursor set
Instead of POKEing the ball symbol to the screen we could, of course, PRINT it. Here the cursor can be set directly to a row Rand column C position by using the direct cursor set routines described in Chapter 2. To move to the right C is increased by 1, and to move left C is reduced by 1. For an upward step the value of the row R is reduced by 1, and to move down, the row is increased by 1. Diagonal motions involve combinations of these steps as shown in Fig. 5.2. In the PRINT statement a semicolon should be included after the string or CHR$ code for the ball symbol.
R-1.C-1
R-1.C
R-1 ... C+1
R .. C+1
R+1 .. C-1
R+1 .. C
R+1 .. C+1
Fig. 5.2. Changes in R,C values needed for different directions of motion when using PRINT.
The previously displayed ball has to be blanked out, of course.
Here the cursor is set to the current ball position and a blank space is printed. Then the new values for R, C may be calculated and the cursor repositioned to allow the ball to be printed.
Bouncing off the walls
If you tried moving the ball using the simple program sequence we have just discussed problems would soon arise. Suppose we start with the ball at the centre of the screen and then move it step by step to the right. All will be well until the ball reaches the edge of the screen and then, on its next step, the ball will go off the right edge and reappear at the left side of the screen on the next line down. If the ball is moving to the left it will reappear at the right, one line
86 Commodore 64 Graphics & Sound
higher. If the ball were to run off the top or bottom of the screen the symbol would be POKEd into memory outside the screen memory, and could cause the program to fail; worse still, it could lock up the whole computer system. To avoid this state of affairs we can arrange that when the ball reaches one of the edges of the screen this is detected, and the direction of motion is reversed. This way when the ball reaches a screen edge it is reflected back towards the middle, as if it had bounced off a wall.
This bouncing action is fairly easy to achieve. The technique is to draw a border around the screen using four different graphics symbols. At the right we might use symbol 97, which has its left half lit, while at the left we would use symbol 225, which has its right half lit. For the top and bottom the symbols with codes 98 and 226 respectively are used. A problem occurs in the corners, and here a solid block (code 160) is used. If this were not done the ball might escape through the corner and result in numbers being POKEd into memory areas outside the screen memory.
Now we can allocate two new variables, DX and DY, which give the change in PC required for horizontal or vertical steps. Thus DY would be 40 for moving down, and DX would be I for moving right. Now PN is calculated by adding the current values for DX and DY to PC. When we want to reverse the sideways motion we simply invert the sign of DX by using
7~~ DX=-DX
and to reverse the up-down motion we apply the same process to DY. When only up-down motion is required then DX is set to zero, and for sideways motion DY is set at zero.
Having calculated PN we can detect a screen edge by PEEKing the contents of location PN. The value we get is now compared with the character codes for the edges of the screen. If a match is detected with one of the right or left edge symbols the sign of DX is reversed, and the movement of the ball symbol is skipped so the ball stays where it is. On the next move, however, the left-right motion is reversed, and the ball will move back away from the edge of the screen. If the symbol detected is one of those at the top or bottom of the screen then the sign of DY is changed, and here the up-down motion of the ball is reversed on the next step. If a corner is detected both DX and DY are reversed in sign.
The result is that the ball appears to bounce off the walls, and this is demonstrated by the program listed in Fig. 5.3. In this program the first section from line ll~ to line 28~ simply clears the screen and
Setting Objects in Motion 87
10e REM BOUNCING BALL 110 SM~1024:CM=55296 115 REM CLEAR SCREEN 120 F'RItH";j"
125 REM DRAW BORDER 130 FOR J=1 TO 38
140 F'OKESM+J,9S:POKECM+J.5 150 t'~Ein
160 FOR j~79 TO 983 STEP 40 170 F'OKESM+J.97:POKECM+JJ5 180 ~lE:M:T
190 FOR J=961 TO 999
200 POKESM+JI226:POKECM+j,5 210 NE:"':T
220 FOR J=40 TO 920 STEP 40 230 POKESM+J,225:POKECM+J.5 240 t,jE:":T
245 REM FILL CORNERS 250 POKESM.160:POKECM.5
260 POKESM+39,160:POKECM+39,5 270 POKESM+960,160:POKECM+960,~ 280 POKESM+999,160:POKECM+999,5 285 REt1 SET START POS I T I ON
290 PC=200+300:4d~:ND(0)
295 REM SET START DIRECTION 300 D)t:= 1 : D1t'=40
305 REM BALL MOVEMENT LOOP 3lB'FOR N=lTO 1500
320 GOSUB50el
330 ~lEXT
340 E~m
495 REt1 BALL t10VE SUBROUTmE 500 Pr4=PC+ DX+ DY
505 REM CHECK FOR EDGE OF SCREEN 507 REM At'm APPLY BOUNCE ACT I Or~ 510 I F PEEK (St1+PN) o 160 THEN 530
520 DX=-DX: D'T'=-DY: PN=Pr4+DX+DY: GOT0610 530 I F PEEK (St1+P~4) ()98 THEt,j 550
540 DY=-DY:PN=PN+DY:GOT061B
550 IF PEEK(SM+PN)()97 THEN 570 560 DX=-DX:PN=PN+DX:QOT0610
570 IF PEEK(SM+PN)()226 THEN 590 580 DY=-D,': PH=PN+II'T'; 00T0610
590 IF PEEKCSM+PN)()225 THEN 610 600 DX=-DX:PN=PN+DX
88 Commodore 64 Graphics & Sound
605 REM MOVE BALL
610 POKESt1+PN J 67 : POKECM+PN J 7 620 POKES~1+PC I 32 : PC=PN
6313 RETURN
Fig. 5.3. Program to demonstrate a bouncing ball animation routine.
draws in the border. The ball starts off at a random point somewhere around the centre of the screen memory, and is initially sent off diagonally downward and to the right. The ball movement and edge detection are carried out in the subroutine starting at line 5~~.
If PRINT is used to draw the ball then the bounce can be initiated if C=~ OR 39 for the X direction reversal. Similarly if R=~ OR R=24 the up-down (Y) motion could be reversed. Here it is easier to compare row and column values with the edges of the screen rather than checking for a border symbol.
Thus the check and bounce operation becomes as follows:
6~~ IF R=24 OR R=~ THEN DY=-DY 61~ IF C=39 OR C=~ THEN DX=-DX
This assumes that the movement is stepping one symbol space at a time. For faster movement, of course, the ball could be moved two or three spaces at a time. In this case the test needs to be altered to detect <~ OR>N where N is either 24 or 39 according to whether the row or column limit is being checked. To prevent PRINTing off the screen, the actual PRINT step should be skipped after a limit is detected.
Detecting collisions
In many games the ball has to be hit by a bat. In others missiles are fired, and we need to know if they have hit their target. The basic principle for detecting collisions or hits is the same as that used for detecting the border in the ball routine. The new location of the object is checked by using a PEEK command before the object itself is moved. The contents of the location are then compared with possible objects that could be there, and then appropriate action is taken.
Sometimes we may want to move an object over a background scene without erasing the background. In this case, before the moving object symbol is POKEd into its new position the character code at the new location PN is PEEKed and stored as a variable,
Setting Objects in Motion 89
such as Cc. On the next move this code is POKEd back into its original position again.
If PRINT is used to display the moving object, any collisions that occur may be detected by PEEKing as described above. An alternative approach is to keep track of the positions of all objects that are moving on the screen and these are compared for possible matches at each movement step. Ifthere are several objects this can become a complex exercise.
In general, if collisions and hits are to be detected it is probably much easier to use sprite graphics, where the VICII chip does the checking for you. We shall be exploring sprite graphics in the next chapter.
Scrolling the screen
One method of producing movement in the screen display makes use of an action called scrolling. If you are in the normal text mode, for example while typing in a program, and the display has reached the bottom line of the screen, you will notice that when the bottom line is completed the whole display moves up by one line. This leaves a blank line at the bottom ofthe screen ready to accept new input. This action is known as 'scrolling'; the effect is like a paper scroll moving past a window represented by the screen. Each time the display is scrolled upward the original top row of text is lost, and a new row may be entered at the bottom.
By writing some routines to shift the data stored in the screen and colour memories it is possible to make the display scroll down the screen so that new data may be entered on the top line. It is also possible to carry out sideways scrolling from left to right or vice versa. With sideways scrolling a complete column of symbols is moved off one side of the screen and a new column of symbols is moved in from the opposite side.
The actual process of scrolling involves transferring the contents of the screen memory one position to the right, left, up or down. Suppose we want to scroll to the right. Starting with the top row of the display the 38th character is copied into the 39th position, then the 37th is moved to the 38th position, and so on until the whole row has moved one space to the right. Then all the other rows are moved in the same way. You could write a BASIC program to perform this action by PEEKing locations in the 38th column, then PO KEing the result into column 39, and so on. You will find, however, that it takes
90 Commodore 64 Graphics & Sound
START LOY #39 Column count
LOA #0 From address
CLOOP STA 251
LOA #4 in 251/252
STA 252
LOA #1 To address
STA 253
LOA #4 in 253/254
STA 254
LOX #25 Row count
RLOOP LOA 251, Y Move one byte
STA 253,Y screen memory
CLC
LOA 252 Update
AOC #212 pointers
STA 252 to
CLC colour
LOA 254 memory
AOC #212
STA 254
LOA 251,Y Move colour
STA 253,Y memory byte
SEC
LOA 252 Restore
SBC #212 pointers
STA 252 to
SEC screen
LOA 254 memory
SBC #212
STA 254
CLC
LOA 251 Update
AOC #40 pointers
STA 251 to
LOA 252 next
AOC #€1 row
STA 252
CLC
LDA 253
ADC #4€1
STA 253
LDA 254
ADC #0
STA 254
DEX
BEQ NEXTC Column done?
JMP RLOOP
NEXTC DEY
BMI OONE All done?
JMP CLOOP
DONE RTS
Fig. 5.4. Assembly code routine to scroll the screen tothe right byone column
position. Setting Objects in Motion 91
several seconds to scroll the entire screen one column to the right. Scrolling the screen using BASIC is too slow to be of much use for animation. To produce faster scrolling the movement of data in the screen memory is usually carried out by machine code routines. The Commodore 64 already has a machine code routine for scrolling the screen up and this can automatically be brought into play by printing to the bottom row on the screen.
100 REM SCROLL RIGHT ROUTINE 110 REM USING MACHINE CODE i2~ REM CALL WITH SYS49152 130 T:::::0
140 FOR N=49152 TO 49246 150 READ A:POKE N~A:T=T+A ise t'~D::r
170 READ C
1 :3el 1FT 'OC THEN PF.: I t-H" DATA EF.:ROR " 190 F'R I ~-!T ,: LOADED OK Il
200 DATA 160~38)i69,0,133.251)169~4
210 DATA 133,252,169,1,133~253,169,4
220 DATA 1331254,162~25,177,251~145~253 230 DATA 24.165,2521105,212,133,252124 240 DATA 165,254,lB5)212,133~254,177,251 250 DATA 145,253,56J165,252,233,212;133 260 DATA 252.561165,254.233~212,133,254 270 DATA 24,165,251,105,40,133,251,165 280 DATA 252,105.0,133,252,24,165,253 290 DATA 105,40,133,253,165,254.i05,0 300 DATA 133.254.202,240,3,76,20.192
310 DATA 136,48,3,76,2~192196114210
Fig. 5.5. BASIC program to load the machine code scroll right routine.
If you want to scroll the screen sideways or downwards a machine code routine has to be written for this function. The assembly language program listed in Fig. 5.4 provides a machine code routine to scroll the screen to the right. This routine in fact scrolls both the screen memory and the colour memory at the same time. To get the routine into the Commodore 64 the data representing the machine code instructions is loaded into the computer memory using the short BASIC program listed in Fig. 5.5. This machine code routine starts at location 49152 and takes up 96 bytes of memory. It may be called from a BASIC program by using the statement
SYS49152
92 Commodore 64 Graphics & Sound
Since the machine code is stored above the memory area used by BASIC you can type NEW and load another BASIC program without affecting the scrolling routine, which remains in memory until the machine is switched off.
As usual, some care is needed when typing the DATA statements.
Any error can produce unpredictable results when the machine code is run, and will probably cause the whole computer system to lock up. A simple check routine has been built in which should pick up most errors and give a warning message. This adds up all of the DA T A items and compares the result with a test total which is stored immediately after the machine code data. If the test checks out the computer will print 'LOADED OK'. The check is not infallible, since two errors may cancel one another to give the correct check result or one of the data items with a zero value may have been omitted, so it is as well to check the DATA statements anyway. Once a correct version is obtained, save it on tape for future use.
11360 REM SCROLL RIGHT DEMO
1005 REM NEEDS M/C ROUTINE LOADED 113131 REM INTO MEMORY AT 49152 1010 FOR N=l TO 100
102121 C=t'l R!'lD 15
1030 FOR K=lT08:SYS49152:NEXT 1040 FOR J=6T0960 STEP 46
1850 POKE1024+J;42:POKE55296+J,C 1666 t·lE;>::T
107el !-lEx:T
168121 Et·m
Fig. 5.6. BASIC program to demonstrate the action of the scroll right routine.
The program listed in Fig. 5.6 can be used to demonstrate the scroll right routine. It may be added to the end of the loading program of Fig. 5.5 or loaded separately. When RUN, this program should produce a display of vertical coloured bands of * symbols scrolling to the right across the screen. Press RUN/STOP to stop the program and then RUN/STOP with RESTORE to return to normal BASIC operation. Note that when a new column of stars is POKEd into column 0 of the screen memory a column of colour codes must be POKEd into the colour memory as well. If you only want to load the scroll routine, just run the program listed in Fig. 5.5.
Setting Objects in Motion 93
Scrolling to the left
For games programs such as Defender a landscape moves across the bottom of the screen from right to left, and this effect may be achieved by scrolling the entire screen to the left and inserting new data at the right-hand side.
The program listed in Fig. 5.7 will load a machine code routine to scroll the screen to the left. This routine is loaded into memory just above the scroll right routine. The machine code starts at location 49254 and uses 96 bytes of memory. It may be called from BASIC by using the statement
SYS49254
In this routine the symbols in column 2 of the screen are moved to column 1, then column 3 moves to column 2, and so on across the screen. New data may then be placed in column 39 ready to scroll across the screen. Once again, a careful check should be made for
100 REM SCROLL LEFT ROUTINE 110 REM USING MACHINE CODE 126 REM CALL WITH SYS49254 13iZI 1-"0
140 FOR N=49254 TO 49350 150 READ A:POKE N,A:T=T+A 160 t-lE::·::T
170 r.:EAD C
1:30 IF 1':::>C THai F'RH·iTPDATA EF.:ROR" 191~ FR I nr: LOADED Of<"
200 DATA 160.0.169.1.1331251.169,4
210 DATA 133.252,169.0.1331253,169,4 220 DATA 133,254.162,25,177,251,145,253 236 DATA 24,165,252.105.212.133.252,24
250 DATA 145.253.56,165.252,233,212.133 260 DATA 252.56.165,254,233,212,133.254 270 DATA 24,165;251.105,46,133.251.165 280 DATA 252,105,0.133,252,24.165.253 290 DATA 105.40.133.253.165;254,105;0 388 DATA 133,254,202.240,3.76,122,192 310 DATA 266.192.39,240,3,76;104,192 320 DATA 96.14863
Fig. 5.7. Program to load a machine code routine to scroll the screen to the left.