The Commodore 128: A Hands-On Report
Tom R. Halfhill, Editor
Commodore's new three-in-one machine, the Commodore 128 Personal Computer, should be hitting store shelves in June. In mid-March, COMPUTE! visited Commodore's U.S. headquarters in West Chester, Pennsylvania to more closely examine the 128, which was announced at the Winter Consumer Electronics Show in January (see "The Next Generation: New Computers at the Winter CES," April 1985). Although a few specifications were not finalized, we found the 128 to be a versatile machine with one of the most powerful BASIC programming languages ever offered in a microcomputer. Here's our report.
One of the most imitated trends in personal computing lately has been "integrated software"—products that are actually three or more programs in one, like Lotus 1-2-3.
Now Commodore is introducing a fresh twist—integrated hardware. With the Commodore 128 Personal Computer, essentially Commodore is wrapping up three computers in one box to sell for under $300 retail. The deceptively small package contains:
- A standard Commodore 64 with 64K of Random Access Memory (RAM) capable of running virtually all existing 64 software—estimated at 6,000 to 10,000 programs, mostly home and educational.
- An enhanced Commodore 64 with 128K of RAM and an extremely powerful new BASIC that almost makes PEEK and POKE obsolete.
- A Z80-based 128K computer designed to run existing software written for the CP/M (Control Program for Microcomputers) operating system—at least 10,000 programs, mostly business/professional.
Expandable to 512K with a RAM disk option, the Commodore 128 also works with all Commodore 64 peripherals as well as a new line of accessories, such as the much faster 1571 disk drive. Rounding out the package are such features as 80-column video in the 128K and CP/M modes, RGB (red-green-blue) high-resolution video output, and all the same ports and interfaces found on the Commodore 64.
Before the Commodore 128 was announced at the Winter CES, rumors indicated it would simply be an expanded Commodore 64. Even after it was unveiled, some people described it as a CP/M computer with a Commodore 64 emulation mode.
But the Commodore 128 truly is the near-equivalent of three computers in a single box. Outside, all three computers share the same sleek plastic case and 92-key key-board. Inside, they share the same RAM chips and power supply, but that's about all. The 128 actually contains three separate central processing units (CPUs), two separate BASICs, two independent video display chips, separate banks of Read Only Memory (ROM), and even different memory maps, depending on which mode is selected. What's more, the machine can be operated in five distinct modes: Commodore 64 mode, 128 mode with 40-column video and graphics, 128 mode with text-only 80-column video, CP/M mode with 80-column video, and CP/M mode with 40-column video.
CPU chips include the 6510 for 64 mode and the 8502 for 128 mode—both 6502-compatible—and the Z80A for CP/M mode. Video chips include the VIC-II for 64 mode and 40-column 128 mode, plus an 80-column chip for 80-column 128 mode and CP/M mode. A synthesizer chip—the Sound Interface Device (SID)—is shared by all three microprocessors. Programming languages include BASIC 2.0 in 64 mode and BASIC 7.0 in 128 mode, and a machine language monitor is available in 128 mode and CP/M mode.
Does all this sound confusing? Don't feel bad—it is. Even when using the Commodore 128, you can sometimes forget which mode the computer is in. This is especially true of the 64 mode and 40-column 128 mode, which appear virtually identical on screen.
Furthermore, some modes let you switch to other modes, but not back again without restarting the machine. And speaking of cold-starts, the Commodore 128 can be switched on in any of its five modes, depending on its state at power-up. When you hit the power switch, the computer first checks to see if a CP/M system disk is inserted in the drive. If so, it defaults to 40- or 80-column CP/M mode (usually 80 columns). Otherwise, it checks the cartridge slot for a Commodore 64 cartridge program. If it finds one, it automatically switches to 64 mode and runs the cartridge. If there's no 64 cartridge, the computer checks for a 128 cartridge. If it finds one, it comes up in 128 mode (either 40 or 80 columns) and runs the 128 cartridge. If no 128 cartridge is plugged in, the computer checks to see if its 40/80 DISPLAY key is pressed. If so, it starts up in 80-column 128 mode. Otherwise, it switches to 40-column 128 mode.
With so many options, operating the Commodore 128 will take some getting used to.
One of the biggest questions about the Commodore 128 is its degree of Commodore 64 compatibility. Stung by criticism and slow sales because of the Plus/4's lack of 64 compatibility, Commodore went to great lengths to make sure the 128 would run all existing 64 software. In fact, Commodore claims the 128 is 100 percent 64 compatible.
Our tests showed the 128 had no trouble with a wide range of Commodore 64 programs written in BASIC and machine language. We ran a number of programs published in recent issues of COMPUTE! and COMPUTE!'s GAZETTE, including SpeedScript 3.0. Only one program failed: "TurboDisk" (COMPUTE!, April 1985). TurboDisk, a machine language utility which speeds up disk loading by as much as 300 percent, ran fine on a 128 hooked up to a 1541 disk drive, but would not work on a 128 connected to the new 1571 disk drive. We weren't particularly surprised, because TurboDisk works by reprogramming the load routines both inside the computer and in the drive. Any drive that isn't completely 1541-compatible cannot handle TurboDisk.
Since the 1571 is designed to be much faster than the 1541, it may seem that utilities such as TurboDisk are superfluous anyway. However, keep in mind that the 1571, like the Commodore 128, is a multimode device. When the 128 is operating in 64 mode, the 1571 drive behaves just like a 1541—it stores 170K of data per disk and runs fairly slow. When the computer is switched to 128 mode, the 1571 speeds up about 500 percent and becomes a double-sided drive, storing about 360K per disk. And when the computer is in CP/M mode, the 1571 runs about 12 times faster than a 1541 and stores 410K on a floppy.
In CP/M mode, the 1571 also is supposed to read disks in IBM System 34 format, such as those made for Osborne and Kaypro CP/M computers. However, the 1571 drive we tested would not load our Osborne disk. A Commodore representative told us the 1571 we were using was still a prototype, and that final production models definitely would read CP/M disks. He also said that production 1571s would be fully 1541 compatible, so that programs like TurboDisk should work too.
If the final 1571s are not completely 1541 compatible, Commodore will run into trouble on another front—commercial copy protection. Some copy-protection schemes depend on precise timing and certain routines within the 1541 disk drive ROMs. If much is changed, the disks won't load. Before acquiring a Commodore 128 and 1571 drive to run 64 software, it would be a good idea to try loading some commercial disks first to make sure they work.
The best news about the Commodore 128 is BASIC 7.0, the powerful BASIC interpreter available in 128K mode. It is, perhaps, the most powerful BASIC ever offered in a personal computer—more complete than even IBM BASIC and MSX BASIC. It contains all the commands in Commodore 64 BASIC 2.0, all the disk and file commands of BASIC 4.0 (as found on the Commodore 8032 and Super-PET), and nearly all the graphics and sound commands of the Super Expander 64 cartridge, Simon's BASIC, and the Plus/4's BASIC 3.5.
BASIC 7.0 makes it possible to draw graphics, define and move sprites, create sound effects, and play music without PEEKs, POKEs, or machine language. Sprite movement is implemented during a machine-level interrupt, so a few BASIC statements can keep up to eight sprites moving simultaneously while the program performs other tasks—or even stops. To make it easier to define sprites, you can grab any predrawn shape off the screen and store it as sprite data, or design the sprite bit by bit with a built-in sprite editor. Playing music with the SID chip has always been tedious because of the large number of POKEs required, so BASIC 7.0 has ten predefined musical instrument sounds available with a single command.
Because BASIC 7.0 is so extensive, we can't explain every command in detail, but we can cover some highlights. Remember that some specifications or syntax rules may have changed by the time the Commodore 128 entered final production.
The disk and file commands include DLOAD and DSAVE (for loading and saving to disk without adding ,8 to the filename); DVERIFY (compare a disk file with a file in memory); CATALOG and DIRECTORY (for displaying disk directories without erasing a BASIC program in memory); COPY (duplicate a file using dual drives); BACK-UP (copy an entire disk with dual drives); APPEND (open a sequential file for updating); COLLECT (reorganize the Block Allocation Map); CONCAT (combine two disk files); HEADER (format a disk); RENAME (assign a new filename to an existing file); SCRATCH (delete a file); DOPEN and DCLOSE (open or close a disk file); DCLEAR (close all disk channels); RECORD (for positioning the relative file pointer); DS and DS$ (read the error channel); BLOAD (load a binary machine language file); BSAVE (save a block of memory as a binary file); and BOOT (load and run a machine language file).
Note that none of these commands adds new capabilities not available with a Commodore 64 and 1541 drive; they merely simplify the syntax. For example, COLLECT is equivalent to OPEN 15,8,15, "V0":CLOSE 15. The commands can also be abbreviated, as in DSHIFT-L for DLOAD or even SHIFT-RUN/STOP to automatically load and run. In addition, the special function keys are preprogrammed to execute certain frequently used commands, such as DIRECTORY.
Sprite commands not only replace the old-fashioned POKEs, but also offer more options. And the demo programs we saw proved that BASIC 7.0 can move sprites fast enough for good-quality games without machine language.
Entered in direct mode, this command activates the built-in sprite editor. An editing window appears on screen, and you're prompted to select sprite 1 through 8. A number of subcommands let you clear all the sprite data, move a crosshair, turn pixels on and off, and change colors for multicolor sprites. When you're done designing the sprite, you reenter BASIC by pressing SHIFT-RETURN, then RETURN again. BASIC 7.0 does not require you to set aside memory for sprite data; instead, it reserves a 512-byte block (for eight 64-byte sprites) beginning at location 3584 ($E00 hex).
SPRITE #,on/off,foreground, priority,X,Y,mode
Sets up various sprite attributes, including sprite color, foreground/background priorities, initial X and Y position, and single color/multicolor.
Defines the multicolor registers shared by all sprites.
SPRSAV sprite #,string SPRSAV string,sprite#
Moves sprite definition data into a string or vice versa. For example, you can define a sprite by first drawing a shape on the screen with various graphics commands, then copy the shape into a string with the SSHAPE command, and finally move the string into the sprite data block with SPRSAV. You could also copy the sprite pattern directly to the screen with SPRSAV and GSHAPE.
Moves a sprite to the horizontal and vertical screen coordinates specified by X,Y. This is called absolute movement and is like the POKEs used to move sprites to screen positions on the Commodore 64.
MOVSPR sprite#, + /-X, +/-Y
Moves a sprite plus or minus the number of screen coordinates specified by X,Y. This is called relative movement and is useful when you don't know the sprite's current position. For example, you could move sprite 5 seven positions to the left and ten positions down with MOVSPR 5, -7, + 10.
MOVSPR sprite#,angle #speed
Moves a sprite continuously in a certain direction at a specified speed via a machine level interrupt, even when the BASIC program is executing other lines or is stopped. When the sprite disappears off the screen, it wraps around and reappears at the opposite end of the screen. This command is useful when you want to send a sprite flying on a predetermined course and speed while your program does other things. For instance, with this command you could quite easily animate the rocks in an Asteroids-type game while your program takes care of checking the joystick and moving the player's ship. The angle parameter specifies the direction in degrees (0 = up), and #speed the velocity. To move sprite 1 continuously along a horizontal path from left to right, you would type MOVSPR 1, 90 #5. To move it vertically from top to bottom a little faster, you would type MOVSPR 1, 180 #5. Of course, the sprite must be positioned somewhere on the visible screen to begin with.
Detects sprite collisions and diverts the program to a subroutine starting at the line specified by line#. The type parameter lets you detect different kinds of collisions. Examples: COLLISION 0, 1000 passes control to a subroutine at line 1000 when two sprites collide. (The subroutine must end with a RETURN.)
COLLISION 1,2000 passes control to a subroutine at line 2000 when a sprite collides with a screen object. COLLISION 2,10000 diverts the program to a subroutine at line 10000 when a sprite is touched with a light pen.
Detects sprite collisions and returns a value corresponding to the sprites involved. This makes it possible to determine which sprites collided or if a collision happened off the visible screen (invisible to COLLISION). BUMP(0) records sprite-to-sprite collisions, and BUMP(1) records sprite-to-screen collisions.
Graphics commands make up for the deficiencies in BASIC 2.0 and complement the sprite commands. They're also fairly fast for a BASIC interpreter. Here's just a sampling:
GRAPHIC mode #, clear,window
Flips the screen to the graphics mode specified by mode#. Mode 0 is 40-column text (default); 1 is hi-res graphics; 2 is hi-res graphics with a text window; 3 is multicolor graphics; 4 is multicolor graphics with a text window; and 5 is 80-column text (RGB only). The text windows are similar to those on Atari and Apple computers—they allow a few lines of text beneath the graphics window on the upper part of the screen. The text windows start at line 19, but that can be changed with the window parameter in the GRAPHIC statement. The clear parameter lets you specify whether the screen will be cleared upon entering the new mode (0 = no clear, 1 = clear).
COLOR source #, color#
Sets up the color registers. The color# parameter defines the color from 1 to 16. The source# parameter specifies the color register affected—0 for the 40-column background, 1 for the graphics mode foreground, 2 for the multicolor graphics mode primary color, 3 for the multicolor graphics mode secondary color, 4 for the 40-column border, 5 for the character color, and 6 for the 80-column background color.
Draws a box on the hi-res screen. Source# defines the color register (0 to 3), X1, Y1, X2, Y2 are the X and Y coordinates of the opposite corners, angle is the rotation in degrees (default = 0), and paint specifies whether the box will be filled (0 = hollow, 1 = solid). Example: BOX 1,10,10,60,60,0,1 draws a filled green box in the upper-left corner of the screen.
CIRCLE source #,X center,Ycenter, X radius,Y radius,arc angle1,arc angle2,angle,increment
Draws circles, ellipses, arcs, triangles, octagons, and other polygons on the hi-res screens. Source# is the color register (0 to 3), X center and Y center are the X and Y coordinates of the centerpoint, X radius and Y radius are the X and Y coordinates of the radius, arc angle1 is the starting arc angle in degrees (default = 0), arc angle2 is the ending arc angle in degrees (default = 360), angle is the rotation in degrees (default = 0), and increment specifies the number of degrees between segments (default = 2). Examples: CIRCLE 1,160,100,65,50 draws a green circle; CIRCLE 1,160,100,65,10 draws a green ellipse; CIRCLE ,60,40,20,18,,,,45 draws an octagon, and CIRCLE ,260,40,20,,,,,90 draws a diamond.
DRAW source #,X1,Y1 TO X2,Y2…etc.
Draws a dot, line, or figure on the hi-res screens. Source# is the color register (0 to 3), X1 and Y1 are the starting screen coordinates, X2 and Y2 are the following screen coordinates, and more coordinates can follow, up to BASIC's line length limit. Examples: DRAW 1,100,50 plots a dot at coordinates 100,50 because no endpoint is specified; DRAW 1,100,50 TO 100,75 draws a vertical line from 100,50 to 100,75; and DRAW 1,10,10 TO 10,60 TO 100,60 TO 10,10 makes a triangle.
Positions the invisible graphics cursor at hi-res screen coordinates X,Y. This defines the default starting point for all the drawing commands.
PAINT source#,Xstart,Ystart, mode
Fills an area on the hi-res screen. Source# is the color register, Xstart and Ystart define the starting coordinates, and mode specifies which area to fill (0 = fill the area defined by source#, 1 = fill the area defined by any nonbackground color). Example: CIRCLE ,160,100,65,50: PAINT ,160,100 draws and fills a circle using the default foreground color.
Stores shapes drawn on the hi-res screens into string variables. The rectangular area of screen data between coordinates corner1 and corner2 is saved in the string variable string. The area which can be stored is limited by the 255-character capacity of a BASIC string. SSHAPE is very similar to GET in IBM BASIC.
GSHAPE string,corner1,corner2, mode
Plots the data stored in a string variable as a shape on the hi-res screens. It is the opposite of SSHAPE. Corner1 and corner2 define the rectangular screen coordinates, and mode specifies how the shape will be plotted. If mode = 0, the shape is placed as it exists; 1 inverts the shape; 2 performs a bitwise OR when the shape is overlapped onto the screen; 3 ANDs the shape with the screen; 4 XORs (exclusive-ORs) the shape with the screen. GSHAPE corresponds to PUT in IBM BASIC.
Sound commands in BASIC 7.0 take much of the tedium out of creating sound effects and music with the versatile but complex SID chip. Together, BASIC 7.0 and the SID chip give the Commodore 128 the best sound capability of any personal computer now on the market. Here are a few examples:
Plays a sound with the selected voice, frequency, and duration. Voice can be 1 to 3, freq 0 to 65535, and dur 0 to 32767 jiffies (a jiffy equals 1/60 second). The following parameters are optional. Sweep defines the direction for a sweep (shifting frequencies), with 0 = up, 2 = down, and 3 = oscillation. Min sets the minimum frequency for a sweep; step picks the step value for a sweep; wave chooses a SID wave-form (0 = triangle, 1 = saw, 2 = square, 3 = noise); and width specifies the width for a pulse waveform.
PLAY "O oct,T tune,U vol,V voice,X filter,notes"
Plays one or more notes using a selected octave, envelope, volume, voice, and filter. Oct specifies the octave 1 to 6; tune an envelope 0 to 9 (see below); vol the volume 0 to 9; voice 0 to 2; filter (0 = off, 1 = on); and note can be A, B, C, D, E, F, or G with sharps, flats, dots, and standard durations (quarter notes, half notes, etc.). An M in this parameter tells the computer to wait for all voices currently playing to end. Any number of notes can be strung together in this field, up to BASIC's line length limit. The predefined envelopes selectable with the tune parameter are 0 = piano, 1 = accordian, 2 = calliope, 3 = drum, 4 = flute, 5 = guitar, 6 = harpsicord, 7 = organ, 8 = trumpet, and 9 = xylophone.
Commodore 128 Memory Management And Machine Language
Charles Brannon, Program Editor
Using an external memory cartridge, the Commodore 128 can be expanded up to 512K RAM. This memory is not directly available for programs, though, but is used as a RAM disk—the functions of a disk drive are simulated with the memory chips. This provides faster throughput than a hard disk, but all information is lost when the power is turned off. You need to dump the contents of a RAM disk to a regular disk at the end of each session.
A special memory management unit (MMU), located at $FF00, controls the 128's complicated memory map. The MMU interprets memory addresses even before the microprocessor sees them. It permits you to swap between banks of 64K, but can leave a small portion of memory as common memory. You don't always want zero page and the stack to disappear when you change banks. The MMU lets you bank between four 64K banks, and allows multiple banks of 256K, up to one megabyte of memory.
The MMU controls whether the VIC chip or 80-column chip controls the screen display, and even senses the position of the 40/80 DISPLAY switch (though the software must interpret this switch). The MMU controls access to RAM or ROM, allowing either to be visible in the memory map. A programmer can set up a series of preset memory configurations and quickly select them by writing to the MMU. The address of the VIC chip can be relocated anywhere within the virtual 256K memory space.
The MMU also controls the fast serial port used with the 1571 disk drive (and conceivably with other fast peripherals). It determines the clock speed of the 8502, and controls which of the three microprocessors (6510, 8502, Z80A) is in control.
Although not supported in ROM, it's possible to have all three microprocessors running by quickly switching between them. Maybe someone will find a way to take advantage of this potential multiprocessing capability.
Machine language programmers will appreciate the Commodore 128's machine language monitor, entered from BASIC with the MONITOR command. It pretends that the 128K of memory is contiguous and permits five-digit hexadecimal addresses. It makes full use of 80 columns if selected. The monitor works much like 64 Supermon, with commands to assemble, disassemble, fill, go to address, hunt through memory for a hexadecimal string, load, display memory with ASCII equivalents, display registers, save, transfer a block of memory, verify a saved program, exit to BASIC, modify memory, modify registers, and display disk error status.
BASIC commands for machine language include BLOAD and BSAVE to load and save machine language programs or other binary files, and BOOT to load and run a machine language program. The familiar USR, WAIT, POKE, PEEK, and SYS commands can now reference the second 64K of memory with the BANK command. SYS can be followed by four parameters that are transferred into the accumulator, X register, Y register, and status flag register. After a SYS, the RREG command can transfer the contents of these registers into four variables. This makes it much easier to pass information between BASIC and ML.
The 8502 microprocessor in 128 mode is opcode-compatible with the 6502 and 6510, but can now run at two megahertz, twice the speed of the VIC-20's 6502 and Commodore 64's 6510. All VIC/64 Kernal routines are supported, making program translation much easier. New Kernal routines support special features of the 128, including routines for memory management.
A RESET button near the power switch can coldstart the machine. Holding down RUN/STOP with RESET initiates a "lukewarm" start. It's a more thorough reset than RUN/STOP-RESTORE, but still retains your BASIC program. This reset puts you into the machine language monitor, where you can exit back to BASIC with no harm done.
Redefines any of the ten predefined music envelopes for the tune parameter of the PLAY command. The # specifies the envelope (0 to 9), followed by the values for attack, decay, sustain, and release. Wave sets the SID waveform and width selects the width of a pulse waveform.
FILTER freq,lopass,bandpass, hipass,res
Switches the SID filters for use with the filter parameter of the PLAY command. Freq selects the frequency; lopass the low-pass filter (0 = off, 1 = on); bandpass the notch-reject filter (0 = off, 1 = on); hipass the high-pass filter (0 = off, 1 = on); and res the resonance (0 to 15).
Despite the almost bewildering array of commands listed above, we've barely scratched the surface of BASIC 7.0. Indeed, a preliminary manuscript for the Commodore 128 System Guide is a stack of single-spaced, typewritten pages two and a half inches thick.
There are commands for windowing, switching 64K memory banks, renumbering BASIC programs, deleting ranges of BASIC lines, assigning new definitions to the predefined special function keys, entering the machine language monitor, trapping runtime errors and diverting execution to an error-handling routine at a certain line number, resuming execution after a runtime error, high-lighting errors in BASIC lines, constructing loops without FOR-NEXT, and inserting delay loops. Plus additional commands for sprites, sound, music, and graphics that we didn't have room to mention.
Commodore BASIC 7.0 is a predictable step in the evolution of high-level programming languages for personal computers. It continues the trend away from low-level instructions such as PEEK and POKE—vestiges of machine language—and further shields users from intimate contact with the bits and bytes of computer circuitry. Yet, unlike some other personal computers introduced in recent years, the Commodore 128 retains its BASIC as a built-in feature and also provides a machine language monitor for those who want to explore the computer at every level. It's a welcome combination.