/*
**  EMM4C.C  (Expanded Memory Manager for C)
**
**   --- please read this ! ---
**
**  This source code is in "shrouded" form. It is distributed in this form
**  rather than as a library (.LIB) file because of the inconsistancies
**  between object files generated by different compilers. To support several
**  compilers would require a .LIB file for each compiler manufacturer, and
**  sometimes several versions of the .LIB file are needed for the different
**  versions of the same manufacturers compiler! This problem doesn't occur
**  with assembler libraries, which is why EMS4C.LIB can be used with all C
**  compilers.
**
**  You can compile this code, but you will have to register with us in order
**  to get the normal (commented) C source code with normal variable names.
*/

#include <stdio.h>
#include "ems4c.h"

#define V215 1
#define V170 0

#define V130 unsigned char
#define V950 unsigned int
#define V800 static

#ifndef FALSE
#define FALSE 0
#define TRUE !FALSE
#endif


#define V620  200


#define V630   512



typedef struct V750
{int V900;
 V130 V50[128];
} V750;

V800 V750 *V740;
V800 V750 *V760[V630];



typedef struct V500
{
 V950 V650;
 V950 V670;
 V950 V320;
 V950 V400;
 V950 V660;
} V500;

V800 V500 *V450;
V800 V500 *V510[V620];



V800 int V410[4];

V800 int V570 = 0;
V800 int V560 = 0;
V800 int V430 = 0;
V800 int V210 = -1;

#define V10 -1
#define V690     -2
#define V710   -3
#define V720     -4
#define V700    -5
#define V550 -6
#define V40     -7
#define V20   -8
#define V30     -9

#define V640     -9
#define V610     -1



V800 int V820(V50,V110)
V130 V50[128];
int V110;
{int V730, V810;
 int V600;

 V730 = V110 / 8;
 V810 = V110 % 8;
 V600 = 0x80;
 if(V810>0) V600 = V600 >> V810;

 V50[V730] |= V600;
#if V170
printf("SetBit(%d): V730=%d V810=%d V600=%xH V50[%d]=%xH\n",
  V110,V730,V810,V600,V730,V50[V730]);
#endif
 return(0);
}

V800 int V140(V50,V110)
V130 V50[128];
int V110;
{int V730, V810;
 int V600;

 V730 = V110 / 8;
 V810 = V110 % 8;
 V600 = 0x80;
 if(V810>0) V600 = V600 >> V810;

 V50[V730] &= (~V600);
#if V170
printf("$$$ V140(%d): V730=%d V810=%d V600=%xH V50[%d]=%xH\n",
  V110,V730,V810,V600,V730,V50[V730]);
#endif
 return(0);
}

V800 int V840(V50,V110)
V130 V50[128];
int V110;
{int V730, V810;
 int V600;

 V730 = V110 / 8;
 V810 = V110 % 8;
 V600 = 0x80;
 if(V810>0) V600 = V600 >> V810;
#if V170
printf("TestBit(%d): V730=%d V810=%d V600=%xH V50[%d]=%xH\n",
  V110,V730,V810,V600,V730,V50[V730]);
#endif

 if(V600&V50[V730]) return(1);
 else return(0);
}



V800 int V230()
{int V530;

 for(V530=0;V530<V560;V530++)
   if(V510[V530]->V650==0) return(V530);
 return(-1);
}



V800 int V240(V660)
int V660;
{int V530,V540;
 int V160 = 0;

 if(V660<1)
   {printf("FindFreePages: ERROR: V660=%d\n",V660);
    return(-1);
   }

#if V170
printf("$$$ V240: V660=%d ",V660);
#endif
 for(V530=0;V530<=(V570-V660);V530++)
   {
    if(V760[V530]->V900==0)
      {
       V160 = 1;
       for(V540=1;V540<V660;V540++)
         {if(V760[V530+V540]->V900>0)
            {
             V530 = V530 + V540;
             break;
            }

          V160++;
         }

       if(V160>=V660)
         {
#if V170
          printf("--> V320=%d (%d)\n",V530,V160);
#endif
          return(V530);
         }
      }
   }
#if V170
 printf("--> V320=-1\n");
#endif
 return(-1);
}


