                        XMS Memory Routines in C
                    (c) Copyright Jeff Leigh - 1997
                                
                              By Jeff Leigh

Here is my XMS memory access routines.  Anyone familiar with XMS should get
them to work without any problems (Hmm, that is what they told me when I 
started my EMS routines that never worked. Hmm...) 

I distribute these routines as freeware - you may use them in any project 
personal or commercial as long as you give me some sort of credit, like 
"XMS routines programmed by Jeff Leigh."  Or you could just call your game or 
program "Jeff Leigh's Program" (is that going to far?)  Of course, if you feel 
inclined to give me a few bucks, perhaps enough to buy lunch or something, it 
would be really appreciated (especially if you use these routines in a 
commercial product.)

DISCLAIMER: Jeff Leigh is not in any way responsible for any damage to you, 
your house, any of your property, your dog, your friends, your relatives, 
your hair, the guy next door, the mailman, your car, your mental status, or 
even your computer.  As a matter of fact, if difficulties are incurred do to 
the use of these routines, Jeff Leigh doesn't even know that these routines 
exist. 

Specifications:

The routines where written in Microsoft QuickC v2.5, using the MEDIUM memory 
model, and I don't know if they work in other memory modes.  

The important files are

XMSSTUFF.C   - the library of routines.
XMSSTUFF.OBJ - the OBJ file in case you want to link to it.
XMS.C        - a cute little test/demo program    

As way of documentation, I have included the following information.

THE XMS_* functions

int XMS_detect( void )

This routine detects if XMS is present, returning 1 if it is and 0 if not.
YOU MUST RUN THIS PROCEDURE BEFORE ANY OTHERS!!!

void XMS_ini( void )

This performs vital operations, and should be called after you call
XMS_ini and before you call any other routines.

unsigned int XMS_largestavail( void )

This returns the largest block of consecutive memory.

unsigned int XMS_memavail( void )

This returns the amount of free XMS memory.

unsigned int XMS_allocate_block( unsigned int amount )

This allocates a block of memory the size of (AMOUNT)kb.  Notice that this
is in Kilobytes.  That means sending 64 as your amount would allocate 64,000
bytes.  The function returns a simple integer handle.  You should keep track
of this number, because it is in effect the variable name of that region
of memory.

int XMS_free_block( unsigned int handle )

This routine frees a block of memory previously allocated with 
XMS_allocate_block.  It returns a simple success code (0 or 1).

char XMS_handles_free( unsigned int handle )

Returns the amount of handles free to the system (defined in config.sys as
HANDLES = xx) you need at least one to do anything.  The less of these that
you use, the better.

int XMS_move_block( struct ExtMemMoveStruct _far *structin )

This is the hard way to move memory around.  You will have to decipher the 
structure included in the header file.  Use this if you want, or use my 
personal extensions ( discussed later, see XMSE_* functions)

ALL LENGTHS MUST BE EVEN!! (no odd numbers like 20123, round up to 20124)
It is faster if you can word-align the length.
Even faster if you can Dword-align the length.

char _far *XMS_lock_block( unsigned int handle )

This locks a block of memory if you want to do that.  None of my programs
do so, and it is not required to move memory using XMS_move_block or my XMSE_*
routines.  You will probably never use this.  Locked data should be unlocked
as soon as possible.

int XMS_unlock_block( unsigned int handle )

Same thing here.  Don't use unless you know what you are doing...

int XMS_enable_A20( void )

Enables the processor's A20 line.
Again, another routine not to be used unless you are familiar with XMS memory.
Of course, if you are familiar, then you will probably have your own 
routines...

int XMS_disable_A20( void )

Disables the processor's A20 line.

The XMSE_* functions

These functions are extra functions to make moving data easier.

int XMSE_xms_to_con( unsigned int handle, char _far *data, unsigned int length )

Give this procedure the handle of the XMS data, where in memory you want the 
data sent, and the length of the data.

ALL LENGTHS MUST BE EVEN!! (no odd numbers like 20123, round up to 20124)
It is faster if you can word-align the length.
Even faster if you can Dword-align the length.

int XMSE_con_to_xms( unsigned int handle, char _far *data, unsigned int length )

Copies data you have in conventional memory to an handle of XMS memory.
Give it the location of the data, and a XMS handle, and the length of the 
data.

One more time, just so you don't try it...
ALL LENGTHS MUST BE EVEN!!! (No odd numbers like 20123, round up to 20124)
It is faster if you can word-align the length.
Even faster if you can Dword-align the length.

Well, I hope you like my routines.  
If you are unsure about how to use something, check out XMS.C to see how I 
used them.  (it uses all the routines.  It copies data to XMS, clears the 
data in conventional, transfers it back, then checks to see if it matches the 
original.)
If you do use them, drop me a line on CompuServe at Jeff Leigh - 70144,3460.

Be sure to ask me how my game is going, so that I don't give up on it and 
quit!!!











Okay. I'm done.




















What do you want?  
Big deal if I couldn't get EMS to work! No one uses anymore anyway!
Besides, I am a REAL programmer.  I can do anything...
