home *** CD-ROM | disk | FTP | other *** search
- PBASMLIB Assembly Language Routines for PB3C
- Version 1.0
- Expanded Memory (EMS) Module
- (C) Copyright 1994 by Tim Gerchmez
- All Rights Reserved.
-
- This module interfaces you to EMS (Expanded Memory) in your computer,
- if it is available and an EMS driver is loaded. You will be able to
- access any or all of these routines by including the statements
- $INCLUDE "PBASMLIB.INC" and $LINK "PBASMLIB.PBL" at the top of your
- PowerBASIC programs. An interface to XMS (Extended Memory) is included
- in a separate module.
-
- Many of these commands let you access EMS memory at a very low level. For
- an easier way to access EMS memory, see EMSPUTSTRING and EMSGETSTRING.
-
- PowerBASIC is an ideal language to use EMS with because of its ability
- to utilize absolute arrays. EMS memory is mapped into a section of memory
- physically accessible to the CPU, and you can map a PowerBASIC array into
- this "Page Frame" segment for direct access to EMS! Just use the EMSPAGEFRAME
- function to find the page frame segment, then DIM an ABSOLUTE array AT the correct
- segment of memory (see the PB online help for further information on the DIM ABSOLUTE
- array AT sequence). The following is an example:
-
- pf?? = emspageframe 'Get the EMS page frame in your system
- dim absolute arry%(0 to 32767) at pf?? 'DIM an integer array at page frame.
- 'You are not restricted to an integer
- 'array, but could use byte or word arrays
- '(or other numerics) instead. Integers are
- 'convenient because they are fast, easy to
- 'manipulate, and use two bytes per number,
- 'which fills the 64K page frame perfectly
- '(32768 * 2 = 64K).
-
- The newest versions of MS-DOS include Expanded/Extended Memory drivers that
- let you use EMS or XMS interchangeably (they fool the program into thinking
- that a large quantity of both is available, while one or the other "decreases"
- as the other kind of memory is used). Given the choice, and given PowerBASIC's
- ability to use DIM ABSOLUTE for arrays, it's recommended that you use EMS memory
- whenever possible. You can, however, use either or both with modern versions of
- DOS and computers that contain XMS memory and a memory manager that emulates EMS
- memory.
-
- Caution: PB does not seem to like you playing with EMS memory while in the
- IDE. I have gotten EMM386 error #12, followed by an automatic reboot,
- when accessing EMS while in the IDE. You might test this on your system
- to see if you get the same results. If you do, be sure to use EMS routines
- only in a standalone .EXE file.
-
-
- The following is a list of error codes that may be returned
- by function EMSERROR:
-
- 128 Internal error in EMM software 146 Source and target overlap
- 129 Malfunction in EMS hardware 147 Illegal region length
- 130 Memory manager busy 148 Region overlap
- 131 Invalid handle 149 Offset outside logical page
- 132 Function not defined 150 Region length > 1MB
- 133 No more handles available 151 Cannot exchange overlap
- 134 Error in mapping context 152 Memory types undefined
- 135 Not enough pages exist 153 Not used
- 136 Not enough pages available 154 ARS not supported
- 137 Cannot allocate zero pages 155 ARS currently allocated
- 138 Page not allocated to handle 156 ARS not zero
- 139 Illegal physical page number 157 ARS not allocated
- 140 Save state area full 158 DMA channels not supported
- 141 Save of mapping context failed 159 Illegal DMA channel
- 142 Restore of mapping context failed 160 No handle for this name
- 143 Subfunction parameter not defined 161 Name already exists
- 144 Attribute type not defined 162 Memory address wrap
- 145 Feature not supported 163 Invalid pointer
- 240 String too long (EMS Module Internal)
-
- ================================================================================
- function emsactivehandles
-
- Returns the number of currently active EMS handles in use.
- The number of active EMM handles will never exceed 255. If
- this function encounters an error, it can be checked with EMSERROR.
-
- Example: print emsactivehandles
-
- ================================================================================
- sub emsalloc(pg??,h??)
-
- Allocates a certain number of EMS pages (16K per page), and returns
- a handle to be used in future accesses to those pages. Be sure to
- check if there's any EMS available with EMSFREE first, and use the
- function EMSERROR afterwards to make sure there was no error encountered.
-
- pg??: Set to total number of EMS pages (16K per page) to allocate
- h??: Returns a handle if allocation was successful, or zero/
- undefined if error (see example below).
-
- Example: emsalloc 2,h?? 'Allocates 32K of memory (2 16K pages)
- if emserror = 0 then print "32K EMS allocated successfully."
-
- ================================================================================
- sub emsdealloc(h??)
-
- Deallocates (releases) the EMS pages currently assigned to a
- handle, and releases the handle itself. Call this function when
- you are done using a certain section of EMS. It is important to
- deallocate ALL EMS allocated with EMSALLOC before ending your program,
- or that memory will REMAIN allocated until the computer is rebooted.
- Use function EMSERROR to check the status of this command after using it.
- You can also use this command to deallocate EMS strings allocated with
- EMSPUTSTRING (see this command for details).
-
- h??: Set to the handle to deallocate (originally returned with EMSALLOC).
-
- Example: call emsdealloc(h??) 'Deallocates handle h??
-
- ================================================================================
- function emsdetect
-
- This function checks to see whether an expanded memory manager
- (EMM) is installed. It does not check to see whether the EMM is
- activated, or whether EMS memory is actually available. Use this
- function first before calling any of the other functions, as an EMM
- driver is a necessity in using Expanded Memory. This function will
- also detect whether an XMS/EMS driver allows EMS (for example, if the
- NOEMS option is set with EMM386, zero (not installed) will be returned).
-
- Note: For those techies who are interested, this routine uses the
- EMMXXXX0 filename method, with a call to IOCTL output status request
- for extra security.
-
- emsdetect: Returns -1 if Expanded Memory Manager is resident, or 0 if not.
-
- Example: if emsdetect then print "EMM detected."
-
- ================================================================================
- function emserror
-
- Returns the status of the last EMS function performed in
- the EMS unit. Will return a zero if no error, or error
- code if error (see listing of possible error codes elsewhere
- in this document). Check the status of EMSERROR after every
- EMS function that could encounter an error.
-
- Example: if emserror then print "EMS Error!":stop
-
- ================================================================================
- function emsfree
-
- Returns total number of 16K EMS pages free. To find out TOTAL
- number of EMS pages instead, use EMSTOTAL. Returns -1 if error
- is encountered, which you can check with EMSERROR.
-
- Example: print (16384*emstotal) "Bytes EMS free."
-
- ================================================================================
- function emsgetstring$(h??)
-
- Retrieves a string previously stored in EMS with EMSPUTSTRING,
- and deallocates the associated handle. This routine, or EMSDEALLOC,
- must eventually be called after EMSPUTSTRING, or the EMS will remain
- allocated until the computer is rebooted. Many errors may be encountered
- in the retrieval process, so be sure to check with EMSERROR after
- using this function to be sure the string was recalled properly.
- See EMSPUTSTRING for details on how to use that function.
-
- h??: Set to handle previously returned by EMSPUTSTRING. Deallocates
- handle h?? if everything goes correctly (it should). If you get
- an error with this routine, you may want to call EMSDEALLOC separately
- to be sure handle h?? is deallocated.
- emsgetstring$: Returns the string originally passed to EMSPUTSTRING.
-
- Example: s$ = emsgetstring$(h??)
- if emserror = 0 the print "String Retrieved."
- if emserror <> 0 then call emsdealloc(h??) 'Insurance
-
- ================================================================================
- sub emsmap(mp??,ep??,h??)
-
- Maps a logical EMS page (16K) onto one of the four physical
- pages (16K apiece) in the EMS page frame, effectively storing
- the EMS page to the physical page, and associating it with any
- changes then made to that physical page. This concept of "mapping"
- can be more confusing than a simple store to/recall from concept,
- so let's go over it. When you map an EMS page to a physical memory
- page, the contents of the EMS page are first moved INTO the physical
- page. Think of the physical page as being soft like wet concrete, and
- the EMS page being a metal mold. That EMS page then "softens" and remains
- "on top of" the physical memory page, conceptually changing along with the
- physical contents every time you write to the physical page. When you call
- this function again to map a NEW EMS page to the current physical page, the
- current EMS page is "lifted off of" the physical page and retains its "imprint."
- The new EMS page is then "imprinted" into the physical memory, and the process
- starts over. It may help to envision this process in your mind as you read this.
- XMS storage is more straightforward in some ways than EMS storage (it uses a normal
- store/recall technique rather than the concept of "memory mapping." Examples of EMS
- mapping are included as source code files with PBASMLIB, as a demonstration.
-
- mp??: Set to the Physical Page Number (0-3) in the page frame to map EMS to.
- Remember, each physical page is 16K in size.
- ep??: Set to the EMS page (each logical page is 16K in length) to map onto the
- physical page you specified in mp??. This number should be in the range
- of 0 to N-1, where N is the number of pages previously allocated to the
- EMM handle with the EMSALLOC function (next parameter).
-
- h??: Set to the EMS handle associated with the pages you're mapping to physical
- memory.
-
- To actually access the physical page frame memory, use function EMSPAGEFRAME
- to find the EMS page frame segment address. You can then use DEF SEG along with
- PEEK and POKE, or DIM an ABSOLUTE array AT the value returned by EMSPAGEFRAME.
-
- Note: Be sure to use EMSERROR to check if an error occurred after using this routine.
-
- Example: emsmap 0,85,h?? 'Maps EMS page 85 of handle h?? onto page frame page 0.
-
- ================================================================================
- function emsowned(h??)
-
- Returns the number of 16K EMS pages allocated to a particular
- handle. An EMM handle never has zero pages of memory allocated
- to it. If an error occurs with this routine (invalid handle, for
- example), the value 0 will be returned, and error number can be
- checked with EMSERROR.
-
- Example: print emsowned(h??)
-
- ================================================================================
- function emspageframe
-
- Returns the physical segment of memory the EMM manager maps
- EMS memory to. This will be the area of memory to retrieve
- data from once EMS is mapped there. The EMS page frame area
- is 64K in size, and starts at offset zero of the segment
- returned by this function. It consists of four 16K "pages"
- that 16K EMS pages can be mapped on to (see EMSMAP). If 0 is
- returned by this function, an error was encountered, which you
- should check with function EMSERROR.
-
- Example: print emspageframe
-
- ================================================================================
- sub emsputstring(s$,h??)
-
- Saves a string in EMS memory, and returns a handle for later
- retrieval of the string. This is one of the easiest to use EMS
- routines in the PBASMLIB EMS unit, and requires only that
- you check for the presence of an EMS driver with EMSDETECT.
- The routine will check for free EMS memory, allocate a handle
- for you, and store the string in EMS. Many errors can be
- encountered along the way, so BE SURE TO CHECK after calling
- this routine with the EMSERROR function. EMSERROR will return
- a value of zero if the function was successful, or an error number
- listed at the top of this document.
-
- NOTE: This routine uses physical page zero (and 1 if needed) of the page
- frame, and maps its own handle's EMS onto that page. You may need to
- remap your EMS pages back if you're using EMS independent of this routine.
-
- s$: Set to string to store, up to a maximum of 32,750 bytes in
- length (make sure to set the $STRING metastatement appropriately).
- Each string passed will be allocated a handle and a FULL 16K of
- EMS memory AT LEAST, so the longer the string, the less memory will
- be wasted (at each 16K boundary). Note that a string longer than 16K
- will be allocated 32K of EMS memory. It is suggested that you group
- smaller strings into one long string, use emsputstring, get the string
- back later with EMSGETSTRING, then parse the string back out.
-
- h??: Returns an EMS handle for later retrieval of the passed string, if
- everything worked correctly. If not, h?? will be undefined.
- Note that you must eventually either (1) use EMSGETSTRING to retrieve
- the string (this deallocates handle h?? automatically), or use EMSDEALLOC
- to deallocate h??, or the handle will remain allocated until the computer
- is rebooted.
-
- Example: s$="This is a test" 'Short string, lots of EMS wasted
- emsputstring s$,h?? 'Save the string
- if emserror = 0 then print "S$ was stored in EMS memory."
- if emserror <> 0 then print "EMS Error Number";emserror : end
- s$="" 'Deallocate s$, now that it's in EMS.
-
- ================================================================================
- function emsstatus
-
- This function checks whether the installed EMS hardware is
- functioning properly. Be sure to check for the existence of
- an expanded memory manager with EMSDETECT before calling this
- function. This function should generally return an ok status
- with EMS emulators like EMM386, since XMS hardware is used to
- emulate the presence of EMS memory.
-
- emsstatus: Returns -1 if hardware ok, or 0 if error (use EMSERROR
- to check error code if a zero is returned).
-
- Example: if emsstatus = -1 then print "EMS hardware is ok."
-
- ================================================================================
- function emstotal
-
- Returns the total number of logical EMS pages present in the
- system (NOT FREE pages). Each EMS page is 16K in size. To
- find number of pages free, use EMSFREE instead. Returns -1 if
- error occurs, which you can check with EMSERROR.
-
- Example: tot?? = emstotal
-
- ================================================================================
- function emsversion
-
- Returns the version number of the EMM driver currently
- installed. The version number is encoded as BCD, and can
- be converted by using the HEX$() equivalent (see examples below).
- If an error is encountered (unlikely), it can be checked with EMSERROR.
-
- Example: print hex$(emsversion) 'Version 4.x of EMM386 prints "40"
- Example: v% = val(hex$(emsversion)) 'Get version number in a numeric variable
-
-