V800 int V300(V780,V670)
int V780;
int V670;
{int V530, V540;
 int V160 = 0;

 if(V670<1)
   {printf("FindFreeParas: ERROR: NbrParas\n",V670);
    return(-1);
   }
#if V170
printf("$$$ V300: V780=%d V670=%d ",V780,V670);
#endif
 if((V780<0)||(V780>=V570)) return(V30);

 V740 = V760[V780];
 if(1024-V740->V900<V670) return(V30);

 for(V530=0;V530<=(1024-V670);V530++)
   {
    if(V840(V740->V50,V530)==0)
      {
       V160 = 1;

       for(V540=1;V540<V670;V540++)
         {if(V840(V740->V50,V530+V540)==1)
            {
             V530 = V530 + V540;
             break;
            }
          V160++;
         }
       if(V160>=V670)
         {
#if V170
printf(" --> V790= %d\n",V530);
#endif
          return(V530);
         }
      }
   }

#if V170
printf(" --> V790 = -1\n");
#endif
 return(-1);
}

V800 int V220(V660)
int V660;
{int V530, V540;
 int V160 = 0;

 if(V660<1)
   {printf("FindFreeFrame: ERROR: V660=%d\n",V660);
    return(-1);
   }
#if V170
printf("$$$ V220: V660=%d Frames=[%d %d %d %d] ",
 V660,V410[0],V410[1],V410[2],V410[3]);
#endif
 for(V530=0;V530<=(4-V660);V530++)
   {if(V410[V530]==-1)
      {
       V160 = 1;
       for(V540=V530+1;V540<V660;V540++)
         {if(V410[V540]>=0) break;

          V160++;
         }
       if(V160>=V660)
         {
#if V170
printf(" --> V440 = %d\n",V530);
#endif
          return(V530);
         }
      }
    }
#if V170
printf(" --> V440 = -1\n");
#endif
 return(-1);
}



V800 int V310(V320,V660)
int V320;
int V660;
{int V530, V540;

 if(V660<1)
   {printf("FindPageFrame: ERROR: V660=%d\n",V660);
    return(-1);
   }
#if V170
printf("$$$ V310: V320=%d V660=%d Frames=[%d %d %d %d] ",
 V320,V660,V410[0],V410[1],V410[2],V410[3]);
#endif
 for(V530=0;V530<=(4-V660);V530++)
   {if(V410[V530]==V320)
      {
       for(V540=1;V540<V660;V540++) if(V410[V530+V540]!=V320+V540) return(-1);
#if V170
printf("--> V440=%d\n",V530);
#endif
       return(V530);
      }
   }
#if V170
printf("--> V440=-1\n");
#endif
 return(-1);
}



V800 int V580(V440,V780)
int V440;
int V780;
{int V150;
#if V170
 printf("$$$ Mapping page %d to frame %d ",V780,V440);
#endif
 if(V410[V440]!=V780)
   {V150 = emsMapMemory(V440,V780,V210);
    if(V150<0) return(V150);
#if V170
    printf(" --> OK\n");
#endif
    V410[V440] = V780;
   }
#if V170
 else printf(" --> already mapped\n");
#endif
 return(0);
}



int emmError(V150)
int V150;
{if(V150)
   {
    if((V150>=V640)&&(V150<=V610))
      {printf("EMM: Error %d (%xH): ",V150,V150);
       switch(V150)
         {case V10:
            puts("EMM already initialized");
            break;
          case V690:
            puts("EMM not initialized");
            break;
          case V710:
            puts("No handles remaining");
            break;
          case V720:
            puts("No pages remaining");
            break;
          case V700:
            puts("No (unmapped) frames remaining");
            break;
          case V550:
            puts("malloc() fails");
            break;
          case V40:
            puts("Size out of range");
            break;
          case V20:
            puts("Handle out of range");
            break;
          case V30:
            puts("Page out of range");
            break;
         }
      }
    else
      {printf("EMS: ");
       emsError(V150);
      }
   }
 return(V150);
}



