#include <stdio.h>

unsigned int Udisegment = 0xd000;

extern int proc_type();
extern int ems_installed();
extern int get_DOS_version();
extern int get_conv_mem();
extern int get_CPU_speed();
extern int get_display_mode();

struct PC_equip {
char DOS_version [5];	/* 3.3,4.01 */
char video_adaptor [4]; /* HGC,MDA,CGA,EGA,VGA */
char video_mem [5];	/* 64K,128K,256K */
char CPU_type [8];	/* V20/V30,8086/8,80186/8,80286,80386,80486 */
char CPU_speed [6];	/* 999.9  note: 4.77 MHz IBM PC-XT = 1.0 */
char EMS_version [9];	/* EMS 4.0 , NONE*/
char EMS_page_frame [5];/* C800 ,---- */
char conv_mem [5];	/* 512K,640K */
char ext_mem [7];	/* 0K,16000K */
char mem_map [6] [16];	/* A000 ---------------- */
			/* B000 ---------------- */
			/* C000 ---------------- */
			/* D000 ---------------- */
			/* E000 -----A---------- */
			/* F000 XXXXXXXXXXXXXXXX */
} Installed_equip;

struct X {unsigned int ax,bx,cx,dx,si,di,ds,es;};
struct H {unsigned char al,ah,bl,bh,cl,ch,dl,dh;};
union {struct X x; struct H h;} regs;

/* VIDEO TEST ************************************************************* */

void get_video_info()
{
  int test_mask = 1;
  int v_mode;
  char bios_info = (peekb(0x87,0x40) & 0xff);

/*  if ((bios_info & 0x8) == 0)*/

    regs.h.ah = 0x12;
    regs.h.bl = 0x10;
    regs.h.bh = 0xff;
    sysint(0x10,&regs,&regs);		/* EGA info interrrupt */

    if ((regs.h.bl != ((bios_info & 0x60) >> 5)) ||
       (regs.h.bh != ((bios_info & 0x2) >> 1)) ||
       (regs.h.bh == 0xff))

    {
       v_mode = get_display_mode();
       switch (v_mode) {
	 case 3 : sprintf(Installed_equip.video_adaptor,"MDA");break;
       default	: sprintf(Installed_equip.video_adaptor,"CGA");break;
       }
       sprintf(Installed_equip.video_mem,"N/A");
    }
    else
    {
      sprintf(Installed_equip.video_mem,"%3dK",64*(regs.h.bl+1));

      outport(0x3ce,8);
      outport(0x3cf,test_mask);
      outport(0x3ce,8);
      if (inport(0x3cf) == test_mask)
	sprintf(Installed_equip.video_adaptor,"VGA");
      else
	sprintf(Installed_equip.video_adaptor,"EGA");
      outport(0x3ce,8);
      outport(0x3cf,0xff);
    }
}

/* EXT MEM TEST ************************************************************* */

get_ext_mem_size()

{
  regs.h.ah = 0x88;
  sysint(0x15,&regs,&regs);
  sprintf(Installed_equip.ext_mem,"%5dK",regs.x.ax);
}

/* EMS MEM TEST ************************************************************* */

#define EMM_INT 0x67

int result;

unsigned EMS_get_page_frame_addr()

{
  unsigned int temp;

  regs.h.ah = 0x41;
  temp = (unsigned int) sysint(EMM_INT,&regs,&regs);
  if (!(regs.x.ax & 0xff00))
    return(regs.x.bx);
  else
    return(0);
}

unsigned get_EMS_version()

{
 unsigned int temp;

 regs.h.ah = 0x46;
 temp = (unsigned) sysint(EMM_INT,&regs,&regs);
 if (!(regs.x.ax & 0xff00))
  return(regs.x.ax & 0x00ff);
 else
   return(0);
}

get_EMS_info()

{
  unsigned int	version;
  if(ems_installed() == 1)
    {
      version = get_EMS_version();
      sprintf(Installed_equip.EMS_version,
	      "EMS %x.%x",((version & 0x00f0) >> 4),(version & 0x000f));
      version = EMS_get_page_frame_addr();
      sprintf(Installed_equip.EMS_page_frame,"%4x",version);

    }
    else
    {
       sprintf(Installed_equip.EMS_version,"     N/A");
       sprintf(Installed_equip.EMS_page_frame," N/A");

    }
}



/* HI MEM TEST ************************************************************* */

rom_chk(rom_segm)
unsigned rom_segm;

