
                  |====================================|
                  |                                    |
                  |   TELEMACHOS proudly presents :    |
                  |                                    |
                  |    Part 1 of the PXDTECH serie -   |
                  |                                    |
                  |           XMS-HANDLING             |
                  |                                    |
                  |====================================|

               ___---__-->   The PXDTECH serie   <--__---___

<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>


INTRODUCTION
-------------

Hiya!
Welcome to my new trainer serie! The name of the serie is PXDTECH and it's
some sort of add-on serie to my main trainer serie - the PXDTUT serie.
Why a new serie you might ask? Well, I thought about making this particular
trainer a PXDTUT, but then I realized that even though XMS programming is
very interresting and all, not much can be said about it. So I decided to make
a new trainer serie with another goal than the PXDTUT serie.
The PXDTECH's will be less detailed than the PXDTUT serie and it will deal
with much smaller subjects.
Therefore the PXDTECH will be less talk, more code - leaving more of the hard
work needed to understand the stuff up to the reader!

This first one will be on XMS memory handling in TP 7.0.
Supplied with this text are :
                 - A neat XMS unit called TMXMS written by me.
                 - A sample program to test the unit.
                 - The official XMS ver2.0 specs.

In this text I will briefly descripe XMS memory and how to use the TMXMS unit
in your own programs. I suggest you read the official specs too - and use my
unit as a reference on the functions. It's always nice to have some code when
reading specs - they tend to be tedious reading :)


As always get this serie from the Peroxide homepage at :

http://peroxide.home.ml.org

and mail me at :

tm@image.dk


I don't think I'll release this serie other places than on my homepage (the
PXDTUTS is released to a bunch of FTP sites too) as it's pretty tedious work
to upload stuff to the FTP sites - but if you feel like it, you could do me a
great favour by spreading this text to various FTP sites on the net. As a
matter of fact there is an opening in Peroxide for a net-courrier. Such a
courrier will be 100% responsible for spreading the Peroxide material all
around the net!
Mail me if this sounds interresting to you!



XMS MEMORY : WHAT IS IT & HOW DOES IT WORK?
--------------------------------------------

First of all - I assume you know about the 20bit memory model used by
processors in real mode! Ie. you know why memory is addressed as
segment:offset in real mode and understand why only 1MB of memory can be
addressed this way!
If you don't know about all this I suggest you get a copy of PXDTUT2.ZIP
which deals with EMS handling and has a detailed description of the stuff
mentioned above included.

The main difference between XMS and EMS memory is that you have to actually
MOVE the data from XMS to conventional memory before you can access it (in
EMS you access memory through the PAGE FRAME which is located in himem and
thus is addressable directly even in real mode).
This means that XMS is great for storing static data - ie. data that does'nt
change much during runtime. This could be textures, sound files, bitmaps etc.
Then you would have to move the bitmap or sound file you currently are using
into a buffer in conventional memory and then address it normally.
XMS on the other hand is NOT great for storing things as lookup-tables and
other kinds of data which is constantly used because you would then have to
first move the data from the lookup-table into another variable and THEN use
the value in your program.

The advantages of XMS are that the allocated blocks can be very large - in DOS
you could easily allocate a XMS block of 5MB and use it to store very large
data structures. (Just remember that the buffer in conventional cannot be
larger than 64K)
In Windows 95 the function QueryFreeXMS somehow returns a 'largest_block' value
of 1 or 2MB - but things will still work if you try to allocate a block larger
than that. But if you want your program to run safe on all machines you should
not do that - it COULD be that the program was running under DOS and that the
largest free block actually IS smaller than the block you try to allocate.
In this case it's better to allocate the needed XMS memory as multiple blocks
with different handles - just remember that there is not an unlimited number
of handles available. Check how many free handles you have available by calling
'GetXMSHandleInfo' on the first handle you allocate and add one to this value
(because you have allready used one handle to call the function).

Another great advantage of XMS is that all computers supports it! This is not
the case with EMS - even though Win95 tries to :)
As an example take a look at the sample program from PXDTUT1.ZIP
This program uses EMS - but even though my Windows does not complain it fucks
up the texture data!




HOW TO USE THE XMS API
-----------------------

