;----------------------------------------------------------------------------;
;                            Mystic version 1.0                              ;
;                                                                            ;
;                       User's and Developer's Guide                         ;
;----------------------------------------------------------------------------;

                              Table Of Contents
                             -------------------

  1. Introduction........................................................02
       1.1 Disclaimer...................02
       1.2 What is Mystic?..............02
       1.3 Target audience..............02
       1.4 Distribution.................02

  2. Getting started.....................................................03
       2.1 Obtaining Mystic.............03
       2.2 System requirements..........03
       2.3 Installing Mystic............03

  3. Developing screen savers............................................04
       3.1 Rules & regulations..........04
       3.2 Writing the code.............04
       3.3 Building the screen saver....04
       3.4 Running the screen saver.....04
       3.5 A sample screen saver........05
       3.6 Limitations..................09

  4. Help from other quarters............................................10
       4.1 External routines............10
       4.2 Calling conventions..........10

  5. Technical notes.....................................................11
       5.1 How does it work?............11
       5.2 Re-entrancy issues...........12
       5.3 InDOS & INT 28h..............12
       5.4 Intercepting INT 09h.........13
       5.5 Screen saver structure.......14
       5.6 API services.................14

  6. Miscellaneous.......................................................16
       6.1 Tips & Tricks................16
       6.2 Known bugs...................17
       6.3 Possible conflicts...........17
       6.4 Contacting me................17

;----------------------------------------------------------------------------;
  1. Introduction

       1.1 Disclaimer
             This software is provided "as-is", without any warranty or
             guarantee of any sort. The user shall use this program at his
             own risk, and in the event that the program causes any damage
             or destruction of data or otherwise, I cannot be held respons-
             ible and cannot be forced to supply the user with a fix. In
             simple language, you're on your own with this program.

       1.2 What is Mystic?
             Mystic is a development system which facilitates the construc-
             tion of screen savers for MS-DOS. If you've used Microsoft
             Windows, you'll know what a screen saver is, but just in case
             you don't, well, a screen saver is a program that jumps into
             action when the user stops interacting with the machine for a
             pre-set period of time. A screen saver may blank the screen,
             animate an object around the screen, sound an alarm or do one
             of several hundred other things. Some screen savers provide a
             bit of security by asking for a password before letting the
             user take control of the machine. Thus, unauthorised people
             cannot use the machine while the actual user is away.

             Windows has its own screen savers and it's not very difficult
             to write screen savers for Windows if you know a bit of Windows
             programming. There are even several packages available that
             make it a snap to create screen savers for Windows. MS-DOS,
             however, is a totally different ball game. Screen savers are
             very difficult to program in MS-DOS, because it was not designed
             to be a multitasking system. Writing a screen saver for DOS can
             thus be a Herculean task.

             Here's where Mystic comes in. With just a little knowledge of
             80x86 assembly language, you can create some stunning screen
             savers with very little effort. Mystic takes a heavy burden
             off your back and lets you unleash your creativity.

       1.3 Target audience
             This program is targeted at hobbyist assembly language progra-
             mmers. The source code provides a good base for understanding
             and programming TSRs.

       1.4 Distribution
             I have decided not to place any restriction on the distribution
             of the package or of screen savers developed with the aid of
             the package. You are also welcome to modify the code for the
             package so as to make it more stable/reliable. However, it is
             my sincere request that you include all the files you received
             as part of the package if and when you distribute it. In case
             you do succeed in making the system stabler, I would be grateful
             if you sent me a copy of the hacked version. If you think the
             package is worth paying for, you may consider sending a donation
             of Rs. 100 to any charitable institution. Your comments and
             suggestions as regards the package are always welcome. See
             section 6.4 on how to contact me. I will try my best to respond
             to every communication.

