#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <mem.h>
#define  VIDLIB
#include "vidlib.h"

int debugtimeson=0;
void static *_initstate_=NULL;

int Vinit(void)
{
  if ( !_vidinit) {
     ReadDACs(&_olddacs);
     _oldmode=BIOScrtmode;
     _vidinit=1;
     _initstate_=Vsavestate(_initstate_);
  }
  return(_oldmode);
}

void Vclose(void)
{
  struct REGPACK r;
  if ( _vidinit ) {
     /* use mode set to clear screen */
     VGAmode(_oldmode,NULL);
     Vrestorestate(_initstate_);
     if ( BIOScrtpoints != 16 ) {
	if (BIOScrtpoints < 12) { /* CGA */
	   r.r_ax=0x1102;
	   r.r_bx=0;
	   intr(0x10,&r);
	} else {
	   if (BIOScrtpoints < 14) { /* custom 12-point */
	      r.r_ax=0x1100;
	      r.r_cx=256;
	      r.r_dx=0;
	      r.r_bx=0x0c00;
	      r.r_bp=FP_OFF(&EGA12set);
	      r.r_es=FP_SEG(&EGA12set);
	      intr(0x10,&r);
	   } else { /* EGA */
	      r.r_ax=0x1101;
	      r.r_bx=0;
	      intr(0x10,&r);
	   } /* endif custom else EGA */
	} /* endif CGA */
     } /* endif non-VGA character set */
     _vidinit=0;
  }
  return;
}

void * Vsavestate(void *savebuffer)
{
   union REGS r;
   struct SREGS s;
   r.x.ax=0x1c00;
   r.x.cx=0x0007; /* bit 0-hardware 1-data areas 2-DAC state and color regs*/
   int86(0x10,&r,&r);
   if (r.x.bx) {
      if ( (savebuffer=malloc(r.x.bx*64)) == NULL) {
	 return(NULL);
      } else {
	 r.x.ax=0x1c01;
	 r.x.cx=0x0007;
	 r.x.bx=FP_OFF(savebuffer);
	 s.es=FP_SEG(savebuffer);
	 int86x(0x10,&r,&r,&s);
	 if (r.h.al != 0x1c) {
	    free(savebuffer);
	    savebuffer=NULL;
	 }
	 return(savebuffer);
      }
   } else {
      savebuffer=NULL;
      return(NULL);
   }
}

void Vrestorestate(void *savebuffer)
{
   union REGS r;
   struct SREGS s;
   if (savebuffer) {
	 r.x.ax=0x1c02;
	 r.x.cx=0x0007;
	 r.x.bx=FP_OFF(savebuffer);
	 s.es=FP_SEG(savebuffer);
	 int86x(0x10,&r,&r,&s);
   }
}

int   VGAmode(unsigned int mode, char *palette)
{
   union REGS r;

   if ( (mode <= 0x13) && (mode >= 0)){
       r.h.ah=0;
       r.h.al=mode & 0x00ff;
       int86(0x10,&r,&r);
       if (BIOScrtmode != mode) {
          return(0);
       }
       if ( palette != NULL ) {
          Vdisable_refresh();
          if (mode == 0x13) {
             if ( palette == DEFAULTDAC)
                WriteDACs(&_olddacs); /* restore defaults */
             else
                WriteDACs(palette);
          } else {
             Load_Palette(0, 16, palette);
          }
          Venable_refresh();
       }
       switch (mode) {
         /* 80 x 25, text mode */
         case 0x03 :  _screen_width=80;
                      _memory_length=409;
                      _screen_length=25;
                      _screen_start=(char *)(0xB8000000L);
                      break;
         case 0x0f :                                /* x 2 planes */
         /* 640 x 200, 1 bit per pixel x 4 planes */
         case 0x0e :  _screen_width=80;
                      _memory_length=819;
                      _screen_length=200;
                      _screen_start=(char *)(0xA0000000L);
                      break;
         /* 320 x 200, 1 bit per pixel x 4 planes */
         case 0x0d :  _screen_width=40;
                      _memory_length=1638;
                      _screen_length=200;
                      _screen_start=(char *)(0xA0000000L);
                      break;
         /* 640 x 350, 1 bit per pixel */
         case 0x10 :  _screen_width=80;             /* x 4 planes */
                      _memory_length=819;
                      _screen_length=350;
                      _screen_start=(char *)(0xA0000000L);
                      break;
         /* 640 x 480, 1 bit per pixel x 4 planes */
         case 0x12 :  _screen_width=80;
                      _memory_length=819;
                      _screen_length=480;
                      _screen_start=(char *)(0xA0000000L);
                      break;
         /* 320 x 200, 1 byte per pixel */
         case 0x13 :  _screen_width=320;
                      _memory_length=204;
                      _screen_length=200;
                      _screen_start=(char *)(0xA0000000L);
                      break;
       }
       if (vgadebug != NULL) {
          sprintf(tdbg,"\nVGAmode: mode=%u, _sw=%u, _sl=%u, _ss=%lx\n",
                       mode, _screen_width, _memory_length, _screen_start);
          fputs(tdbg,vgadebug);
       }
       return(1);
   } else
       return(0);
}

int isVGA(void)
{
   union REGS r;
   r.x.ax=0x1a00;
   int86(0x10,&r,&r);
   if ( (r.h.al == 0x1a )&& (r.h.bl > 7))
      return(1);
   else
      return(0);
}

void Start_vgadebug(char *path)
{
   if (debugtimeson)
      vgadebug=fopen(path,"a");
   else
      vgadebug=fopen(path,"w");
   debugtimeson++;
}

void Close_vgadebug(void)
{
   fclose(vgadebug);
}