The EMS functions supplied in the EMS API was called through an interrupt -
this is not the case with the XMS API.
All XMS functions must be called by calling the XMS CONTROL FUNCTION. The
memory location of this function can be found using the INT 2Fh.
(Check out the xms2spec.doc and TMXMS.PAS to see how this is done)

When you got that function address you call it with the ah register loaded
with the number of the XMS function you want to execute. Fx. to get the version
nuber of the XMS API (function 00h in the API) you do the following :

   asm
    mov ah, 00h
    call [XMSFunction]
   end;


Then the ax register will be loaded with the XMS version number.

Most of the API functions will return a status register showing if the call
executed succesfully. This status register will usually be ax containing a
$01 if success and $00 upon failure. If there is an error the error code will
usually be located in the bl register.



HOW TO USE THE TMXMS UNIT IN YOUR OWN PROGRAMS :
-------------------------------------------------

Using the TMXMS unit is very easy!
The unit will detect if XMS is available automatically and get the location
of the XMS CONTROL FUNCTION.
So all you have to do is allocate some XMS memory and start using it :)

Before you allocate a block of XMS memory I suggest you call the function
'QueryFreeXMS' to find out how much memory you have available.
Then you need to allocate the memory. To each allocated block of XMS memory
a handle is assigned. This handle is used later to determine what block you are
talking about when you later tries to move data to and from XMS.

status := AllocateXMS(64, MyXMSHandle);

will allocate a 64Kb big block of memory and return the handle of that block to
MyXMSHandle.


Before you can use the XMS you need a memory buffer of equal size in conv.
memory. And you'll need the 32bit linear address of that buffer.
If your using the 'mem[seg:ofs] := value' method of handling memory buffers
you get the linear address by : linAddr := Longint(ptr(seg,0));
Otherwise use the pascal function 'Addr' to get the address of the buffer!


You move the data to and from XMS by calling the 'MoveXMS' function.
'MoveXMS' takes several params. :
     - size         : size of block to move. MUST be an equal number - ie.
                      the smallest amount you can move to and from XMS is one
                      word (or two bytes if you prefer....)
     - SourceHandle : The handle of the XMS block you wish to move data FROM!
                      If you wish to move FROM conventional TO XMS set this to
                      zero.
     - SourceOffset : A 32bit offset value to the XMS block you wish to move
                      data FROM. If 'SourceHandle' was set to zero this is the
                      32bit linear address of the memory buffer in conventional
                      memory you wish to move data FROM.
     - DestHandle   : The handle of the XMS block you wish to move data TO!
                      If you wish to move FROM XMS TO conventional set this to
                      zero.
     - DestOffset   : A 32bit offset value to the XMS block you wish to move
                      data TO. If 'DestHandle' was set to zero this is the
                      32bit linear address of the memory buffer in conventional
                      memory you wish to move data TO.


In TMXMS I have implemented ALL XMS Ver2.0 function but my guess is that you'll
only need very few of them.... Fx. all the A20 stuff will probably be useless
to you - same thing with the HMA stuff.
The LockXMSBlock is only interresting when in FLAT mode so don't worry about
that one either!

Otherwise, what can I say... go experiment!



FINAL WORDS
-----------

Well, that's about all for now.
Hope you found this doc useful - and BTW : If you DO make anything public using
these techniques please mention me in your greets or where ever you se fit.
I DO love to see my name in a greeting :=)

So, what do you think ??

Should I continue doing this PXDTECH serie? I feel like I have left pretty
much work for you to do... but that's probably only good! That way you'll have
to actually WORK a little to get the stuff working :)
And hey - I figured the stuff out! How hard can it be ??  8]

I have a few ideas for other topics that would fit nicely in a PXDTECH - ie. I
find them to small to actually do a PXDTUT on. These are :

        - ModeX : how to set, use and why is it cool with 4 planes :)

        - 15/16/24 bit SVGA graphics : This is actually just a VERY small
          change to the routines descriped in PXDTUT5.ZIP

        - SB coding : Dunno about this one - might have to be a PXDTUT

        - Some simple graphic effects : Free Directional Tunnels/planes,
          Voxel and so on...

        - The FLAT mode in TP.. This way we can have 4GB of linear memory
          in TP 7.0 WITHOUT protected mode. Nice for LFB SVGA graphics.


As always : mail me about anything you like :)

Telemachos


