watgfx: WATCOM C Graphics library wrapper for FreeGLUT/GL

watgfx is a source-compatible, partial implementation of the WATCOM‘s C Graphics library that draws on a OpenGL surface using FreeGLUT (a GLUT clone).

watgfx can be built on any operating system where FreeGLUT is available, allowing old graphical software that expect immediate-mode drawing to be ported somewhat more easily.

Download

watgfx.zip: last updated around 2005.

watgfx is distributed under the Revised BSD license (see COPYING).
Copyright(c) 2004-2005 by wave++ “Yuri D’Elia” <wavexx@thregr.org>.

Suggestions/comments are welcome.

Foreword

Around 2003 I received some large, non-working DOS code dating back to 1985 that quickly transformed into an exercise in reverse engineering and code archaeology. With no comments to be seen and no instructions whatsoever I had to port it to a current system. I/O was quite easy to rewrite directly just using POSIX calls, but this being a graphical/plotting program it clearly became obvious that graphics was another kind of a problem.

With hard-coded coordinates, and expecting immediate-mode processing at all times (typical requirements of a 386 real mode program) I absolutely had no clue as to what the program was supposed to be doing, let alone rewrite it using a modern event-based loop.

I was lucky enough that the program made heavy use of the WATCOM’s C Graphics library instead of manipulating the framebuffer directly. Implementing a source-compatible replacement seemed like a good start. I started by rewriting some of the few required functions quickly using FreeGLUT along with manual event loop processing so that I could implement the same blocking behavior of _getch() and similar functions. The approach sucked (of course, the window wouldn’t redraw itself when damaged), but the application started to work almost immediately. As soon as I could see, completing the port became a whole lot easier. My plan, of course, was to trash FreeGLUT and re-implement some proper code later.

Once the program was working as expected though, the customer was already happy with the results and refused to wait for a code cleanup. He instead asked for several customizations (yes, there’s a lesson to be learned here). I just kept on building opon the existing WATCOM graphical stack. In the end it turns out that several parts of the program could be greatly simplified by a simple turtle-like graphics library instead of keeping internal state throughout the code. By using sub-pixel accuracy I could even fix some of the existing visual bugs of the program. Adding stack-based operations was the icing on the cake, cutting the existing code-size in half as many drawing procedures could then be reused by simply nesting.

FreeGLUT was also a “blessing” for the customer. I discovered 10 years later that the program was still working as expected, basically unchanged and ported to yet another OS. Some new features were even added, but this time using full-blown GL calls directly. You should have seen my smile when I saw this shiny bump-mapped 3D plot with the message “press any key to continue” written in the same 8x16 font in the top-left corner of the screen. And yes… you could trash the graphics by simply moving the window around.

I decided to release this code after seeing this, hoping that somebody else could find it useful. Maybe even use it to revamp some old DOS program - who knows! Let me know!

Developer’s notes

The documentation for the functions in watgfx.h can be found in the official WATCOM library reference manual.

The only supported video mode currently is _VRES16COLOR, although other modes can be simply implemented by adding the proper resolution/window sizes (internally everything is implemented in RGB anyway).

The sources include the EGA palette, as well as the original 8x16 font extracted from a DOS BIOS, providing pixel-exact results of the graphical output.

Included in the source there is also a minimal turtle-graphics package wattgx, supporting stack-based operations along with sub-pixel accuracy.

The sample program watcon.c demonstrates the use of the whole library.

Demo

images/demo-01.png
/* Initialize the default graphic mode */
_setvideomode(_VRES16COLOR);

/* color/bk color tests */
_moveto(0, 0);
_lineto(640, 480);
_setpixel(100, 10);
_rectangle(_GBORDER, 10, 10, 50, 50);
_rectangle(_GFILLINTERIOR, 50, 50, 100, 100);
_rectangle(_GBORDERFILL, 100, 100, 150, 150);
_moveto(0, 200);
for(i = 0; i != 16; ++i)
{
  _setcolor(15 - i);
  _rectangle(_GFILLINTERIOR, i * 10,
             200, (i + 1) * 10, 300);
  _lineto(i * 10, 200);
  _setcolor(i);
  _lineto(i * 10, 300);
}
_pause();

images/demo-02.png
/* turtle */
_clearscreen();
_moveto(320, 240);
for(i = 2; i != 500; ++i)
{
  _rotate(89.);
  _setcolor(i % 16);
  if(i % 2)
    _penup();
  else
    _pendown();
  _advance(i);
}
_pendown();
_setcolor(_CWHITE);
_settextposition(0, 0);
_outtext("Turtle graphics ...");
_pause();

images/demo-03.png
/* subpixel accuracy tests */
_clearscreen();
_settextposition(0, 0);
_setcolor(_CWHITE);
oldcolor = _CWHITE;
_outtext("Subpixel accuracy ...");
_syncscreen();
_moveto(320, 240);
for(z = 0; z != 360; ++z)
{
  for(i = 0; i != 270; ++i)
  {
    _advance(2);
    _rotate(1);
    newcolor = (z / (i + 1)) % 16;
    if(newcolor != oldcolor)
    {
      _setcolor(newcolor);
      oldcolor = newcolor;
    }
  }
  _moveto(320, 240);
  _rotate(91);
}
_syncscreen();
_pause();