In part 1, we talked about the basics of how GEM VDI works and how that applies to the concept of VDI functions being passed from an application to a device driver.

This time around, we’ll talk about the printer driver kit that Atari sent out to selected developers. Printers were by far the most commonly supported device, and also had perhaps the greatest variety in technology.

Before we talk about the printer driver kit, let’s take a look at the state of technology for printers back in the mid-80’s.

The Printer Market At The Dawn Of Time (the mid 80’s)

Today, you can walk into a store and for $200 or so, maybe less, you can buy a fairly decent color laser printer that prints 10 pages a minute or more at resolutions upwards of 1200 dpi. To those of us who survived using computers in the mid’80’s, that is simply insane. You get so much more bang for the buck from printers these days that some people buy new printers instead of replacing toner cartridges.

In the mid-80’s, the printer market was much different than it is now. Aside from the differences in technology, printers were relatively much more expensive.  A basic 9-pin printer in 1985 would cost you $250 or $300. That’d be like $500-$600 today. You could literally buy a half-dozen cheap laser printers today for what it cost for a good 9-pin dot matrix printer back then. A good 24-pin printer would set you back $500 or more.

Laser printers, in 1985, were about $2500 for a basic Hewlett Packard LaserJet or similar model. Apple introduced the LaserWriter in March with a price tag of almost $7000. Fortunately, more and more manufacturers were entering the market, and prices were starting to drop. I paid about $1300 for my first laser printer in late ’86, and that was as cheap as they came back then. It was compatible with PCL 2 (printer control language version 2) which meant that most drivers for the HP LaserJet would work with it.

Today, the typical printer found in most people’s homes is an inkjet dot-matrix printer. That kind of printer wasn’t really a mainstream thing yet in 1985. The first truly popular model would be the HP DeskJet in 1988.

Graphics Printing Was SLOW!

Today, most printer output, other than speciality devices like receipt printers, is done using bitmapped graphics. The printer driver on your computer builds an image in the computer’s memory, and then when the page is complete, sends it to the printer. This gives the application and printer driver nearly complete control over every pixel that is printed.

However, in 1985, sending everything to the printer as one or more large bitmaps didn’t work so well, for a couple of reasons. First was the fact that sending data from the computer to the printer was fairly slow. Most printers connected to the computer via a Centronics-style parallel data port, which typically used the system’s CPU to handshake the transfer of data. Typical transfer speeds were rarely more than a couple of dozen kilobytes per second, even though the hardware was theoretically capable of much faster speeds.

Even though the data connection was fairly slow, the main bottleneck in most cases was the printer’s ability to receive the data and output it. Most printers had no more than a couple of kilobytes of buffer space to receive data, generally no more than about one pass of the print head when doing graphics. It was the speed of the print head moving back-and-forth across the page that was the ultimate bottleneck.

A popular add-on in those days was a print buffer, basically a little box filled with RAM that connected in-between the printer and the computer. This device would accept data from the computer as fast as the computer could send it, and store it in its internal RAM buffer. Then it would feed the data out the other end as fast as the printer could accept it. The print buffer could accept data from the computer more quickly than the printer could, and assuming it had enough RAM to hold the entire print job, it would free up the computer to do other things.

But even with a print buffer, if you had an impact dot-matrix printer and wanted to produce graphics output, you simply had to get used to it taking awhile to print. For those with bigger budgets, there were other options. Laser printer manufacturers started to make smarter printers that were capable of generating graphics in their own local memory buffers. This was generally done using what we call a Page Description Language, or PDL.

Page Description Languages

With a PDL, instead of sending a bitmap of a circle, you would send a series of commands that would tell the printer where on the page to draw it, what line thickness to use, how big it should be, the fill pattern for the interior, etc. This might only take a couple dozen or perhaps a few hundred bytes, rather than several hundred kilobytes.

One of the most capable and popular PDLs was PostScript, which was introduced to the world with the release of the Apple LaserWriter printer. PostScript was actually a programming language, so you could define a fairly complex bit of output and then use it as a subroutine over and over, varying things like the scale factor, rotation, and so forth. PostScript also popularized the concept of using outline scalable fonts.

The downside to Postscript or other PDLs was that the printer needed a beefy processor and lots of RAM, making the printer fairly expensive. Often more expensive than the computer you used to generate the page being printed.The Apple LaserWriter actually had a faster version of the Motorola 68020 processor and more memory than early models of the Mac computer.

