/*
	xms.C

	Version 1.5

	eXtended Memory Specification API Tester

	Copyright (C) 1993, Geoff Friesen B.Sc.
	All rights reserved.

	Developed with: Borland C++ 3.1
*/

/*
	set ti=c:\borlandc\tsr\tsrlib
	t xms -hx -i
*/

#if !defined(__TINY__)
#error Tiny Memory Model Expected
#endif

#include "tsrlib.H"

char *title = "\r\n"

"ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r\n"
"º ±   ± ±   ±  ±±±                        º\r\n"
"º ±   ± ±   ± ±   ±                       º\r\n"
"º  ± ±  ±± ±± ±                           º\r\n"
"º   ±   ± ± ±  ±±±  Version 1.5           º\r\n"
"º  ± ±  ±   ±     ±                       º\r\n"
"º ±   ± ±   ± ±   ±                       º\r\n"
"º ±   ± ±   ±  ±±±                        º\r\n"
"º                                         º\r\n"
"º Copyright (C) 1993, Geoff Friesen B.Sc. º\r\n"
"º All rights reserved.                    º\r\n"
"ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ¼\r\n"
"$";

char buffer [1024];
char screen_buffer [80*25*2];

void main (void)
{
   long adr;
   EMMS info;
   int cshape, i, j, row = 3, vmode, x, y;
   unsigned handle, maxblocksize, ndefblocks = 0, totalXMSkilos;

   if ((vmode = v_getmode ()) != BW80 && vmode != C80 && vmode != MONO)
       return;

   cshape = v_getshape ();
   v_setshape (0x2000);         /* hide cursor */

   x = v_wherex ();
   y = v_wherey ();

   v_screen (SCREEN_SAVE, 1, 1, 80, 25, screen_buffer);

   v_gotoxy (1, 1);
   v_setattr (LIGHTGRAY << 4);

   v_border (SINGLE_LINE, 1, 1, 80, 25);
   v_clear(2, 2, 78, 23);

   v_gotoxy (13, 1);
   v_cputs ("´ XMS v1.1 þ eXtended Memory Specification API Tester Ã");

   v_gotoxy (20, 25);
   v_cputs ("´ PRESS ANY KEY TO TERMINATE THE TEST Ã");

   v_gotoxy (2, row);

   if (!XMS_Exists ())
   {
       v_cputs ("XMS driver not installed!");
       beep ();
       goto error_exit;
   }

   if (!XMS_Query (&totalXMSkilos, &maxblocksize))
   {
       v_cputs ("Unable to query XMS memory!");
       beep ();
       goto error_exit;
   }

   v_cprintf ("Total available XMS memory = %u kilobytes", totalXMSkilos);
   v_gotoxy (2, ++row);
   v_cprintf ("Maximum XMS block size = %u kilobytes", maxblocksize);
   v_gotoxy (2, ++row);

   if (maxblocksize > 0)
   {
	if ((handle = XMS_Alloc (maxblocksize)) == 0)
	{
	    v_cputs ("Unable to allocate XMS memory block.");
	    beep ();
	    goto error_exit;
	}

	v_cprintf ("Allocation handle = %u (%04X hex)", handle,
		   handle);
	v_gotoxy (2, ++row);

	if ((adr = XMS_Lock (handle)) == 0L)
	{
	    v_cputs ("Unable to lock XMS memory block.");
	    beep ();
	    goto error_exit1;
	}

	v_cprintf ("Locked Address = %lu (%08lX hex)", adr, adr);
	v_gotoxy (2, ++row);

	if (!XMS_Unlock (handle))
	{
	    v_cputs ("Unable to unlock XMS memory block.");
	    beep ();
	    goto error_exit1;
	}

	for (i = 0; i < maxblocksize; i++)
	{
	     v_cprintf ("Testing 1K block: %d", i);

	     for (j = 0; j < 1024; j++)
		  buffer [j] = 0;

	     info.srchandle = 0;
	     info.srcoffset = (long) (void far *) buffer;
	     info.desthandle = handle;
	     info.destoffset = (long) i*1024;
	     info.length = 1024;

	     XMS_Copy (&info);

	     for (j = 0; j < 1024; j++)
		  buffer [j] = 255;

	     info.srchandle = handle;
	     info.srcoffset = (long) i*1024;
	     info.desthandle = 0;
	     info.destoffset = (long) (void far *) buffer;
	     info.length = 1024;

	     XMS_Copy (&info);

	     for (j = 0; j < 1024; j++)
		  if (buffer [j] != 0)
		  {
		      ndefblocks++;
		      break;
		  }

	     if (k_iskey ())    /* Exit if user presses a key */
		 break;

	     v_gotoxy (2, row);
	}

	v_gotoxy (2, ++row);
	v_cprintf ("Number of defective 1K blocks = %d", ndefblocks);

error_exit1:

	(void) XMS_Free (handle);
   }

error_exit:

   (void) k_fetch ();

   v_screen (SCREEN_RESTORE, 1, 1, 80, 25, screen_buffer);
   v_gotoxy (x, y);
   v_setshape (cshape);
}

#ifndef INCL_KFETCH
#include "kfetch.C"
#endif

#ifndef INCL_KISKEY
#include "kiskey.C"
#endif

#ifndef INCL_VBORDER
#include "vborder.C"
#endif

#ifndef INCL_VCPRINTF
#include "vcprintf.C"
#endif

#ifndef INCL_VCPUTS
#include "vcputs.C"
#endif

#ifndef INCL_VGETMODE
#include "vgetmode.C"
#endif

#ifndef INCL_VGETSHAPE
#include "vgetshap.C"
#endif

#ifndef INCL_VGOTOXY
#include "vgotoxy.C"
#endif

#ifndef INCL_VPAINT
#include "vpaint.C"
#endif

#ifndef INCL_VSCREEN
#include "vscreen.C"
#endif

#ifndef INCL_VSETATTR
#include "vsetattr.C"
#endif

#ifndef INCL_VSETSHAPE
#include "vsetshape.C"
#endif

#ifndef INCL_VWHEREX
#include "vwherex.C"
#endif

#ifndef INCL_VWHEREY
#include "vwherey.C"
#endif
