New Driver for the Graphic Library

Realization of the Low-Level Functions

The linking of the different output devices is realized with two files:

The Header File

The name of the output device is a useful information:

  #define defDISPLAYNAME  "ANSI-Console"

For the clipping functions to work properly, the graphic library needs to know the device's dimensions in pixels:

  #define defDISPLAYWIDTH  80
  #define defDISPLAYHEIGHT 24

The number of colors is important for some commands and must be given in the header file:

  #define defMAXCOLORS     8

The color palette is not the same for all displays, also they often differ in the number of displayable colors. It must be defined, which color is to be assigned to which displayable color. On a B/W display for example, all dark colors (BLACK, BLUE, GREEN, CYAN, RED, MAGENTA, BROWN and DARKGRAY) could be assigned the value 1 (pixel set), all others the value 0 (pixel not set). For ANSI (which defines 8 colors), the table could look as follows:

  const int BLACK=0;
  const int BLUE=1;
  const int GREEN=2;
  const int CYAN=3;
  const int RED=4;
  const int MAGENTA=5;
  const int BROWN=6;
  const int LIGHTGRAY=7;
  const int DARKGRAY=0;
  const int LIGHTBLUE=1;
  const int LIGHTGREEN=2;
  const int LIGHTCYAN=3;
  const int LIGHTRED=4;
  const int LIGHTMAGENTA=5;
  const int YELLOW=6;
  const int WHITE=7;

For the linking, it is necessary to store some data as variables:

  char *DISPLAYNAME=defDISPLAYNAME;
  const int DISPLAYWIDTH=defDISPLAYWIDTH;
  const int DISPLAYHEIGHT=defDISPLAYHEIGHT;
  const int MAXCOLORS=defMAXCOLORS;

The basic structure of the graphic library looks as follows and should not be changed:

  unsigned char display[defDISPLAYWIDTH*defDISPLAYHEIGHT];
  unsigned char rgb[defMAXCOLORS*3];

The prototype declaration section. Because these are called as low-level functions also by the functions of the graphic library, parameters must not be changed:

  void _setpixel(int x, int y);
  void _writearea(int left, int top, int right, int bottom);
  void _writedisplay();
  void _initdisplay();
  void _closedisplay();

The Low-Level Functions

The necessary header files must be included:

  #include <stdio.h>

The low-level functions also need the display dimensions:

  extern const int DISPLAYWIDTH;         /* number of lines    */
  extern const int DISPLAYHEIGHT;        /* number of columns  */
  extern const int MAXCOLORS;            /* number of colors   */

When colors are used, these must also be made known:

  extern const int WHITE;
  extern const int BLACK;

The same applies to the buffer in RAM, whose contents is to be transferred to the display.
When a pixel i to be transferred to the display, the color of the pixel must be known. The buffer contains this information.
Because the buffer is a one-dimensional array, it cannot be accessed like a two-dimensional array, with display[x][y]. The display lines are sequentially stored in the array. You can determine the correct color value as follows:
Farbwert = display[ y * DISPLAYWIDTH + x ];

  extern unsigned char display[];        /* Buffer in memory */

Now the functions follow.
_setpixel should set one pixel on the output device.

  void _setpixel(int x,int y)
  {
    unsigned char color;
    color=display[y*DISPLAYWIDTH+x];     /* determine pixel color */
    printf("\033[%i;%iH",y+1,x+1);       /* correct position */
    printf("\033[%im",color+40);         /* set output color */
    printf(" ");                         /* write... */
    fflush(stdout);
  }

_writedisplay copies the whole buffer to the display.

  void _writedisplay()
  {
    unsigned char color;
    int x,y;
    for(y=0;y<DISPLAYHEIGHT;y++)
    {
      printf("\033[%i;1H",y+1);          /* go to the beginning of the current line */
      for(x=0;x<DISPLAYWIDTH;x++)
      {
        color=display[y*DISPLAYWIDTH+x]; /* determine pixel color */
        printf("\033[%im",color+40);     /* set output color */
        printf(" ");                     /* write... */
      } 
    }
    fflush(stdout);
  }

_writearea is the same as _writedisplay but copies only part of the buffer:

  void _writearea(int left, int top, int right, int bottom)
  {
    unsigned char color;
    int x,y;
    for(y=top;y<=bottom;y++)
    {
      printf("\033[%i;%iH",y+1,x1+1);    /* Position */
      for(x=left;x<=right;x++)
      {
        color=display[y*DISPLAYWIDTH+x]; /* determine pixel color */
        printf("\033[%im",color+40);     /* set output color */
        printf(" ");                     /* write... */
      }
    }
    fflush(stdout);
  }

With the following function the display should be prepared for output:

  void _initdisplay()
  {
    printf("\033c");                     /* reset */
    printf("\033[0;%i;%im",30+BLACK,40+WHITE); /* set color attributes (black writing on white background) */
    printf("\033[2J");                   /* clear screen */
    fflush(stdout);
  }

And finally a function resetting the device to the initial state.

  void _closedisplay()
  {
    printf("\033[0;%i;%im",30+WHITE,40+BLACK); /* set color attributes */
    printf("\033[%i;1H",DISPLAYHEIGHT+1);  /* go to the end of the screen */
    printf("\033[K");
    fflush(stdout);
  }
www.mct.net