?? tsr.cpp
字號:
{ if ((hotkey & ALT) != 0)
hotscan += ALT_FKEY;
else if ((hotkey & CTRL) != 0)
hotscan += CTRL_FKEY;
else if ((hotkey & (LSHIFT | RSHIFT)) != 0)
hotscan += SHIFT_FKEY;
}
// set length of timeslice
interval = timeslice;
nexttick = *timer + interval;
// perform user startup actions
if (instance->startup () != 0)
{ stat = STARTUP_ERR;
return;
}
// do TSR setup if hotkey or timeslice specified
if (hotkey != NONE || timeslice != 0)
{ if (setup() == 0)
{ stat = STACK_FAIL;
return;
}
}
// hook multiplex interrupt for self-identification
oldint2F = getvect (0x2F);
setvect (0x2F, Handler (TSRint2F));
// terminate and stay resident (exit status = 0), memory size taken
// from bytes 3 and 4 of arena header in paragraph preceding PSP.
keep (0, *(unsigned far*) MK_FP(_psp-1, 3));
// this line should never be reached
stat = LOAD_FAIL;
}
//--------------------------------------------------------------------------
//
// TSR::unload
//
// Unloads a previously loaded copy of the TSR from memory. The
// function returns 0 if the TSR was unloaded successfully, 1 if
// there is no previously loaded copy, and 2 if the previous copy
// cannot be unloaded. The TSR is invoked to unload itself using
// the multiplex interrupt (2F).
//
int TSR::unload ()
{
union REGS r;
struct SREGS s;
// call TSR to unload itself via multiplex interrupt
r.h.ah = TSRfunction, r.h.al = 1;
r.x.bx = FP_SEG (COPYRIGHT);
r.x.di = FP_OFF (COPYRIGHT);
s.es = FP_SEG (TSRname);
r.x.si = FP_OFF (TSRname);
int86x (0x2F, &r, &r, &s);
// exit if TSR is not loaded
if (compare ((char far*) MK_FP(s.es, r.x.si), COPYRIGHT) != 0)
return NOT_LOADED;
// exit if TSR cannot be unloaded
if (r.x.ax == 0)
return UNHOOK_FAIL;
// locate the TSR environment segment from the PSP
const unsigned env = *(unsigned far*) MK_FP(r.x.ax, 0x2C);
// free the TSR's memory
s.es = r.x.ax;
r.h.ah = 0x49;
intdosx (&r, &r, &s);
if (r.x.cflag != 0)
return MEM_FROZEN;
// free the TSR's environment
s.es = env;
r.h.ah = 0x49;
intdosx (&r, &r, &s);
if (r.x.cflag != 0)
return ENV_FROZEN;
// successfully unloaded
return SUCCESS;
}
//--------------------------------------------------------------------------
//
// TSR::request
//
// This function is used by foreground copies of the program to
// communicate with a resident copy. "Fn" is the function code
// and "p1" and "p2" are application-specific parameters to be
// passed to the resident copy. Their updated values are returned
// to the caller.
//
int TSR::request (int& fn, int& p1, int& p2)
{
union REGS r;
struct SREGS s;
r.h.ah = TSRfunction, r.h.al = fn | 0x80;
r.x.bx = FP_SEG (COPYRIGHT);
r.x.di = FP_OFF (COPYRIGHT);
s.es = FP_SEG (TSRname);
r.x.si = FP_OFF (TSRname);
r.x.cx = p1, r.x.dx = p2;
int86x (0x2F, &r, &r, &s);
if (compare ((char far*) MK_FP(s.es, r.x.si), COPYRIGHT) != 0)
return NOT_LOADED;
fn = r.x.ax, p1 = r.x.cx, p2 = r.x.dx;
return SUCCESS;
}
//--------------------------------------------------------------------------
//
// Unhook TSR.
//
// This function prepares the TSR for unloading from memory. The
// function returns the PSP address if the TSR can be unloaded
// successfully, and 0 otherwise (if any of the interrupt vectors
// have been re-hooked). The virtual function "shutdown" is also
// called to perform any class-specific finalisation. Interrupts
// 08, 09, 13 and 28 only need unhooking if there is a non-null
// hotkey or timeslice.
//
static int unhook ()
{
// exit if something has hooked the multiplex interrupt
if (getvect (0x2F) != Handler (TSRint2F))
return 0;
// try to unhook wake-up interrupts if necessary
if (hotshift != 0 || hotscan != 0 || interval != 0)
{ if (getvect (0x08) != Handler (TSRint8) ||
getvect (0x09) != Handler (TSRint9) ||
getvect (0x13) != Handler (TSRint13) ||
getvect (0x28) != Handler (TSRint28))
return 0;
setvect (0x08, oldint8);
setvect (0x09, oldint9);
setvect (0x13, oldint13);
setvect (0x28, oldint28);
}
// unhook multiplex interrupt
setvect (0x2F, oldint2F);
// perform user shutdown actions
if (instance->shutdown () != 0)
return 0;
// return PSP address
return _psp;
}
//--------------------------------------------------------------------------
//
// TSR::loaded
//
// Returns true if a copy of the TSR is already in memory.
//
int TSR::loaded ()
{
union REGS r;
struct SREGS s;
r.h.ah = TSRfunction, r.h.al = 0;
r.x.bx = FP_SEG (COPYRIGHT);
r.x.di = FP_OFF (COPYRIGHT);
s.es = FP_SEG (TSRname);
r.x.si = FP_OFF (TSRname);
int86x (0x2F, &r, &r, &s);
return r.h.al == 0xFF
&& compare ((char far*) MK_FP(s.es, r.x.si), COPYRIGHT) == 0;
}
//--------------------------------------------------------------------------
//
// Display a string using BIOS calls.
//
// This function is used by "dos_error" below to display error
// messages without using DOS calls.
//
static void display (int page, const char* s)
{
union REGS r;
while (*s != '\0')
{ if (*s >= ' ') // set colours for printing characters
{ r.x.ax = 0x0920; // display a space, using...
r.h.bh = page;
r.h.bl = 0x0E; // ...yellow on black
r.x.cx = 1;
int86 (0x10, &r, &r);
}
r.h.ah = 0x0E; // now display actual character
r.h.al = *s++;
r.h.bh = page;
int86 (0x10, &r, &r);
}
}
//--------------------------------------------------------------------------
//
// TSR::dos_error
//
// This function is called if an unsafe DOS call is made from the
// main TSR function. If it is called, it indicates a program bug.
// This is a virtual function so that a more appropriate function
// can be provided in classes derived from TSR. The parameter "fn"
// is the function code from register AH; "ce" is non-zero if a
// critical error is being handled; "cs:ip" is the return address
// (i.e. the address of the instruction after the illegal call).
//
void TSR::dos_error (int fn, int ce, int cs, int ip)
{
union REGS r;
char fmt [10];
// get video mode
r.h.ah = 0x0F;
int86 (0x10, &r, &r);
const int mode = r.h.al;
// select text mode if in graphics mode
const int graphics = (r.h.al > 3 && r.h.al != 7);
if (graphics)
{ r.x.ax = 0x0002;
int86 (0x10, &r, &r);
}
// get active page
r.h.ah = 0x0F;
int86 (0x10, &r, &r);
const int page = r.h.bh;
// display error message
display (page, "\a\r\n*** Illegal DOS call detected in TSR \"");
display (page, TSRname);
display (page, "\"\r\nFunction ");
sprintf (fmt, "%02X", fn); display (page, fmt);
display (page, " called from ");
sprintf (fmt, "%04X:%04X", cs, ip - 2); display (page, fmt);
if (ce != 0)
display (page, " during critical error handling");
display (page, ".\r\nThis call should not be used by a TSR and indicates"
" a bug in the program.\r\nPress any key to ignore the"
" call and continue... ");
// wait for a keypress
bioskey (0);
display (page, "\r\n");
// restore screen mode if it was a graphics mode
if (graphics)
{ r.x.ax = mode;
int86 (0x10, &r, &r);
}
}
//--------------------------------------------------------------------------
//
// TSR::pause
//
// This function generates an INT 28 (the DOS scheduler interrupt).
// This interrupt is used to wake up TSRs, so the main TSR function
// can call this during lengthy processing to ensure that other TSRs
// get a chance to wake up.
//
void TSR::pause ()
{
union REGS r;
int86 (0x28, &r, &r);
}
//--------------------------------------------------------------------------
//
// TSR::sync
//
// This function resynchronises the timeslice interval so that the
// next timed wakeup will happen after "interval" ticks from now.
//
void TSR::sync ()
{
nexttick = *timer + interval;
}
//--------------------------------------------------------------------------
//
// TSR::userbreak
//
// This function returns the value of the flag which indicates if
// control-break has been pressed. It also resets the flag.
//
int TSR::userbreak ()
{
int b = breakflag;
breakflag = 0;
return b;
}
//--------------------------------------------------------------------------
//
// TSR::name
//
// This function returns the name of the TSR instance.
//
const char* TSR::name ()
{
return TSRname;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -