home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / Pascal / Samples / MCUNIT10.ARJ / MCXMS10.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1993-02-03  |  18.7 KB  |  576 lines

  1. {*******************************************************************************
  2. *   Unit name: MCXMS10 interface
  3. *      Author: Martin CEKAL
  4. *        Note: This unit is based on unit XMSheap by Michael Gallias and
  5. *              TPXMS by Vernon E.Davis,Jr.
  6. *        Date: January 15, 1993
  7. *     Version: 1.0
  8. *     Purpose: Usage of XMS (extended) memory
  9. ********************************************************************************}
  10. Unit MCXMS10;
  11.  
  12. Interface
  13.  
  14. Uses DOS;
  15.  
  16. Const
  17.   MaxPointers       = 100;
  18.  
  19.   BlockFree         = 0;        {Free XMS Memory Block}
  20.   BlockUsed         = 1;        {Allocated in XMS, not in Conventional}
  21.   BlockRead         = 2;        {Allocated in XMS and Conventional (Read Mode)}
  22.   BlockReadWrite    = 3;        {Allocated in XMS and Conventional (R/W Mode)}
  23.   BlockWrite        = 4;        {Allocated in XMS and Conventional (Write Mode)}
  24.  
  25.   XMSReadMode       = 0;
  26.   XMSReadWriteMode  = 1;
  27.   XMSWriteMode      = 2;
  28.  
  29. Type
  30.   XMSModes          = XMSReadMode..XMSWriteMode;
  31.  
  32.  
  33.  
  34. {*******************************************************************************
  35. *        Name: InitXMS
  36. *  Parametres: init_XMS =0 initialization OK
  37. *        Date: January 14, 1993
  38. *     Version: 1.0
  39. *     Purpose: Initialization of XMS heap, all XMS is used for heap
  40. *   Important: Use only once
  41. ********************************************************************************}
  42. procedure InitXMS(var init_XMS:byte);
  43.  
  44. {*******************************************************************************
  45. *        Name: FreeXMSHeap
  46. *        Date: January 14, 1993
  47. *     Version: 1.0
  48. *     Purpose: Realease XMS heap from  XMS
  49. ********************************************************************************}
  50. Procedure FreeXMSHeap;
  51.  
  52. {*******************************************************************************
  53. *        Name: MaxXMSAvail
  54. *        Date: January 14, 1993
  55. *     Version: 1.0
  56. *     Purpose: Returns largest block in XMS heap
  57. ********************************************************************************}
  58. Function  MaxXMSAvail    :LongInt;
  59.  
  60. {*******************************************************************************
  61. *        Name: XMSAvail
  62. *        Date: January 14, 1993
  63. *     Version: 1.0
  64. *     Purpose: Returns total available XMS heap
  65. ********************************************************************************}
  66. Function  XMSAvail       :LongInt;
  67.  
  68. {*******************************************************************************
  69. *        Name: GetXMS
  70. *  Parametres: Handle block's unique number
  71. *              Size size of blocks in bytes
  72. *              OK = true request succesfull
  73. *        Date: January 14, 1993
  74. *     Version: 1.0
  75. *     Purpose: Requests handler to XMS heap
  76. ********************************************************************************}
  77. Procedure GetXMS(Var Handle:Word;Size:LongInt;var ok:boolean);
  78.  
  79. {*******************************************************************************
  80. *        Name: FreeXMS
  81. *  Parametres: Handle block's unique number
  82. *        Date: January 14, 1993
  83. *     Version: 1.0
  84. *     Purpose: Release block from XMS heap
  85. ********************************************************************************}
  86. Procedure FreeXMS(Handle:Word);
  87.  
  88. {*******************************************************************************
  89. *        Name: AwakePointer
  90. *  Parametres: Handle block's unique number
  91. *              p pointer to data copied from XMS
  92. *              mode mode of acces to block
  93. *        Date: January 14, 1993
  94. *     Version: 1.0
  95. *     Purpose: Gets a block in conventional memory
  96. *   Important: Never call on awake handle
  97. ********************************************************************************}
  98. Procedure AwakePointer(Handle:Word;Var P:Pointer;Mode:XMSModes);
  99.  
  100. {*******************************************************************************
  101. *        Name: SleepPointer
  102. *  Parametres: Handle block's unique number
  103. *        Date: January 14, 1993
  104. *     Version: 1.0
  105. *     Purpose: Reverse of AwakePointer
  106. *   Important: Never call on sleeping handle
  107. ********************************************************************************}
  108. Procedure SleepPointer(Handle:Word);
  109.  
  110. Var
  111.   XMSHeapSize :Word;
  112.   XMSResult   : Word;
  113.   XMSError    : Byte;
  114.   XMM_Control : Array[0..1] of Word;
  115.   init_XMS    : Byte;
  116.   isXMS       : Boolean;
  117.  
  118. {*******************************************************************************
  119. *   Unit name: MCXMS10 implementation
  120. *      Author: Martin CEKAL
  121. *        Note: This unit is based on unit XMSheap by Michael Gallias and
  122. *              TPXMS by Vernon E.Davis,Jr.
  123. *        Date: January 15, 1993
  124. *     Version: 1.0
  125. *     Purpose: Usage of XMS (extended) memory
  126. ********************************************************************************}
  127. Implementation
  128.  
  129. type
  130.    Bit32Struct = LongInt;
  131.  
  132.    ExtMemMoveStruct =
  133.    Record
  134.       Length       : Bit32Struct;
  135.       SourceHandle : Word;
  136.       SourceOffset : Bit32Struct;
  137.       DestHandle   : Word;
  138.       DestOffset   : Bit32Struct
  139.    End;
  140.  
  141.   OneXMSPointer     = Record
  142.                         XMSAddr  :LongInt;    {Offset into XMS Heap}
  143.                         ConvAddr :Pointer;    {Pointer to Conventional Memory}
  144.                         Size     :LongInt;    {Size in Bytes of Pointer}
  145.                         Status   :Byte;       {Block Status}
  146.                       End;
  147.  
  148.   AllXMSPointers    = Array [1..MaxPointers] Of OneXMSPointer;
  149.  
  150. Var
  151.   OldExitProc   :Pointer;
  152.   HeapHandle    :Word;
  153.   HeapPointer   :^AllXMSPointers;
  154.  
  155.  
  156. Procedure PokeAddrXMS(Var b32 : Bit32Struct; sb,ob : Word);
  157.    Procedure PTR_W_W(iptr : Pointer; incr,wval : Word);
  158.    Var
  159.       vptr    : ^Word;
  160.    Begin
  161.       vptr    := Ptr(Seg(iptr^),Ofs(iptr^)+incr);
  162.       vptr^   := wval
  163.    End;
  164. Begin
  165.    PTR_W_W(Addr(b32),0,ob);
  166.    PTR_W_W(Addr(b32),2,sb)
  167. End; {*** end PokeAddrXMS ***}
  168.  
  169. Function EXISTXMS : Boolean;
  170. Var
  171.    regs : Registers;
  172. Begin
  173.    regs.AX := $4300;
  174.    Intr($2F,regs);
  175.    If regs.al = $80 Then
  176.    Begin
  177.       regs.AX := $4310;
  178.       Intr($2F,regs);
  179.       XMM_Control[0] := regs.bx;
  180.       XMM_Control[1] := regs.es;
  181.       EXISTXMS := TRUE
  182.    End
  183.    Else
  184.       EXISTXMS := FALSE
  185. End; {*** end EXISTXMS ***}
  186.  
  187.  
  188.  
  189.  
  190. Procedure MoveExtMemBlockXMS(Var MoveStructure : ExtMemMoveStruct);
  191. (* NOTE: This procedure assumes that the ExtMemMove structure is valid *)
  192. Var
  193.    ax,
  194.    segs,
  195.    ofss : Word;
  196.    bl   : Byte;
  197. Begin
  198.    XMSResult := 1;
  199.    XMSError  := 0;
  200.    If NOT isXMS Then
  201.    Begin
  202.       XMSResult := 0;
  203.       XMSError  := $80;
  204.       Exit
  205.    End;
  206.    segs := Seg(MoveStructure);
  207.    ofss := Ofs(MoveStructure);
  208.    Inline
  209.    (  $1E/                                 {  PUSH DS                    }
  210.       $1E/                                 {  PUSH DS                    }
  211.       $07/                                 {  POP  ES                    }
  212.       $8B/$86/segs/                        {  MOV  AX,segs[BP]           }
  213.       $8E/$D8/                             {  MOV  DS,AX                 }
  214.       $8B/$B6/ofss/                        {  MOV  SI,ofss[BP]           }
  215.       $BF/XMM_Control/                     {  MOV  DI,XMM_Control        }
  216.       $B8/$00/$0B/                         {  MOV  AX,0B00               }
  217.       $55/                                 {  PUSH BP                    }
  218.       $26/                                 {  ES:                        }
  219.       $FF/$1D/                             {  CALL FAR[DI] (XMM_Control) }
  220.       $5D/                                 {  POP  BP                    }
  221.       $1F/                                 {  POP  DS                    }
  222.       $89/$86/ax/                          {  MOV  ax[BP],AX             }
  223.       $88/$9E/bl                           {  MOV  bl[BP],BL             }
  224.    );
  225.    XMSResult := ax;
  226.    XMSError  := bl
  227. End; {*** end MoveExtMemBlockXMS ***}
  228.  
  229. {*******************************************************************************
  230. *        Name: FreeXMSHeap
  231. *        Date: January 14, 1993
  232. *     Version: 1.0
  233. *     Purpose: Realease XMS heap from  XMS
  234. ********************************************************************************}
  235. Procedure FreeXMSHeap;
  236.  
  237.   Procedure FreeExtMemBlockXMS(handle : Word);
  238.   Var
  239.      ax : Word;
  240.      bl : Byte;
  241.   Begin
  242.      XMSResult := 1;
  243.      XMSError  := 0;
  244.      If NOT isXMS Then
  245.      Begin
  246.         XMSResult := 0;
  247.         XMSError  := $80;
  248.         Exit
  249.      End;
  250.      Inline
  251.      (  $BF/XMM_Control/                     {  MOV  DI,XMM_Control        }
  252.         $8B/$96/handle/                      {  MOV  DX,handle[BP]         }
  253.         $B8/$00/$0A/                         {  MOV  AX,0A00               }
  254.         $55/                                 {  PUSH BP                    }
  255.         $FF/$1D/                             {  CALL FAR[DI] (XMM_Control) }
  256.         $5D/                                 {  POP  BP                    }
  257.         $89/$86/ax/                          {  MOV  ax[BP],AX             }
  258.         $88/$9E/bl                           {  MOV  bl[BP],BL             }
  259.      );
  260.      XMSResult := ax;
  261.      XMSError  := bl
  262.   End;  {*** end FreeExtMemBlockXMS ***}
  263.  
  264. Begin
  265.   FreeExtMemBlockXMS(HeapHandle);
  266.   ExitProc:=OldExitProc;
  267.   FillChar(HeapPointer^,SizeOf(HeapPointer^),0);
  268. End; {*** end FreeXMSHeap ***}
  269.  
  270. {*******************************************************************************
  271. *        Name: MaxXMSAvail
  272. *        Date: January 14, 1993
  273. *     Version: 1.0
  274. *     Purpose: Returns largest block in XMS heap
  275. ********************************************************************************}
  276. Function MaxXMSAvail:LongInt;
  277. Var
  278.   Size   :LongInt;
  279.   X      :Word;
  280. Begin
  281.   X:=2;
  282.   Size:=HeapPointer^[1].Size;
  283.   While (HeapPointer^[X].Size>0) And (X<=MaxPointers) do
  284.   Begin
  285.     If HeapPointer^[X].Status=BlockFree Then
  286.       If HeapPointer^[X].Size>Size Then
  287.         Size:=HeapPointer^[X].Size;
  288.     Inc(X);
  289.   End;
  290.   MaxXMSAvail:=Size;
  291. End; {*** end MaxXMSAvail ***}
  292.  
  293. {*******************************************************************************
  294. *        Name: XMSAvail
  295. *        Date: January 14, 1993
  296. *     Version: 1.0
  297. *     Purpose: Returns total available XMS heap
  298. ********************************************************************************}
  299. Function XMSAvail:LongInt;
  300. Var
  301.   Size   :LongInt;
  302.   X      :Word;
  303. Begin
  304.   X:=2;
  305.   Size:=HeapPointer^[1].Size;
  306.   While (HeapPointer^[X].Size>0) And (X<=MaxPointers) do
  307.   Begin
  308.     If HeapPointer^[X].Status=BlockFree Then
  309.       Size:=Size+HeapPointer^[X].Size;
  310.     Inc(X);
  311.   End;
  312.   XMSAvail:=Size;
  313. End; {*** end XMSAvail ***}
  314.  
  315. Function IndexForData(Amount:LongInt):Word;
  316. Var
  317.   X     :Word;
  318.   Found :Boolean;
  319. Begin
  320.   X:=1;
  321.   Found:=False;
  322.   While (Not Found) And (X<=MaxPointers) do
  323.   Begin
  324.     If (HeapPointer^[X].Status=BlockFree) And (HeapPointer^[X].Size>=Amount) Then
  325.       Found:=True
  326.     Else
  327.       Inc(X);
  328.   End;
  329.   If Not Found Then
  330.     IndexForData:=0
  331.   Else
  332.     IndexForData:=X;
  333. End; {*** end IndexForData ***}
  334.  
  335. Function FindBlankIndex:Word;
  336. Var
  337.   X     :Word;
  338.   Found :Boolean;
  339. Begin
  340.   X:=1;
  341.   Found:=False;
  342.   While (Not Found) And (X<MaxPointers) do
  343.   Begin
  344.     If HeapPointer^[X].Size=0 Then
  345.       Found:=True
  346.     Else
  347.       Inc(X);
  348.   End;
  349.   If Not Found Then
  350.     FindBlankIndex:=0
  351.   Else
  352.     FindBlankIndex:=X;
  353. End; {*** end FindBlankIndex ***}
  354.  
  355. {*******************************************************************************
  356. *        Name: GetXMS
  357. *  Parametres: Handle block's unique number
  358. *              Size size of blocks in bytes
  359. *              OK = true request succesfull
  360. *        Date: January 14, 1993
  361. *     Version: 1.0
  362. *     Purpose: Requests handler to XMS heap
  363. ********************************************************************************}
  364. Procedure GetXMS(Var Handle:Word;Size:LongInt;var ok:boolean);
  365. Var
  366.   FreeIndex  :Word;
  367. Begin
  368.   ok:=false;
  369.   If Odd(Size) Then Inc(Size);
  370.   Handle:=IndexForData(Size);
  371.   If Handle = 0 Then exit;
  372.   If HeapPointer^[Handle].Size>Size Then
  373.   Begin
  374.     FreeIndex:=FindBlankIndex;
  375.     If FreeIndex=0 Then exit;
  376.  
  377.     HeapPointer^[FreeIndex].Size     :=HeapPointer^[Handle].Size - Size;
  378.     HeapPointer^[FreeIndex].Status   :=BlockFree;
  379.     HeapPointer^[FreeIndex].XMSAddr  :=HeapPointer^[Handle].XMSAddr + Size;
  380.  
  381.     HeapPointer^[Handle].Size        :=Size;
  382.   End;
  383.   ok:=true;
  384.   HeapPointer^[Handle].Status        :=BlockUsed;
  385. End; {*** end GetXMS ***}
  386.  
  387. {*******************************************************************************
  388. *        Name: FreeXMS
  389. *  Parametres: Handle block's unique number
  390. *        Date: January 14, 1993
  391. *     Version: 1.0
  392. *     Purpose: Release block from XMS heap
  393. ********************************************************************************}
  394. Procedure FreeXMS(Handle:Word);
  395. Var
  396.   X     :Word;
  397. Begin
  398.   HeapPointer^[Handle].Status:=BlockFree;
  399.   X:=Handle+1;
  400.   While (X<MaxPointers) And (HeapPointer^[X].Status=BlockFree) do
  401.   Begin
  402.     If HeapPointer^[X].Size>0 Then
  403.     Begin
  404.       Inc(HeapPointer^[Handle].Size,HeapPointer^[X].Size);
  405.       HeapPointer^[X].Size:=0;
  406.     End;
  407.     Inc(X);
  408.   End;
  409. End; {end FreeXMS ***}
  410.  
  411. {*******************************************************************************
  412. *        Name: AwakePointer
  413. *  Parametres: Handle block's unique number
  414. *              p pointer to data copied from XMS
  415. *              mode mode of acces to block
  416. *        Date: January 14, 1993
  417. *     Version: 1.0
  418. *     Purpose: Gets a block in conventional memory
  419. *   Important: Never call on awake handle
  420. ********************************************************************************}
  421. Procedure AwakePointer(Handle:Word;Var P:Pointer;Mode:XMSModes);
  422. Var
  423.   AlreadyIn:Boolean;
  424.   XMSInfo  :ExtMemMoveStruct;
  425. Begin
  426.    If HeapPointer^[Handle].Status in [BlockRead,BlockReadWrite,BlockWrite] Then
  427.     AlreadyIn:=True
  428.   Else
  429.     AlreadyIn:=False;
  430.   Case Mode Of
  431.     XMSReadMode      :HeapPointer^[Handle].Status:=BlockRead;
  432.     XMSReadWriteMode :HeapPointer^[Handle].Status:=BlockReadWrite;
  433.     XMSWriteMode     :HeapPointer^[Handle].Status:=BlockWrite;
  434.   End;
  435.   If AlreadyIn Then
  436.     P:=HeapPointer^[Handle].ConvAddr
  437.   Else
  438.   Begin
  439.     GetMem(P,HeapPointer^[Handle].Size);
  440.     HeapPointer^[Handle].ConvAddr:=P;
  441.     If Mode in [XMSReadMode,XMSReadWriteMode] Then
  442.     Begin
  443.       XMSInfo.Length       :=HeapPointer^[Handle].Size;
  444.       XMSInfo.SourceHandle :=HeapHandle;
  445.       XMSInfo.SourceOffset :=HeapPointer^[Handle].XMSAddr;
  446.       XMSInfo.DestHandle   :=0;
  447.       PokeAddrXMS(XMSInfo.DestOffset,Seg(P^),Ofs(P^));
  448.       MoveExtMemBlockXMS(XMSInfo);
  449.     End;
  450.   End;
  451. End; {*** end AwakePointer ***}
  452.  
  453. {*******************************************************************************
  454. *        Name: SleepPointer
  455. *  Parametres: Handle block's unique number
  456. *        Date: January 14, 1993
  457. *     Version: 1.0
  458. *     Purpose: Reverse of AwakePointer
  459. *   Important: Never call on sleeping handle
  460. ********************************************************************************}
  461. Procedure SleepPointer(Handle:Word);
  462. Var
  463.   XMSInfo  :ExtMemMoveStruct;
  464. Begin
  465.   If Not(HeapPointer^[Handle].Status=BlockRead) Then
  466.   Begin
  467.     XMSInfo.Length       :=HeapPointer^[Handle].Size;
  468.     XMSInfo.SourceHandle :=0;
  469.     PokeAddrXMS(XMSInfo.SourceOffset,Seg(HeapPointer^[Handle].ConvAddr^),
  470.                                      Ofs(HeapPointer^[Handle].ConvAddr^) );
  471.     XMSInfo.DestHandle   :=HeapHandle;
  472.     XMSInfo.DestOffset   :=HeapPointer^[Handle].XMSAddr;
  473.     MoveExtMemBlockXMS(XMSInfo);
  474.   End;
  475.   FreeMem(HeapPointer^[Handle].ConvAddr,HeapPointer^[Handle].Size);
  476.   HeapPointer^[Handle].Status:=BlockUsed;
  477. End; {*** end SleepPointer ***}
  478.  
  479. {*******************************************************************************
  480. *        Name: InitXMS
  481. *  Parametres: init_XMS =0 initialization OK
  482. *        Date: January 14, 1993
  483. *     Version: 1.0
  484. *     Purpose: Initialization of XMS heap, all XMS is used for heap
  485. *   Important: Use only once
  486. ********************************************************************************}
  487. procedure InitXMS(var init_XMS:byte);
  488.  
  489.   Procedure QueryFreeBlockXMS;
  490.   (* XMSResult = largest free block of Extended Memory in kilobytes *)
  491.   Var
  492.      dx : Word;
  493.   Begin
  494.      XMSResult := 1;
  495.      XMSError  := 0;
  496.      If NOT isXMS Then
  497.      Begin
  498.         XMSResult := 0;
  499.         XMSError  := $80;
  500.         Exit
  501.      End;
  502.      Inline
  503.      (  $BF/XMM_Control/                     {  MOV  DI,XMM_Control        }
  504.         $B8/$00/$08/                         {  MOV  AX,0800               }
  505.         $55/                                 {  PUSH BP                    }
  506.         $FF/$1D/                             {  CALL FAR[DI] (XMM_Control) }
  507.         $5D/                                 {  POP  BP                    }
  508.         $89/$96/dx                           {  MOV  dx[BP],DX             }
  509.      );
  510.      XMSResult := dx
  511.   End;
  512.  
  513.   Function AllocExtMemBlockXMS(malloc : Word) : Word;
  514.   (* If successful, returns handle to Extended Memory Block *)
  515.   Var
  516.      ax : Word;
  517.      dx : Word;
  518.      bl : Byte;
  519.   Begin
  520.      XMSResult := 1;
  521.      XMSError  := 0;
  522.      If NOT isXMS Then
  523.      Begin
  524.         XMSResult := 0;
  525.         XMSError  := $80;
  526.         AllocExtMemBlockXMS := 0;
  527.         Exit
  528.      End;
  529.      Inline
  530.      (  $BF/XMM_Control/                     {  MOV  DI,XMM_Control        }
  531.         $8B/$96/malloc/                      {  MOV  DX,malloc[BP]         }
  532.         $B8/$00/$09/                         {  MOV  AX,0900               }
  533.         $55/                                 {  PUSH BP                    }
  534.         $FF/$1D/                             {  CALL FAR[DI] (XMM_Control) }
  535.         $5D/                                 {  POP  BP                    }
  536.         $89/$86/ax/                          {  MOV  ax[BP],AX             }
  537.         $88/$9E/bl/                          {  MOV  bl[BP],BL             }
  538.         $89/$96/dx                           {  MOV  dx[BP],DX             }
  539.      );
  540.      XMSResult := ax;
  541.      XMSError  := bl;
  542.      AllocExtMemBlockXMS := dx
  543.   End;
  544.  
  545.   Procedure GetXMSHeap(Amount:Word);         {Call ONCE Only}
  546.   Begin
  547.     HeapHandle:=AllocExtMemBlockXMS(Amount);
  548.     If XMSResult=1 Then
  549.     Begin
  550.       OldExitProc:=ExitProc;
  551.       ExitProc:=@FreeXMSHeap;
  552.       HeapPointer^[1].Size:=LongInt(Amount)*1024;
  553.       HeapPointer^[1].XMSAddr:=0;
  554.       XMSHeapSize:=Amount;
  555.     End
  556.     Else
  557.       HeapHandle:=0;
  558.   End;
  559.  
  560.  
  561. begin
  562.   queryfreeblockxms;
  563.   getxmsheap(xmsresult);
  564.   if xmsresult=1 then init_xms:=0 else init_xms:=1;
  565. end; {*** end InitXMS ***}
  566.  
  567. Begin
  568.   XMM_Control[0] := 0;
  569.   XMM_Control[1] := 0;
  570.   XMSResult      := 1;
  571.   XMSError       := 0;
  572.   isXMS          := EXISTXMS;
  573.   System.New(HeapPointer);
  574.   FillChar(HeapPointer^,SizeOf(HeapPointer^),0);
  575. End. {*** unit MCXMS10 ***}
  576.