    ------------------------------------------------------------------------
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                 T S R                                |
    |                                                                      |
    |                              Version 1.5                             |
    |                                                                      |
    |                Copyright (C) 1993, Geoff Friesen B.Sc.               |
    |                         All rights reserved.                         |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    ------------------------------------------------------------------------

    ------------------------------------------------------------------------
    |                                                                      |
    |                                History                               |
    |                                -------                               |
    |                                                                      |
    | TSR TOOLKIT has a long history.  I first became interested in build- |
    | ing TSRs back in the fall of 1988.  I tried building a few but found |
    | the amount of work involved very tiring.  If I had a nickle for each |
    | time I had to reboot the computer while testing, I could retire.  It |
    | became apparent that some mechanism was needed to handle TSR details |
    | allowing me to concentrate on the application.  This would save alot |
    | of time.  In 1989, I put together my first toolkit.  I pre-wrote the |
    | resident and installation kernels.  The library was in object form   |
    | and could quickly be linked with the application module.  Although   |
    | this technique worked and saved alot of time, it was pretty bloated. |
    | There were other problems as well.  After giving up on the toolkit   |
    | for a few years, I decided to take one last crack in 1992.  I began  |
    | development work on TSR TOOLKIT.  TSR TOOLKIT has gone through alot  |
    | of versions.  Version 1.5 is the latest and the most complete.  For  |
    | the first time, this toolkit feels like a winner.  I am very glad to |
    | be able to share this package with you and hope that you will find   |
    | it useful in writing your own TSRs.                                  |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    ------------------------------------------------------------------------
				      - 2 -

    ------------------------------------------------------------------------
    |                                                                      |
    |                             TSR Structure                            |
    |                             -------------                            |
    |                                                                      |
    | Before you can write your own TSRs, it would be a good idea to get   |
    | comfortable with the internal structure.  In this section, I want to |
    | explain how the kernels work and how everything fits together.  You  |
    | can examine the source code when you create a TSR (or look at TSR.C) |
    | for additional information.  Let's start with a diagram.             |
    |                                                                      |
    |  ----------------                                                    |
    |  |   RESIDENT   |                                                    |
    |  |    KERNEL    |                                                    |
    |  ----------------                                                    |
    |  |  APPLICATION |                                                    |
    |  ----------------                                                    |
    |  | INSTALLATION |                                                    |
    |  |    KERNEL    |                                                    |
    |  ----------------                                                    |
    |                                                                      |
    | This is as basic as it gets.  A TSR is structured as a .COM format   |
    | program.  Internally, a TSR resembles a sandwich.  The resident and  |
    | installation kernels surround the application.  When you create a    |
    | TSR, you can focus your attention on creating this application.  The |
    | kernels have already been written for you.  The option does exist to |
    | extend the installation kernel to add customization to your program. |
    | We'll see this later on in this document.                            |
    |                                                                      |
    | The resident kernel has one basic goal.  It must respond to hotkey   |
    | presses, delay activation until the computer system is in a stable   |
    | state, and then perform a launch sequence.  The launch sequence is   |
    | sort of equivalent to the start up code in a regular application.    |
    | The stack is switched, registers are saved and then initialized as   |
    | appropriate, interrupt vectors are saved, the keyboard buffer is     |
    | emptied, and other tasks are performed prior to calling the main ()  |
    | function (the entry point) within the application.  Once main () has |
    | returned to the launch sequence, everything is restored and the TSR  |
    | exits as if the hotkey had never been pressed.                       |
    |                                                                      |
    | The basic goal behind the installation kernel is to install the TSR  |
    | once and only once and provide a means to remove the TSR (uninstall) |
    | when necessary.                                                      |
    |                                                                      |
    | Over the years, these kernels have grown in size and capability.     |
    | They perform a staggering amount of work.  In order to really under- |
    | stand how TSRs work, we're going to have to look in detail at these  |
    | kernels.  Here we go.                                                |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    ------------------------------------------------------------------------
				      - 3 -

    ------------------------------------------------------------------------
    |                                                                      |
    | When a TSR is loaded into memory, execution begins at address 100h   |
    | because the TSR is a .COM program.  The JMP instruction at 100h will |
    | cause execution to continue at the first address in the installation |
    | kernel.                                                              |
    |                                                                      |
    | The personal identification section (aka communications API) follows |
    | the JMP instruction.  The communications API is a collection of use- |
    | ful pieces of information organized in a standard manner and access- |
    | ible to other TSRs and regular programs.  The first piece of infor-  |
    | mation is the hotkey character.  This is the ASCII letter or digit   |
    | of the default hotkey.  The equivalent scancode follows.  Following  |
    | a NULL byte is the version number.  The version number was designed  |
    | to make it easy to change the kernel structure for subsequent ver-   |
    | sions of TSR TOOLKIT without crashing previously written TSRs and    |
    | regular programs which access the kernel.  All versions prior to 1.4 |
    | have version number zero.  Version zero should not be considered as  |
    | a reliable means of identifying different kernel locations since I   |
    | made a number of changes without changing this number.  Version 1.4  |
    | has version number 1.  Version 1.5 has version number 2.  These num- |
    | bers are stored in binary in a single byte.  The address of the main |
    | procedure follows.  I have not encountered a use for this knowledge  |
    | as yet but will undoubtedly find a use in the future.  The starting  |
    | address of the installation kernel follows.  Again, this information |
    | is present but not being used at this time.  A two-byte field marked |
    | "reserved" follows.  I may use this field in the future to extend    |
    | the communications API past the signature field which follows.  The  |
    | signature identifies the TSR and always starts with "TSR:".  The sig |
    | is stored as an ASCIZ string (a C-style string with a terminating 0  |
    | byte).                                                               |
    |                                                                      |
    | The resident data section follows the communications API.  All data  |
    | storage required by the resident kernel is located in this section.  |
    | The beep flag variable (beepf) is really part of the communications  |
    | API (even though this is not indicated).  This variable will always  |
    | following the terminating 0 byte of the signature.                   |
    |                                                                      |
    | The resident code section follows the data section.  This section is |
    | divided into a variety of redirected interrupt vectors, the launch   |
    | sequence procedure, the sound API, the XMS API, and the stack.       |
    |                                                                      |
    | Interrupt 9 is activated whenever a hotkey is pressed.  If the TSR   |
    | is not already active (as indicated by the tsr_state variable then   |
    | interrupt 9 sets this variable to a TRIGGERED status.  Interrupt 9   |
    | will also generate a beep if the beep flag (beepf) is set.  The pur- |
    | pose of this beep is to provide positive assurance to the user that  |
    | the hotkey has been acknowledged.  Sometimes a TSR may not activate  |
    | immediately when its hotkey is pressed for the following reasons.    |
    |                                                                      |
    |                                                                      |
    ------------------------------------------------------------------------
				      - 4 -

    ------------------------------------------------------------------------
    |                                                                      |
    | DOS may not be in a stable state.  The extended memory manager found |
    | in HIMEM.SYS may not be in a stable state.  The BIOS disk service    |
    | (interrupt 13h) may be active.  The chaining order of installed TSRs |
    | may be such that a TSR cannot activate until a currently active TSR  |
    | becomes inactive.                                                    |
    |                                                                      |
    | Interrupts 8 and 28h monitor tsr_state.  Interrupt 8, the timer tick |
    | interrupt, activates about 18.2 times per second (unless the timer   |
    | frequency has been changed).  Interrupt 28h is called repeatedly by  |
    | the DOS buffered keyboard input function (function 10) when DOS is   |
    | waiting for input at the command line (a function code such as 10 is |
    | placed in the AH register and interrupt 21h is called to request DOS |
    | perform a function such as buffered keyboard input).  When DOS is    |
    | waiting for a command at the command line, DOS is active but is in a |
    | state where it is safe to call DOS functions higher than 12.         |
    |                                                                      |
    | When interrupts 8 and 28h detect that tsr_state has been set to the  |
    | TRIGGERED status, they perform four tests to ensure that everything  |
    | is as stable as possible.  The first test is to make sure that the   |
    | critical error handler is not active.  The second is to ensure that  |
    | DOS is not operating in a critical section.  The third is to be cer- |
    | tain that interrupt 13h is not active.  The fourth and final test is |
    | to make certain that HIMEM.SYS is not active.  If all four tests are |
    | passed then the launch sequence procedure is called to complete the  |
    | activation.                                                          |
    |                                                                      |
    | Interrupt 13h is redirected to monitor itself by setting a flag upon |
    | input and resetting this flag upon output.  Interrupts 8 and 28h use |
    | this flag in testing to see if it is safe to activate.               |
    |                                                                      |
    | Interrupts 1bh and 23h have also been redirected but only by the     |
    | launch sequence procedure.  This was done to ensure an even higher   |
    | degree of reliability in the event that CTRL-BREAK should be pressed |
    | when a standard I/O function is called (not a console I/O function   |
    | whose code is less than 13).                                         |
    |                                                                      |
    | The reason why TSR TOOLKIT does not support any version of DOS less  |
    | than 3.30 has to do with the critical error handler interrupt.  This |
    | interrupt has been set to return a FAIL code whenever called.  Doing |
    | this ensures that you never need to include a critical error handler |
    | in your application.  DOS 3.30 was the first version of DOS to offer |
    | a FAIL code which always causes the offending interrupt 21h function |
    | to return to the application with a suitable error code in the AX    |
    | register.                                                            |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    ------------------------------------------------------------------------
				      - 5 -

    ------------------------------------------------------------------------
    |                                                                      |
    | The multiplex interrupt needs to be redirected as well.  When 4310h  |
    | is passed in the AX register, interrupt 2fh responds with the entry  |
    | address to the HIMEM.SYS XMS handler (if HIMEM.SYS is installed).    |
    | One of the tests performed by interrupts 8 and 28h is to ensure that |
    | HIMEM.SYS is not active when a TSR activates.  It turns out that the |
    | XMS handler is not reentrant.  By redirecting interrupt 2fh, we can  |
    | pass a different entry point address.  This new handler (see the XMS |
    | XMS_rdriver procedure) can set a flag upon entry, call the handler,  |
    | and reset the flag upon exit allowing interrupts 8 and 28h to carry  |
    | out their test.                                                      |
    |                                                                      |
    | The launch sequence procedure is called by either interrupt 8 and    |
    | 28h to complete the activation process.  This procedure must setup   |
    | an appropriate environment so that the application can execute in a  |
    | completely safe environment.  The first step is to switch stacks.  A |
    | stack follows this procedure.  There is no telling what stack will   |
    | be in use when the launch sequence procedure begins execution.  This |
    | stack could have room for several hundred to several thousand bytes. |
    | On the other hand, there may only be enough room for a handful.  Our |
    | application needs its own stack.  Who knows how many local variables |
    | will be defined.  The launch sequence procedure switches back to the |
    | original stack just before it exits.  All registers are saved on the |
    | switched stack since any could be modified.  Interrupts are enabled  |
    | and the string move direction flag in the processor flags register   |
    | is cleared to ensure that any string instructions accessed by the    |
    | application will operate in a forward manner.  The data segment (DS) |
    | register is set to the same segment as the code segment (since the   |
    | application is written in C, it will be accessing static data via    |
    | its DGROUP which has its address set to the data segment address).   |
    | Interrupts 1bh, 23h, and 24h are redirected for greater reliability. |
    | Interrupt 24h is the critical error handler interrupt.  The program  |
    | segment prefix (PSP) of the currently active application (or TSR)    |
    | which we are interrupting is saved and then set to our PSP.  The     |
    | same thing happens to the data transfer area (DTA).  Extended error  |
    | information is also saved.  Whenever a DOS function is called and an |
    | error occurs, information is saved constituting the extended error   |
    | state.  This tells us more about what error occurred and where it    |
    | occurred.  We now come to the strangest section of the launch seq-   |
    | uence procedure.  In this section, we redirect interrupts 8, 9, 16h, |
    | and 1ch.  We actually set them to values that they had before the    |
    | TSR was installed.  I would rather not have done this but it turns   |
    | out that various Microsoft programs including DOS 5.0 EDIT/QBASIC    |
    | and Microsoft Word 5.0 crash when a TSR is activated with these ints |
    | redirected.  Go figure Microsoft.  The unfortunate part about this   |
    | is you cannot take advantage of the kernel's interrupt 8 to add some |
    | additional timing code for creating timers.  You must install your   |
    | own.  Finally, we flush the keystroke buffer, disconnect the speaker |
    | and hide the mouse cursor.  We then call the application main ()     |
    | function and restore everything to its original state prior to exit. |
    ------------------------------------------------------------------------
				      - 6 -

    ------------------------------------------------------------------------
    |                                                                      |
    | The SOUND API follows.  This API provides four functions that your   |
    | application can use to take advantage of sound and processor speed-  |
    | independent timing.  These functions are documented in a separate    |
    | section.                                                             |
    |                                                                      |
    | The XMS API follows the SOUND API and contains a group of functions  |
    | that your application can call to access extended memory.  These     |
    | functions are documented in a separate section.                      |
    |                                                                      |
    | The resident code section and the resident kernel conclude with the  |
    | stack.  The stack follows the XMS API and builds down towards it.  I |
    | chose a default stack size of 256 bytes but you have the option of   |
    | increasing the stack as will be seen later.                          |
    |                                                                      |
    | The application code follows the stack.  The code comprising EXTRA.  |
    | ASM (if specified) would be loaded following the application.        |
    |                                                                      |
    | The installation kernel begins with the installation data section.   |
    | This section contains all of the data local to this section.  The    |
    | command tail address is used by the command tail parsing logic to    |
    | locate the next parse location on the command tail.  The psp is used |
    | to refer to the segment of a resident TSR.  The scancodes table is   |
    | used to convert a hotkey letter read from the command tail to an     |
    | equivalent scancode which will be stored in the communications API.  |
    | A variety of messages along with a variable to hold the major por-   |
    | tion of the DOS version number complete this section.                |
    |                                                                      |
    | The first piece of code has the task of displaying the TSR title.    |
    | This gives you the ability to personalize your TSR.  The TSR title   |
    | is actually stored in your application .C file.  The examples found  |
    | in TSREX.ZIP show how the title would be formatted.  Every line must |
    | end with a carriage return/line feed sequence.                       |
    |                                                                      |
    | The next step is to obtain the DOS version number and make sure that |
    | the version is at least 3.30 (because of the critical error handler  |
    | FAIL code).  We save the major portion in the ver variable so we can |
    | access this later (HIMEM.SYS was only introduced with DOS 5.0 and so |
    | we cannot redirect the multiplex interrupt if our DOS version is not |
    | 5.0 or higher).                                                      |
    |                                                                      |
    | We obtain the addresses of the critical error and critical section   |
    | flags since these must be tested by interrupts 8 and 28h as part of  |
    | the task in ensuring that DOS is stable.                             |
    |                                                                      |
    | The next step is to search for a previously installed copy (it would |
    | be wasteful of memory to install more than one copy).  The search is |
    | also important when we wish to uninstall (if the TSR has not been    |
    | installed then how can we uninstall).                                |
    |                                                                      |
    ------------------------------------------------------------------------
				      - 7 -

    ------------------------------------------------------------------------
    |                                                                      |
    | Command tail parsing follows.  The command tail is stored in the PSP |
    | at offset 81h.  The last byte in the command tail must be a carriage |
    | return character.  We skip leading whitespace (blanks and tabs) and  |
    | then parse the first nonwhitespace character.  This character can be |
    | only a carriage return or a forward slash (/).  If a carriage return |
    | then parsing is finished.  We would then display the current hotkey  |
    | status and exit if this is a second install attempt or continue with |
    | the install logic.  If this is a slash then we check for either a B, |
    | K, or U character immediately following.  The B character indicates  |
    | that we want to set the BEEP state.  The K character indicates that  |
    | we want to set the HOTKEY.  The U character indicates that we want   |
    | to UNINSTALL.  If B is selected then we parse the next character     |
    | following the B (must be 0 for disable or 1 for enable) and save it. |
    | If K is selected then we parse the next character following the K    |
    | (must be A-Z or 0-9 - a-z is converted to A-Z) and save it.  In the  |
    | event of B or K as the command option, we continue parsing.  If U is |
    | selected then we check to see if a copy of this TSR already exists.  |
    | If it does then we attempt to uninstall.  Otherwise, we display an   |
    | error message and exit.                                              |
    |                                                                      |
    | A call to an xparse () function defined in the application will fol- |
    | low if this extension option is specified.  This gives the applica-  |
    | tion the ability to extend command tail parsing.  Numerous examples  |
    | of this can be found in TSREX.ZIP.  This function returns nonzero if |
    | an error is detected during the extended parse.  Otherwise, command  |
    | tail parsing resumes.  The B, K, and U options will always override  |
    | any equivalent options defined in xparse ().  Therefore, they will   |
    | never be passed to xparse () and there is no point in trying to use  |
    | them.                                                                |
    |                                                                      |
    | The next step is application-specific.  Some applications may need   |
    | to perform additional setup such as redirecting other interrupt vec- |
    | tors.  If this is the case then the installation kernel would call a |
    | setup () function defined in the application.  The setup () function |
    | returns nonzero if an error is detected.                             |
    |                                                                      |
    | The next part of the install logic is to redirect the HIMEM.SYS XMS  |
    | handler if the current version of DOS is 5.0 or higher and HIMEM.SYS |
    | has been installed.                                                  |
    |                                                                      |
    | Interrupts 8, 9, 13h, 28h, and 2fh are redirected.  Note that inter- |
    | rupt 9 is redirected last to ensure that all other interrupts are    |
    | installed in case the hotkey is pressed before we finish the instal- |
    | lation.  At the same time, the environment segment is freed.  Note   |
    | that we obtain the current addresses of interrupt 16h and 1ch.  The  |
    | launch sequence procedure requires this information.                 |
    |                                                                      |
    | Finally, we calculate the amount of memory (in paragraphs) to keep   |
    | and terminate but stay resident.                                     |
    ------------------------------------------------------------------------
				      - 8 -

    ------------------------------------------------------------------------
    |                                                                      |
    | It would be instructive to take a look at the uninstall procedure.   |
    | The first step is to ensure that interrupts 8, 9, 13h, 28h, and 2fh  |
    | match their saved addresses.  We cannot uninstall if any different   |
    | address is detected.  This would indicate that the TSR is not the    |
    | most recently installed.  If all interrupts match then we restore    |
    | them to their saved addresses.  We then attempt to call cleanup ()   |
    | in the application (if defined for the application).  Any addtional  |
    | redirected interrupts would be restored as well as any other cleanup |
    | tasks.  A nonzero value is returned if cleanup is unsuccessful.  In  |
    | previous versions of TSR TOOLKIT, no value was returned.  This fea-  |
    | ture has been added to version 1.5 to ensure a more reliable kernel. |
    | We attempt to release all memory previously allocated when we TSRed. |
    | If cleanup is unsuccessful or we cannot release this memory then we  |
    | display a reboot error message and exit.  Otherwise we display a     |
    | success message and exit.                                            |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    ------------------------------------------------------------------------
				      - 9 -

    ------------------------------------------------------------------------
    |                                                                      |
    |                               Sound API                              |
    |                               ---------                              |
    |                                                                      |
    | * void beep (void);                                                  |
    |                                                                      |
    | Generate a beep for 1/3 of a second.                                 |
    |                                                                      |
    | * void nosound (void);                                               |
    |                                                                      |
    | Disable sound.                                                       |
    |                                                                      |
    | * void pause (unsigned ticks);                                       |
    |                                                                      |
    | Generate a delay in timer ticks.  By default, the tick rate is 18.2  |
    | ticks per second (approximately).  The minimum value passed to this  |
    | function should be 1 tick otherwise you might be waiting for a very  |
    | long time.  There is the possibility, due to the unpredictability of |
    | when a timer interrupt occurs that you may lose one tick.  I have    |
    | not come up with any solution to this problem.                       |
    |                                                                      |
    | * void sound (unsigned frequency);                                   |
    |                                                                      |
    | Enable sound at the specified frequency.  The lowest valid frequency |
    | is 19 Hertz.  Any lower value and sound () immediately exits.        |
    |                                                                      |
    |                                                                      |
    | These functions are prototyped in TSRLIB.H (see TSRLIB.ZIP).         |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    ------------------------------------------------------------------------
				     - 10 -

    ------------------------------------------------------------------------
    |                                                                      |
    |                                XMS API                               |
    |                                -------                               |
    |                                                                      |
    | One of the best things added to DOS 5.0, as far as I am concerned,   |
    | was HIMEM.SYS.  At last, a decent gateway to extended memory.  TSR   |
    | TOOLKIT takes advantage of this capability.                          |
    |                                                                      |
    | typedef struct                                                       |
    |         {                                                            |
    |            long length;                                              |
    |            unsigned srchandle;                                       |
    |            long srcoffset;                                           |
    |            unsigned desthandle;                                      |
    |            long destoffset;                                          |
    |         }                                                            |
    |         EMMS; /* Extended Memory Move Structure */                   |
    |                                                                      |
    | * int XMS_Alloc (unsigned nkilos);                                   |
    |                                                                      |
    | Attempt to allocate a block of extended memory in kilobytes.  If no  |
    | error occurs then a handle is returned.  This handle references the  |
    | extended memory region indirectly.  If an error occurs then zero is  |
    | returned.                                                            |
    |                                                                      |
    | * int XMS_Copy (EMMS *x);                                            |
    |                                                                      |
    | This function allows you to copy a block of conventional memory to   |
    | extended memory or the other way around.  You need to create an EMMS |
    | variable and fill it in appropriately.  The length specifies the     |
    | number of bytes to copy and must be an even number.  The handles     |
    | cannot come from locked extended memory blocks.  If zero is the han- |
    | dle then the offset field would specify the segment:offset address   |
    | in conventional memory where the block starts.  Zero is returned on  |
    | failure.  See XMS.C in TSREX.ZIP for an example.                     |
    |                                                                      |
    | * int XMS_Exists (void);                                             |
    |                                                                      |
    | This function returns a nonzero value if HIMEM.SYS is not installed. |
    |                                                                      |
    | * int XMS_Free (unsigned handle);                                    |
    |                                                                      |
    | This function frees a previously allocated block.  It returns zero   |
    | on failure.                                                          |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    ------------------------------------------------------------------------
				     - 11 -

    ------------------------------------------------------------------------
    |                                                                      |
    | * long XMS_Lock (unsigned handle);                                   |
    |                                                                      |
    | This function attempts to lock a memory block to a specific address. |
    | If successful then the 32-bit linear address of this block will be   |
    | returned.  Zero is returned otherwise.  This allows you to work with |
    | this block directly via the BIOS int 15h facility.                   |
    |                                                                      |
    | * int XMS_Query (unsigned *nkilos, unsigned *maxblocksize);          |
    |                                                                      |
    | This function returns the total number of kilobytes of available     |
    | extended memory in *nkilos and the size of the largest block in      |
    | *maxblocksize.  Both values take the high memory area (HMA) which is |
    | 64K in length into account.  Zero is returned on error.              |
    |                                                                      |
    | * int XMS_Realloc (unsigned handle, unsigned nkilos);                |
    |                                                                      |
    | This function allows you to adust the size of a memory block.  Zero  |
    | is returned on error.                                                |
    |                                                                      |
    | * int XMS_Unlock (unsigned handle);                                  |
    |                                                                      |
    | This function performs the inverse of XMS_Lock ().  Zero is returned |
    | on error.                                                            |
    |                                                                      |
    |                                                                      |
    | These functions are prototyped in TSRLIB.H (see TSRLIB.ZIP).         |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    ------------------------------------------------------------------------
				     - 12 -

    ------------------------------------------------------------------------
    |                                                                      |
    |                              Install API                             |
    |                              -----------                             |
    |                                                                      |
    | * int cleanup (void);                                                |
    |                                                                      |
    | This is the prototype for the cleanup () function which must be      |
    | defined in the application source file if you decide to incorporate  |
    | setup/cleanup.  A nonzero value must be returned on error or zero on |
    | success.                                                             |
    |                                                                      |
    | * int parse (void);                                                  |
    |                                                                      |
    | This function returns the next character on the command tail.  The   |
    | parse position is updated unless a carriage return is returned.      |
    |                                                                      |
    | * void setcseg (void);                                               |
    |                                                                      |
    | This function sets both the DS and ES registers to the current seg-  |
    | ment (the same segment as CS) and is used with xparse ().            |
    |                                                                      |
    | * void setrseg (void);                                               |
    |                                                                      |
    | This function sets both the DS and ES registers to the resident seg- |
    | ment and is used with xparse ().                                     |
    |                                                                      |
    | * int setup (void);                                                  |
    |                                                                      |
    | This is the prototype for the setup () function which must be        |
    | defined in the application source file if you decide to incorporate  |
    | setup/cleanup.  A nonzero value must be returned on error or zero on |
    | success.                                                             |
    |                                                                      |
    | * void skipws (void);                                                |
    |                                                                      |
    | This function skips leading whitespace on the command tail.  White-  |
    | space consists of blanks and tabs.                                   |
    |                                                                      |
    | * void unparse (void);                                               |
    |                                                                      |
    | This function backs up the parse pointer by one position unless the  |
    | pointer is pointing to a carriage return.                            |
    |                                                                      |
    | * int xparse (int option);                                           |
    |                                                                      |
    | This is the prototype for the xparse () function which must be       |
    | defined in the application source file if you decide to incorporate  |
    | extended parsing.  The option passed is the character which follows  |
    | the / on the command tail.  A nonzero value must be returned on      |
    | error or zero on success.                                            |
    ------------------------------------------------------------------------
				     - 13 -

    ------------------------------------------------------------------------
    |                                                                      |
    |                                 Tools                                |
    |                                 -----                                |
    |                                                                      |
    | TSR TOOLKIT provides two utility programs and a batch file that work |
    | together with BCC.EXE, TASM.EXE, and TLINK.EXE to generate TSRs from |
    | C source files.                                                      |
    |                                                                      |
    | T.BAT serves as the crux.  It calls all other programs in a proper   |
    | sequence.  The format of the T command line is:                      |
    |                                                                      |
    | T filename arguments                                                 |
    |                                                                      |
    | The filename consists of the TSR .C name with an optional drive and  |
    | path.  A file extension must not be specified since T.BAT appends a  |
    | .C to the filename.                                                  |
    |                                                                      |
    | The arguments which will shortly be discussed consist of either a -  |
    | or / character followed by a sequence of characters.  Each argument  |
    | must be separated by whitespace (blanks and/or tabs).  These argu-   |
    | ments may appear in any order but must follow the file name.         |
    |                                                                      |
    | * -hx                                                                |
    |                                                                      |
    | h is the hotkey argument.  Any letter A-Z or digit 0-9 may appear in |
    | place of the x.  This letter/digit when combined with ALT serves as  |
    | the default hotkey.                                                  |
    |                                                                      |
    | * -i                                                                 |
    |                                                                      |
    | i is the include argument.  This argument causes the contents of     |
    | EXTRA.ASM to be included after the application code.                 |
    |                                                                      |
    | * -sy                                                                |
    |                                                                      |
    | s is the stack argument.  This argument specifies the size of the    |
    | TSR stack (y ranges from the default of 256 to 8192 bytes).          |
    |                                                                      |
    | * -sc                                                                |
    |                                                                      |
    | sc is the setup/cleanup argument.  This argument allows the instal-  |
    | lation kernel to incorporate calls to setup () and cleanup ().  They |
    | must be defined in the application source file.                      |
    |                                                                      |
    | * -x                                                                 |
    |                                                                      |
    | x is the xparse argument.  This argument allows the installation     |
    | kernel to incorporate a call to xparse ().  This must be defined in  |
    | the application source file.                                         |
    |                                                                      |
    ------------------------------------------------------------------------
				     - 14 -

    ------------------------------------------------------------------------
    |                                                                      |
    | What does T.BAT do?  After parsing the command line, it calls the    |
    | BCC.EXE program to compile the application .C file and create an     |
    | equivalent assembler source file (via the -S switch).  At this time, |
    | the TI environment variable is passed to BCC.EXE telling it where to |
    | find the TSRLIB source files should any be referenced in the app.    |
    | If everything is successful then FILTER.EXE is called.  BCC.EXE will |
    | generate a file with an .ASM extension which is the equivalent of    |
    | the .C file.  However, this file is not in a format suitable for     |
    | turning into a TSR.  FILTER.EXE takes this .ASM file and turns it    |
    | into a properly formatted file with a .TSR extension.  This is then  |
    | passed to TSR.EXE which creates a sandwich .ASM file.  The .TSR file |
    | is placed between the resident and installation kernels.  Once this  |
    | has been accomplished, the resulting .ASM file is assembled and then |
    | linked.  TLINK.EXE creates a .COM file directly.  If any errors are  |
    | detected during any step then T.BAT displays an error message and    |
    | aborts.                                                              |
    |                                                                      |
    | Note that TSR.EXE takes identical arguments as T.BAT but in reverse  |
    | order.  Don't let that be a point of confusion.  Always use T.BAT.   |
    | Each example program (see TSREX.ZIP) shows the calling sequence via  |
    | T.BAT in the comments section at the start of the source file.       |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    |                                                                      |
    ------------------------------------------------------------------------
				     - 15 -