The other downside was that even if you’re printing a couple of dozen pages everyday, the printer is actually sitting idle most of the time. Meaning that extra processing power and RAM isn’t really fully utilized.

Graphics Output On A Budget

Back in the 8-bit days and early PC days, most people didn’t have thousands of dollars to drop on a laser printer. If you had a basic 9-pin dot matrix printer, it had relatively primitive graphics and it was fairly slow to output a page using graphics mode. Most of the time you made a printout of something text-oriented, it used the printer’s built-in text capabilities. Basic printing modes were fast but low-quality, but more and more printers introduced a “letter quality” mode which was somewhat slower, but still much faster than doing graphics output.

However, the whole situation with printers was on the cusp of a paradigm shift. RAM was getting cheaper by the day. Computers were getting faster. The quality of graphics printing was improving. And, perhaps more than anything, the release of the Apple Macintosh computer in 1984 had whetted the market’s interest in the flexibility of bitmapped graphics output, and the subsequent release of Microsoft Windows and GEM with similar capabilities had added fuel to the fire.

Being able to combine text and graphics side by side was the new target, even for people with basic 9-pin dot matrix printers, and even though it was often orders of magnitude slower than basic text output, people were willing to wait. And for higher-quality output, they were willing to wait a bit longer.

Printer Drivers In The Wild West

Today, when you buy a printer, you get a driver for Windows, maybe one for Mac OS X. I would imagine Linux users recompile the kernel or something to get things going there.  (Kidding!)  And once you install that driver on your computer, that’s pretty much all you need to worry about. You tell an application to print, and it does.

By comparison, back when the ST first came out, printing was the wild wild west, and getting your printer to produce output could make you feel like you were in an old-fashioned gunfight. Before GUI-based operating systems became popular, every single program required its own printer driver.

And then we have the fact that there were about fourteen billion different ways of outputting graphics to a printer. Even within the product line of a single manufacturer, you’d find compatibility issues between devices that had more or less the same functionality as far as graphics output went. Even with the same printer, two different programs might have different ways of producing what appeared to be the same exact result.

Back in those days, most dot-matrix printer manufacturers followed the standards set by Epson. For example, when Star Micronics came out with their Gemini 10x 9-pin dot matrix printer, it used most of the same printer codes as the Epson FX and MX printers. Likewise with many other manufacturers. Overall, there was often as much as approximately 95% compatibility between one device and another.

The problem was, most of the efforts towards compatibility were oriented around text output, not graphics. That is, the same code would engage bold printing on most printers, but the code for “Advance the paper 1/144th inch” used for graphics printing might be different from one printer to the next.  This was further complicated by the fact that printers sometimes differed somewhat in capability. One printer might be able to advance the paper 1/144″ at a time, while another could do 1/216″.

The one good thing was that in most cases it was possible for users to create their own driver, or more accurately, a printer definition file. For most programs, this was nothing more than a text file containing a list of the printer command codes required by the program. In some cases it was a small binary file created by a separate utility program that let you enter the codes into a form on screen.

The Transition To OS-Based Printing

The main reason every DOS application (or Atari 8-bit program, or Commodore 64 program, etc.) had its own proprietary printing solution was, of course, the fact that the operating system did not offer any alternative. It facilitated the output of raw data to the printer, but otherwise provided no management of the printing process.

That started to change for desktop computer users in 1984, when Apple introduced the Macintosh. The Mac’s OS provided developers with the means to create printer output using the same Quickdraw library calls that they used to create screen output. And it could manage print jobs and take care of all the nitty-gritty details like what printer codes were required for specific printer functions. Furthermore, using that OS-based printing wasn’t simply an option. If you wanted to print, you had to go through the system. Sending data directly to a printer was a big no-no.

One significant issue with the whole transition to OS-based printing was the fact that printer drivers were significantly more complex. It generally wasn’t possible, or at least not practical, for users to create their own.

Apple addressed the potentially murky driver situation by simply not supporting third party printers. They had two output devices in those early years, the ImageWriter 9-pin dot-matrix printer, and then the LaserWriter. It would be a couple of years before third party printing solutions got any traction on Macintosh.