;----------------------------------------------------------------------------;
  2. Getting started

       2.1. System requirements
              Fortunately, Mystic does not require a Pentium III with 64M RAM
              and 4GB hard disk to run on. The minimum requirements are listed
              below.

           Ŀ
                Hardware              Minimum requirement           
           Ĵ
            Main Processor       Intel 8086/8088 or compatible      
            Memory (RAM)         6 kilobytes (max. 64 Kb)           
            Disk space           ~100kb                             
            Keyboard             PC/XT/AT/Enhanced (83/101-102 Key) 
            Display              IBM Compatible (MDA/CGA/EGA/VGA)   
           Ĵ
                Software              Minimum requirement           
           Ĵ
            Operating system     MS/PC-DOS version 2.0 or above     
            Assembler            Tasm/Masm or compatible            
            Linker               TLink/Link or compatible           
            Other              * Exe-to-Com converter (Exe2Bin)     
           

       2.1. Obtaining Mystic
              I have uploaded Mystic to the SimtelNet archives as well as
              the Jumbo download archives. You can get the package from
              either of these sites. The file to download is MYSTIC.EXE.
              If you have any difficulty locating these sites, send me an
              e-mail with your e-mail address in it requesting for a copy
              of the stuff, and I'll mail it to you.

       2.2.  Installing Mystic
              Once you have the file MYSTIC.EXE file in your possession, the
              rest is a breeze. The file is a self-extracting archive. To
              unpack it, just copy it to the directory where you wish to
              install it and run it just as you would any other program.
              The archive unpacks itself and you're all set to go. The
              package consists of the following files.

              Mystic-directory -- Directory where you unpacked the archive
                    
                     BIN -- Binaries
                        MC_CORE.OBJ  -- Core module (obj module)
                        MC_INIT.OBJ  -- Initialization module (obj module)
                        MYSTIC.INC   -- Include file (plain/text)
                        TEMPLATE.SCR -- Screen saver template (plain/text)
                        MC_BUILD.BAT -- Builds a screen saver (plain/text)
                        MCC.EXE      -- Mystic Control Centre (DOS binary)
                        ASMPRINT.EXE -- Assembler source printer (binary)
                    
                     SRC -- Source code
                        MC_CORE.ASM  -- Core module (assembler)
                        MC_INIT.ASM  -- Initialization module (assembler)
                        MCC.C        -- Mystic Control Centre (C source)
                        ASMPRINT.C   -- Assembler source printer (C source)
                    
                     DOC -- Documentation
                         READ_ME.TXT  -- Documentation file (plain/text)

;----------------------------------------------------------------------------;
  3. Developing screen savers

       3.1. Rules and regulations
              You must adhere to some (rather strict) norms when it comes to
              writing screen savers. Since the screen saver binary is in
              DOS Image (COM) format, the total size of code and data the
              screen saver can address is 64KB. About 4KB is taken up for
              saving the screen. You have to fit in all the code and data
              for the screen saver in about 60KB. All the code and data must
              be in the same segment named _TEXT. In case you're using sim-
              plified segment directives, always remember to use the TINY
              memory model for assembling your screen savers.

              For the screen saver to co-exist harmoniously (!) with other
              programs, it is necessary to save and restore the state of the
              machine before and after activating the screen saver. You must
              make it a point to save all system resources the screen saver
              modifies (the video buffer, DAC & CRT registers, etc.). Failure
              to do so may cause unpredictable behaviour on part of the
              interrupted program.

       3.2. Writing the code
              You can write the screen saver just as you write any other
              normal assembly-language module. However, I would strongly
              recommend that you use the template provided as a base upon
              which to build the screen saver. To do so, just copy the
              template file (TEMPLATE.SCR) to your screen saver module
              name, open this file in a text editor and fill up the code
              and data at the specified locations.

       3.3. Building the screen saver
              You may build the screen saver by using the assembler and
              linker in succession at the DOS prompt but due to the way the
              screen saver is implemented, linking MUST be in the right
              order, or else the program will crash. To avoid these problems,
              use the MC_BUILD.BAT script to build your screen saver. Type
              MC_BUILD without any parameters at the DOS prompt to learn
              how to use the script. In case your assembler/linker combina-
              tion is not able to adapt to the way MC_BUILD calls it, comp-
              lete the following steps --

       -->    Assemble the screen saver just as you would any other module.

       -->    Invoke the linker in such a way that the link order is

                  MC_CORE  other-objs/libs  YOUR_MODULE  MC_INIT

              The link order is VERY IMPORTANT and should it be any different
              from the one described above, the screen saver will likely
              crash.

       3.4. Running the screen saver
              The MC_BUILD script produces an executable DOS image (COM) file
              with the same name as that of the screen saver source file.
              To run the screen saver, just execute this program by typing
              its name at the DOS prompt. The screen saver will acknowledge
              the fact that it has been installed by displaying a message.
              Only one screen saver can be resident at a time. Hence, any
              attempts to run another screen saver while one is already
              active will result in failure.

       3.5. A sample screen saver
              In this section, we'll actually go through the whole process
              of developing a screen saver. We'll call this screen saver
              BLANKER, because all it's going to do is clear the screen
              when the user does not press a key for 2 minutes. Okay, it
              isn't a very complex screen saver, but it gives an idea of
              the basics and is an ideal launching pad for creative minds
              to develop stunning screen savers.

       -->    Copy the file TEMPLATE.SCR as BLANKER.SCR.
                    
       -->    Open BLANKER.SCR in your favourite text editor. Once you've
              done that, this is what you'll see --

