返回
{***************************************************************}
{*** FVision Unit Version1.0 ***}
{*** 蓝蚂蚁工作室 ***}
{***************************************************************}
{*** 内存驻留程序支持单元 ***}
{***************************************************************}
{$V-,I-,R-,F+}
UNIT TSRU;
INTERFACE
USES
DOS,CRT;
CONST
OLDSTACKSS:WORD=0; {SS保存被中断程序内容}
OLDSTACKSP:WORD=0; {SP保存被中断程序内容}
OURSTACKSEG:WORD=0; {SS保存本程序内容}
OURSTACKSP:WORD=0; {SP保存本程序内容}
{STACKSW指示中断是否从本TSR发出}
{-1 :在本TSR外,转换栈}
{0 :在本TSR内,不转换栈}
STACKSW:INTEGER=-1;
ENDDOS:WORD=0;
CONST
SCANCODE:BYTE=0; {用于定义热键}
KEYMASK :BYTE=0; {是扫描码}
VAR
{保存原中断指针}
TIMERVEC,
KBDVEC,
OLD28VEC,
OLDCRITVEC : POINTER;
DOSSEG : WORD;
DOSBUSY : WORD;
OLDDTASEG,
OLDDTAOFS,
OURDTASEG,
OURDTAOFS : WORD;
SAVEBREAK : BYTE;
POPRTN : POINTER;
TSR_BYTE,
TSR_VEC : BYTE;
TSR_PSP : WORD;
INT_PSP : WORD;
PSPARRAY : ARRAY[1..2] OF WORD;
PSP_COUNTER : BYTE;
OLD_INTTABLE,NEW_INTTABLE:ARRAY[0..1023] OF BYTE;
CONST
TIMERINT=$1C;
KBDINT=$09;
INT28INT=$28;
CRITINT=$24;
POPFLAG:BOOLEAN=FALSE;
RUNNING:BOOLEAN=FALSE;
TSROFF :BOOLEAN=FALSE;
unrelease:boolean=false;
PROCEDURE CALLOLDINT(SUB:POINTER);
PROCEDURE POPSETUP(PR:POINTER;SC,KM:BYTE);
PROCEDURE BEGINPOP;
PROCEDURE ENDPOP;
PROCEDURE INSTALL_INT;
FUNCTION TSREXIT:BOOLEAN;
FUNCTION DUPCHECK(VAR S:STRING; RTN:POINTER):BYTE;
PROCEDURE BEGININT;
INLINE($FF/$06/STACKSW/
$75/$10/
$8C/$16/OLDSTACKSS/
$89/$26/OLDSTACKSP/
$8E/$16/OURSTACKSEG/
$8B/$26/OURSTACKSP);
PROCEDURE ENDINT;
INLINE($FF/$0E/STACKSW/
$7D/$08/
$8E/$16/OLDSTACKSS/
$8B/$26/OLDSTACKSP);
PROCEDURE CLI; INLINE($FA);
PROCEDURE STI; INLINE($FB);
PROCEDURE CALLPOP(SUB:POINTER);
IMPLEMENTATION
PROCEDURE NEWCRIT(FLAGS,CS,IP,AX,BX,CX,DX,SI,DI,DS,ES,BP:WORD);INTERRUPT;
BEGIN
AX:=0;
END;
PROCEDURE SAVESTACK;
BEGIN
OURSTACKSEG:=SSEG;
INLINE($89/$26/OURSTACKSP);
END;
PROCEDURE CALLPOP(SUB:POINTER);
BEGIN
INLINE($FF/$5E/$06);
END;
PROCEDURE CALLOLDINT(SUB:POINTER);
BEGIN
INLINE($9C/
$FF/$5E/$06);
END;
PROCEDURE NEW28(FLAGS,CS,IP,AX,BX,CX,DX,SI,DI,DS,ES,BP:WORD);INTERRUPT;
BEGIN
CLI;
BEGININT;
STI;
CALLOLDINT(OLD28VEC);
IF ((POPFLAG) AND (MEM[DOSSEG:DOSBUSY]<>0)) THEN
BEGIN
PORT[$20]:=$20;
POPFLAG:=FALSE;
unrelease:=false;
beginpop;
CALLPOP(POPRTN);
endpop;
END;
CLI;
ENDINT;
STI;
END;
PROCEDURE CLOCK(FLAGS,CS,IP,AX,BX,CX,DX,SI,DI,DS,ES,BP:WORD);INTERRUPT;
BEGIN
CLI;
BEGININT;
STI;
CALLOLDINT(TIMERVEC);
IF ((POPFLAG) AND (MEM[DOSSEG:DOSBUSY]=0)) THEN
BEGIN
PORT[$20]:=$20;
POPFLAG:=FALSE;
unrelease:=true;
beginpop;
CALLPOP(POPRTN);
endpop;
END;
CLI;
ENDINT;
STI;
END;
PROCEDURE KEYBOARD(FLAGS,CS,IP,AX,BX,CX,DX,SI,DI,DS,ES,BP:WORD);INTERRUPT;
LABEL
TSRDOWN,KEYEXIT;
BEGIN
CLI;
BEGININT;
STI;
IF TSROFF THEN GOTO TSRDOWN;
IF (PORT[$60]=SCANCODE) THEN
BEGIN
IF (MEM[$0000:$0417] AND KEYMASK)=KEYMASK THEN
BEGIN
TSR_BYTE:=PORT[$61];
PORT[$61]:=TSR_BYTE OR $80;
PORT[$61]:=TSR_BYTE;
CLI;
PORT[$20]:=$20;
STI;
IF NOT RUNNING THEN POPFLAG:=TRUE;
GOTO KEYEXIT;
END;
END;
TSRDOWN:
CALLOLDINT(KBDVEC);
KEYEXIT:
CLI;
ENDINT;
STI;
END;
PROCEDURE INSTALL_INT;
BEGIN
SETINTVEC(TIMERINT,@CLOCK);
SETINTVEC(KBDINT,@KEYBOARD);
SETINTVEC(INT28INT,@NEW28);
IF STACKSW=-1 THEN SETINTVEC($1B,SAVEINT1B);
END;
PROCEDURE REL_MEM;
VAR R:REGISTERS;
BEGIN
WHILE (MEM[ENDDOS:0]=$4D) DO
BEGIN
IF (MEMW[ENDDOS:1]=TSR_PSP) THEN
BEGIN
R.AH:=$49;
R.ES:=ENDDOS+1;
MSDOS(R);
END;
ENDDOS:=ENDDOS+MEMW[ENDDOS:3]+1;
END;
END;
FUNCTION TSREXIT:BOOLEAN;
VAR P,Q,R,S,T:POINTER;
BEGIN
GETINTVEC(TIMERINT,P);
GETINTVEC(KBDINT,Q);
GETINTVEC(INT28INT,R);
IF (P=@CLOCK) AND (Q=@KEYBOARD) AND (R=@NEW28) THEN
BEGIN
SETINTVEC(TIMERINT,TIMERVEC);
SETINTVEC(KBDINT,KBDVEC);
SETINTVEC(INT28INT,OLD28VEC);
T:=NIL;
SETINTVEC(TSR_VEC,T);
REL_MEM;
TSREXIT:=TRUE;
END ELSE
BEGIN
TSREXIT:=FALSE;
TSROFF :=TRUE;
END;
END;
PROCEDURE POPSETUP(PR:POINTER;SC,KM:BYTE);
VAR
R:REGISTERS;
ARD:WORD;
I:INTEGER;
BEGIN
SCANCODE:=SC;
KEYMASK:=KM;
POPRTN:=PR;
CHECKBREAK:=FALSE;
OURSTACKSEG:=SSEG;
INLINE($89/$26/OURSTACKSP);
R.AH:=$34;
MSDOS(R);
DOSSEG:=R.ES;
DOSBUSY:=R.BX;
R.AH:=$2F;
MSDOS(R);
OURDTASEG:=R.ES;
OURDTAOFS:=R.BX;
R.AH:=$51;
MSDOS(R);
TSR_PSP:=R.BX;
R.AH:=$52;
MSDOS(R);
ENDDOS:=MEMW[R.ES:R.BX-2];
PSP_COUNTER:=0;
ARD:=0;
WHILE (PSP_COUNTER<2) AND ((DOSSEG SHL 4 + ARD)<(ENDDOS SHL 4)) DO
BEGIN
IF MEMW[DOSSEG:ARD]=TSR_PSP+1 THEN
BEGIN
PSP_COUNTER:=PSP_COUNTER+1;
PSPARRAY[PSP_COUNTER]:=ARD;
R.AH:=$50;
R.BX:=TSR_PSP;
MSDOS(R);
END;
ARD:=ARD+1;
END;
GETINTVEC(TIMERINT,TIMERVEC);
GETINTVEC(KBDINT,KBDVEC);
GETINTVEC(INT28INT,OLD28VEC);
MOVE(PTR(0,0)^,OLD_INTTABLE,1024);
END;
PROCEDURE RESIDENTPSP;
VAR I:BYTE;
R:REGISTERS;
BEGIN
R.AH:=$51;
MSDOS(R);
INT_PSP:=R.BX;
FOR I:=1 TO PSP_COUNTER DO
MEMW[DOSSEG:PSPARRAY[I]]:=TSR_PSP;
END;
PROCEDURE RESTOREPSP;
VAR I:BYTE;
BEGIN
FOR I:=1 TO PSP_COUNTER DO
MEMW[DOSSEG:PSPARRAY[I]]:=INT_PSP;
END;
PROCEDURE BEGINPOP;
VAR R:REGISTERS;
BEGIN
RUNNING:=TRUE;
MOVE(PTR(0,0)^,NEW_INTTABLE,1024);
MOVE(OLD_INTTABLE,PTR(0,0)^,1024);
R.AH:=$2F;
MSDOS(R);
OLDDTASEG:=R.ES;
OLDDTAOFS:=R.BX;
R.AH:=$1A;
R.DS:=OURDTASEG;
R.DX:=OURDTAOFS;
MSDOS(R);
R.AX:=$3300;
MSDOS(R);
SAVEBREAK:=R.DL;
R.AX:=$3301;
R.DL:=0;
MSDOS(R);
GETINTVEC(CRITINT,OLDCRITVEC);
SETINTVEC(CRITINT,@NEWCRIT);
RESIDENTPSP;
END;
PROCEDURE ENDPOP;
VAR R:REGISTERS;
BEGIN
RUNNING:=FALSE;
R.AH:=$1A;
R.DS:=OLDDTASEG;
R.DX:=OLDDTAOFS;
MSDOS(R);
R.AX:=$3301;
R.DL:=SAVEBREAK;
MSDOS(R);
SETINTVEC(CRITINT,OLDCRITVEC);
MOVE(NEW_INTTABLE,PTR(0,0)^,1024);
RESTOREPSP;
END;
FUNCTION DUPCHECK(VAR S:STRING; RTN:POINTER):BYTE;
VAR
VEC:WORD;
DIF:WORD;
PTR:POINTER;
PTRARR:ARRAY[1..2] OF INTEGER ABSOLUTE PTR;
PTNARR:ARRAY[1..2] OF INTEGER ABSOLUTE RTN;
I:BYTE;
ST:STRING;
BEGIN
DIF:=DSEG-PTNARR[2];
FOR VEC:=$60 TO $67 DO
BEGIN
GETINTVEC(VEC,PTR);
IF PTR=NIL THEN
BEGIN
SETINTVEC(VEC,RTN);
TSR_VEC:=VEC;
DUPCHECK:=0;
EXIT;
END;
MOVE(MEM[PTRARR[2]+DIF:OFS(S)],ST,LENGTH(S)+1);
IF ST=S THEN
BEGIN
DUPCHECK:=VEC;
EXIT;
END;
END;
END;
END.