home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / CPROG / ISC366.ZIP / README.TXT < prev   
Text File  |  1993-09-01  |  21KB  |  401 lines

  1. ----------------------------------------------------------------------------
  2.                              ISC V3.66
  3.                    by: Ofer Laor (AKA LeucroTTA)
  4. ----------------------------------------------------------------------------
  5.  
  6.  
  7.                     ISC- Interrupt Service Class
  8.            -----------------------------------------------
  9.             hooking interrupts into C++ objects made easy
  10.            -----------------------------------------------
  11.  
  12.  
  13. ----------------------------------------------------------------------------
  14.                              NEW in version
  15. ----------------------------------------------------------------------------
  16.  
  17. ■ ver 3.66 - ISC destructor turned virtual. Encorperated a __NOT_TSR__ macro
  18.   for the guys that are using ISC in embedded systems (via Paradigm systems'
  19.   "Paradigm Locate" package), as well as interrupt handlers in non-TSRs.
  20.   To use this feature define __NOT_TSR__ before including ISC.h (or place
  21.   this macro in the defines section in Options|Compiler options. Killed the
  22.   ASSUME DS!=SS problem (no specific settings neccessary for SMALL & COMPACT
  23.   models). Also, Added KBD class that hooks keyboard (for programs with a
  24.   hotkey). Added a DOSFREE example (DOSFREE + KBD) that snaps a picture of
  25.   the screen and appends to a file called <snap.dat>. Dosfree allocates more
  26.   stack for it's ISC (so that sprintf, and other stack memory hogs will not
  27.   crash the system). More docs on the derived classes can be found here also.
  28.  
  29.   +++ ISC turned PD. Info about that can be found in the end of this file.
  30.  
  31. ----------------------------------------------------------------------------
  32.                            OVERVIEW
  33. ----------------------------------------------------------------------------
  34.  
  35.   This article describes a class for Turbo / Borland C++ (checked with
  36. versions 3.x), for hooking interrupts into C++ objects. For those of us
  37. who need to write heavy TSRs or regular programs that need interrupt
  38. handlers - hooking the interrupt handlers into the C++ code was a bit of
  39. a fuss. Borland made it easy enough for us to hook interrupts into C code
  40. through the "interrupt" keyword, but objects could not use this feature.
  41.   The reason for this is that every C++ object needs an identifier to be passed
  42. to it when using one of it's functions. This identifier (called "this") is the
  43. real name of the object and is used by it to access data and function members.
  44.   When a member function is called - (a.foo() for example) a is the "this" and
  45. foo() is the function to be called. When the actual call is made - a is
  46. pushed unto the stack and foo() is called. Now, foo() uses data members
  47. through "this" and knows it's own name through it. If you could somehow
  48. get foo's address and called it (something that C++ prohibits and protects
  49. its programmers from) you would not pass on the right "this" and cause a
  50. malfunction when foo() accesses an internal data member or calls a
  51. virtual function. What people would usually do is to make a static interrupt
  52. function for each of the interrupts in the system. This is a common solution
  53. (in lack of a better one). ISC offers a different approach - and a more useful
  54. one.
  55.  
  56.   A class that uses ISC will derive from it and overload a function called
  57. isr() - (Interrupt Service Routine). Now all that needs doing is activating
  58. the interrupt (activate(int_num)) and the interrupt is hooked into that
  59. OBJECT!!! What this means is that if you have a class for Serial
  60. communications that works through interrupts - you don't have to make a
  61. different interrupt function for each of the possible ports you'd be using-
  62. you would write the class as you would any other. Each of the instances of
  63. the Serial class you are writing will hook into a different interrupt (or the
  64. same one if needs be).
  65.  
  66.   ISC works in a simple way, it produces what Windows 3.x programmers call
  67. a thunk (a small piece of code that contains your data segment and sets it
  68. just before the real call is made- or in this case the id of your object) for
  69. each of the objects that are currently hooked into interrupts through ISC.
  70.   ISC reproduces the thunk for each object. Each Thunk contains in it's code
  71. - the id of the object that owns it. Then it calls a special dispatcher that
  72. handles the call to the right ISC derived object. The dispatcher also sets
  73. up the stack for all the ISC users (so that no stack cramming is needed in
  74. your interrupt routines). The dispatcher also sets up a structure that
  75. contains the registers that the interrupt entered through (so you may modify
  76. them or use them if they are needed).
  77.  
  78.   In the first two versions of this class I tried to utilize (without much
  79. success) properties in the local C++ compilers (how the virtual function
  80. tables work) and tried to call virtual functions directly from ASM. While
  81. this was fairly easy to do (a bit of reverse engineering) - it was compiler
  82. dependent (and even compiler version dependent). I have seen the light and
  83. this version is COMPILER INDEPENDENT (although the ASM routines are written
  84. to work specifically under tasm - and a bit of semantic changes might be
  85. needed to make it work under different assemblers). A close look will have
  86. taught you that porting the code to your local machine, and compiler is a
  87. simple enough task!
  88.  
  89.  Since the ISC class is mainly for use in TSRs (although it is usable in
  90. regular programs just as well)- these are some of the pitfalls that TSR
  91. writers in C++ will encounter:
  92.  
  93.  ■ ISC CANNOT be compiled under the TINY memory model (there is a problem
  94.    with the segment locations in the asm module. As it couldn't be solved
  95.    up till now, I don't think I'll spend more time with it...
  96.  
  97. ----------------------------------------------------------------------------
  98.                             ISC functions.
  99. ----------------------------------------------------------------------------
  100.  
  101.   ISC provides your classes with the ability to hook into hardware and
  102. software interrupts.
  103.  
  104. it does this by providing 2 "overloadable" functions: both named isr.
  105.  
  106.   * HARDWARE INTERRUPTS: virtual void isr(void);
  107.  
  108.    just overload this function and when your class is activated the isr will
  109.    be called whenever the hardware calls it.
  110.  
  111.   * SOFTWARE INTERRUPTS: virtual void isr(IREGS& regs);
  112.  
  113.    IREGS is NOT compatible with the regular REGS union although it is very
  114. close to it (it has MORE registers than REGS). The 32 bit option is not
  115. supported in the interrupt keyword - so I have not incorporated it into ISC.
  116.  
  117.   * IREGS contains two structures:
  118.  
  119.     struct IBYTEREGS  {
  120.            unsigned char  al, ah, bl, bh;
  121.            unsigned char  cl, ch, dl, dh;
  122.     };
  123.  
  124.     struct IWORDREGS  {
  125.            unsigned int  ax, bx, cx, dx;
  126.            unsigned int  si, di, ds, es, cs, flags, ip, bp;
  127.     };
  128.  
  129.   you may access IWORDREGS and IBYTEREGS through .x and .h :-
  130.  
  131.       IREGS regs;
  132.          ...
  133.       regs.x.ax= regs.h.bl+ regs.h.dl;
  134.  
  135.   all of these registers are what the register situation was BEFORE the
  136. interrupt was called.
  137.  
  138.   if you change the content of the regs parameter that is passed to you in
  139. the isr function - this will be the value of that register when the
  140. interrupt exits.
  141.  
  142.   * void activate(const int in_num) - will hook the interrupt handler to the
  143. function isr (software). The default software isr calls the hardware isr,
  144. so that if you hook to the hardware isr - you will be called as required.
  145. But if you overload both - you must literally call the hardware interrupt
  146. handler in order for it to work. This function prevents the programmer
  147. from activating an ISC derived class twice (you must deactivate it first).
  148.  
  149.   * void deactivate(void) - will unhook you from the interrupt. The destructor
  150. of ISC also does that - so unless you'd like to unhook and rehook to another
  151. interrupt - you shouldn't need this function. The function enables you to call
  152. activate again (for rehooking to another interrupt, for example).
  153.  
  154.   some GENERAL PURPOSE functions are also available here as part of ISC -
  155. since I use ISC to build TSR's in C++ (for example a real time communication
  156. program that runs in the background)- I though it useful to provide TSR
  157. functions here as well. These STATIC functions ( is_TSR and TSR) take care
  158. of managing your TSR needs (the most basic ones).
  159.  
  160.   * static int is_TSR(const char *app_name)- will figure out if your program is
  161. running already as a TSR. You must choose a unique application name and put
  162. it's name as parameter. Returns (1) if you are RESIDENT already and (0) if
  163. you're not. I used a simple method for this - (for more info. read the
  164. source file).
  165.  
  166.   * static int TSR(const int exit_code= 0, unsigned long extra_heap= 0)- will
  167. keep you resident in memory. if you call TSR() it will attempt to stay
  168. resident (minimal memory possible) and return 0 to DOS. You can return any
  169. exit code by calling TSR(1) for example. If your TSR needs more room to grow
  170. (extra interrupt-time heap for example) put the extra heap (in bytes) in the
  171. second parameter. Remember that in the LARGER models malloc and new use the
  172. far heap so that you may not be able to use your preallocated memory in them
  173. (and most likely no heap at all will be available in those memory models at
  174. all). Problem with run time heap (SMALLER MEMORY MODELS ONLY) is that when
  175. you allocate past the max heap you declared (in parameter extra_heap) the
  176. program will crash (in a probably very bizarre way!!!). USE THOUGHTFULLY.
  177.  
  178.   The method for finding the minimum memory necessary for reallocation is
  179. an algorithm I am quite proud of- it works in all the memory models and with
  180. a lot less memory that the sources Borland provides in their help of KEEP.
  181. It can be converted to C very easily (change new into malloc!). This is a
  182. brand new method (new from V3.6) and is not prone to heap failures and
  183. possible problems (as the previous versions were).
  184.  
  185.  ■ One ISC specific static function is reallocStack(unsigned long stacklen):-
  186.  
  187.   * static int reallocStack(unsigned stackLen)- will reallocate the hardware
  188. interrupt stack frame to the specified size. If you need to call this
  189. function you must:- either call it while no ISC derived class is active or
  190. simply disable interrupts before you call it (don't forget to re-enable them).
  191.  
  192. ----------------------------------------------------------------------------
  193.                          ISC data members.
  194. ----------------------------------------------------------------------------
  195.  
  196.  ■* There are 2 data members of major importance - int_num and old_vect;
  197.  
  198.   both must not be changed (since deactivate uses them to recover the state
  199. of the interrupt as it was before ISC was used.
  200.  
  201.    int_num - contains the number of the interrupt hook.
  202.  
  203.    old_vect - is a pointer to the function that was the previous interrupt
  204. vector. It can be called - by -> old_vect();
  205.              DO NOT CALL IT WITH PARAMETERS!!!!
  206.   To get the registers to be as they were use PSEUDO VARIABLE (_AX, _BX...)
  207. or call the vector in some alternative way!!!
  208.    Beware of changing _BP (will demolish automatic parameter referencing),
  209.    and _DS (will demolish static parameter referencing).
  210.  
  211.  *■ There are 3 static data members that refer to the hardware stack frame:-
  212.  
  213.    StackFrame- points to the actual stack frame.
  214.  
  215.    StackFrameLen- contains the current stack frame length.
  216.  
  217.    ISCcount- holds the number of ISC objects that currently exist in the
  218. system.
  219.  
  220. ----------------------------------------------------------------------------
  221.                               EXAMPLES
  222. ----------------------------------------------------------------------------
  223.  ■ There are 4 examples:-
  224.  
  225.  ■■ EXAMPLE1:- is a resident that keeps a timer tick watcher on screen (by
  226.     incrementing the first char on the top left of the screen once every timer
  227.     tick). Also, it keeps a keyboard interrupt watcher right next to it. This
  228.     example shows how to make an ISC derivative- how to check if already
  229.     resident. How to use 2 ISCs together...
  230.  
  231.  ■■ EXAMPLE2:- is an example of a software interrupt - it is a software
  232.     interrupt that beeps with a length and pitch which are passed as register
  233.     parameters. The main routine will test it and verify that it had not
  234.     failed through return values (also through register as well as flags).
  235.  
  236.     ** - when using ISC classes on automatic (local vars) rememeber:- NOT ALL
  237.     COMPILERS call DESTRUCTORS for automatic vars if exit() or do-alike funcs
  238.     (like abort()) run (they simply do not call the destructors), so that loca
  239.     ISC vars might not be freed and the interrupt will stay hooked, resulting
  240.     in a crash in most cases). So, using stack ISC (or derivitives) is ill
  241.     advised unless you know what you're doing...
  242.  
  243.  ■■ EXAMPLE3:- is a more complex example of a class that has to do a lot of
  244.   processing (each one taking longer than the timer tick interval).
  245.   it slows the computer down (so <mark> before running it).
  246.  
  247.  ■■ EXAMPLE4:- sends a novell look alike "send" message onto the screen (which
  248.   stops the forground and waits for the user to free it). Pretty annonying
  249.   program, so <mark> it before running.
  250.  
  251. ----------------------------------------------------------------------------
  252.                      MORE DIRECTORIES:- an overview
  253. ----------------------------------------------------------------------------
  254.  
  255.  ■ Also included are some more files and directories:-
  256.  
  257.  ■■ ISC :- This directory contains all that you need in order to work with
  258.     ISC. (Include ISC.cpp and ISCSERVE.asm into your project and #include
  259.          ISC.h in your source files).
  260.  
  261.  ■■ KBD :- keyboard hooking. example can be found in DOSFREE/EXAMPLE.
  262.  
  263.  ■■ DOSFREE :- allows you to execute dos functions (except 0-ch meaning that
  264.     line input through scanf is forbidden) - such as opening a file and reading
  265.     writing or deleting it.
  266.     ■■■ an example can be found that hooks a keyboard (via the kbd class),
  267.       and snap a shot from the screen into a file called snap.dat in the local
  268.       directory. The example program (called snap) is a parellel to a snap
  269.       program that is found in the "DOS ENCYLOPEDIA" from Microsoft press.
  270.       The hotkey for this program is SHIFT-TAB.
  271.  
  272.  ■■ SERIAL :- Some more advanced ISC derivative classes that handle interrupt
  273.     driven serial and modem communications. Although ISC has changed in the
  274.     past year - no changes have been made to these sources. Previously these
  275.     sources were distributed under XSERIAL.arj and XSERIAL1.arj. Also included
  276.     is a sample of a Buffer class I used that a colleague of mine wrote...
  277.  
  278.     ■■■ there are two examples in serial- RECEIVE and TRANSMIT:- RECEIVE
  279.       will set COM1 to 9600baud, 8bytes, 1stopbit, No parity- and put on the
  280.       screen anything that comes in from the port. The program will stop if
  281.       a key is typed in, as well as if the string "hello there!!!" is entered
  282.       from the com port.
  283.       TRANSMIT will transmit the string "hello there!!!" to com1 (same port
  284.       settings as receive), wait until the string is completely sent and exit.
  285.  
  286.     These classes works great in TSRs (that's what I use it for).
  287.  
  288. ----------------------------------------------------------------------------
  289.                                KBD
  290. ----------------------------------------------------------------------------
  291.  
  292.   This class makes hooking into keyboard hotkeys very easy.
  293.  
  294. ■ Constructor:-
  295.   KBD(unsigned char scan_code, unsigned char controls= 0, int kill_key= 1);
  296.   first parameter is the hot-key itself (KB_A is the letter A , etc.).
  297.   the hot-key's shift state (ALT/CTRL/SHIFT) is found in controls. The control
  298.   codes start with KBS (KBS_LSHIFT, etc.). For Ctrl-Alt-A you would pass
  299.   KB_A as the scan_code, KBS_CTRL| KBS_ALT as the controls parameter. The
  300.   third parameter is kill_key. To kill the key is to make the hot-key not
  301.   visible to the forground app. The default is 1 (meaning make the hot-key
  302.   invisible to forground).
  303.  
  304. ■ To hook a hotkey, just derive from KBD and overload the virtual function
  305.   hotkey. This function gets called if the hotkey matches.
  306.  
  307. ■■ An example is joined with DOSFREE (take a look at DOSFREE's example).
  308.  
  309. ----------------------------------------------------------------------------
  310.                                DOSFREE
  311. ----------------------------------------------------------------------------
  312.   This class allows using DOS functions inside your TSRs in an easy manner.
  313.  
  314. ■ Go - call this function when you want your app to run (use this instead of
  315.   calling AppFunc directly.
  316.  
  317. ■ AppFunc - overload this function (by deriving to DOSFREE), this function is
  318.   called when it is safe to use dos. Call this function using Go. Do not use
  319.   int21h funcs 0-0ch within this function.
  320.  
  321. ■■ There is an example of DOSFREE in directory examples. The example uses
  322.   the KBD class to hook a hotkey, and DOSFREE to photograph the screen and
  323.   save it into a file. The hotkey for this program is SHIFT-TAB. (Window's
  324.   users beware..).
  325.  
  326. ----------------------------------------------------------------------------
  327.                              SERIAL CLASSES
  328. ----------------------------------------------------------------------------
  329.  These classes are 3:- SERIAL_PORT, XONOFF, MODEM.
  330.  
  331.  ■ To use serial port comunications you need only know the following:-
  332.    create a serial port with serial port num. as constructor param (1 is
  333.    com1, 1-4 are allowed in this way). For compatible systems, a diffrent
  334.    constructor is provided that allows changing every param in the serial
  335.    port. If you prefer changing/ setting the com port on a later occasion
  336.    use activate with com num param. To set the serial port's communication
  337.    parameters use function-
  338.  
  339.        void set_up_port(const long baud_rate,const BYTE word_len,
  340.                         const BYTE parity, const BYTE stop_bits);
  341.  
  342.   for example:- com1.set_up_port(9600, 8, 'N', 1) sets up com1 object
  343.    with a 9600 baud rate, 8 bits, no parity, and 1 stop bit.
  344.  
  345.   to read from that object use com1>> my_char (my_char is an unsigned char).
  346.   to write to that object use  com1<< my_char  (ditto).
  347.  
  348.   to peek at the next char that arrived without pulling it from the buffer use:
  349.     com1> my_peek_char
  350.  
  351. ■ MODEM, XONOFF adhere to the same principles but have additional functions
  352.   and will also handle the flow control (outgoing only).
  353.  
  354. ■ The BUFF class is a buffer class that adheres to the same I/O operators,
  355.   and can be used as FIFO, or as an array (however the user wishes). This
  356.   class was jointly designed and written with my colleague- Ram Machness,
  357.   god bless him (;-D).
  358.  
  359. ----------------------------------------------------------------------------
  360.                               NOTE
  361. ----------------------------------------------------------------------------
  362.  ■ If you need to hook with ISC to a software interrupt like int13h or int21h
  363.    don't forget that when you call { old_vect() } you must set the correct
  364.    registers to what they were after the isr was called (these register values
  365.    are in the IREGS parameter passed to isr). Usually the pseudo variables
  366.    _AX, _BX, _FLAGS, etc... will do just fine. Also remember that the values
  367.    of the registers after the software interrupts are called might be needed
  368.    by the forground too (so you can put them back into the IREGS parameter).
  369.    WARNING- if you do not do these things you will probably either crash the
  370.    forground or mash things up. You may encounter problems using BP and DS
  371.    in the interrupt (SO HOOKING INT21 is out of the question).
  372.  
  373.  ■ Use and abuse!!!
  374. ----------------------------------------------------------------------------
  375.                       --> THE BOTTOM LINE <--
  376. ----------------------------------------------------------------------------
  377.  
  378.  ■■ since I am quite poor and FOOBAR, this and previous versions of ISC have
  379.  now been declared ShareWare. What this means to you - user is that you get
  380.  my support upon problems (Email or textmail), but you need to pay a cheap
  381.  little sum of money - which is $30 bucks cheap (larger donations also
  382.  accepted).
  383.  
  384.  You may still change the code without putting my name in it!!! But please
  385.  pay up so that even more wonderful versions of ISC and derived classes
  386.  can reach the PD market safely...
  387.  
  388.  registered users will receive some more lovely classes that I will not
  389.  include in the PD ver. of ISC!!!
  390.  
  391.                     SO - PAY UP!!!!
  392.  
  393.   +++++
  394.   |_ -|             Ofer Laor (AKA LeucroTTa)
  395.  @|o O|@            27 KKL St., Kiriat Bialik (27000)
  396.   | ^ |             Israel.
  397.   |---|             telephone @ work (972) - 3 - 9684643
  398.     -                         @ home (972) - 4 - 701845
  399.                     EMail:- s5919325@techst02.technion.ac.il
  400.  
  401.