******************************************************************************
 title <<Any text you wish (usually a description of the screen saver)>>

 include Mystic.Inc                    ; contains necessary PUBLICs

; <<INCLUDES, EQUATES go here>>

 _TEXT segment byte public use16 'CODE'
     assume cs:_TEXT, ds:_TEXT

;----------------------------------------------------------------------------; 
 Module_Name_Is  <<"Screen saver name">> ; screen saver name
 Authors_Name_Is <<"Author's name">>     ; author's name
 Time_Delay_Is   <<Delay in seconds>>    ; time delay in seconds (max. 3640)
 Valid_Modes_Are <<Valid mode list>>     ; video modes in which SS activates

;----------------------------------------------------------------------------;
 SS_Resident_Data:

;     <<Resident data go here>>

;----------------------------------------------------------------------------; 
 SS_Start_Up_Code proc near

;     <<Startup code goes here>>

     retn
 SS_Start_Up_Code endp

;----------------------------------------------------------------------------; 
 SS_Main_Body_Code proc near

;     <<Core code goes here>>

     retn
 SS_Main_Body_Code endp

;----------------------------------------------------------------------------; 
 SS_Clean_Up_Code proc near

;     <<Cleanup code goes here>>

     retn
 SS_Clean_Up_Code endp

;----------------------------------------------------------------------------;
 SS_API_Handler proc near

;     <<API handling code goes here>>

     retn
 SS_API_Handler endp

;----------------------------------------------------------------------------;
 SS_Resident_Code_End equ this byte           ; resident up to here

;----------------------------------------------------------------------------;
 SS_Transient_Data:
     SS_Message db '<<Screen saver message goes here>>', 0dh, 0ah, 0

;     <<Transient (non-resident) data go here>>

;----------------------------------------------------------------------------; 
 SS_Initialize proc near

;     <<First time initialisation code goes here>>

     retn
 SS_Initialize endp

;----------------------------------------------------------------------------;
 _TEXT ends

     end