When Microsoft Windows came out a short time later, it addressed the question of printing in largely the same way as the Macintosh, except that it supported a variety of third-party printer devices. 

When the Atari ST came out, the situation regarding printing with GEM should have been theoretically similar to the Mac and Windows, except for two little things.

First was the minor tripping point that the part of GEM responsible for printing (GDOS) wasn’t included with the machine at first. What was included was BIOS and GEMDOS functions for outputting raw data to the printer. As a result, application programmers ended up using their own proprietary solutions.

Second was the fact that even after GDOS was released, there were only a few printer drivers included. And Atari didn’t seem to be in any big rush to get more out the door. As a result, application developers were slow to embrace GEM-based printing.

GDOS Printing On The Atari

As far as I know, the first commercial product to ship with GDOS support included was Easy Draw from Migraph at the start of 1986, about six months after the ST was released, and about two months after Atari starting shipping machines with the TOS operating system in ROM rather than being disk-loaded.

Migraph included pretty much exactly what Atari had given them as a redistributable setup: the GDOS.PRG file which installed the GEM VDI functionality missing from the ROM, the OUTPUT program for printing GEM metafiles, and a set of GEM device drivers and matching bitmapped fonts. The device drivers included a GEM Metafile driver and printer drivers for Epson FX 9-pin dot-matrix printers and Epson LQ 24-pin dot-matrix printers.

Compared to most other programs, this situation had a significant drawback. This was not Migraph’s fault in any way. It was a GEM issue, not an Easy-Draw issue. So what was the problem? Well, basically it comes down to device support. The GDOS printer drivers supplied by Atari simply didn’t work with a lot of printers. They targeted the most popular brand and models, but if you had something else, you had to take your chances regarding compatibility. This was a major problem for users, not to mention something of a surprise.

If there’s any aspect of GEM’s design or implementation where the blame for something wrong can be pointed at Atari rather than Digital Research, it’s got to be the poor selection of printer drivers.

With a word processor like First Word, if your printer wasn’t supported by a driver out of the box, chances were pretty good you’d be able to take your printer manual and figure out how to modify one of the existing drivers to work. Or, maybe you’d pass the ball to a more tech-savvy friend and they’d figure it out for you, but one way or the other, you probably weren’t stuck without a way to print. Not so with Easy-Draw, or any other program that relied on GDOS for output. GDOS printer drivers weren’t simply a collection of printer codes required for specific functions. If there was no driver for your printer, and chances of that were pretty good, you couldn’t print. Period.

The GDOS Printer Driver Kit

When I was at Neocept (aka “Neotron Engineering“) and our WordUp! v1.0 word processor shipped, we included basically the same GDOS redistributable files that Migraph had included with Easy-Draw, except for the OUTPUT program which we didn’t need because WordUp! did its own output directly to the printer device. It wasn’t long before we started getting a lot of requests from users who had printers that weren’t supported, or which were capable of better results with a more customized driver.

We asked Atari repeatedly for the information necessary to create our own drivers. I dunno if they simply eventually got tired of our incessant begging, or if they thought it was a way to get someone else to do the work of creating more drivers, but eventually we got a floppy disk in the mail with a hand-printed label that read “GDOS Printer Driver Kit” that had the source code and library files we needed.

There weren’t really a lot of files on that floppy disk, so I’ll go ahead and list some of them here:

  • FX80DEP.S
  • FX80DATA.S
  • LQ800DAT.S
  • LQ800DEP.S
  • STYLES.C
  • INDEP.LIB
  • DO.BAT

That might not be 100% accurate as I’m going from memory, but it’s close enough. I think there might have “DEP” and “DATA” files for the Atari SMM804 printer as well, but it’s possible those were added later.

The “*DEP” files were the device-dependent code for a specific device.  Basically there was a version for 9-pin printers and one for 24-pin printers.  There were some constants unique to individual printers that should have been elsewhere.

The “*DATA” files were the related data, things like printer codes and resolution-based constants.

INDEP.LIB” was the linkable library for what amounted to a GEM VDI bitmap driver.

The STYLES.C file contained definitions for the basic pre-defined VDI line styles and fill styles.

The DO.BAT file was a batch file that did the build.

Figuring It Out

