{ Sean Palmer > I did not mean to imply that I expected a library that could provide > access to XMS With simple Pointer dereferences. I understand the > difficulty of accessing >1MB from a Real-mode Program. I would be > happy(ECSTATIC in fact) if I could find a library that would allow an > allocation to XMS, returning a handle to the block, and allow > access(copying) of the block via a Procedure call. Of course, the > catch is that the library would have to be able to deal With random > allocations and deallocations-like a heap manager For XMS. I know that > there are VMM's out there that can do this-I just can't get my hands > on one! Try this: turbo pascal 6.0 source } Unit xms; {this Unit won't handle blocks bigger than 64k} Interface Function installed : Boolean; Function init(Var h : Word; z : Word) : Boolean; {alloc xms} Procedure avail(Var total, largest : Word); {how much free?} Function save(h, z : Word; Var s) : Boolean; {move main to xms} Function load(h, z : Word; Var s) : Boolean; {move xms to main} Procedure free(h : Word); {dispose xms} Function lock(h : Word) : LongInt; Function unlock(h : Word) : Boolean; Function getInfo(h : Word; Var lockCount, handlesLeft : Byte; Var sizeK : Word) : Boolean; Function resize(h, sizeK : Word) : Boolean; Implementation {Error codes, returned in BL reg} Const FuncNotImplemented = $80; {Function is not implemented} VDiskDeviceDetected = $81; {a VDISK compatible device found} A20Error = $82; {an A20 error occurred} GeneralDriverError = $8E; {general driver error} UnrecoverableError = $8F; {unrecoverable driver error} HmaDoesNotExist = $90; {high memory area does not exist} HmaAlreadyInUse = $91; {high memory area already in use} HmaSizeTooSmall = $92; {size requested less than /HMAMIN} HmaNotAllocated = $93; {high memory area not allocated} A20StillEnabled = $94; {A20 line is still enabled} AllExtMemAllocated = $A0; {all extended memory is allocated} OutOfExtMemHandles = $A1; {extended memory handles exhausted} InvalidHandle = $A2; {invalid handle} InvalidSourceHandle = $A3; {invalid source handle} InvalidSourceOffset = $A4; {invalid source offset} InvalidDestHandle = $A5; {invalid destination handle} InvalidDestOffset = $A6; {invalid destination offset} InvalidLength = $A7; {invalid length} OverlapInMoveReq = $A8; {overlap in move request} ParityErrorDetected = $A9; {parity error detected} BlockIsNotLocked = $AA; {block is not locked} BlockIsLocked = $AB; {block is locked} LockCountOverflowed = $AC; {lock count overflowed} LockFailed = $AD; {lock failed} SmallerUMBAvailable = $B0; {a smaller upper memory block is avail} NoUMBAvailable = $B1; {no upper memory blocks are available} InvalidUMBSegment = $B2; {invalid upper memory block segment} xmsProc : Pointer = nil; {entry point For xms driver, nil if none} Var copyRec : Record size : LongInt; {Bytes to move (must be even)} srcH : Word; {handle (0=conventional mem)} srcP : Pointer; dstH : Word; dstP : Pointer; end; Function installed : Boolean; begin installed := (xmsProc <> nil); end; Function init(Var h : Word; z : Word) : Boolean; Assembler; Asm mov dx, z test dx, $3FF jz @S add dx, $400 @S: {allow For partial K's} mov cl, 10 shr dx, cl {convert to K} mov ah, 9 call xmsProc {allocate XMS block} cmp ax, 1 je @S2 xor al, al @S2: les di, h mov es:[di], dx end; Procedure avail(Var total, largest : Word); Assembler; Asm mov ah, 8 call xmsProc {query free xms} les di, total mov es:[di], dx les di, largest mov es:[di], ax end; Function copy : Boolean; Assembler; Asm {internal} push ds mov si, offset copyRec {it's in DS, right?} mov ah, $B call xmsProc {copy memory} cmp ax,1 je @S xor al,al @S: pop ds end; Function save(h, z : Word; Var s) : Boolean; begin if odd(z) then inc(z); With copyRec do begin size := z; srcH := 0; srcP := @s; {source, from main memory} dstH := h; dstP := ptr(0,0); {dest, to xms block} end; save := copy; end; Function load(h, z : Word; Var s) : Boolean; begin if odd(z) then inc(z); With copyRec do begin size := z; srcH := h; srcP := ptr(0,0); {source, from xms block} dstH := 0; dstP := @s; {dest, to main memory} end; load := copy; end; Procedure free(h : Word); Assembler; Asm mov dx, h mov ah, $A call xmsProc end; Function lock(h : Word) : LongInt; Assembler; Asm mov ah, $C mov dx, h call xmsProc {lock xms block} cmp ax, 1 je @OK xor bx, bx xor dx, dx @OK: {set block to nil (0) if err} mov ax, bx end; Function unlock(h : Word) : Boolean; Assembler; Asm mov ah, $D mov dx, h call xmsProc {unlock xms block} cmp ax, 1 je @S xor al, al @S: end; Function getInfo(h : Word; Var lockCount, handlesLeft : Byte; Var sizeK : Word) : Boolean; Assembler; Asm mov ah, $E mov dx, h call xmsProc {get xms handle info} cmp ax, 1 je @S xor al, al @S: les di, lockCount mov es:[di], bh les di, handlesLeft mov es:[di], bl les di, sizeK mov es:[di], dx end; Function resize(h, sizeK : Word) : Boolean; Assembler; Asm mov ah, $F mov dx, h mov bx, sizeK call xmsProc {resize XMS block} cmp ax ,1 je @S xor al, al @S: end; begin Asm {there is a possibility these ints will trash the ds register} mov ax, $4300 {load check Function For xms driver} int $2F {call multiplex int} cmp al, $80 jne @X mov ax, $4310 int $2F {get adr of entry point->es:bx} mov Word ptr xmsProc, bx mov Word ptr xmsProc+2, es @X: end; end.