#if V215

int DisplayBits(V120)
V130 V120;
{int V530;
 for(V530=0;V530<8;V530++)
  {if(0x80&V120) printf("1");
   else printf("0");
   V120 = V120<<1;
  }
 return(0);
}


int PageDump(V575)
int V575;
{int V530,V540;
 int V160 = 0;
 int UsedBytes;
 int FreeBytes;
 int V733;
 int V405;
 puts("*** Page Dump ***");
 for(V530=0;V530<V570;V530++)
   {V740 = V760[V530];
    if(V740->V900==0) continue;
    printf("Page %3d: UsedParas=%2d (%u bytes)\n",
      V530,V740->V900,16*V740->V900);
    V540 = 0;
    UsedBytes = 0;
    FreeBytes = 0;
    while(V540<1024)
      {
       V160 = 0;
       while((V540<1024)&&(V840(V740->V50,V540++)==0)) V160++;
       if(V160>0)
          {FreeBytes += (16*V160);
           printf("   Free: %5u bytes\n",16*V160);
          }
       if(V540<1024) V540--;

       V160 = 0;
       while((V540<1024)&&(V840(V740->V50,V540++)==1)) V160++;
       if(V160>0)
          {UsedBytes += (16*V160);
           printf("   Used: %5u bytes\n",16*V160);
          }
       if(V540<1024) V540--;
      }
    printf("   Totals: Used=%u Free=%u (%u)\n",
      UsedBytes,FreeBytes,UsedBytes+FreeBytes);

    if(V575)
      {for(V733=0;V733<128;V733+=8)
        {V405=FALSE;
         for(V540=V733;V540<V733+8;V540++) if(V740->V50[V540]) V405=TRUE;
         if(V405)
           {printf("%2d: ",V733);
            for(V540=V733;V540<V733+8;V540++)
              {DisplayBits(V740->V50[V540]);
               printf(" ");
              }
            printf("\n");
           }
        }
      }
   }
 return(0);
}

int HandleDump()
{int V530;
 puts("*** V524 Dump ***");
 for(V530=0;V530<V560;V530++)

     {V450 = V510[V530];
printf("%2d: V650=%d V670=%d V320=%d V400=%d V660=%d\n",
        V530,V450->V650,
        V450->V670,V450->V320,
        V450->V400,V450->V660);
     }
 return(0);
}

#endif



int emmInit(V772,V522)
int V772;
int V522;
{int V530, V540;
 int V842;
 int V442;
 int V736;
 char *malloc();
 int V150;
#if 0
 printf("emmInit: V772=%d V522=%d\n",V772,V522);
#endif

 if(V210>=0) return(V10);

 if((V772<1)||(V772>V630)) return(V30);

 if((V522<1)||(V522>V620)) return(V20);
 V560 = V522;

 if((V150=emsLoaded())!=0) return(V150);
 if((V150=emsGetStatus())!=0) return(V150);

 V150 = emsGetPages(&V442,&V842);
 if(V150) return(V150);
 if(V772>V442) return(V720);
 V570 = V772;

 V150 = emsAllocate(V570,&V210);
 if(V150) return(V150);
 V150 = emsGetFrame(&V430);
 if(V150) return(V150);

 for(V530=0;V530<V570;V530++)
   {V740 = (V750 *)malloc(sizeof(V750));
    if(V740==NULL) return(V550);
    V760[V530] = V740;
    V740->V900 = 0;
    for(V540=0;V540<128;V540++) V740->V50[V540] = 0;
   }

 for(V530=0;V530<V560;V530++)
   {V450 = (V500 *)malloc(sizeof(V500));
    if(V450==NULL) return(V550);
    V510[V530] = V450;
    V450->V650 = 0;
    V450->V670 = 0;
    V450->V320 = 0;
    V450->V400 = 0;
    V450->V660 = 0;
   }

 for(V530=0;V530<4;V530++) V410[V530] = -1;
 return(0);
}


