home *** CD-ROM | disk | FTP | other *** search
/ FMI Superhry 1 / Superhry-I.bin / bonus / doom / programs / ktsdht10 / ems.pas < prev    next >
Pascal/Delphi Source File  |  1994-05-02  |  13KB  |  251 lines

  1. {***************************************************************************
  2. *   E M S : a unit that can be used as an interface between a program and  *
  3. *          the Expanded Memory Manager (EMM) - this allows access to EMS   *
  4. *          memory                                                          *
  5. **------------------------------------------------------------------------**
  6. *  Author           : MICHAEL TISCHER                                      *
  7. *  developed on     : 06/09/1989                                           *
  8. *  last update on   : 06/09/1989                                           *
  9. ***************************************************************************}
  10.  
  11. unit Ems;
  12.  
  13. interface
  14.  
  15. uses Dos;
  16.  
  17. {-- declaration of functions and procedures that can be called from  ------}
  18. {-- other programs                                                   ------}
  19.  
  20. function  EmsGetFreePage   : integer;
  21. function  EmsGetPtr        ( PhysPage : byte ) : pointer;
  22. function  EmsAlloc         ( Amount : integer ) : integer;
  23. procedure EmsMap           ( Handle, LogPage : integer; PhysPage : byte );
  24. procedure EmsFree          ( Handle : integer );
  25. procedure EmsRestoreMapping( Handle : integer );
  26. procedure EmsSaveMapping   ( Handle : integer );
  27.  
  28. {-- constants, public -----------------------------------------------------}
  29.  
  30. const {--------------------------------------------- EMS error codes ------}
  31.  
  32.       EmsErrOk        = $00;   { everything o.k., no error                 }
  33.       EmsErrSw        = $80;   { error in EMM (software)                   }
  34.       EmsErrHw        = $81;   { EMS hardware error                        }
  35.       EmsErrInvHandle = $83;   { invalid EMS handle                        }
  36.       EmsErrFkt       = $84;   { invalid function called                   }
  37.       EmsErrNoHandles = $85;   { no more handles free                      }
  38.       EmsErrSaResMap  = $86;   { error while saving or restoring Mapping   }
  39.       EmsErrToMany    = $87;   { more pages were requested than are        }
  40.                                { physically available                      }
  41.       EmsErrNoPages   = $88;   { more pages requested than are free        }
  42.       EmsErrNullPages = $89;   { null page requested                       }
  43.       EmsErrLogPInv   = $8A;   { logical page does not belong to handle    }
  44.       EmsErrPhyPInv   = $8B;   { invalid physical page number              }
  45.       EmsErrMapFull   = $8C;   { Mapping memory region is full             }
  46.       EmsErrMapSaved  = $8D;   { Mapping already saved                     }
  47.       EmsErrMapRes    = $8E;   { attempt to restore Mapping without        }
  48.                                { previously saving it                      }
  49.  
  50. {-- global variables accessible to other programs -------------------------}
  51.  
  52. var EmsInst    : boolean;      { contains TRUE if EMS memory is available }
  53.     EmsPages    : integer;                     { total number of EMS pages }
  54.     EmsVersion,                  { EMS version number (32 = 3.2, 40 = 4.0) }
  55.     EmsError    : byte;                          { stores EMM error number }
  56.  
  57. implementation
  58.  
  59. {-- constants internal to this program ------------------------------------}
  60.  
  61. const EMS_INT = $67;              { interrupt vector for accessing the EMM }
  62.  
  63. {-- global variables internal to this module ------------------------------}
  64.  
  65. var EmsFrameSeg : word;           { segment address of the EMS page frames }
  66.  
  67. {***************************************************************************
  68. *  EmsInit : Initialializes the unit                                       *
  69. ***************************************************************************}
  70.  
  71. procedure EmsInit;
  72.  
  73. type EmmName  = array [1..8] of char; { name of the EMM from driver header }
  74.      EmmNaPtr = ^EmmName;               { pointer to name in driver header }
  75.  
  76. const Name : EmmName = 'EMMXXXX0';                    { name of EMS driver }
  77.  
  78. var Regs  : Registers;            { processor registers for interrupt call }
  79.  
  80. begin
  81.   {-- start by determining if EMS memory and the proper EMM are installed -}
  82.  
  83.   Regs.ax := $35 shl 8 + EMS_INT;              { get interrupt vector with }
  84.   msdos( Regs );                               { DOS function $35          }
  85.  
  86.   EmsInst := ( EmmNaPtr(Ptr(Regs.ES,10))^ = Name );  { compare driver name }
  87.  
  88.   if ( EmsInst ) then                               { is an EMM installed? }
  89.     begin                                                            { yes }
  90.  
  91.       {-- get total number of EMS pages -----------------------------------}
  92.       Regs.AH := $42;             { function no. for "get number of pages" }
  93.       intr( EMS_INT, Regs );                                    { call EMM }
  94.       EmsPages := Regs.DX;                   { store total number of pages }
  95.  
  96.       {-- get segment address of EMS page frame ---------------------------}
  97.       Regs.AH := $41;  { Function no. for "get segment add. of page frame" }
  98.       intr( EMS_INT, Regs );                                    { call EMM }
  99.       EmsFrameSeg := Regs.BX;                      { store segment address }
  100.  
  101.       {-- get version number of EMM ---------------------------------------}
  102.       Regs.AH := $46;          { function no. for "get EMM version number" }
  103.       intr( EMS_INT, Regs );                                    { call EMM }
  104.       EmsVersion := ( Regs.AL and 15 ) + ( Regs.AL shr 4 ) * 10;
  105.  
  106.       EmsError := EmsErrOk;                                { no errors yet }
  107.  
  108.     end;
  109. end;
  110.  
  111. {***************************************************************************
  112. *  EmsGetPtr : returns a pointer to one of the four physical pages of the  *
  113. *              EMS page frame                                              *
  114. **------------------------------------------------------------------------**
  115. *  Input   : PhysPage = number of the physical page                        *
  116. *  Output  : pointer to this page                                          *
  117. ***************************************************************************}
  118.  
  119. function EmsGetPtr( PhysPage : byte ) : pointer;
  120.  
  121. begin
  122.   EmsGetPtr := ptr( EmsFrameSeg, PhysPage shl 14 );
  123. end;
  124.  
  125. {***************************************************************************
  126. *  EmsGetFreePage : gets the number of free EMS pages (1 page = 16K)       *
  127. **------------------------------------------------------------------------**
  128. *  Output  : the number of free pages                                      *
  129. ***************************************************************************}
  130.  
  131. function EmsGetFreePage : integer;
  132.  
  133. var Regs : Registers;             { processor registers for interrupt call }
  134.  
  135. begin
  136.   Regs.AH := $42;                 { function no. for "get number of pages" }
  137.   intr( EMS_INT, Regs );                                        { call EMM }
  138.   EmsGetFreePage := Regs.BX;                 { return number of free pages }
  139. end;
  140. {***************************************************************************
  141. *  EmsAlloc : allocates a given number of EMS pages                        *
  142. **------------------------------------------------------------------------**
  143. *  Input   : Amount = number of pages to allocate                          *
  144. *  Output  : handle for later access to the allocated pages                *
  145. *  Info    : if an error occurs, the variable EmsError will contain a      *
  146. *            value not equal to 0 (an error code) after the function call  *
  147. ***************************************************************************}
  148.  
  149. function EmsAlloc( Amount : integer ) : integer;
  150.  
  151. var Regs : Registers;             { processor registers for interrupt call }
  152.  
  153. begin
  154.   Regs.AH := $43;                      { function no. for "allocate pages" }
  155.   Regs.BX := Amount;                     { number of pages is passed to BX }
  156.   intr( EMS_INT, Regs );                                        { call EMM }
  157.   EmsAlloc := Regs.DX;                        { the handle is passed to DX }
  158.   EmsError := Regs.AH;                                            { error? }
  159. end;
  160. {***************************************************************************
  161. * EmsMap : loads one of the allocated logical pages into one of the 4      *
  162. *           physical pages of the EMS page frame                           *
  163. *-------------------------------------------------------------------------**
  164. *  Input   : Handle   = handle that identifies the allocated page          *
  165. *            LogPage  = number of the logical page to be loaded            *
  166. *            PhysPage = the physical page number                           *
  167. *  Info    : if an error occurs, the variable EmsError will contain a      *
  168. *            value other than 0 (error code) after the function call       *
  169. ***************************************************************************}
  170.  
  171. procedure EmsMap( Handle, LogPage : integer; PhysPage : byte );
  172.  
  173. var Regs : Registers;             { processor registers for interrupt call }
  174.  
  175. begin
  176.   Regs.AH := $44;            { function no. for "map expanded memory page" }
  177.   Regs.DX := Handle;                { load the parameters in the registers }
  178.   Regs.BX := LogPage;
  179.   Regs.Al := PhysPage;
  180.   intr( EMS_INT, Regs );                                        { call EMM }
  181.   EmsError := Regs.AH;                                            { error? }
  182. end;
  183.  
  184. {***************************************************************************
  185. *  EmsFree : frees EMS pages previously allocated with EmsAlloc            *
  186. **------------------------------------------------------------------------**
  187. *  Input   : Handle = the handle under which the pages were allocated      *
  188. *  Info    : if an error occurs, the variable EmsError will contain a      *
  189. *            value other than 0 (error code) after the function call       *
  190. ***************************************************************************}
  191.  
  192. procedure EmsFree( Handle : integer );
  193.  
  194. var Regs : Registers;             { processor registers for interrupt call }
  195.  
  196. begin
  197.   Regs.AH := $45;             { function number for "release handle & EMS" }
  198.   Regs.DX := Handle;                      { load parameter in the register }
  199.   intr( EMS_INT, Regs );                                        { call EMM }
  200.   EmsError := Regs.AH;                                            { error? }
  201. end;
  202.  
  203. {***************************************************************************
  204. * EmsSaveMapping : saves a mapping of the current logical EMS pages in     *
  205. *                   the four physical pages of the EMS page frame          *
  206. **------------------------------------------------------------------------**
  207. *  Input   : Handle = the handle under which the pages were allocated      *
  208. *  Info    : if an error occurs, the variable EmsError will contain a      *
  209. *            value other than 0 (error code) after the function call       *
  210. ***************************************************************************}
  211.  
  212. procedure EmsSaveMapping( Handle : integer );
  213.  
  214. var Regs : Registers;             { processor registers for interrupt call }
  215.  
  216. begin
  217.   Regs.AH := $47;                     { function number for "save mapping" }
  218.   Regs.DX := Handle;                  { load the parameter in the register }
  219.   intr( EMS_INT, Regs );                                        { call EMM }
  220.   EmsError := Regs.AH;                                            { error? }
  221. end;
  222.  
  223. {***************************************************************************
  224. *  EmsRestoreMapping : retrieves a mapping previously saved with the       *
  225. *                      procedure EmsSaveMapping                            *
  226. **------------------------------------------------------------------------**
  227. *  Input   : Handle = the handle under which the pages were allocated      *
  228. *  Info    : if an error occurs, the variable EmsError will contain a      *
  229. *            value other than 0 (error code) after the function call       *
  230. ***************************************************************************}
  231.  
  232. procedure EmsRestoreMapping( Handle : integer );
  233.  
  234. var Regs : Registers;             { processor registers for interrupt call }
  235.  
  236. begin
  237.   Regs.AH := $48;                  { function number for "restore mapping" }
  238.   Regs.DX := Handle;                      { load parameter in the register }
  239.   intr( EMS_INT, Regs );                                        { call EMM }
  240.   EmsError := Regs.AH;                                            { error? }
  241. end;
  242.  
  243. {**----------------------------------------------------------------------**}
  244. {** Starting code of the unit                                            **}
  245. {**----------------------------------------------------------------------**}
  246.  
  247. begin
  248.   EmsInit;                                           { initialize the unit }
  249. end.
  250.  
  251.