There were no instructions or documentation of any kind. That may have been why Atari was originally reluctant to send anything out. It took a little experimenting but eventually I figured out what was what. The idea here was that the bulk of the code, the routines that actually created a page from the VDI commands sent to the driver, was in the INDEP.LIB library. The actual output routine that would take the resulting bitmap and send it to the printer was in the *DEP file. By altering that routine and placing the other information specific to an individual printer into the DEP and DATA files, you customized the library’s operation as needed for a specific printer.

The ****DATA file would contain things like the device resolution, the printer codes required to output graphics data, and so forth. This included the various bits of information returned by the VDI’s Open Workstation or Extended Inquire functions.

The first drivers I created were relatively simple variations on the existing drivers, but fortunately that’s mainly what was needed. There were a ton of 9-pin dot-matrix printers in those days, and while many of them worked fine with the FX80 driver, some were ever so slightly different. Like literally changing one or two printer codes would make it work. The situation was a little better with the 24-pin printers but again there were a few that needed some changes.

The first significant change we made was probably when I created a 360 DPI driver for the NEC P-series 24-pin printers. These were compatible with the Epson printers at 180 DPI, but offered a higher-resolution mode that the Epson did not. I’ll admit I had a personal stake here, as I’d bought a nice wide-carriage NEC P7 printer that I wanted to use with the Atari. That thing was slower than crap but oh, gosh was the output good looking. At the time, for a dot-matrix impact printer, that is.

One thing that was confusing at first was that the startup code for the drivers was actually contained in the library. The code in the ****DEP.S files was called as subroutines from the v_opnwk and v_updwk functions.

Anatomy Of A GDOS Printer Driver, Circa 1986

The INDEP.LIB library (or COLOR.LIB for color devices) contained the vast bulk of the driver code. It contained all of the functions necessary to handle all of the VDI functions supported by the device. It would spool VDI commands until the v_updwk function was called. That was the call which triggered the actual output. At that point, it would create a GEM standard raster format bitmap and render all of the VDI commands which had been spooled up since the open workstation, or previous update workstation.

In order to conserve memory, the printer drivers were designed to output the page in slices. A “slice” was basically a subsection of the overall page that extended the entire width, but only a fraction of the height. The minimum slice size was typically set to whatever number of lines of graphics data you could send to the printer at once. For example, with a 9-pin printer, the minimum “slice height” would be 8 scanlines tall. If the horizontal width of the page was 960 pixels (120 dots per inch), then the minimum slice size would be 960 pixels across by 8 pixels tall. The maximum slice height could be the entire page height, if enough memory was available to the driver.

The driver would allocate a buffer for a slice, then render all of the VDI commands with the clipping set to the rectangle represent by that slice.  Then it would call the PRT_OUT function.  This was a bit of code in the DEP.S file that would output whatever was in the slice buffer to the printer, using whatever printer codes and other information were defined by the DATA.S file. After a slice was output to the printer, the library would clear the buffer and repeat the whole process for the next slice down the page.  For example, the first slice might output scanlines 0-95, then the next slice would do scanlines 96-191, and so forth until it had worked its way all the way down to the bottom of the page.

Once it got to the bottom of the last slice, the code in DEP.S would send a form feed code to the printer to advance the paper to the start of the next page.

This all may sound inefficient, since it had to render all of the VDI commands for the page over and over again, but the bottleneck here was sending the data to the printer so that didn’t really matter.

A Semi-Universal Printer Driver

Something I always kind of wanted to do, but never got around to, was creating a reasonably universal GDOS printer driver that stored printer codes and other parameters in an external configuration file that could be edited by the user. Or, perhaps, stored within the driver but with a utility program that could edit the data.

You see, the main part of the library didn’t have any clue if the printer was 9-pin, 24-pin, or whatever. So there’s no reason it shouldn’t have been possible to create an output routine that would output to any kind of printer.

In hindsight, that probably should have been the goal as soon as I had a good handle on how the driver code worked.

Next Time

Next time we’ll jump right into creating our driver shell.

Related Articles


If you look at the documentation for the GEM AES Scrap Library, two things soon become very obvious.

First, it’s clear that the designers of GEM at Digital Research recognized the need for and utility of a well-designed system clipboard that applications could use to quickly and easily exchange data.

Second, it’s even more clear that within no more than a couple of minutes after sitting down to map out what sort of library functions were needed and what sort of predefined data exchange formats should be used, something distracted them to such a degree that they put down their engineering comp books, got up from their desks, and left the office.