{
  unsigned test_word;

  test_word = (unsigned) peekw(0x0,rom_segm);
  if (test_word == 0xAA55)
    return( (int) (0xff &(peekb(0x0002,rom_segm) / 8)));   /* ret # of 4K blks */
  else
    return(0);
}

ram_chk(test_segm)
unsigned test_segm;

{
char test_byte,safe_byte;
int offs;
int ram_here;

  ram_here = 1;
  offs = 0;
  while ((offs < 0x1000) && (ram_here==1))
  {
    safe_byte = (unsigned) peekb(offs,test_segm);
    pokeb (offs,test_segm,0x5a);
    test_byte = (unsigned) peekb(offs,test_segm);
    if ((test_byte & 0xff) == 0x5a)
    {
      pokeb(offs,test_segm,0xa5);
      test_byte = (unsigned) peekb(offs,test_segm);
      if ((test_byte & 0xff) == 0xa5)
      {
	pokeb(offs,test_segm,safe_byte);
	offs += 0x100 ;
	ram_here = 1;
      }
      else
      {
	pokeb(offs,test_segm,safe_byte);
	ram_here = 0;
      }
    }
    else
    {
      pokeb(offs,test_segm,safe_byte);
      ram_here = 0;
    }
  }
  if (ram_here == 1)
    return(1);
  else
    return(0);
}

get_hi_mem_info()
{
  unsigned segm;
  unsigned index;

  int i,blks_4K_mem;

  index = 0;
  segm = 0xA000;
  while (index < 80)
  {
    blks_4K_mem = rom_chk(segm + (index << 8));
    if (blks_4K_mem != 0)
    {
      for (i = 0;(i<blks_4K_mem);i++)
      {
	Installed_equip.mem_map [index / 16] [index % 16] = 'X';
	index++;
      }
    }
    else
    {
      blks_4K_mem = ram_chk(segm+(index << 8));
      if (blks_4K_mem != 0)
      {
	Installed_equip.mem_map [index / 16] [index % 16] = 'X';
	index++;
      }
      else
      {
	Installed_equip.mem_map [index / 16] [index % 16] = '-';
	index++;
      }
    }
  }
  for (i = 80;(i<96);i++)
  {
    Installed_equip.mem_map [i / 16] [i % 16] = 'X';
    index++;
  }
}


get_installed_equip()
{
  int cpu,temp;
  unsigned speed;
  cpu = proc_type();
  switch (cpu) {
    case 0x30:	sprintf(Installed_equip.CPU_type,"V20/V30");  break;
    case 0x86:	sprintf(Installed_equip.CPU_type," 8086/8");   break;
    case 0x186: sprintf(Installed_equip.CPU_type,"80186/8");  break;
    case 0x286:
    case 0x386:
    case 0x486: sprintf(Installed_equip.CPU_type,"  80%x", cpu);break;
    default:	sprintf(Installed_equip.CPU_type,"???????");     break;
  }
  switch (cpu) {
    case 0x286:
    case 0x386:
    case 0x486: get_ext_mem_size();  break;
    default :	sprintf(Installed_equip.ext_mem,"   N/A");     break;
  }
  get_video_info();
  get_EMS_info();
  get_hi_mem_info();
  sprintf(Installed_equip.conv_mem,"%3dK",get_conv_mem());
  temp = get_DOS_version();
  sprintf(Installed_equip.DOS_version,"%d.%2d", (temp & 0xff),(temp & 0xff00) >> 8);
  speed = 2500 / get_CPU_speed();
  sprintf(Installed_equip.CPU_speed,"%2d.%1d", speed / 10,speed % 10);

}

/*
main()
{
  int i,j;

  get_installed_equip();
  printf("\n%s\n",Installed_equip.DOS_version);
  printf("%s\n",Installed_equip.CPU_type);
  printf("%s\n",Installed_equip.CPU_speed);
  printf("%s\n",Installed_equip.conv_mem);
  printf("%s\n",Installed_equip.ext_mem);
  printf("%s\n",Installed_equip.video_adaptor);
  printf("%s\n",Installed_equip.video_mem);
  printf("%s\n",Installed_equip.EMS_version);
  printf("%s\n",Installed_equip.EMS_page_frame);

  for (i = 0;(i < 6);i++)
  {
     for (j = 0;(j < 16);j++)
     {
       putchar(Installed_equip.mem_map [i] [j] );
     }
    printf("\n");
  }
}

*/