;x------------------------ Screen Saver Module Ends ------------------------x;
******************************************************************************

              Before proceeding any further, let me explain some of the
              important elements in the screen saver template.

           *  Module_Name_Is "Screen saver name" -- This line lets you chri-
              sten your screen saver. Replace "Screen saver name" with what-
              ever name you wish to give your screen saver.

           *  Authors_Name_Is "Author's name" -- This line indicates who
              wrote the screen saver. Replace "Author's name" with your own
              name.

           *  Time_Delay_Is <<Delay in seconds>> -- This command enables you
              to set the initial (default) time delay for the screen saver.
              Note, though, that the delay can be changed after the screen
              saver is installed using MCC.

           *  Valid_Modes_Are <<Mode list>> -- This command enables you to
              control in which video modes the screen saver should be acti-
              vated. 15 modes are accepted. The modes should be as per the
              BIOS numbering conventions.

           *  SS_Start_Up_Code -- This procedure is called once at the begi-
              nning of every activation of the screen saver. You can use it
              to perform startup activities such as saving the screen and
              other resources.

           *  SS_Main_Body_Code -- This procedure is called repeatedly as
              long as the user does not press a key. It contains the main
              code of the screen saver.

           *  SS_Clean_Up_Code -- This procedure is called once at the end
              of every screen saver activation. Use it to perform cleanup
              activities such as restoring the screen data, etc.

           *  SS_API_Handler -- This function opens up a completely new
              customisable world for your screen saver and enables you to
              write programs that are capable of communicating with the
              screen saver once it is resident. The function code is passed
              in the AL register and additional parameters in other registers
              depending upon the function. See section 5.6 for more infor-
              mation on this topic.

           *  SS_Initialize -- This function is called only once - when you
              type the screen saver name at the DOS prompt. Use it to perf-
              orm any initialization activities your screen saver requires.

           *  SS_Message -- This string is displayed whenever the user
              invokes the screen saver at the DOS prompt for the first time.

       -->    Now that the explanations are over, let's proceed. We call our
              screen saver BLANKER and so,

                         Module_Name_Is "Blanker"

       -->    Assuming our name is The Gang, we say

                         Authors_Name_Is "The Gang"

       -->    We want a default time delay of 2 min. (120 sec.), hence we say

                         Time_Delay_Is 120

       -->    To keep the screen saver simple, we'll save only the text mode
              screen. Thus, the screen saver must activate only in the text
              modes or we'll see garbage on the screen when the screen saver
              quits. The BIOS text mode IDs are 0, 1, 2 and 3. Therefore,

                         Valid_Modes_Are 0, 1, 2, 3

       -->    We don't have any startup processes to carry out, so we don't
              place any code in the SS_Start_Up_Code procedure. In the
              SS_Main_Body_Code procedure, we place the code that clears
              the screen. The code is as follows --

                         SS_Main_Body_Code proc near
                             mov ax, 0b800h
                             mov es, ax
                             mov cx, 2000
                             mov ax, 0720h
                             sub di, di
                             rep stosw
                             retn
                         SS_Main_Body_Code endp

              We don't have any cleanup processes either, so SS_Clean_Up_Code
              is blank too. SS_API_Handler is a little out of our league at
              this stage. To learn about it, see section 5.6.

       -->    We would like a nice, descriptive message to be printed out
              when the user first invokes the screen saver. Hence,

                   SS_Message db ' Blanker : Clears the screen.'

       -->    After all this work the final screen saver source should look
              something like this --

******************************************************************************
 title Blanker (scr) clears the screen

 include Mystic.Inc                    ; contains necessary PUBLICs

 _TEXT segment byte public use16 'CODE'
     assume cs:_TEXT, ds:_TEXT
;----------------------------------------------------------------------------; 
 Module_Name_Is  "Blanker"               ; screen saver name
 Authors_Name_Is "The Gang"              ; author's name
 Time_Delay_Is   120                     ; time delay in seconds (max. 3640)
 Valid_Modes_Are 0, 1, 2, 3              ; video modes in which SS activates

;----------------------------------------------------------------------------;
 SS_Resident_Data:

;----------------------------------------------------------------------------; 
 SS_Start_Up_Code proc near
     retn
 SS_Start_Up_Code endp

;----------------------------------------------------------------------------; 
 SS_Main_Body_Code proc near
     mov ax, 0b800h
     mov es, ax
     mov cx, 2000
     mov ax, 0720h
     sub di, di
     rep stosw
     retn
 SS_Main_Body_Code endp

;----------------------------------------------------------------------------; 
 SS_Clean_Up_Code proc near
     retn
 SS_Clean_Up_Code endp

;----------------------------------------------------------------------------;
 SS_API_Handler proc near
     retn
 SS_API_Handler endp

;----------------------------------------------------------------------------;
 SS_Resident_Code_End equ this byte           ; resident up to here
;----------------------------------------------------------------------------;
 SS_Transient_Data:
     SS_Message db ' Blanker : Clears the screen.', 0dh, 0ah, 0

;----------------------------------------------------------------------------; 
 SS_Initialize proc near
     retn
 SS_Initialize endp

;----------------------------------------------------------------------------;
 _TEXT ends

     end
;x------------------------ Screen Saver Module Ends ------------------------x;
******************************************************************************

       -->    Once the code is written, save it under the name BLANKER.SCR
              Now, all we have to do is build the screen saver. To do this,
              use the MC_BUILD script.

                         MC_BUILD blanker.scr

       -->    The build process produces a DOS image binary (COM) module that
              you can execute at the DOS prompt. To run the screen saver,
              simply type BLANKER at the DOS prompt. The screen saver will
              inform you that it has been successfully installed. Now wait a
              couple of minutes without pressing a key, and you'll see that
              BLANKER has faithfully cleared the screen.

       -->    NOTE -- This screen saver is extremely rudimentary in that it
              does not even preserve the contents of the screen before it
              cleared it. You would probably wish to save the contents of the
              screen before performing any operation to it. Ideally, you
              should preserve the state of any system resource you modify
              if you feel that the active program could be using those very
              resources.

       3.6. Limitations

       -->    The screen saver code+data must be less than 60KB.

       -->    The code and space for saving screen data must be provided
              in your module. This is one limitation that's proving to be
              very difficult to work around, mainly because of the large
              memory space required to save graphics screens.

