Metropoli BBS
VIEWER: frmi_ex4.c MODE: TEXT (ASCII)
#include <process.h>
#include <stdio.h>

#include "FRMI.H"

int __cdecl main()
{
   const unsigned short XMS_TO_ALLOC=2*1024;
   const unsigned long  XMS_TO_ALLOC_IN_BYTES=(unsigned long) XMS_TO_ALLOC*1024;

   WORD XMS_Handle;
   XPTR XMS_Address;


   FRMI_START();


   if (CF_SET)
   {
      if (_AH < CPU_80386)
      {
         printf("A 386 CPU or greater is needed !");
         exit(1);
      }

      _BX=_AX;
      printf("You're running under the ");

      switch(_BX)
      {
         case PM_V86     : printf("V86 MODE ! Please remove QEMM386, 386MAX, EMM386, etc.\n");
                           exit(1);
                           break;

         case PM_DPMS    : printf("Novell DOS 7 DPMS");
                           break;

         case PM_PHAR_LAP: printf("Phar Lap 386/DOS-Extender");
                           break;

         case PM_DOS4GW  : printf("Rational Systems DOS/4GW or DOS/16M");
                           break;

         case PM_DOSX    : printf("DOSX (DOS Extender)");
                           break;

         case PM_DPMI    : printf("DPMI 16 or 32");
                           break;
       }

       printf(".\nPlease remove it, and try again...\n");
       exit(1);
   }


   XMS_INIT();

   if (CF_SET)
   {
      switch(_AL)
      {
         case XMS_NOT_INSTALLED: printf("XMS driver is not present !\n");
                                 break;

         case XMS_BAD_VERSION  : printf("XMS driver V2.0 or greater is needed !\n");
                                 break;

         case XMS_BAD_A20      : printf("A20 gate can not be enabled !\n");
                                 break;
      }

      exit(1);
   }


   if (XMS_QUERY_FREE() < XMS_TO_ALLOC)
   {
      printf("Not enough free XMS ! %uKB needed...\n", XMS_TO_ALLOC);
      exit(1);
   }


   XMS_Handle=XMS_ALLOC(XMS_TO_ALLOC);
   XMS_Address=XMS_LOCK(XMS_Handle);

   printf("Writing %uKB to XMS.\n", XMS_TO_ALLOC);
   asm {
         Xor   EDI, EDI            /* Part to fill the XMS block */
         Mov   FS, DI
         Mov   EBX, [XMS_Address]
       }
   XMS_Fill_Loop:
   asm {
         Mov   FS:[DWORD PTR EBX+EDI], 0x12345678
         Add   EDI, 4
         Cmp   EDI, XMS_TO_ALLOC_IN_BYTES
         JB    XMS_Fill_Loop
       }

   printf("Checking the written data...\n");
   asm {
         Xor   EDI, EDI            /* Part to check the filled XMS block */
         Mov   FS, DI
         Mov   EBX, [XMS_Address]
       }
   XMS_Check_Loop:
   asm {
         Cmp   FS:[DWORD PTR EBX+EDI], 0x12345678
         JNE   XMS_Check_Error

         Add   EDI, 4
         Cmp   EDI, XMS_TO_ALLOC_IN_BYTES
         JB    XMS_Check_Loop
         JMP   XMS_Check_NO_ERROR
       }
   XMS_Check_Error:

   printf("XMS checking error !\n");
   goto XMS_Clean;

   XMS_Check_NO_ERROR:
   printf("XMS Checking successful !\n");
   asm {
         Mov   BX, 0xB800          /* FS can be used as a standard segment reg */
         Mov   FS, BX
         Mov   FS:[DWORD PTR 2*80], 0xCF4BBF4F
       }

   XMS_Clean:
   XMS_UNLOCK(XMS_Handle);
   XMS_FREE(XMS_Handle);

   return 0;
}
[ RETURN TO DIRECTORY ]