/* graph256.h - Routinen zur VGA Graphicprogrammierung */

#include <stdlib.h>                             /* min,max */
#include <dos.h>                                /* int86,REGS */
#include <conio.h>                              /* inp,outp */

#define TEXT80x25       0x03
#define GRAPH320x200    0x13
#define GRAPH640x350    0x2d
#define GRAPH640x480    0x2e
#define GRAPH800x600    0x30

void setvideo(int mode) {
  union REGS regs;
  regs.x.ax=mode;                               /* Setmode: AH=0 */
  int86(0x10,&regs,&regs);                      /* Video-Bios */
  switch (mode) {
    case GRAPH320x200:
      xpoints=320;
      ypoints=200;
      break;
    case GRAPH640x350:
      xpoints=640;
      ypoints=350;
      break;
    case GRAPH640x480:
      xpoints=640;
      ypoints=480;
      break;
    case GRAPH800x600:
      xpoints=800;
      ypoints=600;
      break; } }

void setpixel(int x,int y,char c) {
  char far *vptr;
  long address=(long)y*xpoints+x;               /* Zeilenadresse im VGA-RAM */
  outp(0x3cd,FP_SEG(address)+0x40);             /* VGA 64k-Segmentnr. */
						/* (Config. 2, 8x64k Mode) */
  vptr=(char far *)(0xa0000000+FP_OFF(address)); /* VGA-RAM Anfang + Offset */
  *vptr=c; }

void setline(int y,char *buffer) {
  char far *vptr;
  int x;
  long address=(long)y*xpoints;                 /* Zeilenadresse im VGA-RAM */
  outp(0x3cd,FP_SEG(address)+0x40);             /* VGA 64k-Segmentnr. */
						/* (Config. 2, 8x64k Mode) */
  vptr=(char far *)(0xa0000000+FP_OFF(address)); /* VGA-RAM Anfang + Offset */
  for (x=0; x<xpoints; x++) {                   /* alle Bytes kopieren */
    *vptr++=(*buffer == maxiter)?(buffer++,0):(*buffer++)+32; /*  Farb ab 32 */
    if (vptr==(char far *)0xa0000000)           /* falls Segmentgrenze */
      outp(0x3cd,inp(0x3cd)+1); } }             /*  n„chstes Segment */

void invpixel(int x,int y) {
  char far *vptr;
  long address=(long)y*xpoints+x;               /* Zeilenadresse im VGA-RAM */
  outp(0x3cd,9*FP_SEG(address)+0x40);           /* Segment Pointer, Chain 8 */
						/* (Config. 2, 8x64k Mode) */
  vptr=(char far *)(0xa0000000+FP_OFF(address)); /* VGA-RAM Anfang + Offset */
  *vptr^=0xff; }

void invcursor(int x,int y) {
  int i;
  for (i=1; i<=4; i++) {                        /* Kreuzarme 4 lang */
    invpixel(max(x-i,0),y);                     /* oben */
    invpixel(x,min(y+i,(ypoints-1)));           /* rechts */
    invpixel(min(x+i,(xpoints-1)),y);           /* unten */
    invpixel(x,max(y-i,0)); } }                 /* links */

void invbox(int x1,int y1,int x2,int y2) {
  int i;
  if (x1 == x2) {                               /* senkrechte Linie */
    for (i=y1; i<=y2; i++)
      invpixel(i,x1);
    return; }
  if (y1 == y2) {                               /* waagrechte Linie */
    for (i=x1; i<=x2; i++)
      invpixel(i,y1);
    return; }
  for (i=x1; i<x2; i++)                         /* 4 Linien zeichnen, */
    invpixel(i,y1);                             /* Ecken nur ein mal inv! */
  for (i=y1; i<y2; i++)
    invpixel(x2,i);
  for (i=x2; i>x1; i--)
    invpixel(i,y2);
  for (i=y2; i>y1; i--)
    invpixel(x1,i); }

