Category : Files from Magazines
Archive   : TSRPLUS.ZIP
Filename : TSR.C

 
Output of file : TSR.C contained in archive : TSRPLUS.ZIP

/* --------- tsr.c --------- */

/*
* The Turbo C Terminate and Stay Resident (TSR) engine
* The resident part of the code
*/

#define EXTERNS
#include "tsr.h"

/* ------- prototypes -------- */
static void resident_psp(void);
static void interrupted_psp(void);
static void gateway(void);
static void readfile(unsigned, unsigned);
static void writefile(unsigned, unsigned);

/* ---------- TSRPLUSINT (0x2f) communications vector ISR ----------- */
void interrupt int2f(IREGS ir)
{
struct swap_header far *sw = MK_FP(ir.es,ir.bx);
int function = ir.ax & 0xff;

ir.ax = 0;
switch (function) {
case ISLOADED:
/* ---- test for TSRPLUS loaded ---- */
ir.ax = 0xff;
break;
case REGISTER:
/* ----- register a TSR ----- */
if (registered) {
swap.Scancode = sw->Scancode;
swap.Keymask = sw->Keymask;
ir.ax = -1;
break;
}
ir.ax = register_tsr(sw);
break;
case UNLOAD:
/* ------- unload tsrplus ------- */
unloading = 1;
break;
default:
ir.ax = -1;
break;
}
}

/* ---------- 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)
{
unsigned char kbval = inportb(0x60);
if (!hotkeyhit && !running) {
if (swap.Keymask && (peekb(0, 0x417) & 0xf) == swap.Keymask)
if (swap.Scancode == 0 || swap.Scancode == kbval)
hotkeyhit = TRUE;
if (hotkeyhit) {
/* --- 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 && !isinvideo())
gateway();
}

/* ----- 0x28 ISR -------- */
static void interrupt new28(void)
{
(*old28)();
if (hotkeyhit)
gateway();
}

/* --------- intercepted mouse ISR ----------- */
static void interrupt MouseISR(void)
{
outportb(0x20, 0x20);
}

/* ------ switch psp context from interrupted to TSR ----- */
static void resident_psp(void)
{
_AH = 0x51;
geninterrupt(DOS);
intpsp = _BX;
_BX = _psp;
_AH = 0x50;
geninterrupt(DOS);
}

/* ---- switch psp context from TSR to interrupted ---- */
static void interrupted_psp(void)
{
_BX = intpsp;
_AH = 0x50;
geninterrupt(DOS);
}

/* --------- test if OK to unload --------- */
BOOL OKtoUnload(void)
{
/* ---- test if vectors are the same as when hooked ---- */
struct vectors *vc = vectors;
unsigned seg = _psp;
unsigned sz = peek(seg-1, 3);

/* ---- test if any MCB is above the TSR ---- */
if (peekb(seg+sz, 0) != 0x5a)
return FALSE;
while (vc->vno) {
if (getvect(vc->vno) != vc->newvect)
return FALSE;
vc++;
}
return TRUE;
}

/* ------ execute the resident program ------- */
static void gateway(void)
{
if (!running) {
running = TRUE;
hotkeyhit = FALSE;
intsp = _SP;
intss = _SS;
_SP = tsrsp;
_SS = tsrss;
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 */

swaperror = FALSE;
/* ----- swap TPA memory for TSR memory ------ */
openswaps();
writecode(1);
writevectors(1);
readvectors(0);

_ES = _DS;
_DX = (unsigned) MouseState;
_CX = 0;
_BX = 0;
_AX = 22;
geninterrupt(MOUSE);

if (MouseSegment > _CS && MouseSegment < 0xa000 &&
MouseIRQ > 9 && MouseIRQ < 16)
setvect(MouseIRQ, MouseISR);

readcode(0);

WaitingSize = peek(_psp-1, 3);
poke(_psp-1, 3, RunningSize);

if (!swaperror) {
/* --------- execute the TSR ------------ */
enable();
(*swap.startptr)();
disable();
}

poke(_psp-1, 3, WaitingSize);

/* ------ swap the TPA memory back in -------- */
readcode(1);
readvectors(1);
closeswaps();

_ES = _DS;
_DX = (unsigned) MouseState;
_CX = 0;
_BX = 0;
_AX = 23;
geninterrupt(MOUSE);

interrupted_psp(); /* reset interrupted psp */
setdta(intdta); /* reset interrupted dta */
setcbrk(ctrl_break); /* reset ctrl break */
if (unloading) { /* if TSR set the unload flag */
if (OKtoUnload())
resterm(TRUE);
else
/* ------ cannot unload at this time ------ */
unloading = FALSE;
}
_SP = intsp; /* reset interrupted stack */
_SS = intss;
running = FALSE; /* reset TSR running semaphore */
}
}

