home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mega CD-ROM 1
/
megacd_rom_1.zip
/
megacd_rom_1
/
MAGAZINE
/
DDJMAG
/
DDJ9104.ZIP
/
C_PROG.ASC
< prev
next >
Wrap
Text File
|
1991-03-15
|
7KB
|
248 lines
_C PROGRAMMING COLUMN_
by Al Stevens
[LISTING ONE]
/* --------- tsr.c --------- */
/*
* A Terminate and Stay Resident (TSR) engine
*/
#include <dos.h>
#include <stdlib.h>
#include <stdio.h>
#include "mouse.h"
#include "keys.h"
void tsr_program(void);
#define KEYMASK 8
#define SCANCODE 52
extern unsigned _stklen = 1024;
extern unsigned _heaplen = 8192;
/* ------- the interrupt function registers -------- */
typedef struct {
int bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,fl;
} IREGS;
/* --- vectors ---- */
#define DISK 0x13
#define CTRLBRK 0x1b
#define INT28 0x28
#define CRIT 0x24
#define CTRLC 0x23
#define TIMER 8
#define KYBRD 9
#define DOS 0x21
unsigned highmemory;
/* ------ interrupt vector chains ------ */
static void (interrupt *oldtimer)(void);
static void (interrupt *old28)(void);
static void (interrupt *oldkb)(void);
static void (interrupt *olddisk)(void);
/* ------ ISRs for the TSR ------- */
static void interrupt newtimer(void);
static void interrupt new28(void);
static void interrupt newdisk(IREGS);
static void interrupt newkb(void);
static void interrupt newcrit(IREGS);
static void interrupt newbreak(void);
static unsigned sizeprogram; /* TSR's program size */
unsigned dossegmnt; /* DOS segment address */
unsigned dosbusy; /* offset to InDOS flag */
static int diskflag; /* Disk BIOS busy flag */
unsigned mcbseg; /* address of 1st DOS mcb */
static char far *mydta; /* TSR's DTA */
int hotkeyhit = FALSE;
int tsrss; /* TSR's stack segment */
int tsrsp; /* TSR's stack pointer */
/* -------------- context for the popup ---------------- */
unsigned intpsp; /* Interrupted PSP address */
int running; /* TSR running indicator */
char far *intdta; /* interrupted DTA */
unsigned intsp; /* " stack pointer */
unsigned intss; /* " stack segment */
unsigned ctrl_break; /* Ctrl-Break setting */
void (interrupt *oldcrit)(void);
void (interrupt *oldbreak)(void);
void (interrupt *oldctrlc)(void);
/* ------- local prototypes -------- */
static void resident_psp(void);
static void interrupted_psp(void);
static void popup(void);
void main(void)
{
unsigned es, bx;
/* ---------- compute memory parameters ------------ */
highmemory = _SS + ((_SP + 256) / 16);
/* ------ get address of DOS busy flag ---- */
_AH = 0x34;
geninterrupt(DOS);
dossegmnt = _ES;
dosbusy = _BX;
/* ---- get the seg addr of 1st DOS MCB ---- */
_AH = 0x52;
geninterrupt(DOS);
es = _ES;
bx = _BX;
mcbseg = peek(es, bx-2);
/* ----- get address of resident program's dta ----- */
mydta = getdta();
/* ------------ prepare for residence ------------ */
tsrss = _SS;
tsrsp = _SP;
oldtimer = getvect(TIMER);
old28 = getvect(INT28);
oldkb = getvect(KYBRD);
olddisk = getvect(DISK);
/* ----- attach vectors to resident program ----- */
setvect(KYBRD, newkb);
setvect(INT28, new28);
setvect(DISK, newdisk);
setvect(TIMER, newtimer);
/* ------ compute program size ------- */
sizeprogram = highmemory - _psp + 1;
/* ----- terminate and stay resident ------- */
_DX = sizeprogram;
_AX = 0x3100;
geninterrupt(DOS);
}
/* ---------- break handler ------------ */
static void interrupt newbreak(void)
{
return;
}
/* -------- critical error ISR ---------- */
static void interrupt newcrit(IREGS ir)
{
ir.ax = 0; /* ignore critical errors */
}
/* ------ BIOS disk functions ISR ------- */
static void interrupt newdisk(IREGS ir)
{
diskflag++;
(*olddisk)();
ir.ax = _AX; /* for the register returns */
ir.cx = _CX;
ir.dx = _DX;
ir.es = _ES;
ir.di = _DI;
ir.fl = _FLAGS;
--diskflag;
}
/* ----- keyboard ISR ------ */
static void interrupt newkb(void)
{
static unsigned char kbval;
kbval = inportb(0x60);
if (!hotkeyhit && !running)
if ((peekb(0, 0x417) & 0xf) == KEYMASK)
if (SCANCODE == kbval) {
hotkeyhit = TRUE;
/* --- reset the keyboard ---- */
kbval = inportb(0x61);
outportb(0x61, kbval | 0x80);
outportb(0x61, kbval);
outportb(0x20, 0x20);
return;
}
(*oldkb)();
}
/* ----- timer ISR ------- */
static void interrupt newtimer(void)
{
(*oldtimer)();
if (hotkeyhit && (peekb(dossegmnt, dosbusy) == 0) &&
!diskflag)
popup();
}
/* ----- 0x28 ISR -------- */
static void interrupt new28(void)
{
(*old28)();
if (hotkeyhit)
popup();
}
/* ------ switch psp context from interrupted to TSR ----- */
static void resident_psp(void)
{
intpsp = getpsp();
_AH = 0x50;
_BX = _psp;
geninterrupt(DOS);
}
/* ---- switch psp context from TSR to interrupted ---- */
static void interrupted_psp(void)
{
_BX = intpsp;
_AH = 0x50;
geninterrupt(DOS);
}
/* ------ execute the resident program ------- */
static void popup(void)
{
running = TRUE;
hotkeyhit = FALSE;
intsp = _SP;
intss = _SS;
_SP = tsrsp;
_SS = tsrss;
oldcrit = getvect(CRIT); /* redirect critical err */
oldbreak = getvect(CTRLBRK);
oldctrlc = getvect(CTRLC);
setvect(CRIT, newcrit);
setvect(CTRLBRK, newbreak);
setvect(CTRLC, newbreak);
ctrl_break = getcbrk(); /* get ctrl break setting */
setcbrk(0); /* turn off ctrl break */
intdta = getdta(); /* get interrupted dta */
setdta(mydta); /* set resident dta */
resident_psp(); /* swap psps */
intercept_mouse(); /* intercept the mouse */
/* ------ save the video cursor configuration ------- */
savecursor();
normalcursor();
unhidecursor();
enable();
tsr_program(); /* call the TSR C program */
disable();
/* ----- restore the video cursor configuration ----- */
restorecursor();
restore_mouse(); /* restore the mouse */
interrupted_psp(); /* reset interrupted psp */
setdta(intdta); /* reset interrupted dta */
setvect(CRIT, oldcrit); /* reset critical error */
setvect(CTRLBRK, oldbreak);
setvect(CTRLC, oldctrlc);
setcbrk(ctrl_break); /* reset ctrl break */
disable();
_SP = intsp; /* reset interrupted stack*/
_SS = intss;
running = FALSE; /* reset semaphore */
}