/*
  egavga.c - Functions of the EGA/VGA-BIOS
  Written by Stefan Pfeiffer, DL1ELY, 940403
  Last Modification: 950712
  (C) 1994 by Stefan Pfeiffer, DL1ELY
*/

#include "egavga.h"
#include <dos.h>
#include <graphics.h>

char vga_chars[64] =
{   0,  0,  0,  0, 15,  3,  5,  9, 16, 32, 64,128,  0,  0,  0,  0,
    0,  0,  0,  0,128, 64, 32, 16,  9,  5,  3, 15,  0,  0,  0,  0,
    0,  0,  0,  0,  1,  2,  4,  8,144,160,192,240,  0,  0,  0,  0,
    0,  0,  0,  0,240,192,160,144,  8,  4,  2,  1,  0,  0,  0,  0 };

char fn_logo[32] =
{0x00,0xFE,0x80,0x80,0x80,0xFC,0x02,0x02,0x02,0x82,0x84,0x78,0x00,0x00,0x00,0x00,
 0x00,0x00,0x00,0x00,0x1E,0x21,0x41,0x41,0x43,0x3D,0x01,0x01,0x41,0x42,0x3C,0x00};

char graphics = 0;
unsigned int xmax, ymax;

void vga_setchars()
{
  struct REGPACK regs;
  
  regs.r_ax = 0x1110;  // Function "Load characters"
  regs.r_bx = 0x1000;  // 16 lines high, chartable 0
  regs.r_cx = 4;       // Load 4 chars
  regs.r_dx = 20;      // beginning with ASCII 20
  regs.r_es = FP_SEG(vga_chars);
  regs.r_bp = FP_OFF(vga_chars);
  intr(0x10,&regs);

  regs.r_ax = 0x1110;  // Function "Load characters"
  regs.r_bx = 0x1000;  // 16 lines high, chartable 0
  regs.r_cx = 2;       // Load 2 chars
  regs.r_dx = 1;       // beginning with ASCII 1
  regs.r_es = FP_SEG(fn_logo);
  regs.r_bp = FP_OFF(fn_logo);
  intr(0x10,&regs);
}

void ega_setchars()
{
  struct REGPACK regs;
  
  regs.r_ax = 0x1110;  // Function "Load characters"
  regs.r_bx = 0x0E00;  // 14 lines high, chartable 0
  regs.r_cx = 1;       // Load 1 char
  regs.r_dx = 20;      // ASCII 20
  regs.r_es = FP_SEG((char *)vga_chars+1);
  regs.r_bp = FP_OFF((char *)vga_chars+1);
  intr(0x10,&regs);

  regs.r_ax = 0x1110;  // Function "Load characters"
  regs.r_bx = 0x0E00;  // 14 lines high, chartable 0
  regs.r_cx = 1;       // Load 1 char
  regs.r_dx = 21;      // ASCII 21
  regs.r_es = FP_SEG((char *)vga_chars+17);
  regs.r_bp = FP_OFF((char *)vga_chars+17);
  intr(0x10,&regs);

  regs.r_ax = 0x1110;  // Function "Load characters"
  regs.r_bx = 0x0E00;  // 14 lines high, chartable 0
  regs.r_cx = 1;       // Load 1 char
  regs.r_dx = 22;      // ASCII 22
  regs.r_es = FP_SEG((char *)vga_chars+33);
  regs.r_bp = FP_OFF((char *)vga_chars+33);
  intr(0x10,&regs);

  regs.r_ax = 0x1110;  // Function "Load characters"
  regs.r_bx = 0x0E00;  // 14 lines high, chartable 0
  regs.r_cx = 1;       // Load 1 char
  regs.r_dx = 23;      // ASCII 23
  regs.r_es = FP_SEG((char *)vga_chars+49);
  regs.r_bp = FP_OFF((char *)vga_chars+49);
  intr(0x10,&regs);


  regs.r_ax = 0x1110;  // Function "Load characters"
  regs.r_bx = 0x0E00;  // 14 lines high, chartable 0
  regs.r_cx = 1;       // Load 1 char
  regs.r_dx = 1;       // ASCII 1
  regs.r_es = FP_SEG((char *)fn_logo+1);
  regs.r_bp = FP_OFF((char *)fn_logo+1);
  intr(0x10,&regs);

  regs.r_ax = 0x1110;  // Function "Load characters"
  regs.r_bx = 0x0E00;  // 14 lines high, chartable 0
  regs.r_cx = 1;       // Load 1 char
  regs.r_dx = 2;       // ASCII 2
  regs.r_es = FP_SEG((char *)fn_logo+17);
  regs.r_bp = FP_OFF((char *)fn_logo+17);
  intr(0x10,&regs);
}