I’m guessing the distraction was lunch time. Maybe the food truck rolled into the parking lot and tooted its horn.

A third thing becomes obvious soon after. After lunch was over, they never came back to finish what they’d started.

Three Functions

The GEM AES scrap library consists of three functions.

You heard me. Three functions.  Here they are:

  • scrp_write allowed an application to specify a directory which would contain file(s) containing the data being placed on the clipboard.
  • scrp_read allowed an application to retrieve the directory containing clipboard files.
  • scrp_clear function deleted all files in the clipboard directory.

Actually, I lied. The scrp_clear function was only on PC, not Atari. I can only imagine that two or three minutes into the five minute task of bringing the PC code over, the guy doing it said, “screw it — nobody’s gonna use this anyway” and went off for a long weekend.

And Yet, Not Very Useful Functions

The first problem with this setup is that it makes individual applications responsible for deciding where the clipboard resides, rather than the system. That’s simply a recipe for disaster, especially on a hard drive where you could easily end up with a separate clipboard folder for each and every application.

The next problem is that it doesn’t provide a definitive way for an application to find out if there is data on the clipboard or not.  It has to read the directory returned by scrp_read to see if there are any files there or not.  That doesn’t sound terrible at first, but there’s no mechanism for an application to be notified when the clipboard status is changed by another application.  So, as a practical matter, an application has to check again every time it loses and then regains focus.  On a hard drive system, with a fixed system-defined directory, this would be moderately painful.  With the possibility of the directory changing every single time you check, it’s much less moderate.  And that’s on a hard drive system.

On a floppy drive system… well, shit, that set of problems deserves its own section of the article.

Not Remotely Practical Without Hard Drive

Another problem can be neatly summed up in three words: floppy disk system.

Well, not so much a problem in its own right as a problem magnifier.  Trying to use this clipboard setup on a floppy disk system basically takes every problem and makes it worse. When the user has to use one disk to boot the system, another to launch an application, and yet another to load documents, there’s a lot of disk swapping going on.  So, let’s make it worse by having the clipboard on floppy disk also.  We could use the document disk for that, or we could use a separate disk just for the clipboard.  Let’s assume that last option.

Now imagine that you need to copy some formatted text from your word processor into your favorite graphics program.  Let’s step through it.

Boot system on one disk.  Switch disks to launch word processor.  Switch disks to load the document you want.  Switch disks again to clipboard floppy.  Copy/cut the text, meaning the word processor writes out one or more files with the currently selected text.  Now, maybe, switch back to the document floppy to save changes to the file.  Exit the word processor.  Switch disks to the graphics program floppy and launch that program.  Switch to the floppy with your graphics files and load your graphics file.  Once that’s loaded, switch disks to the clipboard floppy.

Now, remember what we said earlier about an application having to check the clipboard folder ever time it loses and regains focus?  That didn’t actually happen here.  The application stayed in focus the whole time, but we switched floppy disks.  How is the program supposed to know this so it can, or should, check to see if clipboard data is now available?  Should the program have to monitor floppy drive media change just to use the clipboard? Apparently so, even though that’s just ridiculous.

Anyway, let’s just skip past the details and assume the program has checked again for clipboard files.  Maybe there’s a menu item for “refresh clipboard” or something equally inelegant but functional.  So now the graphics program finds the clipboard data with the text saved earlier by the word processor.

But now there’s a new problem.  The word processor saved out plain ASCII into CLPBOARD.ASC and formatted text into CLPBOARD.WUP, because the word processor is WordUp and WUP is that program’s native file format.  But the graphics program, like every other application in the known universe other than WordUp, has no clue whatsoever how to read a WUP file and extract anything useful from it.

Data Formats

There was no problem with the idea of WordUp saving its own native WUP format to the clipboard.  The problem was that it didn’t also save the information using a more universally recognized file format. There was zero documentation to indicate anything about what kind of data could (or should) be exchanged via this whole process, or what file formats should be used.

I’m not exaggerating. When I say “zero” I mean exactly that.  The official GEM 1.0 documentation says nothing whatsoever about clipboard data formats. I would imagine the guys at DRI assumed GEM metafiles would be used for vector graphics and IMG files for bitmapped graphics, but they didn’t actually put those ideas into the docs.

