/* 
  dvideo.c - direct access to the video-RAM
  Written by Stefan Pfeiffer, DL1ELY, 940129
  Last Modification: 961011
  (C) 1994 by Stefan Pfeiffer, DL1ELY
*/


#include <mem.h>
#include <dos.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <alloc.h>
#include "dvideo.h"


unsigned int startseg = 0xB800;
char lastline = 24;
char lastrow = 79;
char save_mode;


void dstart()
{
   union REGS r;
  
   r.h.ah = 0x0F;
   int86(0x10,&r,&r);
  
   save_mode = r.h.al;
   lastrow = r.h.ah-1;
  
   if(r.h.al == 7) 
   {
      startseg = 0xB000;
      lastline = 24;
   }
   else
   {  
      lastline = *(char far *)MK_FP(0x40,0x84);
      if(!lastline) lastline = 24;
   };
};  


void dend()
{
   union REGS r;
  
   r.h.ah = 0;
   r.h.al = save_mode;
   int86(0x10,&r,&r);
};

  
void dframe(char x1, char y1, char x2, char y2, char col)
{
   char i;
  
   dfill(x1+1,y1,x2-1,y1,223,col);
   dfill(x1+1,y2,x2-1,y2,220,col);
   dfill(x1,y1,x1,y2,219,col);
   dfill(x2,y1,x2,y2,219,col);
}
 
     
void dclrscr(unsigned char attr)
{
   dfill(0,0,lastrow,lastline,' ',attr);
}


unsigned dcalcsize(char x1, char y1, char x2, char y2)
{
   return(((y2-y1+1)*(x2-x1+1)*2)+4);
}

  
void drestore(char *ptr)
{
   unsigned far *vptr;
   char i;
   char x1, y1, x2, y2;
   unsigned bytes;
  
   x1 = *ptr;
   ptr++;
   y1 = *ptr;
   ptr++;
   x2 = *ptr;
   ptr++;
   y2 = *ptr;
   ptr++;
   bytes = (x2-x1+1)*2;
  
   for(i=y1;i<=y2;i++)
   {
      vptr = (unsigned far *)MK_FP(startseg,((i*(lastrow+1))+x1)*2);
      memmove(vptr,ptr,bytes);
      ptr+=bytes;
   }
}    


void *dsave(char x1, char y1, char x2, char y2)
{
   char *ptr;
   char *cp;
   unsigned far *vptr;
   char i;
  
   ptr = sec_alloc(dcalcsize(x1,y1,x2,y2));

   cp = ptr;
   *cp = x1;
   cp++;
   *cp = y1;
   cp++;
   *cp = x2;
   cp++;
   *cp = y2;
   cp++;
   for(i=0;i<=y2-y1;i++)
   {
      vptr = (unsigned far *)MK_FP(startseg,(((y1+i)*(lastrow+1))+x1)*2);
      memmove(cp,vptr,(x2-x1+1)*2);
      cp+=(x2-x1+1)*2;
   }

   return(ptr);
}    


void dmove(char x1, char y1, char x2, char y2, char xn, char yn)
{
   unsigned far *vptr;
   unsigned far *nptr;
   char i;
  
   // If whole lines will be copied, copying is sped up...
   if(x1 == 0 && x2 == lastrow)
   {
      vptr = (unsigned far *)MK_FP(startseg,y1*(lastrow+1)*2);
      nptr = (unsigned far *)MK_FP(startseg,yn*(lastrow+1)*2);
      memmove(nptr,vptr,(y2-y1+1)*(lastrow+1)*2);  
      return;
   }
  
   if(yn > y1)
   {
      for(i=y2-y1;i>=0;i--)
      {
         vptr = (unsigned far *)MK_FP(startseg,(((y1+i)*(lastrow+1))+x1)*2);
         nptr = (unsigned far *)MK_FP(startseg,(((yn+i)*(lastrow+1))+xn)*2);
         memmove(nptr,vptr,(x2-x1+1)*2);
      }
   }
   else
   {
      for(i=0;i<=y2-y1;i++)
      {
         vptr = (unsigned far *)MK_FP(startseg,(((y1+i)*(lastrow+1))+x1)*2);
         nptr = (unsigned far *)MK_FP(startseg,(((yn+i)*(lastrow+1))+xn)*2);
         memmove(nptr,vptr,(x2-x1+1)*2);
      }
   }
}    
 
   
void dcolor(char x1, char y1, char x2, char y2, unsigned char attr)
{
   unsigned far *vptr;
   char i,j;
  
   for(i=y1;i<=y2;i++)
   {
      vptr = (unsigned far *)MK_FP(startseg,((i*(lastrow+1))+x1)*2);
      j = x2-x1+1;
      while(j--) *vptr++ = (*vptr & 0xFF) + (attr<<8);
   }
}
 
   
void dfill(char x1, char y1, char x2, char y2, unsigned  char ch,unsigned char attr)
{
   unsigned far *vptr;
   char i,j;

   for(i=y1;i<=y2;i++)
   {
      vptr = (unsigned far *)MK_FP(startseg,((i*(lastrow+1))+x1)*2);
      j = x2-x1+1;
      while(j--) *vptr++ = (attr<<8)+ch;
   }
}


void dprint(char x, char y, unsigned char attr, unsigned char *s)
{
   unsigned far *vptr;

   vptr=(unsigned far *)MK_FP(startseg,((y*(lastrow+1))+x)*2);
   while(*s)
   {
      *vptr++ = (attr<<8)+*s;
      s++;
   }
}


void dprintf(char x, char y, unsigned char attr,const unsigned char *format, ...)
{
   va_list arg;
   char s[81];
  
   va_start(arg,format);
   vsprintf(s,format,arg);
   va_end(arg);
  
   dprint(x,y,attr,s);
};


