home *** CD-ROM | disk | FTP | other *** search
/ PC Underground / UNDERGROUND.ISO / memory / xms / memory.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1995-07-28  |  15.3 KB  |  621 lines

  1. Unit Memory;
  2. {
  3.   **************************************************************************
  4.   ***   Memory - Unit  of  PC Underground by  DATA BECKER/ABACUS         ***
  5.   ***   Author      : Boris Bertelsons                                   ***
  6.   ***   Created     : 01/26/94                                           ***
  7.   ***   Last update : 03/18/94                                           ***
  8.   *** ------------------------------------------------------------------ ***
  9.   ***  The unit provides routines for dealing with memory.               ***
  10.   ***  In particular, this unit contains routines for handling           ***
  11.   ***  XMS and EMS !                                                     ***
  12.   **************************************************************************
  13. }
  14.  
  15. Interface
  16.  
  17. uses dos;
  18.  
  19. TYPE XMSHandle = word;
  20.  
  21.      EMSHandle = word;
  22.  
  23.      XMS_Copyblock = Record     { required for the copy routines }
  24.        Size     : longint;
  25.        Q_Handle : Word;
  26.        Q_Offset : pointer;
  27.        Z_Handle : Word;
  28.        Z_Offset : pointer;
  29.      end;
  30.  
  31.      EMS_Header = Record        { for recognition of EMS }
  32.        dummy   : array[0..9] of byte;
  33.        ID : array[1..7] of char;
  34.      end;
  35.  
  36. VAR XMS_Available   : boolean;  { TRUE, if XMS is available }
  37.     XMST            : pointer;  { Driver - Entry point address }
  38.     XMS_Version     : word;     { Version of XMS driver }
  39.     XC              : XMS_Copyblock;
  40.     EMS_Available   : boolean;  { TRUE, if  EMS is available }
  41.     EMS_Version     : word;     { Number of EMS version. Vers.MAJ
  42.                                               is in the Hi-Byte and VERS.MIN is in the
  43.                                   Lo-Byte ! }
  44.     EMS_Pages_Free : word;     { Number of free EMS pages }
  45.     EMS_Pages_Tot : word;      { Total number of EMS pages
  46.                                   available }
  47.  
  48.  
  49. function  base_free : longint;
  50. {
  51.   The function returns the size of the maximum total of available  
  52.   main memory in bytes
  53. }
  54.  
  55. function  XMS_free  : longint;
  56. {
  57.   The function returns the size of the maximum total of available
  58.   XMS memory in bytes
  59. }
  60.  
  61. Function Getmem_XMS(VAR H : XMSHandle; Size : longint) : byte;
  62. {
  63.  The function allocates a block in XMS that is Size Bytes large. Size   
  64.  is rounded off to the nearest kilobyte limit. The number of the handle
  65.  by which the block can be addressed is returned in H and cannot be    
  66.  lost, because otherwise the block can only be addressed by a reset. If 
  67.  the function was able to allocate the memory, it returns the value 0,   
  68.  otherwise the error table shown in the book applies.
  69. }
  70.  
  71. Function Freemem_XMS(H : XMSHandle) : byte;
  72. {
  73.  The function frees up a memory area in XMS that was allocated by GETMEM_XMS.        
  74.  The meaning of the function result can be found in the XMS error table.
  75. }
  76.  
  77. Function XMS_2_XMS(h1,h2 : XMSHandle; Size : Word) : byte;
  78. {
  79.  This function copies the number of bytes passed in Size in XMS from h1 to h2.
  80.  Size must be an EVEN value. The meaning of the function result can be 
  81.  found in the XMS error table.
  82. }
  83.  
  84. Function RAM_2_XMS(q : pointer; h : XMSHandle; Size : Word) : byte;
  85. {
  86.  This function copies data from RAM to XMS. q is a pointer to the
  87.  source data in RAM. h is the handle that you got from the GETMEM_XMS
  88.  function. Size is the size of the block to be copied in bytes. Here again, Size
  89.  is rounded off to the nearest kilobyte and you can check the XMS error table
  90.  for the meaning of the function result.
  91. }
  92.  
  93. Function XMS_2_Ram(d : pointer; h : XMSHandle; Size : Word) : byte;
  94. {
  95.  This function copies data from XMS to RAM. d is a pointer to the 
  96.  destination in RAM. h is the handle that you got from the GETMEM_XMS
  97.  function. Size is the size of the block to be copied in bytes. Once again, 
  98.  Size is rounded off to the nearest kilobyte and you can check the XMS 
  99.  error table for the meaning of the function result.
  100. }
  101.  
  102. Procedure Check_for_XMS;
  103. {
  104.  The procedure checks whether XMS is available, and initializes the
  105.  variables required by the unit. XMS_Available is set to TRUE when an 
  106.  XMS driver is available. You will find the version number of the driver 
  107.  in XMS_Version.
  108. }
  109.  
  110. procedure Check_for_EMS;
  111. {
  112.  This procedure checks whether EMS is available and initializes 
  113.  the corresponding variables
  114. }
  115.  
  116. Function EMS_free  : longint;
  117. {
  118.  The function returns the size of the free EMS memory in bytes.
  119. }
  120.  
  121. Function EMS_Segment_determine(VAR Segment : word) : byte;
  122. {
  123.  This function determines the segment where EMS starts being  
  124.  overlaid into RAM.
  125. }
  126.  
  127. Function EMS_Get_PageNumber : byte;
  128. {
  129.  This function determines the total number of available pages in EMS
  130.  as well as how many pages are still free. The values are placed in
  131.  the global variables "EMS_Pages_Tot" and "EMS_Pages_Free".
  132. }
  133.  
  134. Function Getmem_EMS(VAR H : EMSHandle; Size : longint) : byte;
  135. {
  136.  This function allocates the specified amount of memory in EMS. The
  137.  memory can be addressed via the "H" handle. Please keep in mind
  138.  that the function allocates at least one page, that is, 16K in EMS.
  139.  That means that you should only page larger data structures 
  140.  in EMS.
  141. }
  142.  
  143. Function Freemem_EMS(H : EMSHandle) : byte;
  144. {
  145.  This function frees up memory allocated by Getmem_EMS.
  146. }
  147.  
  148. Function EMS_Allocation(H : EMSHandle;PagePage,EMSPage : word) : byte;
  149. {
  150.  Use this function to determine the allocation of EMS pages for the
  151.  corresponding handle. PagePage can hold a value from 0 to 3, and 
  152.  stands for the page position at whic it is overlaid in RAM. EMSPage
  153.  is the page in EMS that is to be overlaid. Thus, if you want to assign 
  154.  page 7 of EMS to the EMSH handle (important for blocks > 64K !),
  155.  you need to call the function with the parameters (EMSH,0,7).
  156. }
  157.  
  158. Function EMS_Protect_Allocation(H : EMSHandle) : byte;
  159. {
  160.  This function protects the order of the EMS page set by EMS_Allocation
  161.  for the specified handle from changes.
  162. }
  163.  
  164. Function EMS_Unprotect_Allocation(H : EMSHandle) : byte;
  165. {
  166.  A handle protected by EMS_Protect_Allocation must first be unprotected 
  167.  with this function before the allocation can be changed.
  168. }
  169.  
  170. Function RAM_2_EMS(q : pointer; H : EMSHandle; Size : longint) : byte;
  171. {
  172.  Use this function to copy the specified block from RAM to EMS. Size
  173.  refers to the size in bytes, q stands for a pointer to the source area and
  174.  H is the handle from Getmem_EMS.
  175. }
  176.  
  177. Function EMS_2_RAM(q : pointer; H : EMSHandle; Size : longint) : byte;
  178. {
  179.  Similar to RAM_2_EMS, this function copies a memory area from 
  180.  RAM to EMS.
  181. }
  182.  
  183. Function EMS_Handles_assign(Var Number : word) : byte;
  184. {
  185.  This function gives you the number of EMS handles that  have already
  186.  been assigned. A maximum of 256 handles can be assigned.
  187. }
  188.  
  189. function XMS_lock(H : XMSHandle) : longint;
  190. {
  191.  The function locks an XMS block from being moved and returns
  192.  its absolute address
  193. }
  194.  
  195. procedure XMS_unlock(H : XMSHandle);
  196. {
  197.  The procedure unlocks an XMS handle that has been locked from
  198.  being moved.
  199. }
  200.  
  201.  
  202. implementation
  203.  
  204. function base_free : longint;
  205. begin;
  206.   base_free := MemAvail;
  207. end;
  208.  
  209. function XMS_free  : longint;
  210. var xms_in_kb : word;
  211.     xms_long: longint;
  212. begin;
  213.   asm
  214.     mov ax,0800h                { 8 = Get free memory }
  215.     call dword ptr [XMST]
  216.     mov xms_in_kb,dx
  217.   end;
  218.   xms_long := xms_in_kb;
  219.   XMS_free := xms_long * 1024;
  220. end;
  221.  
  222. Function Getmem_XMS(VAR H : XMSHandle; Size : longint) : byte;
  223. var bsize : word;
  224.     Fresult : byte;
  225.     xmsh : word;
  226. begin;
  227.   bsize := (size DIV 1024) + 1;
  228.   asm
  229.     mov ax,0900h                { 9 = allocate memory area }
  230.     mov dx,bsize
  231.     call dword ptr [XMST]
  232.     cmp ax,1
  233.     jne @Error_GetmemXms
  234.     mov xmsh,dx
  235.     mov Fresult,0
  236.     jmp @End_GetmemXms
  237. @Error_GetmemXMS:
  238.     mov Fresult,bl
  239. @End_GetmemXms:
  240.   end;
  241.   h := xmsh;
  242.   Getmem_Xms := Fresult;
  243. end;
  244.  
  245. Function Freemem_XMS(H : XMSHandle) : byte;
  246. var fresult : byte;
  247. begin;
  248.   asm                           { A = deallocate memory area }
  249.     mov ax,0a00h
  250.     mov dx,h
  251.     call dword ptr [XMST]
  252.     cmp ax,1
  253.     jne @Error_FreememXms
  254.     mov Fresult,0
  255.     jmp @End_FreememXms
  256. @Error_FreememXms:
  257.     mov Fresult,bl
  258. @End_FreememXms:
  259.   end;
  260. end;
  261.  
  262. Function XMS_2_XMS(h1,h2 : XMSHandle; Size : Word) : byte;
  263. VAR fresult : byte;
  264. begin;
  265.   XC.Size     := Size;          { size of block in bytes }
  266.   XC.Q_Handle := h1;            { source handle }
  267.   XC.Q_Offset := nil;           { source offset, 0 = start of block }
  268.   XC.Z_Handle := h2;            { destination handle }
  269.   XC.Z_Offset := nil;           { destination offset }
  270.   asm
  271.     mov si,offset XC
  272.     mov ax,0B00h
  273.     call dword ptr [XMST]
  274.     cmp ax,1
  275.     jne @Error_RAM2XMS
  276.     mov fresult,0
  277.     jmp @End_Ram2XMS
  278. @Error_Ram2XMS:
  279.     mov fresult,bl
  280. @End_Ram2XMS:
  281.   end;
  282. end;
  283.  
  284. Function RAM_2_XMS(q : pointer; h : XMSHandle; Size : Word) : byte;
  285. VAR fresult : byte;
  286. begin;
  287.   XC.Size     := Size;
  288.   XC.Q_Handle := 0;               { 0 = RAM }
  289.   XC.Q_Offset := q;
  290.   XC.Z_Handle := h;
  291.   XC.Z_Offset := nil;
  292.   asm
  293.     mov si,offset XC
  294.     mov ax,0B00h
  295.     call dword ptr [XMST]
  296.     cmp ax,1
  297.     jne @Error_RAM2XMS
  298.     mov fresult,0
  299.     jmp @End_Ram2XMS
  300. @Error_Ram2XMS:
  301.     mov fresult,bl
  302. @End_Ram2XMS:
  303.   end;
  304. end;
  305.  
  306. Function XMS_2_Ram(d : pointer; h : XMSHandle; Size : Word) : byte;
  307. VAR fresult : byte;
  308. begin;
  309.   XC.Size     := Size;
  310.   XC.Q_Handle := h;
  311.   XC.Q_Offset := nil;
  312.   XC.Z_Handle := 0;               { 0 = RAM }
  313.   XC.Z_Offset := d;
  314.   asm
  315.     mov si,offset XC
  316.     mov ax,0B00h
  317.     call dword ptr [XMST]
  318.     cmp ax,1
  319.     jne @Error_XMS2RAM
  320.     mov fresult,0
  321.     jmp @End_XMS2Ram
  322. @Error_XMS2Ram:
  323.     mov fresult,bl
  324. @End_XMS2Ram:
  325.   end;
  326. end;
  327.  
  328. Procedure Check_for_XMS; assembler;
  329.   asm
  330.     mov ax,4300h              { check whether driver installed }
  331.     int 2Fh
  332.     cmp al,80h
  333.     jne @No_XMSdriver
  334.     mov ax,4310h              { get entry point address of driver }
  335.     int 2Fh
  336.     mov word ptr XMST + 2,es
  337.     mov word ptr XMST + 0,bx
  338.     xor ax,ax                 { get version numb }
  339.     call dword ptr [XMST]
  340.     cmp  ax,0200h
  341.     jb   @No_XMSdriver     { if version < 2.0 then cancel ! }
  342.     mov  XMS_Version,ax
  343.     mov  XMS_Available,0
  344. @No_XMSdriver:
  345.     mov XMS_Available,1
  346. @End_XMS_Check:
  347. end;
  348.  
  349. procedure Check_for_EMS;
  350. var emsseg : word;
  351.     emsptr : pointer;
  352.     emshead : EMS_Header;
  353. begin;
  354.   asm
  355.     mov ax,3567h
  356.     int 21h
  357.     mov emsseg,es
  358.   end;
  359.   move(ptr(emsseg,0)^,emshead,17);
  360.   if emshead.ID = 'EMMXXXX' then begin;
  361.     EMS_Available := true;
  362.     asm
  363.       mov ah,40h                 { get EMS driver status }
  364.       int 67h
  365.       cmp ah,0
  366.       jne @EMS_Vers_Error
  367.       mov ah,46h                 { get EMS version }
  368.       int 67h
  369.       cmp ah,0
  370.       jne @EMS_Vers_Error
  371.       mov bl,al
  372.       shr al,4
  373.       mov bh,al                 { bh = Vers.maj }
  374.       or  bl,0Fh                { bl = Vers.min }
  375.       mov EMS_Version,bx
  376.       jmp @EMS_Vers_End
  377. @EMS_Vers_Error:
  378.       mov EMS_Available,1
  379. @EMS_Vers_End:
  380.     end;
  381.   end else begin;
  382.     EMS_Available := false;
  383.   end;
  384. end;
  385.  
  386. Function EMS_Segment_determine(VAR Segment : word) : byte;
  387. VAR hseg : word;
  388.     fresult : byte;
  389. begin;
  390.   asm
  391.     mov ah,41h
  392.     int 67h
  393.     cmp ah,0
  394.     jne @EMS_Segdet_Error
  395.     mov hseg,bx
  396.     mov fresult,0
  397.     jmp @EMS_Segdet_End
  398. @EMS_Segdet_Error:
  399.     mov fresult,ah
  400. @EMS_Segdet_End:
  401.   end;
  402.   Segment := hseg;
  403.   EMS_Segment_determine := fresult;
  404. end;
  405.  
  406. Function EMS_Get_PageNumber : byte;
  407. var fresult : byte;
  408. begin;
  409.   asm
  410.     mov ah,42h
  411.     int 67h
  412.     cmp ah,0
  413.     jne @EMS_GetPages_Error
  414.     mov EMS_Pages_Free,bx
  415.     mov EMS_Pages_Tot,dx
  416.     mov fresult,0
  417.     jmp @EMS_GetPages_End
  418. @EMS_GetPages_Error:
  419.     mov fresult,ah
  420. @EMS_GetPages_End:
  421.   end;
  422.   EMS_Get_PageNumber := fresult;
  423. end;
  424.  
  425. function EMS_free  : longint;
  426. var    help : longint;
  427. begin;
  428.   EMS_Get_PageNumber;
  429.   help := EMS_Pages_Free;
  430.   EMS_free := help SHL 14;
  431. end;
  432.  
  433. Function Getmem_EMS(VAR H : EMSHandle; Size : longint) : byte;
  434. var Fresult : byte;
  435.     EPages : word;
  436.     Hhandle : word;
  437. begin;
  438.   EPages := (Size DIV 16384) + 1;
  439.   asm
  440.     mov ah,43h
  441.     mov bx,EPages
  442.     int 67h
  443.     cmp ah,0
  444.     jne @Getmem_Ems_Error
  445.     mov Hhandle,dx
  446.     mov fresult,0
  447.     jmp @Getmem_Ems_End
  448. @Getmem_Ems_Error:
  449.     mov Fresult,ah
  450. @Getmem_Ems_End:
  451.   end;
  452.   H := Hhandle;
  453.   Getmem_EMS := Fresult;
  454. end;
  455.  
  456. Function Freemem_EMS(H : EMSHandle) : byte;
  457. var Fresult : byte;
  458. begin;
  459.   asm
  460.     mov ah,45h
  461.     mov dx,H
  462.     int 67h
  463.     mov Fresult,ah
  464.   end;
  465.   Freemem_EMS := Fresult;
  466. end;
  467.  
  468. Function EMS_Allocation(H : EMSHandle;PagePage,EMSPage : word) : byte;
  469. VAR Fresult : byte;
  470. begin;
  471.   asm
  472.     mov ah,44h
  473.     mov al,byte ptr PagePage
  474.     mov bx,EMSPage
  475.     mov dx,H
  476.     int 67h
  477.     mov Fresult,ah
  478.   end;
  479.   EMS_Allocation := Fresult;
  480. end;
  481.  
  482. Function EMS_Protect_Allocation(H : EMSHandle) : byte;
  483. VAR Fresult : byte;
  484. begin;
  485.   asm
  486.     mov ah,47h
  487.     mov dx,H
  488.     int 67h
  489.     mov Fresult,ah
  490.   end;
  491.   EMS_Protect_Allocation := Fresult;
  492. end;
  493.  
  494. Function EMS_Unprotect_Allocation(H : EMSHandle) : byte;
  495. VAR Fresult : byte;
  496. begin;
  497.   asm
  498.     mov ah,48h
  499.     mov dx,H
  500.     int 67h
  501.     mov Fresult,ah
  502.   end;
  503.   EMS_Unprotect_Allocation := Fresult;
  504. end;
  505.  
  506. Function RAM_2_EMS(q : pointer; H : EMSHandle; Size : longint) : byte;
  507. VAR fresult : byte;
  508.     EMSseg    : word;
  509.     hp        : ^byte;
  510.     li        : word;
  511. begin;
  512.   EMS_Segment_determine(EMSseg);
  513.   hp := q;
  514.   if Size > 16384 then begin;
  515.     { More than one page required }
  516.     for li := 0 to (Size SHR 14)-1 do begin;
  517.       EMS_Allocation(H,0,li);
  518.       move(hp^,ptr(EMSseg,0)^,16384);
  519.       dec(Size,16384);
  520.       inc(hp,16384);
  521.     end;
  522.     EMS_Allocation(H,0,li+1);
  523.     move(hp^,ptr(EMSseg,0)^,16384);
  524.     dec(Size,16384);
  525.     inc(hp,16384);
  526.   end else begin;
  527.     EMS_Allocation(H,0,0);
  528.     move(hp^,ptr(EMSseg,0)^,16384);
  529.     dec(Size,16384);
  530.     inc(hp,16384);
  531.   end;
  532. end;
  533.  
  534. Function EMS_2_RAM(q : pointer; H : EMSHandle; Size : longint) : byte;
  535. VAR fresult : byte;
  536.     EMSseg    : word;
  537.     hp        : ^byte;
  538.     li        : word;
  539. begin;
  540.   EMS_Segment_determine(EMSseg);
  541.   hp := q;
  542.   if Size > 16384 then begin;
  543.     { More than one page required }
  544.     for li := 0 to (Size SHR 14)-1 do begin;
  545.       EMS_Allocation(H,0,li);
  546.       move(ptr(EMSseg,0)^,hp^,16384);
  547.       dec(Size,16384);
  548.       inc(hp,16384);
  549.     end;
  550.     EMS_Allocation(H,0,li+1);
  551.     move(ptr(EMSseg,0)^,hp^,16384);
  552.     dec(Size,16384);
  553.     inc(hp,16384);
  554.   end else begin;
  555.     EMS_Allocation(H,0,0);
  556.     move(ptr(EMSseg,0)^,hp^,16384);
  557.     dec(Size,16384);
  558.     inc(hp,16384);
  559.   end;
  560. end;
  561.  
  562. Function EMS_Pages_allocated(H : EMSHandle;var Pages : word) : byte;
  563. var fresult : byte;
  564.     Hs : word;
  565. begin;
  566.   asm
  567.     mov ah,4Ch
  568.     mov dx,H
  569.     int 67h
  570.     mov HS,bx
  571.     mov fresult,ah
  572.   end;
  573.   Pages := Hs;
  574.   EMS_Pages_allocated := Fresult;
  575. end;
  576.  
  577. Function EMS_Handles_assign(Var Number : word) : byte;
  578. Var Fresult : byte;
  579.     Han       : word;
  580. begin;
  581.   asm
  582.     mov ah,4Bh
  583.     int 67h
  584.     mov Han,bx
  585.     mov Fresult,ah
  586.   end;
  587.   Number := Han;
  588.   EMS_Handles_assign := Fresult;
  589. end;
  590.  
  591. function XMS_lock(H : XMSHandle) : longint; assembler;
  592. asm;
  593.   mov ax,0c00h
  594.   mov dx,h
  595.   call dword ptr [XMST]
  596.   mov ax,bx
  597. end;
  598.  
  599. procedure XMS_unlock(H : XMSHandle); assembler;
  600. asm;
  601.   mov ax,0d00h
  602.   mov dx,h
  603.   call dword ptr [XMST]
  604. end;
  605.  
  606.  
  607. begin;
  608.   Check_for_XMS;
  609.   Check_for_EMS;
  610. end.
  611.  
  612.  
  613.  
  614.  
  615.  
  616.  
  617.  
  618.  
  619.  
  620.  
  621.