And what about other data? How should formatted text be transferred? What about a block of cells from a spreadsheet?  How about MIDI sequencer data?

The answer ultimately was, your guess is as good as mine. Is it any wonder that application programmers basically ignored the scrap library?

The real tragedy of this situation is that it’s entirely a documentation problem. There’s got to be probably no more than 8 or 10 basic, simple types of data that would cover probably 95% of all clipboard requirements. If the guys at DRI, or at Atari for that matter, had written a couple of pages of documentation saying “use this format for this kind of data” then maybe applications would have supported the clipboard.

As with many other GEM shortcomings, there would be 3rd party attempts to fix the broken situation. The PC version of GEM eventually included some documentation about data formats, but it was way too late, and limited mostly to very obvious things like TXT, IMG, IMG, and CSV.  And for whatever reason this information never really circulated to the Atari side of things at the time.

The Simple Fix, Part 1

Making the clipboard genuinely useful would have been fairly simple, had anybody been paying attention at the time. The first fix would have been to define a reasonable list of standard data exchange formats. and to make sure that list wasn’t completely GEM-centric.   For example, here’s a few just off the top of my head:

  • GEM – GEM metafile vector graphics
  • IMG – Bitmapped graphics
  • ASC or TXT – Plain ASCII text.
  • CSV – Comma separated values, text file containing one or more data records with fields separated by commas.
  • RTF – Rich Text Format formatted text.
  • MID – MIDI Data

Each “standard” format would be assigned a 4-byte value like “_ASC” or “_IMG” that will be used as an identifier.  In most cases the code would correspond roughly to the filename extension commonly used.

Keep in mind that there are some file formats in common use today that weren’t around in 1984. For example, the TIFF format for graphics files was introduced in 1986.  JPEG came out in the early 90’s just barely in time for the creation of the WWW.

The choice of IMG files for bitmapped graphics seems unavoidable, yet there is a critical flaw in that IMG doesn’t allow color palette information to be saved with the bitmap.  DRI seemed to think you’d save out a .GEM metafile defining the palette, but that conflicts with another likely scenario: if your source data is vector graphics, then saving out a rendered bitmap version on the clipboard is entirely reasonable.

This is just a short simple list that serves to illustrate the point.

The Simple Fix, Part 2

After defining the basic data formats, the main thing would be to allow for the clipboard to be either disk or RAM-based.  Most copy/paste operations could be done with a fairly small RAM-based clipboard, but it would have been easily to accommodate disk-based clipboard data when needed.

The existing functions scrp_read and scrp_write are history in this scenario as far as I’m concerned.  In their place, I would have suggested a pair of functions for saving & retrieving RAM-based clipboard data.  Something like this:

int resultcode = scrp_copy( CLIPBOARDDATA *cDataSaved )
 
int resultcode = scrp_paste( CLIPBOARDDATA *cDataRequested )

Yeah, I know. We started with two functions and I’m proposing replacing them with two functions. Kind of ironic, but keep reading and I think you’ll agree I get a lot more mileage out of my two functions than AES got out of the original scrap library functions.

The CLIPBOARDDATA Structure

The CLIPBOARDDATA structure defines the information being saved to the clipboard or retrieved from it. It looks like this:

typedef struct
{
    WORD    formatCount;
    DWORD   *formats;
    UCHAR   **data;
    DWORD   *lengths;
} CLIPBOARDDATA;

The formatCount field indicates specifies the size of the arrays pointed to by the formats, data, and lengths parameters.   When writing data to the clipboard, it specifies how many types of data the application is saving.  When requesting data from the clipboard, it specifies the formats that the application knows how to process.  When the system returns clipboard data to the application, it indicates which formats were actually returned. Note that an application can request one format at a time, or many.

Each of the formats specified should represent the same basic data in different formats. For example, a word processor might save formatted text in its own native file format like WUP, but also using both RTF (Rich Text Format) and plain ASCII TXT.  A graphics application might save vector graphics as EPS and GEM, but also a rendered bitmap version as IMG and TIFF.

The formats parameter is a pointer to an array of 32-bit ASCII format identifier codes (like “_IMG” or “_GEM”)  as mentioned earlier.  Each code represents a single type of data, like ASCII text, IMG bitmap, etc.  The list we defined earlier would form the core of this.