void restore_vga_charset()
{
  struct REGPACK regs;
  
  regs.r_ax = 0x1114;
  regs.r_bx = 0x0000;
  intr(0x10,&regs);
}

void restore_ega_charset()
{
  struct REGPACK regs;
  
  regs.r_ax = 0x1111;
  regs.r_bx = 0x0000;
  intr(0x10,&regs);
}

void set_blink(char blink)
{
  struct REGPACK regs;
  
  regs.r_ax = 0x1003;
  regs.r_bx = (unsigned)blink;
  intr(0x10,&regs);
}

void get_graphics()
{
  unsigned gd, gm;

  detectgraph((unsigned far *)&gd,(unsigned far *)&gm);

  switch(gd)
  {
    case EGA:
    case EGA64:
    case EGAMONO:
      xmax = 639;
      ymax = 349;
      graphics = EGA;
      break;
    case ATT400:
      xmax = 639;
      ymax = 399;
      graphics = ATT400;
      break;
    case VGA:
    case IBM8514:
      xmax = 639;
      ymax = 479;
      graphics = VGA;
      break;
    case HERCMONO:
      xmax = 719;
      ymax = 347;
      graphics = HERCMONO;
      break;
  };
};

void patch_driver(unsigned char mode)
{
  struct modetablet
  {
    unsigned nuls,x1,y1,x2,y2,w1,w2;
    unsigned aspect,w3,colormode;
  };  
  struct bgit
  {
    unsigned ID,backspaces;
    char copyrite[95];
    char ctrlz;
    unsigned offset1,driverno1,length1;
    unsigned version1,what1;
    char nuls0[18];
    unsigned offset2,driverno2,length2;
    unsigned version2,what2;
    char driverName[7];
    char nuls1[15];
    char dispatcher[12];
    char nuls2[4];
    char return1;
    char nuls3[4];
    char return2;
    unsigned functions[46];
    char code1[514];
    char mode1string[14];
    char nuls4;
    char mode2string[14];
    char nuls5;
    char mode3string[14];
    char nuls6;
    char mode4string[19];
    char nuls7;
    unsigned modetabladr[4];
    struct modetablet mode1table;
    struct modetablet mode2table;
    struct modetablet mode3table;
    struct modetablet mode4table;
    unsigned what3;
    unsigned setmodeadrs[4];
    char code2[445];
    unsigned maxx1,maxy1;
    char savtable1[11];
    unsigned savsegment;
    char savmode;
    char code3[8];
    char mul80_1[14];
    char code4[23];
    char code5;
    unsigned maxy2;
    char code6;
    char modeno1;
    char code7[4];
    char cols1;
    unsigned code8;
    unsigned bufsize1;
    char code9[3];
    unsigned maxy3;
    char code10;
    char modeno2;
    char code11;
    unsigned bufsize2;
    char code12[3];
    unsigned maxy4;
    char code13;
    char modeno3;
    char code14[3];
    unsigned maxy5;
    char code15;
    char modeno4;
    char code16[3];
    unsigned maxy6;
    char code17;
    char modeno5;
    char code18;
    unsigned bufsize3;
    char code19[3];
    unsigned bufsize4;
    char code20[4];
    char cols2;
    char code21[5];
    unsigned maxx2;
    char code22[5];
    unsigned maxx3;
    char code23[70];
    unsigned segment1;
    char code24[196];
    char mul80_2[16];
    char code25[82];
    char cols3;
    char code26[70];
    char cols4;
    char code27[53];
    char cols5;
    char code28[69];
    char cols6;
    char code29[3060];
    unsigned maxy7;
    char code30[5];
    char JNB2JMP;
    char code31[202];
  };
  
  struct bgit far *bgi;
  struct modetablet modetable;
  char cols;
  unsigned bufsize,aspectratio;

  bgi = EGAVGA_driver_far;
  xmax = 799;
  ymax = 599;
  aspectratio = 10000;
  cols = (xmax+1)/8;
  bufsize = 0xFFF0;
  
  modetable.nuls = 0;
  modetable.x1 = modetable.x2 = xmax;
  modetable.y1 = modetable.y2 = ymax;
  modetable.w1 = 0x2328;
  modetable.w2 = 0x1B58;
  modetable.w3 = 0x0808;
  modetable.aspect = aspectratio;
  modetable.colormode = 0x9090;
  
  bgi->mode1table = bgi->mode2table = bgi->mode3table = bgi->mode4table = modetable;
  bgi->cols1 = bgi->cols2 = bgi->cols3 = bgi->cols4 = bgi->cols5 = bgi->cols6 = cols;
  bgi->maxx1 = bgi->maxx2 = bgi->maxx3 = xmax;
  bgi->maxy1 = bgi->maxy2 = bgi->maxy3 = bgi->maxy4 = bgi->maxy5 = bgi->maxy6 = bgi->maxy7 = ymax;
  bgi->modeno1 = bgi->modeno2 = bgi->modeno3 = bgi->modeno4 = bgi->modeno5 = mode;
  bgi->bufsize1 = bgi->bufsize2 = bgi->bufsize3 = bgi->bufsize4 = bufsize;
  bgi->mul80_1[ 0] = 0x90; bgi->mul80_1[ 1] = 0x90; bgi->mul80_1[ 2] = 0x52;
  bgi->mul80_1[ 3] = 0xB8; bgi->mul80_1[ 4] = cols; bgi->mul80_1[ 5] = 0x00;
  bgi->mul80_1[ 6] = 0xF7; bgi->mul80_1[ 7] = 0xE7; bgi->mul80_1[ 8] = 0x89;
  bgi->mul80_1[ 9] = 0xC7; bgi->mul80_1[10] = 0x5A; bgi->mul80_1[11] = 0xB1;
  bgi->mul80_1[12] = 0x03; bgi->mul80_1[13] = 0x90;
  bgi->mul80_2[ 0] = 0x52; bgi->mul80_2[ 1] = 0x89; bgi->mul80_2[ 2] = 0xC7;
  bgi->mul80_2[ 3] = 0xB8; bgi->mul80_2[ 4] = cols; bgi->mul80_2[ 5] = 0x00;
  bgi->mul80_2[ 6] = 0xF7; bgi->mul80_2[ 7] = 0xE7; bgi->mul80_2[ 8] = 0x89;
  bgi->mul80_2[ 9] = 0xC7; bgi->mul80_2[10] = 0x5A; bgi->mul80_2[11] = 0x90;
  bgi->mul80_2[12] = 0x90; bgi->mul80_2[13] = 0x90; bgi->mul80_2[14] = 0x90;
  bgi->mul80_2[15] = 0x90;
  bgi->JNB2JMP = 0xEB;
};


void my_gotoxy(char x, char y)
{
  struct REGPACK regs;
  
  regs.r_ax = 0x0200;
  regs.r_bx = 0;
  regs.r_dx = (y << 8) + x;
  intr(0x10,&regs);
}

void def_cursor(char start, char end)
{
  struct REGPACK regs;
  
  regs.r_ax = 0x0100;
  regs.r_cx = (start <<8) + end;
  intr(0x010,&regs);
}