int emmDone()
{int V150;
 if(V210>=0) if((V150=emsRelease(V210))!=0) return(V150);
 V210 = -1;
 return(0);
}


int emmPages(V652,V662)
V950 *V652;
V950 *V662;
{int V530;
 V950 V782;
 *V652 = 0;
 *V662 = 0;
 for(V530=0;V530<V570;V530++)
  {V782 = V760[V530]->V900;
   if(V782==0) (*V652)++;
   (*V662) += (1024 - V782);
  }
 return(0);
}


int emmAlloc(V822)
V950 V822;
{int V530,V532,V540;
 int V782;
 int V780;
 int V772;
 int V524;
 int V444;

 if(V210<0) return(V690);

 if(V822==0) return(V40);

 V524 = V230();
 if(V524<0) return(V710);

 if(V822>= 65536-15) V782 = 4*1024;
 else V782 = (V822+15) / 16;

 V772 = (V782 + 1023 ) / 1024;
#if V170
printf("$$$ emmAlloc: V822=%d V782=%d V772=%d\n",V822,V782,V772);
#endif
 if(V772>1)
   {
    V780 = V240(V772);
    if(V780<0) return(V720);


    for(V530=V780;V530<V780+V772;V530++)
      {V740 = V760[V530];
#if V170
printf("$$$ Alloc: V780=%d (V772=%d)\n",V530,V772);
#endif
       if(V530<V780+V772-1)
         {
          V740->V900 = 1024;
          for(V540=0;V540<128;V540++) V740->V50[V540]=0xff;
         }
       else
         {
          V540 = V782 - 1024*(V772-1);
          V740->V900 = V540;
          for(V532=0;V532<V540;V532++) V820(V740->V50,V532);
        }
      }

    V450 = V510[V524];
    V450->V650 = V822;
    V450->V670 = V782;
    V450->V320 = V780;
    V450->V400 = 0;
    V450->V660 = V772;
    return(V524);
   }
 else
   {
    for(V530=0;V530<V570;V530++)
      {
       V540 = V300(V530,V782);
       if(V540>=0)
         {
          V740 = V760[V530];
          V740->V900 += V782;
          for(V532=0;V532<V782;V532++) V820(V740->V50,V540+V532);

          V450 = V510[V524];
          V450->V650 = V822;
          V450->V670 = V782;
          V450->V320 = V530;
          V450->V400 = V540;
          V450->V660 = 1;
          return(V524);
         }
      }
   }

 return(-991);
}


int emmFree(V524)
int V524;
{int V530, V540;
 V950 V440;
 V950 V320;
 V950 V660;
 V950 V400;
 V950 V670;
 V950 V541;

 if(V210<0) return(V690);

 if((V524<0)||(V524>V560)) return(V20);
 V450 = V510[V524];
 V320 = V450->V320;
 V660 = V450->V660;
 V400 = V450->V400;
 V670 = V450->V670;
#if V170
printf("$$$ emmFree: V524=%d V320=%d V660=%d V400=%d V670=%d\n",
V524,V320,V660,V400,V670);
#endif

 emmUnlock(V524);

 if(V660>1)
   {
    for(V530=V320;V530<V320+V660;V530++)
      {
#if V170
printf("$$$ V444: V780=%d\n",V530);
#endif
       V740 = V760[V530];

       if(V530<V320+V660-1)
         {
          V740->V900 = 0;

          for(V540=0;V540<128;V540++) V740->V50[V540] = 0;
         }
       else
         {
          V541 = V670 - 1024*(V660-1);
          V740->V900 -= V541;
          for(V540=0;V540<V541;V540++) V140(V740->V50,V540);
         }
      }
   }
 else
   {
    V740 = V760[V320];
    V740->V900 -= V450->V670;

    for(V540=V400;V540<V400+V670;V540++)
      V140(V740->V50,V540);
   }

 V450->V650 = 0;
 V450->V400 = 0;
 V450->V670 = 0;
 V450->V320 = 0;
 V450->V660 = 0;
 return(0);
}