The data parameter is a pointer to an array of UCHAR pointers (WORD aligned), with formatCount elements,  that point to the data.  This field is ignored as input to the scrp_paste function.

Finally, the lengths parameter points to an array, with formatCount elements, where each element specifies the length of the data items pointed to by the data parameter.   This field is ignored as input to the scrp_paste function.

The API Functions

The scrp_copy function would save data, as defined in the CLIPBOARDDATA structure, to the clipboard, in each of the specified formats. Depending on the length of the data, it will be copied from the application space to a buffer allocated and maintained by AES, or saved out as a file to the system clipboard directory.  Or possibly both.

Calling scrp_copy would cause AES to send a message to all open applications indicating that the clipboard had been updated.  (Some later 3rd party revision of GEM added a message named SC_CHANGED for this purpose but it was not part of GEM’s original specification.)

The scrp_paste function would retrieve the current data on the clipboard, if any is available in the requested formats.  On input, the CLIPBOARDDATA structure specifies the data formats the application can accept.  This allows the AES to ignore clipboard formats the program won’t be using.  On output, the structure will be updated to indicate the data formats being returned and the actual data.

The resultcode value returned is 0 for no error,  or various negative values to indicate different errors.

Do We Need More Than That?

We could stop right there and the result would be a billion times more useful than the original scrap library.  There is at least one more function which would be nice to have, though.

  • scrp_bufferinfo – Retrieve information about the RAM-based clipboard data buffer, like maximum size.

Something like this would have been easy to create, fairly compact, and it would have made the GEM clipboard a genuinely useful tool from day one.

Next Time

I think we’ll be headed back to VDI topics for next time around but it’s still up in the air.   Don’t be afraid to comment and let me know what topics you’d like!

Other Articles In This Series

I had originally planned to cover some things about GEM AES in this installment but I’ve recently seen a variety of questions or comments about a couple of VDI related things lately that I’d like to address.

I’m also gonna cut down a bit on the exposition at the beginning that I’ve included in previous posts in this series.  If you don’t know, at least generally, what GEM is, or what VDI is, then why are you reading this? If you need to, go look at earlier posts in the series and then come back to this one.

A disclaimer. Much of what I’m going to discuss here pertains to developments at Atari that occurred long before my employment began. Some of the information was obtained while I was a third-party developer, and some from having conversations with guys who worked in the TOS group at Atari in the years before I started working there. Finally, quite a lot of it comes from conversations with coworkers after I started working there as the ST developer support guy.

GDOS In ROM.

One of the biggest questions people have about GDOS, to this day, is why didn’t Atari put it into the TOS ROM?  Even it wasn’t ready for v1.0, why not v1.02 or v1.04?  Why not 2.0x or 3.0x when the Mega STE and TT030 came out?

Ok, here’s a LITTLE exposition.  GDOS was the part of GEM VDI which was responsible for reading device drivers into memory on request and hooking them into the system so that VDI requests went to the right place.  It also handled loading fonts into memory and hooking them in so that they were available to be used by GEM VDI.

The PC version of GEM had GDOS in its own separate executable file, loaded separately from the rest of GEM. Since GEM was never in ROM at all on the PC this largely escaped attention, but the Atari simply followed this example.

You can download the PC GEM/3 source code here if you’re interested in having a look. The “GDOS (GEMVDI.EXE) source” file contains what corresponds to GDOS.PRG on the Atari.  The “Screen Drivers” file corresponds to the Atari’s ROM portion of VDI, which was really just the screen device driver plus a basic trap handler that routed VDI commands to it.

Beyond following the PC’s example, perhaps the main reason GDOS was not included in ROM on the Atari was that there wasn’t room.

When the ST was designed, it included a ROM space of 192 kilobytes. The problem was, the total size of early versions of TOS came in at a little over 200 kb, not even including GDOS, so it simply didn’t fit within the available ROM space. So instead of having everything in ROM, the operating system was loaded into RAM from disk.  So, the first problem that needed solving was getting everything else squeezed down to 192k.  This took another few months after the ST was put on the market, but finally at the end of 1985, Atari started including TOS 1.0 ROMs in new 520ST shipments, and made ROM chips available to existing owners.

But the TOS 1.0 ROMs still didn’t include GDOS.  It remained a separate executable file of about 9 kb that you loaded by placing into your boot disk’s AUTO folder. Not that big, in the overall scheme of things, but it was big enough that there was no room in ROM even if they had wanted to include it.

