home *** CD-ROM | disk | FTP | other *** search
- /* -------- Listing 1 - tsr.h --------- */
- void resinit(void);
- void resident_psp(void);
- void interrupted_psp(void);
- int resident(char *);
- void terminate(void);
- void restart(void);
- void suspend(void);
- int get_char(void);
- void popup(void);
- void openfiles(void);
- void closefiles(void);
- void vpoke(unsigned, unsigned, unsigned);
- unsigned vpeek(unsigned, unsigned);
- int keyrdy(void);
- unsigned getsp(void);
- unsigned peek(unsigned, unsigned);
- char peekb(unsigned, unsigned);
- void poke(unsigned, unsigned, unsigned);
- int keyhit(void);
-
-
-
- /* ---------- Listing 2 - tsr.c ---------- */
- #include <dos.h>
- #include <stdio.h>
- #include <string.h>
- #include <bios.h>
- #include "tsr.h"
- static union REGS rg;
- static struct SREGS sg;
- /* -------- modify this for each TSR ------------ */
- unsigned heaplen = 128; /* heap length */
- unsigned scancode = 52; /* (Period) HOT KEY SCAN CODE */
- unsigned keymask = 8; /* (Alt) HOT KEY STATUS MASK */
- char signature [] = "CLOCK"; /* TSR SIGNATURE */
- void main(void);
- /* --------- main function for the TSR program ------- */
- void main()
- {
- int r;
- if ((r = resident(signature)) == 0) {
- printf("\nResident clock is loaded");
- openfiles();
- resinit();
- }
- printf("\nClock is %s", (r == 1 ? "already resident" : "restarted"));
- }
- /* ------------- get a keyboard character ---------------- */
- int get_char()
- {
- int c;
- while (keyhit() == 0)
- ;
- c = _bios_keybrd(_KEYBRD_READ);è return ((c&0xff)==0) ? (((c>>8)&0xff)|128) : (c&0xff);
- }
- /* ------- set the Disk Transfer Address ---------- */
- void setdta(char far *dta)
- {
- rg.h.ah = 0x1a;
- rg.x.dx = FP_OFF(dta);
- sg.ds = FP_SEG(dta);
- int86x(0x21, &rg, &rg, &sg);
- }
- /* ------- get the Disk Transfer Address ---------- */
- char far *getdta(void)
- {
- static char far *dta;
- rg.h.ah = 0x2f;
- int86x(0x21, &rg, &rg, &sg);
- FP_SEG(dta) = sg.es;
- FP_OFF(dta) = rg.x.bx;
- return dta;
- }
- /* ----- peek, peekb, poke --------- */
- unsigned peek(unsigned s, unsigned o)
- {
- static unsigned far *ip;
- FP_SEG(ip) = s;
- FP_OFF(ip) = o;
- return *ip;
- }
- char peekb(unsigned s, unsigned o)
- {
- static char far *ip;
- FP_SEG(ip) = s;
- FP_OFF(ip) = o;
- return *ip;
- }
- void poke(unsigned s, unsigned o, unsigned c)
- {
- static unsigned far *ip;
- FP_SEG(ip) = s;
- FP_OFF(ip) = o;
- *ip = c;
- }
-
- /* -------- Listing 3 - resident.c --------- */
- #include <dos.h>
- #include <conio.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <malloc.h>
- #include "tsr.h"
- #pragma intrinsic (inp, outp)
- char far *getdta(void);
- void setdta(char far *);
- static union REGS rg;
- static struct SREGS seg;è/* --- vectors ---- */
- #define KEYBD 9
- #define VIDEO 0x10
- #define TIMER 0x1c
- #define DISK 0x13
- #define ZERODIV 0
- #define INT28 0x28
- #define CRIT 0x24
- #define CTRLC 0x23
- #define CTRLBRK 0x1b
- /* ------ interrupt vector chains ------ */
- static void (interrupt far *oldbreak)(void);
- static void (interrupt far *oldctrlc)(void);
- static void (interrupt far *oldtimer)(void);
- static void (interrupt far *old28)(void);
- static void (interrupt far *oldkb)(void);
- static void (interrupt far *oldcrit)(void);
- void (interrupt far *olddisk)(void);
- void (interrupt far *oldvideo)(void);
- /* ------ ISRs for the TSR ------- */
- static void interrupt far newtimer(void);
- static void interrupt far new28(void);
- static void interrupt far newkb(void);
- static void interrupt far newcrit(int,int,int,int,int,int,int,int,int,int);
- static void interrupt far newbreak(void);
- extern void interrupt far newdisk(void);
- extern void interrupt far newvideo(void);
-
- extern unsigned heaplen; /* TSR's heap size */
- static unsigned sizeprogram; /* TSR's program size */
- static unsigned dosseg; /* DOS segment address */
- static char far *dosbusy; /* points to InDOS flag */
- static char far *mydta; /* TSR's DTA */
- static unsigned intpsp; /* Interrupted PSP address */
- static unsigned far *psps[2]; /* Table of DOS PSP addresses */
- static int pspctr; /* # of DOS PSP addresses */
- static int popflg; /* Hot key pressed flag */
- unsigned myss; /* TSR's stack segment */
- unsigned stack; /* TSR's stack pointer */
- int suspending; /* suspend/resume flag */
- int terminating; /* terminate flag */
- int diskflag; /* Disk BIOS busy flag */
- int videoflag; /* Video BIOS busy flag */
- /* ------- local prototypes -------- */
- static void resterm(void);
- static void pspaddr(void);
- void dores(void);
- void _ctermsub(void);
- void popup_tsr(void);
- /* -------- establish & declare residency --------- */
- void resinit()
- {
- /* ------ save TSR stack pointer ------- */
- stack = getsp();
- segread(&seg);è myss = seg.ss;
- /* ------ get address of DOS busy flag ---- */
- rg.h.ah = 0x34;
- int86x(0x21, &rg, &rg, &seg);
- dosseg = seg.es;
- FP_SEG(dosbusy) = seg.es;
- FP_OFF(dosbusy) = rg.x.bx;
- /* ----- get address of resident program's dta ----- */
- mydta = getdta();
- /* -------- get addresses of PSP in DOS ------- */
- pspaddr();
- /* ----- get original interrupt vectors ----- */
- oldtimer = _dos_getvect(TIMER);
- old28 = _dos_getvect(INT28);
- oldkb = _dos_getvect(KEYBD);
- olddisk = _dos_getvect(DISK);
- oldvideo = _dos_getvect(VIDEO);
- /* ----- attach vectors to resident program ----- */
- _dos_setvect(TIMER, newtimer);
- _dos_setvect(INT28, new28);
- _dos_setvect(KEYBD, newkb);
- _dos_setvect(DISK, newdisk);
- _dos_setvect(VIDEO, newvideo);
- /* ------ compute program size ------- */
- sizeprogram = heaplen/16 + ((myss + (stack+50) / 16) - _psp);
- /* ---- restore zero divide interrupt vector --- */
- _ctermsub();
- /* ----- terminate and stay resident ------- */
- _dos_keep(0, sizeprogram);
- }
- /* ---------- break handler ------------ */
- static void interrupt far newbreak()
- { return; }
- /* -------- critical error ISR ---------- */
- static void interrupt far newcrit(es,ds,di,si,bp,sp,bx,dx,cx,ax)
- { ax = 0; }
- static int kbval;
- static char far *kmask = (char far *) 0x417;
- /* ----- keyboard ISR ------ */
- static void interrupt far newkb()
- {
- extern unsigned scancode, keymask, running;
- if (scancode && inp(0x60) == scancode) {
- kbval = *kmask & keymask;
- if (!suspending && kbval == keymask) {
- /* --- reset the keyboard ---- */
- kbval = inp(0x61);
- outp(0x61, kbval | 0x80);
- outp(0x61, kbval);
- outp(0x20, 0x20);
- /* ---- set hotkey indicator ---- */
- if (!running)
- popflg = 1;
- return;
- }è }
- (*oldkb)();
- }
- /* ----- timer ISR ------- */
- static void interrupt far newtimer()
- {
- extern unsigned scancode, keymask, running;
- (*oldtimer)();
- if (!scancode) {
- kbval = *kmask & keymask;
- if (!suspending && kbval == keymask)
- if (!running)
- popflg = 1;
- }
- if (popflg && *dosbusy == 0)
- if (diskflag == 0 && videoflag == 0) {
- outp(0x20, 0x20);
- popflg = 0;
- dores();
- }
- }
- /* ----- INT28 ISR -------- */
- static void interrupt far new28()
- {
- (*old28)();
- if (popflg && *dosbusy != 0) {
- popflg = 0;
- dores();
- }
- }
- /* ------ switch psp context from interrupted to TSR ----- */
- void resident_psp()
- {
- int pp;
- intpsp = *psps[0]; /* save interrupted program's psp */
- for (pp = 0; pp < pspctr; pp++) /* set resident program's psp */
- *psps [pp] = _psp;
- }
- /* ---- switch psp context from TSR to interrupted ---- */
- void interrupted_psp()
- {
- int pp;
- for (pp = 0; pp < pspctr; pp++) /* reset interrupted program's psp */
- *psps [pp] = intpsp;
- }
- void popup_tsr()
- {
- static char far *intdta; /* interrupted DTA */
- static unsigned intsp, intss; /* " stack */
- static unsigned char ctrl_break; /* Ctrl-Break setting */
- oldcrit = _dos_getvect(CRIT);/* redirect critical error */
- oldbreak = _dos_getvect(CTRLBRK);
- oldctrlc = _dos_getvect(CTRLC);
- _dos_setvect(CRIT, newcrit);
- _dos_setvect(CTRLBRK, newbreak);è _dos_setvect(CTRLC, newbreak);
- rg.x.ax = 0x3300; /* get ctrl break setting */
- int86(0x21, &rg, &rg);
- ctrl_break = rg.h.dl;
- rg.x.ax = 0x3301; /* turn off ctrl break logic */
- rg.h.dl = 0;
- int86(0x21, &rg, &rg);
- intdta = getdta(); /* get interrupted dta */
- setdta(mydta); /* set resident dta */
- resident_psp(); /* swap psps */
- popup(); /* execute resident program */
- interrupted_psp(); /* reset interrupted psp */
- setdta(intdta); /* reset interrupted dta */
- _dos_setvect(CRIT, oldcrit); /* reset critical error*/
- _dos_setvect(CTRLBRK, oldbreak);
- _dos_setvect(CTRLC, oldctrlc);
- rg.x.ax = 0x3301; /* reset ctrl break */
- rg.h.dl = ctrl_break;
- int86(0x21, &rg, &rg);
- if (terminating)
- terminate();
- }
- /* ------- test to see if the TSR is already resident ------- */
- int resident(signature)
- char *signature;
- {
- char *sg;
- unsigned df, mcbseg, blkseg;
- segread(&seg);
- df = seg.ds - _psp;
- rg.h.ah = 0x52; /* get the seg addr of 1st DOS MCB */
- intdosx(&rg, &rg, &seg);
- mcbseg = peek(seg.es, rg.x.bx-2);
- while (peekb(mcbseg, 0) == 0x4d) { /* walk thru chain, srch for TSR */
- blkseg = peek(mcbseg, 1);
- if (peek(blkseg, 0) == 0x20cd) {
- if (blkseg == _psp) /* this is a psp */
- break; /* if the transient copy */
- for (sg = signature; *sg; sg++)
- if (*sg!=peekb(blkseg+df,(unsigned)sg))
- break;
- if (!*sg) { /* if TSR is already resident */
- if (peek(blkseg+df, (unsigned) &suspending)) {
- poke(blkseg+df, (unsigned) &suspending, 0);
- return 2; /* unsuspend a suspended TSR */
- }
- return 1;
- }
- }
- mcbseg += peek(mcbseg, 3) + 1;
- }
- return 0;
- }
- /* -------- find address of PSP ---------- */
- static void pspaddr()è{
- unsigned adr = 0;
- unsigned enddos; /* offset to the end of DOS */
- static unsigned far *ed, far *ps;
- rg.h.ah = 0x52; /* find the end of the DOS segment */
- int86x(0x21, &rg, &rg, &seg);
- FP_SEG(ed) = seg.es;
- FP_OFF(ed) = rg.x.bx-2;
- enddos = *ed;
- while (pspctr < 2 && /* search for matches on the psp in dos */
- (unsigned)((dosseg<<4) + adr) < (enddos<<4)) {
- FP_SEG(ps) = dosseg;
- FP_OFF(ps) = adr;
- if (*ps == _psp) {
- rg.h.ah = 0x50;
- rg.x.bx = _psp + 1;
- int86(0x21, &rg, &rg);
- if (*ps == _psp+1)
- psps[pspctr++] = ps;
- rg.h.ah = 0x50; /* reset the original psp */
- rg.x.bx = _psp;
- int86(0x21, &rg, &rg);
- }
- adr++;
- }
- }
- /* ------- terminate function ----------- */
- static void resterm()
- {
- static unsigned far *env;
- closefiles(); /* close TSR files */
- _dos_setvect(TIMER, oldtimer); /* restore the interrupt vectors */
- _dos_setvect(INT28, old28);
- _dos_setvect(KEYBD, oldkb);
- _dos_setvect(DISK, olddisk);
- _dos_setvect(VIDEO, oldvideo);
- FP_SEG(env) = _psp; /* release memory owned by the TSR */
- FP_OFF(env) = 0x2c;
- _dos_freemem(*env);
- _dos_freemem(_psp);
- }
- /* --------- terminate the resident program --------- */
- void terminate()
- {
- if (_dos_getvect(VIDEO) == (void (interrupt far *)()) newvideo)
- if (_dos_getvect(DISK) == (void (interrupt far *)()) newdisk)
- if (_dos_getvect(KEYBD) == newkb)
- if (_dos_getvect(INT28) == new28)
- if (_dos_getvect(TIMER) == newtimer) {
- resterm();
- return;
- }
- terminating = 0; /* another TSR is above, suspend */
- suspending = 1;
- }è
- ;------------------- Listing 4 - tsrasm.asm ------------------------
- dosseg
- .model small
- .data
- public _running
- extrn _myss : word
- extrn _stack : word
- extrn _suspending : word
- extrn _olddisk : dword
- extrn _oldvideo : dword
- extrn _diskflag : word
- extrn _videoflag : word
- intss dw ?
- intsp dw ?
- _running db 0
- .code
- extrn _popup_tsr : near
- public _getsp
- ; -------- return the stack pointer
- ; stackpointer = getsp()
- ; ------------------------------------------
- _getsp proc near
- mov ax,sp
- ret
- _getsp endp
- public _keyhit
- ; ------- test for a keystroke, return 1 if key ready, 0 if not
- ; k = keyhit();
- ;--------------------------------------
- _keyhit proc near
- mov ah,1 ; BIOS read key status
- int 16h
- mov ah,1 ; in case of ctrl-break
- jnz keyret ; if a key is ready
- int 28h ; else, call int 28 to allow other TSRs in
- mov ax,0 ; and return false
- keyret: ret
- _keyhit endp
- public _dores
- ; -------- swap the stack and call the popup function
- _dores proc near
- cmp _suspending,0
- jne resret ; don't pop up if the TSR is suspended
- mov _running,1 ; prevent reentrant TSRs
- cli
- mov intss,ss ; save the interrupted stack
- mov intsp,sp
- mov ss,_myss ; set the TSR's stack
- mov sp,_stack
- sti
- call _popup_tsr ; pop up the TSR utility
- cli
- mov ss,intss ; restore the interrupted stack
- mov sp,intspè sti
- mov _running,0
- resret: ret
- _dores endp
- public _newdisk
- ;--------- 0x13 (disk) BIOS Interrupt Service Routine
- _newdisk proc far
- push ds
- push bp
- mov bp,dgroup ; set ds to TSR's data segment
- mov ds,bp
- inc _diskflag ; set disk in process flag
- pushf
- call _olddisk ; chain to old disk interrupt
- dec _diskflag ; reset disk in process flag
- pop bp
- pop ds
- ret 2 ; ret 2 passes on the flags
- _newdisk endp
- public _newvideo
- ;--------- 0x10 (video) BIOS Interrupt Service Routine
- _newvideo proc far
- push ds
- push bp
- mov bp,dgroup ; set ds to TSR's data segment
- mov ds,bp
- inc _videoflag ; set video in process flag
- pop bp ; some EGA functions use bp in
- pushf
- call _oldvideo ; chain to old video interrupt
- dec _videoflag ; reset video in process flag
- pop ds
- iret
- _newvideo endp
- public _vpoke
- ; -------- insert a word into video memory
- ; vpoke(unsigned vseg, unsigned adr, unsigned ch);
- ; ------------------------------------------
- _vpoke proc near
- push bp
- mov bp,sp
- push di
- push es
- mov cx,4[bp] ; video board base address
- mov es,cx
- mov di,6[bp] ; offset address from caller
- cmp cx,45056 ;mono?
- jz mono1
- mov dx,986 ; video status port address
- loop1: in al,dx ; wait for retrace to quit
- test al,1
- jnz loop1
- loop2: in al,dx ; wait for retrace to start
- test al,1
- jz loop2èmono1: mov ax,8[bp] ; word to insert
- stosw ; insert it
- pop es
- pop di
- pop bp
- ret
- _vpoke endp
- public _vpeek
- ; -------- retrieve a word from video memory
- ; unsigned vpeek(unsigned vseg, unsigned adr);
- ; ------------------------------------------
- _vpeek proc near
- push bp
- mov bp,sp
- push si
- push ds
- mov si,6[bp] ; offset address
- mov cx,4[bp] ; video board base address
- mov ds,cx
- cmp cx,45056 ;mono?
- jz mono2
- mov dx,986 ; video status port address
- loop3: in al,dx ; wait for retrace to stop
- test al,1
- jnz loop3
- loop4: in al,dx ; wait for retrace to start
- test al,1
- jz loop4
- mono2: lodsw ; get the word
- pop ds
- pop si
- pop bp
- ret
- _vpeek endp
- end
-
- /* ---------- Listing 5 - clock.c ------------ */
- #include <dos.h>
- #include <time.h>
- #include "tsr.h"
- #define VSG 0xb800 /* video memory segment (MDA=0xb000) */
- #define ROW 10 /* where the clock displays */
- #define COL 30
- #define vad(x,y) ((y)*160+(x)*2)
- extern int terminating, suspending;
- /* --- function called when TSR is popped up ----- */
- void popup()
- {
- int c, v;
- unsigned sv[24];
- char *tm;
- long tim;
- for (v = 0; v < 24; v++) /* save the video memory */
- sv[v] = vpeek(VSG, vad(COL+v, ROW));
- while (!keyhit()) { /* run until a key is pressed */è time(&tim); /* get the current date and time */
- tm = ctime(&tim); /* display the date and time */
- for (v = 0; v < 24; v++)
- vpoke(VSG, vad(COL+v, ROW), *(tm + v) | 0x7000);
- }
- terminating = ((c = get_char()) == 'u');
- suspending = (c == 's');
- /* -------- restore the video memory ---- */
- for (v = 0; v < 24; v++)
- vpoke(VSG, vad(COL+v, ROW), sv[v]);
- }
- /* --- null startup & shutdown functions --- */
- void openfiles() {}
- void closefiles() {}
-