#include <memory.h>
#include <dos.h>
#include <scl1ems.h>


/****************************************************
    Shows the use of EMS (Expanded memory functions */

void HandleReport(void);
void Pause(void);
void PrintError(unsigned int Error);

char *TestStr[]={
    "Data for Page 0",
    "Data for Page 1",
    "Data for Page 2",
    "Data for Page 3",
    };

typedef struct{
    unsigned int ErrorCode;
    char *ErrorMess;
    }EMSERRORS;

EMSERRORS emse[]=
    {
    EMS_NOT_AVAILABLE       ,"EMS is not available",
    EMS_INTERNAL_ERROR      ,"Internal EMM error",
    EMS_HARDWARE_ERROR      ,"Hardware Error",
    EMS_MANAGER_BUSY        ,"EMS Manager busy",
    EMS_INVALID_HANDLE      ,"Invalid handle",
    EMS_NOT_IMPLEMENTED     ,"Function is not implemented",
    EMS_NO_MORE_HANDLE      ,"No more handles availables",
    EMS_SAVE_REST_ERROR     ,"Save/restore error",
    EMS_LOG_GREATER_PH      ,"Not enough physical pages",
    EMS_LOG_GREATER_AVA     ,"Not enough available logical pages",
    EMS_ZERO_ALLOC          ,"Allocation of 0 pages",
    EMS_INVALID_LOG         ,"Invalid logical page number",
    EMS_INVALID_PH          ,"Invalid physical page number",
    EMS_STATE_SAVE_FULL     ,"Save Stack full",
    EMS_SAVE_ALREADY        ,"Already saved",
    EMS_RESTORE_FAIL        ,"Failure restoring",
    EMS_S_NOT_IMPLEMENTED   ,"Subfunction number not implemented",
    EMS_SOURCE_OVERWRITTEN  ,"Source overwritten",
    EMS_SIZE_ERROR          ,"Size error",
    EMS_OVERLAP             ,"Overlapping regions",
    EMS_OFFSET_ERROR        ,"Offset error",
    EMS_TOO_BIG             ,"Size too big",
    EMS_OVERLAP_ERROR       ,"Overlapping error",
    EMS_UNDEFINED_TYPE      ,"Undefined memory type",
    EMS_DUPLICATE           ,"Duplicate handle name",
    EMS_WRAP_ERROR          ,"Wrap error",
    };

EMSMove emove;
char HandleName[9]="SCL1V30";

main()
{
char buffer[80];
int i,handle;
unsigned int ppages,lpages;
void far *p,far *s;
void *t;

printf("\n\nSCL1 Version 3.0 Expanded Memory (EMS) Test\n");

/* Initialize expanded memory manager */

if(EMS_Init() != EMS_OK)
    {

    /* no EMS available */

    printf("No EMS available\n");
    exit(-1);
    }

    /* Get EMM version number */

EMS_Version(&i);
memset(buffer,0,sizeof(buffer));

/* use predefined macros to get the major and minor version number
   add 0x30 to these values to convert to ASCII, store in buffer */

buffer[0]=EMS_MAJOR_VER(i) + 0x30;
buffer[1]='.';
buffer[2]=EMS_MINOR_VER(i) + 0x30;

     /* print version number */

printf("EMS version: %s\n",buffer);

     /* get EMM status and print answer */

printf("EMS status: ");
if((i=EMS_Status())==EMS_OK)
    printf("OK\n");
else
    PrintError(i);

Pause();

     /* get physical pages info */

printf("Physical pages report\n");

     /* get total number of physical pages */

EMS_TotalPhPages(&ppages);
printf("\tTotal physical pages: %i\n",ppages);

     /* get each physical page address */

for(i=0;i < ppages;++i)
     {
     EMS_PageAddress(i,&p);
     printf("\tPhysical page %i address %X:%X\n",i,FP_SEG(p),FP_OFF(p));
     if(i > 0 && i % 21 == 0)
        Pause();
     }

Pause();

     /* get logical pages info */

printf("Logical pages report\n");

     /* get total number of logical pages */

EMS_TotalLogPages(&lpages);
printf("\tTotal logical pages: %i\n",lpages);

     /* get number of available logical pages */

EMS_AvailableLogPages(&lpages);
printf("\tAvailable logical pages: %i\n",lpages);
Pause();

printf("Allocation/mapping/reallocation Test\n");

if(lpages)
    {

    /* allocate all available memory */

    if((i=EMS_Alloc(&handle,lpages))==EMS_OK)
        {
        printf("\tSuccesful allocation of %i pages\n",lpages);

        if(EMS_SetHandleName(handle,HandleName)==EMS_OK)
            {
            printf("\tEMS handle has been named %s\n",HandleName);
            if(EMS_GetNamedHandle(HandleName,&i)==EMS_OK)
                printf("\tHandle number is %i\n",i);
            }

        /* print memory handle info */

        HandleReport();

        for(i=0;i < lpages,i < 4;++i)
            {
            printf("\tMapping Logical Page %i to Physical Page %i\n",i,i);
            EMS_Map(handle,i,i);
            EMS_PageAddress(i,&p);
            printf("\tPhysical page %i segment: %X\n",i,FP_SEG(p));
            printf("\tWriting to logical page %i\n",i);
            _fmemcpy(p,TestStr[i],sizeof(TestStr[i]));
            printf("\tCopying from expanded memory to conventional memory using EMS_Move\n");

            /* copy page 0 to our conventional memory buffer */

            emove.bytes=sizeof(TestStr[i]);
            emove.stype=EMS_EXPANDED_MEM;
            emove.shandle=handle;
            emove.soffset=0;
            emove.sseg=0;
            emove.dtype=EMS_CONVENTIONAL_MEM;
            emove.dhandle=0;
            s=(void far *)buffer;
            emove.doffset=FP_OFF(s);
            emove.dseg=FP_SEG(s);
            EMS_Move(&emove);

            /* compare our buffer with page 0 */

            if(_fmemcmp(p,(void far *)buffer,sizeof(TestStr[i]))==0)
                printf("\tLogical page %i copied to conventional memory, compares OK\n",i);
            else
                printf("\tLogical page %i copied to conventional memory, error in compare\n",i);
            Pause();
            }

        /* re-allocate to 1 page (16Kb) */

        if((i=EMS_Realloc(handle,1))==EMS_OK)
            {
            printf("\tReallocated to 1 page\n");

            /* print memory handle info */

            HandleReport();
            }

        /* free allocated memory */

        EMS_Free(handle);
        }
    else
        printf("\tError allocating EMS %x\n",i);
    }
}

void HandleReport(void)
{
EMSHandle p[255];
char buffer[9];
int i;

     /* get number of active handles */

memset(buffer,0,sizeof(buffer));

EMS_GetHandleCount(&i);
printf("\tHandle report\n");
printf("\t\tActive handles: %i\n",i);

 /* print the number of memory pages associated with each handle */

if(EMS_GetAllHandlePages(p,&i)==EMS_OK)
    {
    while(i--)
        {
        EMS_GetHandleName(p[i].handle,buffer);
        printf("\t\tHandle %s %i, %i pages\n",buffer,p[i].handle,p[i].pages);
        }
    }
}

void Pause(void)
{
printf("-- more --");
GetKey();
printf("\r          \n");
}

void PrintError(unsigned int Error)
{
int i;

for(i=0;i < sizeof(emse) /sizeof(EMSERRORS);++i)
    {
    if(emse[i].ErrorCode==Error)
        {
        printf("\t%s\n",emse[i].ErrorMess);
        return;
        }
    }
printf("\tUnknown error #%X\n",Error);
}