int emmLock(V524,V812)
int V524;
int *V812;
{int V530, V540;
 V950 V320;
 V950 V660;
 int V150;
 int V440;

 if(V210<0) return(V690);

 if((V524<0)||(V524>V560)) return(V20);
 V450 = V510[V524];
 V320 = V450->V320;
 V660 = V450->V660;

 V440 = V310(V320,V660);
 if(V440>=0)
   {
    *V812 = V430 + 1024*V440 + V450->V400;
#if V170
printf("$$$ emmLock(mapped): V440=%d V400=%d V812=%xH\n",
  V440,V450->V400,*V812);
#endif
    return(0);
   }

 V440 = V220(V660);
 if(V440<0) return(V700);

 for(V530=0;V530<V660;V530++)
   {
    if((V150=V580(V440+V530,V320+V530))!=0) return(V150);
   }

 *V812 = V430 + 1024*V440 + V450->V400;
#if V170
printf("$$$ emmLock: V440=%d V400=%d V812=%xH\n",
  V440,V450->V400,*V812);
#endif
 return(0);
}

int emmUnlock(V524)
int V524;
{int V530;
 int V440;
 V950 V320;
 V950 V660;

 if(V210<0) return(V690);

 if((V524<0)||(V524>V560)) return(V20);
 V450 = V510[V524];
 V320 = V450->V320;
 V660 = V450->V660;

 V440 = V310(V320,V660);
#if V170
printf("$$$ emmUnlock: V320=%d V660=%d ==> V440=%d\n",
  V320,V660,V440);
#endif
 if(V440>=0)
   {
    for(V530=V440;V530<V440+V660;V530++)
      {

       V410[V530] = -1;
      }
   }
 return(0);
}


#if V215

int emmStats(V524,V771,V731,V821)
int V524;
int *V771;
int *V731;
int *V821;
{
 if((V524<0)||(V524>V560)) return(V20);
 V450 = V510[V524];
 *V771 = V450->V320;
 *V731 = 16 * V450->V400;
 *V821 = 16 * V450->V670;
 return(0);
}

#endif

#if V215

int emmCheck()
{int V530, V540;
 V950 V670;
 V950 V320;
 V950 V400;
 long V526;
 long V534;

 if(V210<0) return(V690);

 puts("*** emmCheck: checking...");
 for(V530=0;V530<V560;V530++)
   {V450 = V510[V530];
    if(V450->V650>0)
      {
       V670 = V450->V670;
       V320 = V450->V320;
       V400 = V450->V400;
       V526 = (long)1024*V320 + (long)V400;

       for(V540=V530+1;V540<V560;V540++)
         {if(V510[V540]->V670>0)
            {
             V534 = (long)1024*V510[V540]->V320
                 + (long)V510[V540]->V400;
             if(V526<V534)
                {
                 if(V526+(long)V670
                   >=V534+(long)V510[V540]->V670)
                   {
                    printf("emmCheck: ERROR1: V524 %d overlaps %d\n",V530,V540);
                    return(FALSE);
                   }
                }
             else if(V534<V526)
                {
                 if(V526+(long)V670
                   <=V534+(long)V510[V540]->V670)
                   {
                    printf("emmCheck: ERROR2: V524 %d overlaps %d\n",V530,V540);
                    return(FALSE);
                   }
                }
             else
                {
                 printf("emmCheck: ERROR3: V524 %d overlaps %d\n",V530,V540);
                 return(FALSE);
                }
            }
         }
      }
   }
 return(TRUE);
}

#endif

