Brilliant engineers at Commodore tried to address most of these issues in this next model (and as it turned out later, the last 8-bit computer by Commodore). BASIC 7.0 is much improved comparing to version 2.0 seen in C-64. It offers keywords that take advantage of the built in graphic and sound hardware as well as memory management (bank selection with BANK command) without the need of remembering the addresses of all the involved hardware registers. The new BASIC also adds some structural constructs like multiple line IF/THEN/BEGIN/BEND decision branches, open-ended (with optional condition) flow/loop control constructs like DO/WHILE/LOOP, DO/LOOP/WHILE, DO/UNTIL/LOOP, DO/LOOP/UNTIL in addition to standard BASIC's FOR/NEXT loop. C-128 offers so much more than C-64 that in fact I put it on my permanent retro-computer desk and replaced C-64 that was there before. Now I have 3-in-1 system (C-64, CP/M and C-128) taking up only slightly more space than C-64.
To do a little BASIC 7.0 exercise, I decided to write a simple analog clock application that would use the basic graphic capabilities of the machine. I will add sound/alarm abilities to it later, it should be as easy as graphics part with all the extensions that BASIC 7.0 provides.
To switch C-128 to high resolution mode (or a bitmap mode), BASIC command GRAPHIC is used.
Formats: GRAPHIC mode, [clear], [split]
Where mode can be one of:
0 - 40 columns (composite or monochrome monitor, tv set),
1 - hi-res graphics (composite or monochrome monitor, tv set),
2 - hi-res graphics (split screen, the same type of output like 0 or 1),
3 - multicolor graphics (the same output as above),
4 - multicolor graphics (split screen, the same output as above),
5 - 80 columns (RGB or monochrome monitor).
I did not mention before that C-128 features 2 separate video output ports, the composite/TV and RGB. Composite/TV output is of the same format as C-64 video output, that provides 40 column text and high-resolution (320x200) graphics mode as well as other graphics modes (multicolor). Technically it is possible for C-128 to work with two monitors at the same time, one RGB and one composite (or a TV set). This is the setup that I have. User can freely switch between these modes in immediate mode and in program mode where application can output text to 80-column (RGB) monitor while drawing graphics on the composite monitor or alternate text output to both monitors by switching the modes with GRAPHIC command. I think this is pretty cool for a 8-bit 30 years old computer to be able to do that.
The "GRAPHICS CLR" command is NOT a screen clearing command. It clears and de-allocates memory used for graphics operations reclaiming it back for BASIC. To clear any given graphics mode, use flag clear in the GRAPHIC command or command SCNCLR.
You may want to use "GRAPHIC CLR" if you run out of memory for BASIC and you're no longer using hi-res graphics.
Flag split lets user have graphics and text on the same screen, thus allowing to present text output of the application in the more convenient text mode while having hi-res picture on top of it as well as allowing the standard text input from user (INPUT command). The number used in split tells BASIC interpreter at which line number the split screen starts. The text can also be mixed with graphics on the hi-res screen, but BASIC command PRINT can not be used for that - CHAR command is the graphics command designed for that purpose.
To draw a circle in one of the bitmap modes, BASIC command CIRCLE can be used:
Format: CIRCLE color_source, x_center, y_center, x_radius, y_radius, [start_angle], [end_angle], [rotation], [segment]
Computer must be in proper graphics mode to be able to draw a circle.
The color source is a number from 0 to 3, as in the COLOR command:
0 - 40-column (composite) background,
1 - 40-column foreground,
2 - multicolor 1,
3 - multicolor 2.
The COLOR command stores a color into the color source register.
Format: COLOR color_source, color_number
Please refer to the C-128 system guide for the colors and their assigned numbers.
BASIC command DRAW puts a line on the hi-res screen.
Formats: DRAW color_source, x1, y1 [TO x2, y2]
DRAW TO x, y
DRAW is used to draw points and lines in the hi-res and multicolor modes. It can draw a line from one specified location (x1, y1) to another (x2, y2) or from the current graphic cursor position to the specified coordinates (DRAW TO). If the 1st format is used but the 2nd set of coordinates is ommited (TO x2, y2), a point is turned on. The color_source as in COLOR and CIRCLE commands tells BASIC which color to use for a point/line. This can also be used to remove existing points or lines, when we draw with background as a color source (color_source=0). You can also specify relative coordinates by supplying a distance and an angle. This method of locating a point requires to use semicolon in the command.
Example: GRAPHIC 1:LOCATE 50,50:DRAW 1,25;90
will plot a point at coordinates 75,50.
Example: DRAW 0,160,100 to 50;hr%*(360/12)+(mi%/15)*(360/48)
will plot a line from point at coordinates 160,100, length=50 at the angle calculated from hr% and mi% variables (this particular example shows how to draw a small hand of the analog clock).
Without further ado, let me present the BASIC code that will display graphical (very simplified) analog clock image that is updated every minute (except seconds which are drawn more often) based on the system time TI$. I used petcat program (part of the WinVICE Commodore emulator software) to convert native BASIC code (PRG) to the text format.
petcat -70 -o analogclock.txt -- analogclock.prg
10 rem analog clock v1.0
20 rem (c) by marek karcz 2014
30 rem all rights reserved
50 rem variables
80 input "set time (hhmmss) ";tm$
900 goto 10000
1000 rem initgr
1010 graphic 1,1:width 2
1020 color 0,1:color 1,6:color 5,6
1030 circle 1,160,100,110,90
1050 rem draw short hand
1060 draw 1,160,100 to 50;hr%*(360/12)+(mi%/15)*(360/48)
1080 rem draw long hand
1090 draw 1,160,100 to 90;mi%*(360/60)
1130 rem eraseshorthand
1140 locate 160,100
1150 draw 0,160,100 to 50;hr%*(360/12)+(mi%/15)*(360/48)
1170 rem eraselonghand
1180 draw 0,160,100 to 90;mi%*(360/60)
1200 rem gethr
1225 if hr%>11 then hr%=hr%-12
1240 rem getmi
1280 rem getsec
1320 rem draw seconds
1330 char 1,0,24,se$,1
1350 rem gethrmi
10000 rem main
10010 gosub 1000
10015 gosub 1200:gosub 1240:gosub 1280:rem get hr%,mi%,se%
10017 rem gosub 1050:gosub 1090:rem draw hands
10025 gosub 1350:get hrmi
10030 if pr%<>hm% then begin:
10040 gosub 1130:gosub 1170:rem erase hands
10050 gosub 1200:gosub 1240:rem get hr%,mi%
10060 gosub 1050:gosub 1090:rem draw hands
10080 gosub 1280:rem get se%
10090 gosub 1320:rem draw seconds
10110 loop:rem loop forever
Thanks to support for graphics modes in BASIC, code is short and clear.
Because image speaks 1,000 words, here are some pictures of this code in action:
Thank you for your time.
COMPUTE!'s 128 Programmer's Guide, ISBN 0-87455-031-9.