EMS Functions & Utilities (c) 1993 4D Interactive Systems, Inc. Written by Paul Penrose LEGAL STUFF ----------- The files in this archive (4DEMS.ZIP) are being released as FREEWARE. This means that you may use the programs and functions enclosed (see below for a complete list) for whatever use you wish, at no cost, with the following restrictions: 1.) The 4D Interactive Systems copyright notices are not removed or altered in any way. 2.) The following notice is included in any documentation, printed or in electronic form, that accompanies any program or package containing any or all of the aformentioned programs and/or functions: EMS functions provided and (c) 1993 by 4D Interactive Systems, Inc. Warranties: Basically there are none, either expressed or implied. We do not make any claims as to the usefulness of the programs and functions included for any particular purpose. Niether are we responsible for any loss incurred by their use. Any rights not specifically granted in this document are reserved. CONTENTS -------- This archive contains some of the EMS functions we created to take advantage of EMS memory. Included is a function library used to call the EMS services, a program to test the EMS driver, a program to free allocated EMS pages by name, and a TSR to reserve EMS pages from greedy programs. It is assumed that the user is already familar with the C language and EMS basics. You should have the following files: README.TXT EMS.ASM EMS.H EMSTEST.C EMSTEST.PRJ EMSTEST.MAK EMSTEST.EXE EMSFREE.C EMSFREE.PRJ EMSFREE.MAK EMSFREE.EXE RESEMS.ASM RESEMS.EXE EMS Functions ------------- This package provides C callable functions to access the basic LIM 4.0 EMS services. It is composed of EMS.ASM which contains the code, and EMS.H which contains the structures, function prototypes, and external declarations needed to use the functions. The following functions are available: int ems_init(void) This function is used to initialize the function package. It returns a TRUE (1) if a valid EMS driver exists, otherwise FALSE (0) will be returned. None of the other functions will work correctly if ems_int() is not called, or if it is called and returns a FALSE. unsigned int ems_num_free_pages(int true_size) This function returns the number of free EMS pages available. The parameter 'true_size' should be set to TRUE (!0) to force the function to pass along a signature that will cause the RESEMS TSR to return the true amount of free pages, if RESEMS has been installed. See the section below on RESEMS for more information. int ems_alloc(int num_pages, char *name) This function is used to allocate pages of EMS memory and optionally assocate a name with it. If the pages can't be allocated then a -1 will be returned, otherwise a handle will be returned that is used with many of the following functions to identify the EMS pages just allocated. int ems_free(int handle) This function is used to free EMS pages that were previously allocated. Note that this function can fail if the handle has a mapping context saved for it that has not been restored. int ems_map_page(int handle, int logical_page, int physical_page) This function is used to map an EMS logical page to a physical page in the EMS page frame. If the page is mapped successfully, then a TRUE is returned, otherwise a FALSE is returned. A page must be mapped into the page frame in order to be accessed by your program. int ems_unmap_page(int handle, int physical_page) This function is used to unmap an EMS page from the EMS page frame. Once a page is unmapped it can't be accessed by your program until it is mapped into the page frame again. int ems_num_physical_pages(void) This function returns the number of physical pages available in the EMS page frame. Normally this number is four, but don't count on it. int ems_num_open_handles(void) This function returns the number of open EMS handles. Open handles are defined as those handles that are currently in use ('opened' by a call to ems_alloc). int ems_get_handle_directory(handle_directory_struct *hdir) This function returns a map of all open EMS handles. The information is returned in the array pointed at by the parameter 'hdir'. The space for the array must have already been malloc'ed or declared before the call to this function. The structure handle_directory_struct can be found in the EMS.H file. If successfull, TRUE will be returned, else FALSE will be returned. int ems_find_handle(char *handle_name) This function returns the handle number associated with the name 'handle_name'. If no match is found, -1 will be returned instead. int ems_save_mapping_context(int handle) This function is used to save the current mapping state of the EMS page frame. Once saved, it can quickly be restored by a call to the ems_restore_mapping_context() function (see below). Only one context can be stored per handle at one time and the handle can't be freed while there is a context saved for it. int ems_restore_mapping_context(int handle) This function is used to restore the mapping state of the EMS page that was previously saved for the specifed handle. Once called, further calls to this function for the same handle will fail until the ems_save_mapping_context() function is called again. The following variables are used by the functions: unsigned char ems_errnum This variable contains the function number of the most recently used EMS service. In the case of an error, this will be the service that returned the error. unsigned char ems_function This variable contains the error number of the most recent error returned by an EMS service. unsigned char ems_version This variable contains the EMS version number detected by the ems_init() function. For example, 4.0 will be coded as 0x40. unsigned int ems_pageframe This variable contains the segment of the EMS page frame. EMSTEST program --------------- This program was initially written to test the EMS function library. Now we include it in our commerical products that use the EMS library to test the customer's EMS capibility. It was written in C and is a good example of how to call most of the functions in the EMS library. EMSFREE program --------------- While developing programs that use EMS memory we discovered that if the program crashed (nobody's perfect ) it could leave open EMS handles. This memory would be unavailable until the machine was rebooted (or if running under OS/2, the VDM was closed), so we wrote a simple program that will free EMS handles by name. This was good enough for us since we always name our EMS memory, but an obvious improvement would be to allow using a handle number as well as a name for the parameter. Another one would be to steal some code from the EMSTEST program to print out a map of all the open handles if the handle specified did not exist. I'll leave that as an excercise for the reader! RESEMS program -------------- While testing some software we had developed that used EMS memory we discoved that there are some programs out there that will grab all available EMS memory (whether they need it or not) leaving none for our program! There is at least one BBS that does this as well as TD286 and TD386. No doubt there are more. We resolved this problem by writing a TSR that intercepts the EMS 'get free pages' service and returns a number that is LESS than the actual number of free pages. How can this help your application? Good question. The answer is that the TSR will recognize a "signature" placed in some of the unused registers and will return the actual number of EMS pages. This can be used reserve an number of EMS pages for use only by applications that pass the signature. The signature is the value 4444H and must be placed in both the BX and DX registers when the 'get free pages' (EMS function 42H) is called. I won't go into how the TSR works - that's an entire discussion in its own right - but I have tested it on DOS 5.0 and OS/2 VDMs and it has worked flawlessly. To use it just type RESEMS nn, where nn is the number of EMS pages that you want to reserve (hide from other apps). After the TSR is installed you can use the program again to change the number of EMS pages reserved. Compiling the Programs ---------------------- The C programs were compiled with Borland C++ 3.1, and the ASM modules were assembled with TASM 3.1 using TASMs IDEAL mode. If you have a different compiler and/or assembler you will have to figure out how what changes need to be made. I don't think you'll have many problems with the C modules, but converting from the IDEAL mode to, say, MASM mode would not be for the faint of heart. For those of you using the Borland products, you are in luck. Just use the enclosed PRJ and/or MAK files to recompile EMSTEST and EMSFREE programs. To reasseble the RESEMS program just issue the command 'TASM -mx RESEMS'. Support ------- Since this is FREEWARE we can't afford to spend much time supporting users. However, if you do find a bug, I would appreciate it if you would drop me a note, and we can both benefit. Have fun. Paul A. Penrose 4D Interactive Systems, Inc. 1885 University Ave, West Suite 229 St. Paul, MN 55104 612-646-8104 Compuserve: 72610,3377 Internet: 72610.3377@compuServe.COM