⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tsr.cpp

📁 多任务操作系统控制的DOS环境下的实现的C语言源程序。 利用时间片的方式
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    {   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 + -