;----------------------------------------------------------------------------;
  4. Help from other quarters

       4.1. External routines
              The screen saver you saw being developed in the previous sec-
              tion gave just a faint idea of the true possibilities of what
              you can do with Mystic. As you begin to develop ever more com-
              plex screen savers, you will find that you require a lot of
              procedures to implement them. It may not always be possible to
              write these procedures in the screen saver module itself. This
              section teaches you the conventions you must follow so that
              you can link in other object/library modules to your screen
              saver. These external modules may be written by you or may be
              developed by a third party. The conventions to be followed
              while creating an object module for linking with the screen
              saver are --

       -->    The module must contain only one segment named _TEXT of class
              CODE. If you're using simplified segment directives, use the
              TINY memory model.

       -->    The total code size of the screen saver+your module should not
              exceed the specified maximum.

       -->    Declare all identifiers you wish to "see" as PUBLIC in the
              external module and as EXTRN in your screen saver module.
              You can then use these identifiers.

       -->    Do not give an entry point to the module after the END directive.

       -->    To link in the external module with your program, first assemble
              it to get an OBJ module. Then, include this module name on the
              MC_BUILD command line, like so --

                  MC_BUILD screen-saver-name external-module(s)

       4.2. Calling conventions
              The REGISTER calling convention is the most compact and fastest
              method of passing parameters and should be used whenever your
              procedures are assembly-specific. If you're writing generic
              procedures, then it's best to use the C or PASCAL calling conv-
              ention, since you may then use these procedures in other prog-
              rams. Whatever calling convention you choose, always keep the
              stack balanced because an unbalanced stack is a sure recipe for
              disaster.

;----------------------------------------------------------------------------;
  5. Technical notes

       5.1. How does Mystic work ?
              Mystic is basically a memory-resident program (also known as
              a TSR). TSRs are a peculiar breed of programs - whereas normal
              programs release their memory to the operating system when
              they're done, TSRs hold on to their memory; that is, they
              Terminate, but Stay Resident (hence the name TSR). This way,
              they can continue processing in the background. Many popular
              programs such as Sidekick, DosKey, Calc, etc. are TSRs. How
              do TSRs work in the background? After all, DOS is not a mult-
              itasking operating system.

              The key to the functioning of TSRs is INTERRUPTS. Interrupts
              are electronic signals the processor receives from the devices
              it's connected to. For example, the keyboard, the mouse and the
              printer generate interrupts. Each interrupt has its own unique
              ID. The IBM PC supports upto 256 interrupts. Each interrupt has
              its own HANDLER, which is nothing but a sequence of instructions
              that takes care of the event. For example, if the user strikes
              a key, the keyboard generates interrupt number 9. Upon receiving
              this signal, the processor pre-empts (interrupts) the currently
              executing program and calls the requisite handler. The handler
              then does its job, which in this case is to read the key from
              the keyboard and store it in a buffer. Once the handler does its
              job, control is returned to the program that was interrupted.
              TSRs use interrupts to spring into action. For example, Calc
              takes over the keyboard interrupt handler and replaces it with
              its own code. Thus, whenever a keyboard interrupt occurs, Calc
              receives control of the machine. It then checks whether the key
              pressed is the Calc hotkey; if so, the calculator program is
              activated; if not, Calc passes control to the original handler,
              and execution proceeds as if nothing had ever occurred.

              Matters are not so simple when it comes to a screen saver. We
              need some way of keeping count of the time continuously so that
              we can activate the screen saver once the pre-set quantity of
              time has expired. It just won't do if we gain control of the
              machine only when a keyboard interrupt occurs. Here's where the
              timer ticker steps in. The timer is a device that generates
              interrupt 8 approximately 18 times a second. If we replace the
              original interrupt 8 handler with our own code, not only do we
              gain control 18 times a second, but we also get a great way of
              keeping track of the time. Talk about killing two birds with
              one stone! We simply maintain a counter which we increment every
              time we gain control, and if the counter equals the pre-set
              amount of time, we activate the screen saver. The only thing is
              that we're keeping track of time in timer ticks rather than in
              seconds, but that's not a problem. Once the screen saver is ac-
              tive and the user presses a key, we simply reset the counter to
              zero. Translation from human time (seconds or minutes) to timer
              ticks is typically done during the build phase itself.

              In reality, things aren't so simple. We'll see in the next
              section how DOS tries its best to thwart our carefully cut
              and dried plans.

       5.2. Re-entrancy issues
              In the previous section, you were treated to an (oversimplified)
              explanation of how Mystic works. It would, no doubt, be wonder-
              ful if everything in life were so simple, but the universe takes
              a perverse delight in complicating seemingly simple issues, and
              writing screen savers for DOS happens to be one of them.

              While working with (admittedly archaic) operating systems such
              as DOS, one has to contend with such beasts as function codes,
              arcane return values, and above all, non-reentrancy. Re-entrancy
              refers to the capability of an operating system (or of the BIOS)
              to handle multiple calls to it. Multitasking systems such as
              Windows and Unix have to be re-entrant since many programs are
              running at the same time and may simultaneously request system
              services. For example, suppose program A calls a system service
              to read a file. When the operating system is in the process of
              accomplishing this task, program B calls a system service to
              read a string from the user. If the OS is re-entrant, it will
              handle both requests correctly, but if it isn't, you can bet
              such a situation is pretty sure to crash the machine. Unfortu-
              nately for us, DOS falls into the latter category. Suppose the
              screen saver tried to spring into action just as DOS was writing
              a file to the disk. Not only would the machine crash, but you
              could end up with a scrambled hard disk.

       5.3. InDOS and INT 28h
              Every problem has a solution and the problem of non-reentrancy
              is no exception. No doubt the solution is a tad more complex
              than what we'd like it to be, but that's how matters stand, and
              beggars can't be choosers.

              DOS maintains an internal flag (a byte) called the InDOS flag
              which indicates whether a DOS service is currently active. The
              address of the InDOS flag is obtained using function 34h of
              INT 21h. By testing the InDOS flag, we can determine whether
              DOS is active or not, and consequently whether it's safe to
              activate the screen saver or not. If the flag is zero, DOS is
              inactive and we can activate the screen saver. If it is non-
              zero, DOS is busy and we'll have to wait. So the solution is to
              test the InDOS flag before we activate the screen saver. Well,
              we've solved the problem of non-reentrancy by adding only a
              couple of lines of code. Or have we ?

              There still is a major problem we've got to address. Suppose a
              program has called one of the DOS "keyboard input" functions
              (0Ah, 01h, etc.), or suppose we're at the DOS prompt. Under
              these circumstances, DOS is always active (since it's waiting
              for keyboard input), and the InDOS flag is always non-zero.
              This means that the screen saver will never spring into action
              if we're at the DOS prompt, or if a program calls a DOS function
              for keyboard input (even if the user doesn't hit a key). This
              is not what we want the screen saver to do. Happily, once again
              we're rescued by another provision in DOS, but implementing the
              solution requires more programming effort.

              Though undocumented by Microsoft, it is common knowledge that
              the DOS keyboard input functions periodically invoke INT 28h
              while waiting for keyboard input. By hooking on to INT 28h, it
              is possible for a program to gain control when at the DOS prompt
              or when DOS is processing an "input from keyboard" request. So
              we simply create a procedure that hooks on to INT 28h, and each
              time DOS invokes INT 28h, our procedure gets control. This pro-
              cedure then checks whether it's time to activate the screen
              saver, and if so, activates it (we don't have to worry about
              InDOS here). One minor detail needs to be taken care of - that
              is, how does the INT 28h hook get to know whether it's time to
              activate the screen saver? After all, it's the INT 08h hook that
              keeps track of the time. But now, we have two possible routes
              leading to the activation of the screen saver. These are :

       -->    Via INT 08h when the period expires and InDOS is 0.
       -->    Via INT 28h when the period expires (no InDOS here).

              The solution to this problem is to maintain a flag which indic-
              ates whether or not to activate the screen saver. The flag is
              updated by the INT 08h hook as and when required. For example,
              the INT 08h hook checks if the requisite time period has expi-
              red, and if so, sets the flag to 1. Now, if InDOS is non-zero
              (as in the case when we're at the DOS prompt), INT 08h does
              nothing more. The next time INT 28h is invoked, the INT 28h hook
              tests this flag, and if it is 1, the screen saver is activated.
              After the screen saver has done its duty, this flag is reset to
              zero, as is the count variable which keeps track of the time.

       5.4. Intercepting INT 09h
              We saw in the last few sections how to keep track of the time
              and how to activate the screen saver if the pre-set time period
              expired. However, there remains one important detail we must
              take care of; that is, none of this must happen if the user
              presses a key.

              In order to know when the user presses a key, we have no other
              recourse but to intercept the keyboard interrupt (interrupt 9).
              Once we hook on to INT 09h, our program will gain control when-
              ever a key is pressed. The rest is simplicity itself. Whenever
              INT 09h occurs, our keyboard handler must reset the count vari-
              able (which keeps track of the time) to zero. Then the screen
              saver will not activate if the user presses a key before the
              requisite time period has expired, which is, after all, exactly
              what we'd expect from it.

       5.5. Screen saver structure
              The screen saver is implemented as a "sandwich" DOS binary
              image (COM) module. Your screen saver code is sandwiched
              between the core routines and the initialization routines.
              This is the reason why linking should be strictly in the
              order detailed above. The structure is --

                 Low    - Counters, flags & interrupt handlers
                        - External modules and procedures
                        - Screen saver code and data
                 High   - Initialization code

              The reason for this structure is economy of memory. The end-
              point of the resident portion is defined in the screen saver
              module. By linking this module third, it is possible to keep
              resident only that portion of the screen saver that is requir-
              ed for proper functioning of the screen saver. The initializ-
              ation code need not be resident.

       5.6. Application program interface (API)
              The Mystic development system provides you with a tremendous
              amount of customisability through the API services. An API is
              a set of calls provided by a system that other programs can
              use to perform different functions. For example, INT 21h is
              the DOS API. Using this API, you can not only control Mystic,
              but also individual aspects unique to a screen saver. The MCC
              program provided as part of this package gives you a glimpse
              of the power of this feature.

              The API in this case is implemented as an interrupt call. The
              program that wishes to make use of an API service must place
              the API service code in the AX register and pass other para-
              meters in other registers (the exact registers depend on the
              API call), and then invoke INT 69h. This interrupt is the
              gateway to the Mystic API services. The API services supported
              as of now are --

       -->    00h (MC_SS_API) -- This API service enables you to modify
              screen saver specific parameters. The handling code for this
              must be placed in the SS_API_Handler procedure.

              Input  -- AX = 00h
                        Other regs. = other parameters

              Output -- Depends on screen saver

       -->    01h (MC_GET_INFO) -- This API service collects information
              about the screen saver and returns them to the caller. 

              Input  -- AX     = 01h

              Output -- AH     = 0abh (identification code)
                        AL     = 0ffh (enabled), 00h (disabled)
                        ES:DI --> Screen saver name
                        ES:SI --> Author's name
                        CX     = Time delay in timer ticks
                        DX:BX  = 32-bit integer w/bit-coded mode info.

       -->    02h (MC_SET_DELAY) -- This service enables you to modify the
              default time delay for the screen saver.

              Input  -- AX = 02h
                        CX = Time delay in timer ticks
              Output -- None

       -->    03h (MC_SET_MODES) -- This service enables you to change the
              default active modes setup.

              Input  -- AX    = 03h
                        DX:BX = 32-bit integer w/bit-coded mode info.

              Output -- None

       -->    04h (RESERVED) -- Not yet implemented but is meant for unlinking
              the screen saver.

       -->    05h (MC_SUSPEND) -- This service enables you to disable or
              suspend the screen saver indefinitely. It continues to reside
              in memory.

              Input  -- AX = 05h

              Output -- None

       -->    06h (MC_ACTIVATE) -- This service enables you to activate the
              screen saver if it has been suspended.

              Input  -- AX = 06h

              Output -- None

       -->    You can even add your own API services to the Mystic core. See
              the file MC_CORE.ASM for details on how to do this.

;----------------------------------------------------------------------------;
  6. Miscellaneous

       6.1. Tips & tricks
              Here are a few hints that might make your life a little easier
              as you grapple with the task of writing screen savers.

       -->    Always use the template TEMPLATE.SCR as a foundation upon which
              to build your screen savers. This will not only save you time
              (since you don't have to key in the essential elements), but
              will also minimise the chances of your making mistakes.

       -->    Keep as little code as possible in the SS_Main_Body_Code proce-
              dure. Instead, move as much of the code as possible to the
              SS_Start_Up_Code and SS_Clean_Up_Code procedures. Keep only the
              absolutely essential code in the main body. For example, if
              you're animating an object in graphics mode, keep only the ani-
              mation code in the body, and relegate the mode set code, etc.
              to the SS_Start_Up_Code procedure.

       -->    Since you have only about 60KB for your screen saver code+data,
              try to optimise your code as much as possible. Don't waste any
              space for unnecessary features - don't go about unrolling loops
              to increase speed. Focus instead on memory conservation. Of
              course, if you must, go ahead with speed optimisation, but I'm
              talking about what your general approach should be.

       -->    Do not make very heavy use of the stack. Your screen saver has
              a maximum stack space for about 90 words. Use this space wisely.
              This certainly isn't the place to try out recursion or passing
              large structures on the stack. Overuse of the stack will most
              certainly cause your screen saver to crash. While I'm talking
              about the stack, pray allow me to give you a Very Important
              Warning --

              Never, never, ever leave the stack unbalanced. Your machine
              will go off to never-never land (wherever that is!) if you
              do so.

              This error is only too easy to commit - I have fallen prey to
              it several times; so look out for it.

       -->    If you're using external routines in your screen saver, create
              macros that take care of passing the arguments, calling the
              external procedures, and cleaning up the stack. You'll soon
              realize the tremendous advantages of adopting this strategy.
              With this approach, you won't have to remember the order in
              which to push the arguments, or the registers in which to pass
              them, or whether and how you have to clean up the stack. This
              helps alleviate (though not eliminate) the chances of your
              screen saver leaving the stack unbalanced.

       -->    Mystic does not take it upon itself to save the contents of the
              video buffer or other system resources. If your screen saver
              makes any changes to the system (such as modifying the video
              DACs, or changing the current video page), you must restore it
              to the original state, for there exists every possibility that
              the interrupted program was making use of the very resources
              you modified. Failure to do so may result in unruly behaviour
              on part of the interrupted program.

       -->    You may use the registers as you please without saving them.
              Mystic takes care of saving and restoring registers. Saving
              them in the screen saver code will not only tax the (already
              limited) stack space, but will also increase code size and
              decrease execution speed.

       6.2. Known bugs
              Here is a list of bugs I know Mystic is infected with --

       -->    Mystic does not allow you to use INT 16h or the DOS services for
              keyboard input. This means that till the bug is fixed, you can-
              not prompt the user for keyboard input of any kind. I cannot
              guarantee what will happen if you attempt to use keyboard input
              functions.

       -->    Screen savers written with the aid of Mystic seem to be causing
              undesirable problems while using Microsoft Windows 3.x, such as
              an increase in the number of General Protection Faults (GPFs),
              mysterious reboots and system lockups. As a result, you should
              not use the screen saver if you plan to use Windows 3.x. Input
              from users of Windows 95 is eagerly awaited.

       6.3. Possible conflicts
              The very nature of the program coupled with the (hostile and
              unhelpful) attitude of MS-DOS towards TSRs makes it very diffi-
              cult to write airtight TSRs. Conflicts with other programs,
              especially other TSRs which attempt to hook on to the same
              vectors simply cannot be ruled out. If anyone has any sugges-
              tions as to how conflicts can be minimised and stability
              improved, please pass 'em on to me.

       6.5. Contacting me
              I'm 19 years old and about to complete my first year in engin-
              eering. I can be contacted by --

              Snail-mail at -- 181-A, Jolly Maker Apartment No. 1,
                               Cuffe Parade,
                               Bombay -- 400 005,
                               India.
                               Phone -- (91) (022) 2182197

              E-mail at     -- shank@giasbma.vsnl.net.in

              Keep your suggestions coming. I'll also be grateful if you
              notify me about any inconsistencies/errors in the document-
              ation. Thanks.

;----------------------------- READ_ME.TXT ----------------------------------;
