home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / msdos / pascal / rehack / memory / xms.cpp < prev   
Encoding:
C/C++ Source or Header  |  1993-06-29  |  7.7 KB  |  450 lines

  1. #include "..\MEMORY\MEMORY.HPP"
  2. #include <dos.h>
  3.  
  4. // ------------------------------------------------------------------
  5. // File:        XMS.CPP
  6. // Path:        ...\REHACK\MEMORY\XMS.CPP
  7. // Version:        0.01
  8. // Author:        Pat Reilly
  9. // CIS Id:        71333,2764
  10. // Created On:    6/28/93
  11. // Modified On:
  12. // Description:    XmsMemory class for REHACK. See MEMORY.TXT for
  13. //                more details.
  14. // Tabs:        4
  15. // ------------------------------------------------------------------
  16.  
  17. struct XmsMove
  18. {
  19.     long  size;
  20.     word  srcHandle;
  21.     dword srcAddr;
  22.     word  destHandle;
  23.     dword destAddr;
  24. };
  25.  
  26. // class UMBMemory is used internally by XmsMemory.
  27. //     It represents a Upper Memory Block (UMB) MemoryObject
  28. //     class, but is only used to 'lock' a XmsMemory block from
  29. //  XMS. Since 286 machines won't have UMBs available, its
  30. //    safest to only use these internally. If you want, I suppose
  31. //    you can move the class definition to a header file (ie
  32. //    MEMORY.H) and use this as another MemoryObject derived class.
  33. //    Note that lock() and unlock() do nothing - the UMB is
  34. //    allocated in one place for its life (from allocate() to free()).
  35.  
  36. class UmbMemory : public MemoryObject
  37. {
  38. public:
  39.  
  40.     UmbMemory();
  41.     UmbMemory(word);
  42.  
  43.     virtual MemType type();
  44.     virtual bool allocate(word);
  45.     virtual void free();
  46.     virtual void FAR* lock();
  47.     virtual void unlock();
  48.     virtual long memAvail();
  49.     virtual long maxAvail();
  50.  
  51. protected:
  52.     word theSeg;
  53. };
  54.  
  55. UmbMemory::UmbMemory()
  56. {
  57.     theSeg = 0U;
  58. }
  59.  
  60. UmbMemory::UmbMemory(word sz)
  61. {
  62.     theSeg = 0U;
  63.     allocate(sz);
  64. }
  65.  
  66. MemType UmbMemory::type()
  67. {
  68.     return MemUnknown;
  69. }
  70.  
  71. long UmbMemory::memAvail()
  72. {
  73.     return 0L;
  74. }
  75.  
  76. long UmbMemory::maxAvail()
  77. {
  78.     return 0L;
  79. }
  80.  
  81. bool UmbMemory::allocate(word sz)
  82. {
  83.     if(theSeg != 0 || sz == 0)
  84.         return false;
  85.  
  86.     theSeg = XmsMemory::allocUmb(sz);
  87.     if( theSeg != 0 )
  88.         memsize = sz;
  89.     return bool(theSeg != 0);
  90. }
  91.  
  92. void UmbMemory::free()
  93. {
  94.     if(theSeg != 0 && lockflag == 0)
  95.         {
  96.         XmsMemory::freeUmb(theSeg);
  97.         theSeg = 0;
  98.         memsize = 0;
  99.         }
  100. }
  101.  
  102. void FAR* UmbMemory::lock()
  103. {
  104.     if( theSeg == 0 )
  105.         return 0;
  106.     lockflag++;
  107.     void FAR* ptr = MK_FP(theSeg, 0);
  108.     return ptr;
  109.     }
  110.  
  111. void UmbMemory::unlock()
  112. {
  113.     if( lockflag )
  114.         lockflag--;
  115. }
  116.  
  117.  
  118. bool XmsMemory::isInitialized = false;
  119. XmsMemory* XmsMemory::head = 0;
  120. long XmsMemory::lastAddr = 0L;
  121. word XmsMemory::handle = 0U;
  122. dword XmsMemory::fnAddr = 0UL;
  123. static XmsMove xmsMove;
  124.  
  125. // Function called at program exit to remove all XMS allocated.
  126. void ClearXms()
  127. {
  128.     word handle = XmsMemory::handle;
  129.     dword fn = XmsMemory::fnAddr;
  130.     if( handle != 0 )
  131.         asm    {
  132.             mov        dx, handle
  133.             mov        ah, 0x0A
  134.             call    dword ptr [fn]
  135.             }
  136. }
  137.  
  138. #pragma exit ClearXms
  139.  
  140. XmsMemory::XmsMemory()
  141. {
  142.     init();
  143. }
  144.  
  145. XmsMemory::XmsMemory(word sz)
  146. {
  147.     init();
  148.     allocate(sz);
  149. }
  150.  
  151. bool XmsMemory::allocate(word sz)
  152. {
  153.     if( handle == 0 || memsize != 0 || sz == 0 || sz > XmsMaxBlkSize )
  154.         return false;
  155.  
  156.     long aAddr = 0;
  157.     XmsMemory* parent = head;
  158.     if( head == 0 )
  159.         {
  160.         if( sz > lastAddr )
  161.             return false;
  162.         }
  163.  
  164.     else
  165.         {
  166.         while( parent->next != 0 )
  167.             {
  168.             aAddr = parent->addr + parent->memsize;
  169.             if( fitsInto( aAddr, parent->next->addr, sz) )
  170.                 break;
  171.             parent = parent->next;
  172.             }
  173.         if( parent->next == 0 )
  174.             {
  175.             aAddr = parent->addr+parent->memsize;
  176.             if( !fitsInto( aAddr, lastAddr, sz) )
  177.                 return false;
  178.             }
  179.         }
  180.  
  181.     if( parent == 0 )
  182.         {
  183.         next = 0;
  184.         head = this;
  185.         }
  186.     else
  187.         {
  188.         next = parent->next;
  189.         parent->next = this;
  190.         }
  191.     addr = aAddr;
  192.     memsize = sz;
  193.     return true;
  194. }
  195.  
  196. void XmsMemory::free()
  197. {
  198.     XmsMemory *ptr;
  199.  
  200.     if( memsize == 0 || lockflag != 0 )
  201.         return;
  202.  
  203.     if( head == this )
  204.         head = head->next;
  205.     else
  206.         for( ptr = head; ptr->next; ptr = ptr->next )
  207.             if( ptr->next == this )
  208.                 {
  209.                 ptr->next = ptr->next->next;
  210.                 break;
  211.                 }
  212.     addr = 0;
  213.     next = 0;
  214.     memsize = 0;
  215. }
  216.  
  217. void FAR* XmsMemory::lock()
  218. {
  219.     if( memsize == 0 )
  220.         return 0;
  221.  
  222.     if( !lockflag )
  223.         {
  224.         // Try and use a UMB block first.
  225.         frame = new UmbMemory(memsize);
  226.         if( !frame || frame->memSize() != memsize )
  227.             {
  228.             delete frame;
  229.             // Next, try using conventional memory.
  230.             frame = new ConvMemory(memsize);
  231.             if( !frame || frame->memSize() != memsize )
  232.                 {
  233.                 delete frame;
  234.                 // Finally, try using EMS memory.
  235.                 frame = new EmsMemory(memsize);
  236.                 if( !frame || frame->memSize() != memsize )
  237.                     {
  238.                     delete frame;
  239.                     frame = 0;
  240.                     return 0;
  241.                     }
  242.                 }
  243.             }
  244.         // Now lock the frame (can only fail with an EMS block).
  245.         frameBuf = frame->lock();
  246.         if( frameBuf == 0 )
  247.             {
  248.             frame->unlock();
  249.             frame->free();
  250.             delete frame;
  251.             frame = 0;
  252.             return 0;
  253.             }
  254.  
  255.         xmsMove.size = memsize;
  256.         xmsMove.srcHandle = handle;
  257.         xmsMove.srcAddr = addr;
  258.         xmsMove.destHandle = 0;
  259.         xmsMove.destAddr = ((dword)(FP_SEG(frameBuf)) << 16) |
  260.             ((dword)(FP_OFF(frameBuf)));
  261.         word o = FP_OFF( &xmsMove );
  262.         word s = FP_SEG( &xmsMove );
  263.         dword fn = fnAddr;
  264.         asm    {
  265.             push    ds
  266.             mov        si, o
  267.             mov        ax, s
  268.             mov        ds, ax
  269.             mov        ah, 0x0B
  270.             call    dword ptr [fn]
  271.             pop        ds
  272.             }
  273.         }
  274.     lockflag++;
  275.     return frameBuf;
  276. }
  277.  
  278. void XmsMemory::unlock()
  279. {
  280.     if( !lockflag )
  281.         return;
  282.  
  283.     lockflag--;
  284.     if( lockflag == 0 )
  285.         {
  286.         xmsMove.size = memsize;
  287.         xmsMove.srcHandle = 0;
  288.         xmsMove.srcAddr = ((dword)(FP_SEG(frameBuf)) << 16) |
  289.             ((dword)(FP_OFF(frameBuf)));
  290.         xmsMove.destHandle = handle;
  291.         xmsMove.destAddr = addr;
  292.         word o = FP_OFF( &xmsMove );
  293.         word s = FP_SEG( &xmsMove );
  294.         dword fn = fnAddr;
  295.         asm    {
  296.             push    ds
  297.             mov        si, o
  298.             mov        ax, s
  299.             mov        ds, ax
  300.             mov        ah, 0x0B
  301.             call    dword ptr [fn]
  302.             pop        ds
  303.             }
  304.         frame->unlock();
  305.         frame->free();
  306.         delete frame;
  307.         frame = 0;
  308.         }
  309. }
  310.  
  311. long XmsMemory::memAvail()
  312. {
  313.     if( handle == 0 )
  314.         return 0L;
  315.  
  316.     long l = lastAddr;
  317.     XmsMemory* ptr;
  318.  
  319.     for( ptr = head; ptr != 0; ptr = ptr->next )
  320.         l -= ptr->memsize;
  321.     return l;
  322. }
  323.  
  324. long XmsMemory::maxAvail()
  325. {
  326.     if( handle == 0 )
  327.         return 0L;
  328.  
  329.     long tmp, l = 0L;
  330.     XmsMemory* ptr;
  331.  
  332.     if( head == 0 )
  333.         l = lastAddr;
  334.     else
  335.         {
  336.         for( ptr = head; ptr->next != 0; ptr = ptr->next )
  337.             {
  338.             tmp = ptr->next->addr - ptr->addr - ptr->memsize;
  339.             if( tmp > l )
  340.                 l = tmp;
  341.             }
  342.         tmp = lastAddr - ptr->addr - ptr->memsize;
  343.         if( tmp > l )
  344.             l = tmp;
  345.         }
  346.     return l;
  347. }
  348.  
  349. void XmsMemory::init()
  350. {
  351.     word o, s;
  352.  
  353.     if( !isInitialized )
  354.         {
  355.         isInitialized = true;
  356.  
  357.         if(getvect(0x2F) != 0)
  358.             {
  359.             _AX = 0x4300;        // Ensure XMS installed.
  360.             asm int 0x2F;
  361.             if( !(_AL & 0x80) )
  362.                 return;
  363.  
  364.             _AX = 0x4310;        // Get the function address
  365.             asm int 0x2F;
  366.             o = _BX;
  367.             s = _ES;
  368.             fnAddr = ((dword)(s) << 16) | (dword)o;
  369.             dword fn = fnAddr;
  370.  
  371.             asm    {
  372.                 mov        ah, 0
  373.                 call    dword ptr [fn]
  374.                 }
  375.             if( _AH < 2 )
  376.                 return;
  377.  
  378.             asm    {
  379.                 mov        ah, 8
  380.                 call    dword ptr [fn]
  381.                 }
  382.             o = _AX;
  383.             if( o < 64 )    // Must be 64K to be worthwhile
  384.                 {
  385.                 asm    {
  386.                     mov        ah, 2
  387.                     call    dword ptr [fn]
  388.                     }
  389.                 return;
  390.                 }
  391.  
  392.             asm    {
  393.                 mov        dx, o
  394.                 mov        ah, 9
  395.                 call    dword ptr [fn]
  396.                 }
  397.             s = _DX;
  398.             if( !_AX )
  399.                 {
  400.                 asm    {
  401.                     mov        ah, 2
  402.                     call    dword ptr [fn]
  403.                     }
  404.                 return;
  405.                 }
  406.             handle = s;
  407.             lastAddr = (long)o * 1024L;
  408.             }
  409.         }
  410. }
  411.  
  412. bool XmsMemory::fitsInto(long addr, long next, word sz)
  413. {
  414.     if( next <= addr || next-addr < sz )
  415.         return false;
  416.     else
  417.         return true;
  418. }
  419.  
  420. word XmsMemory::allocUmb(word sz)
  421. {
  422.     if(handle == 0)
  423.         return 0U;
  424.  
  425.     word s = (sz >> 4) + ((sz & 0x0F) != 0);
  426.     dword fn = fnAddr;
  427.     asm    {
  428.         mov        dx, s
  429.         mov        ah, 0x10
  430.         call    dword ptr [fn]
  431.         }
  432.     if( !_AX )
  433.         return 0;
  434.     s = _BX;
  435.     return s;
  436. }
  437.  
  438. void XmsMemory::freeUmb(word s )
  439. {
  440.     if( handle == 0 || s == 0 )
  441.         return;
  442.  
  443.     dword fn = fnAddr;
  444.     asm    {
  445.         mov        dx, s
  446.         mov        ah, 0x11
  447.         call    dword ptr [fn]
  448.         }
  449. }
  450.