OK, so no room in the early 192kb ROM.  Later machines had bigger ROM space, so why didn’t it make its way into those?  Well, at about the same time new machines like the Mega STE and TT030 came out with bigger ROM spaces, Atari was also working on FSMGDOS, which included an outline font scaler as well as new VDI functions for things like drawing bezier curves.  FSMGDOS was too big to fit even with the larger 256kb ROM of the Mega STE.

It might have fit in the TT030’s 512kb space, but by that point, most serious users had hard drives and plenty of RAM. I don’t remember the idea ever even coming up.  Plus, realistically it was too volatile.  There was a new version every week or so for quite awhile and it simply wouldn’t have made sense to put it into ROM. And before the TT030 shipped in significant quantities, FSMGDOS was pulled in favor of replacing it with SpeedoGDOS.

Why Didn’t Atari Make The ST’s ROM Space Bigger?

Not really an expert on the history of ROM chips, but from what I recall from those days, I’m reasonably sure that 32kb was the biggest available ROM chip at the time the ST was first designed.  Or, possibly larger capacities were available but only at significantly greater cost, and maybe they were physically larger.  Either way, larger chips either weren’t available or weren’t practical.

Reasonably, the only way that Atari could have made the ROM space bigger than 192kb would have been to put more sockets onto the motherboard.  Two more sockets would have bumped up the capacity to 256kb, but it also would have required another few square inches of space on the motherboard, which was already pretty much jam-packed.  Look at the picture of the 520ST motherboard below.  Aside from the area at the top center where which was reserved for the RF modulator that is not included in this particular example, there was simply nowhere you could possibly put two more ROM sockets.

520st-motherboard

The other thing to consider was that the basic design of the motherboard was done long before TOS needed to be finalized.  When they decided to include six ROM sockets they very may well have thought they were being generous.  It’s very likely nobody ever even considered the possibility that 192kb wouldn’t have been enough space.

Why Didn’t Atari Put As Much As Possible Into ROM & Disk Load The Rest?

This refers, of course, to the fact that the early 520ST shipments didn’t have TOS in ROM.  Instead, you loaded it from an included floppy disk into RAM, meaning it took up 200K (~40%) of your available memory.  So if the problem was that everything didn’t fit, why didn’t Atari put as much possible into ROM and only soft-load what didn’t fit?

The answer is, they did put some stuff in ROM right from the beginning.  The early 520ST that loaded TOS from disk had two ROM chips instead of six, with the other four sockets left empty.  That means there was as much as 64kb of code in ROM already.

There are essentially 7 components to TOS that ultimately had to fit into the ROM:

  • Bootstrap code – the code that gets the system up and running at power-on, and tries to read a boot sector from floppy disk or hard disk.
  • XBIOS – A variety of low-level functions for accessing hardware resources.
  • BIOS – Low-level functions for accessing hardware devices (i.e. serial ports, printer port, TTY screen driver, disk drives)
  • GEMDOS – Disk operating system & buffered device access
  • GEM VDI – Graphics library
  • GEM AES – Application Environment Services
  • GEM Desktop – Shell application

The preliminary ROMs that were shipped in early machines included the first four items in this list, albeit perhaps not in a finalized form. If you remember the early pre-ROM days, the disk loaded version of TOS was based on having a file named TOS.IMG on your boot disk.  There was nothing else special about the disk. It wasn’t specially formatted or anything.

If you think about what was necessary to read that disk at all, you’ll realize that some version of GEMDOS had to be in ROM, or else the machine wouldn’t have been able to read the disk’s directory, find the TOS.IMG file, and load it. In order for GEMDOS to work, that means a pretty good chunk of the BIOS had to be there.  And that means that certain XBIOS functions had to be there.  And of course, if the bootstrap code wasn’t in place, then the whole system would have been a paperweight when you turned the power on.

So if some of this stuff was in ROM already, then why was TOS.IMG around 200kb in size? Clearly, the TOS.IMG file included new versions of all of the TOS components, not just the GEM stuff.  The main answer to that is, the versions of the components that were in the 64kb ROM were neither complete nor finalized.  They really only included what was necessary to read the TOS.IMG file into RAM and get it started.

« Previous Entries