/* ------- TSR unload function ----------- */
void resterm(int freeup)
{
resident_psp();
if (emmhandle)
emm_release(emmhandle-1);
else if (xmshandle)
xms_free(xmshandle);
else
unlink(SwapPath);
/* ----- restore the interrupt vectors ----- */
oldvectors(vectors);
interrupted_psp();
if (freeup) {
freemem(peek(_psp, 0x2c));
freemem(_psp);
}
}

/* ------- set up EMM or disk for swapping --------- */
void openswaps(void)
{
if (emmhandle)
emm_savecontext(emmhandle-1);
else if (!xmshandle)
if ((diskhandle = _open(SwapPath, O_RDWR)) == -1)
swaperror = TRUE;
}

/* ---- restore EMM mapping context or close disk after TSR is done ---- */
void closeswaps(void)
{
if (emmhandle)
emm_restorecontext(emmhandle-1);
else if (diskhandle)
_close(diskhandle);
}

/* ---------- swap vectors between XMS/EMM/swapfile and 0:0 -------- */
void swapvectors(BOOL wh, BOOL dir)
{
unsigned offset = wh ? 1024 : 0;
disable();
if (xmshandle) {
if (dir)
copy_xmstoconv(xmshandle, 0, offset, 1024);
else
copy_convtoxms(xmshandle, 0, offset, 1024);
}
else if (emmhandle) {
emm_map(1, 0, 0, emmhandle-1);
if (dir)
movedata(frame, offset, 0, 0, 1024);
else
movedata(0, 0, frame, offset, 1024);
}
else {
if (lseek(diskhandle, offset, SEEK_SET) == -1)
swaperror = TRUE;
else {
if (dir)
readfile(0, 1024);
else
writefile(0, 1024);
}
}
enable();
}

/* ---------- swap code between XMS/EMM/swapfile and TPA -------- */
void swapcode(BOOL wh, BOOL dir)
{
unsigned codeseg;
long seekadr;
long swapsize;

if (wh) {
if (dir == 0)
swapsize = TPAlength = allocsize();
else
swapsize = TPAlength;
}
else
swapsize = length;
swapsize *= 16;

if (swapsize == 0)
return;

/* ------- compute position of swap data in swap file ------ */
seekadr = (long) length * 16 * wh + 2048;
codeseg = highmemory;

disable();
if (emmhandle) {
int logpg, frameaddr;
logpg = (int) (seekadr / 16384);
frameaddr = (int) (seekadr % 16384);

while (swapsize > 0) {
unsigned len;

if (swapsize < 16384)
len = (unsigned) swapsize;
else
len = 16384;
if (frameaddr)
len = 16384 - frameaddr;
emm_map(1, 0, logpg++, emmhandle-1);
if (dir)
movedata(frame, frameaddr, codeseg, 0, len);
else
movedata(codeseg, 0, frame, frameaddr, len);
codeseg += len / 16;
swapsize -= len;
frameaddr = 0;
}
}
else if (diskhandle) {
unsigned len;
if (lseek(diskhandle, seekadr, SEEK_SET) == -1) {
swaperror = TRUE;
return;
}
while (swapsize > 0) {
if (swapsize < 32768U)
len = (unsigned) swapsize;
else
len = 32768U;
if (dir)
readfile(codeseg, len);
else
writefile(codeseg, len);
codeseg += 2048;
swapsize -= len;
}
}
else {
long len;
while (swapsize > 0) {
if (swapsize < 65536L)
len = swapsize;
else
len = 65536L;
if (dir)
copy_xmstoconv(xmshandle, codeseg, seekadr, len);
else
copy_convtoxms(xmshandle, codeseg, seekadr, len);
seekadr += 65536L;
codeseg += 4096;
swapsize -= len;
}
}
enable();
}

/* ----------- read a swap file record ------------- */
static void readfile(unsigned seg, unsigned len)
{
unsigned holdds = _DS;
_AH = 0x3f;
_CX = len;
_BX = diskhandle;
_DX = 0;
_DS = seg;
geninterrupt(DOS);
_DS = holdds;
swaperror = _AX - len != 0;
}

/* ----------- write a swap file record ------------- */
static void writefile(unsigned seg, unsigned len)
{
unsigned holdds = _DS;
_AH = 0x40;
_CX = len;
_BX = diskhandle;
_DX = 0;
_DS = seg;
geninterrupt(DOS);
_DS = holdds;
swaperror = _AX - len != 0;
}

/* ---- Compute to the end of the MCB chain ---- */
unsigned allocsize(void)
{
unsigned len, owner, dif;
unsigned mcbs = _psp-1;
unsigned size = 0;
while (peekb(mcbs, 0) == 0x4d)
mcbs += peek(mcbs, 3) + 1;
len = peek(mcbs, 3);
owner = peek(mcbs, 1);
if (highmemory <= mcbs) {
size = mcbs-highmemory+1;
if (owner > _psp)
size += len;
}
else if (owner > _psp) {
dif = highmemory-mcbs;
if (len > dif)
size = len-dif;
}
return size;
}