home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
pascal
/
das_buch
/
tsr
/
popup.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1993-06-04
|
24KB
|
1,336 lines
UNIT PopUp;
{**************************************
* Autor : Robert Flogaus *
* Sprache: Turbo Pascal 7.0 *
* Übersetzung: tpc popup [/DCRT] *
* [/DSCRN] [/DKEYBD] *
* [/DINT16] [/DDOS] *
* [/DNOSWAP] [/DUNSAFE]*
***************************************
* Bedeutung der Compilerschalter: *
* CRT: Einbinden der *
* Unit Crt *
* SCRN: Benutzung von *
* Video-BIOS *
* (INT 10h) *
* und Bildschirm-*
* ausgaben *
* (Bildschirm- *
* seite 0, 80*25)*
* KEYBD: Benutzung von *
* Tastatur *
* (INT 5,INT 9, *
* INT 16h, *
* INT 1Bh) *
* INT16: Aufruf von *
* INT 16h *
* (Tastaturein- *
* gabe) *
* DOS: Benutzung von *
* DOS *
* NOSWAP:kein Auslagern *
* von DOS-Daten *
* UNSAFE:Auslagerung *
* auch wenn InDos*
* >1 und *
* ohne INT 28h *
* jeweils *
* innerhalb der Popup- *
* Routine *
* *
* Zweck: zeitgesteuerter *
* Aufruf von TSR-Popup *
* Routine mit Betriebs-*
* systemaufrufen *
* ACHTUNG: *
* Demo, bitte anpassen!*
***************************************}
{$B-,R-,S-,Q-,I-}
{$IFDEF DOS}
{$DEFINE SCRN}
{$DEFINE KEYBD}
{$ENDIF}
{$IFDEF INT16}
{$DEFINE KEYBD}
{$ENDIF}
INTERFACE
USES Dos {$IFDEF CRT},Crt {$ENDIF};
TYPE
TSR_Proc=FUNCTION:BOOLEAN;
CONST
{BIOS-Statusbits im Word bei $40:$17}
ShiftRight=1;
ShiftLeft=2;
Ctrl=4;
Alt=8;
ScrollLockOn=16;
NumLockOn=32;
CapsLockOn=64;
InsertOn=128; {nicht so übersichtlich...}
CtrlLeft=$100;
AltLeft=$200;
SysReq=$400;
Break=$800; {besser nicht...}
ScrollLock=$1000;
NumLock=$2000;
CapsLock=$4000;
Insert=$8000;
VAR
Prog_Vec_1Bh,Prog_Vec_23h,
Prog_Vec_24h:POINTER;
{$IFDEF SCRN}
Acceptable_Video_Mode:BYTE;
Video_Mode:BYTE ABSOLUTE $40:$49;
Active_Page:BYTE ABSOLUTE $40:$62;
{$IFNDEF CRT}
FUNCTION WhereX:BYTE;
FUNCTION WhereY:BYTE;
PROCEDURE GotoXY(x,y:BYTE);
PROCEDURE ClrScr;
{$ENDIF}
PROCEDURE Save_Screen;
PROCEDURE Restore_Screen;
PROCEDURE Swap_Cursor;
PROCEDURE StrgWrite(s:STRING);
{$ENDIF}
{$IFDEF KEYBD}
{$IFNDEF CRT}
FUNCTION KeyPressed:BOOLEAN;
FUNCTION ReadKey:CHAR;
{$ENDIF}
PROCEDURE Wait4Ctrl;
{$ENDIF}
FUNCTION Setup_TSR(popup_proc:TSR_Proc;hotkey,unused_stack:WORD):BOOLEAN;
PROCEDURE make_resident_without_heap;
IMPLEMENTATION
TYPE
screentype=ARRAY[1..2000] OF WORD;
{$IFDEF DOS}
CONST
dos_swapped:BOOLEAN=FALSE;
{$ENDIF}
{$IFDEF SCRN}
CONST
screen_swapped:BOOLEAN=FALSE;
{$ENDIF}
{$IFNDEF CRT}
CONST
extended_key:CHAR=#0;
{$ENDIF}
VAR
user_proc:TSR_Proc;
{$IFDEF SCRN}
userscreen:screentype;
screenptr:^screentype;
x,y:BYTE;
mousebuffer:POINTER;
mousebufsize,dos_ver,cursor:WORD;
mouse_not_found:BOOLEAN;
{$ENDIF}
{$IFDEF DOS}
old_dta_add,xms_driver_add:POINTER;
crit_err_ptr,indos_ptr:^BYTE;
error_info:ARRAY[1..11] OF WORD;
old_psp
{$IFNDEF NOSWAP}
,swap_size,swapped_dos_seg{$ENDIF}:WORD;
old_a20_state:BYTE;
{$ENDIF}
savess,savesp:WORD;
save_cbreak:BOOLEAN;
addr_6845:WORD ABSOLUTE $40:$63;
{$IFDEF SCRN}
PROCEDURE end_transient;FORWARD;
{$ENDIF}
{$IFDEF DOS}
PROCEDURE StrgWrite(s:STRING);ASSEMBLER;
ASM
PUSH ds
LDS bx,s {DS:BX-->Zeiger auf s}
XOR ch,ch
MOV cl,BYTE Ptr [bx] {CX: Anzahl Bytes}
MOV dx,bx
Inc dx {DS:DX-->auszugebende Zeichen}
MOV bx,1 {Standardausgabe}
MOV ah,$40 {schreiben}
int $21
POP ds
END;
{$ELSE}
PROCEDURE StrgWrite(s:STRING);ASSEMBLER;
ASM
PUSH ds
LDS si,s
CLD
LODSB {Längenbyte}
XOR cx,cx
MOV cl,al
XOR bx,bx
JCXZ @@schluss
@@schleife:
MOV ah,$0E
CLD
LODSB
int $10
loop @@schleife
@@schluss:
POP ds
END;
{$ENDIF}
{$IFDEF SCRN}
{$IFNDEF CRT}
PROCEDURE GotoXY(x,y:BYTE);ASSEMBLER;
{abgemagerte Form, ohne Fehlerchecks
für gesamten 80*25-Bildschirm}
ASM
MOV ah,2
XOR bh,bh {Bildschirmseite 0}
MOV dh,[y]
MOV dl,[x]
Dec dh
Dec dx
int $10
END;
FUNCTION WhereX:BYTE;ASSEMBLER;
{abgemagerte Version; vgl. GotoXY}
ASM
MOV ah,3
XOR bh,bh {Bildschirmseite 0}
int $10
MOV ax,dx
Inc ax
END;
FUNCTION WhereY:BYTE;ASSEMBLER;
{abgemagerte Version; vgl. GotoXY}
ASM
MOV ah,3
XOR bh,bh {Bildschirmseite 0}
int $10
MOV al,dh
Inc ax
END;
PROCEDURE ClrScr;
{nur 80*25-Bildschirm, durch
Überschreiben von Bildschirmseite 1}
CONST
space=#32; {damit wird Bildschirm überschrieben}
White=15;
BEGIN
{$IFDEF DOS}
GotoXY(1,1);
StrgWrite(space); {korrekte DOS-Farbe links oben}
{$ENDIF}
ASM
CLD
LES di,screenptr
MOV cx,2000 {4000 Byte Bildschirmspeicher}
MOV ah,BYTE Ptr ES:[di+1] {Farbattribut links oben}
{$IFNDEF DOS}
OR ah,ah {schwarz auf schwarz?}
jnz @@colour_alright
MOV ah,White
@@colour_alright:
{$ENDIF}
MOV al,space
REP stosw
END;
GotoXY(1,1);
END;
{$ENDIF}
PROCEDURE newmouseroutine;FAR;ASSEMBLER;
ASM
END;
PROCEDURE mouse_off;ASSEMBLER;
ASM
CMP [mouse_not_found],TRUE
JE @@ende
MOV ax,$16 {Mauszustand sichern}
MOV bx,[mousebufsize]
LES dx,mousebuffer
int $33
MOV ax,$0C {neue Mausroutine}
lea dx,newmouseroutine
PUSH cs
POP ES
XOR cx,cx {gar nicht aufrufen}
int $33
MOV ax,2 {Mauscursor aus}
int $33
@@ende:
END;
PROCEDURE mouse_on;ASSEMBLER;
ASM
CMP [mouse_not_found],TRUE
JE @@ende
MOV ax,$17 {Mauszustand wiederherstellen}
LES dx,mousebuffer
MOV bx,[mousebufsize]
int $33
@@ende:
END;
PROCEDURE Swap_Cursor;ASSEMBLER;
ASM
MOV ah,3
XOR bh,bh
int $10
XCHG cx,[cursor]
MOV ah,1
MOV al,[Acceptable_Video_Mode]
int $10
END;
PROCEDURE Save_Screen;
{Bildschirmspeicher sichern (nur 80*25-Bildschirm)}
BEGIN
x:=WhereX;
y:=WhereY;
userscreen:=screenptr^; {Bildschirm sichern}
screen_swapped:=TRUE;
END;
PROCEDURE Restore_Screen;
{Bildschirmspeicher wiederherstellen
(nur 80*25-Bildschirm)}
BEGIN
IF screen_swapped THEN BEGIN
GotoXY(x,y);
screenptr^:=userscreen
END
END;
{$ENDIF}
PROCEDURE popup_flag;ASSEMBLER;
ASM
db 0
END;
PROCEDURE os_busy;ASSEMBLER;
ASM {muß 0 sein bei popup}
db 1
END;
{$IFDEF INT16}
PROCEDURE oldint16h;ASSEMBLER;
ASM
dw $9090
nop
END;
PROCEDURE newint16h;ASSEMBLER;
ASM
PUSH bp
MOV bp,sp
PUSH WORD Ptr [bp+6] {Original-Flags}
Inc BYTE Ptr cs:[os_busy]
popf
POP bp
pushf
cli
CALL dword Ptr cs:[oldint16h]
pushf
Dec BYTE Ptr cs:[os_busy]
popf
retf 2 {ursprüngliche Flags raus}
END;
{$ENDIF}
PROCEDURE user_hotkey;ASSEMBLER;
ASM
nop
END;
PROCEDURE oldint9h;ASSEMBLER;
ASM
dw $9090
nop
END;
PROCEDURE newint9h;ASSEMBLER;
ASM
pushf
{$IFDEF KEYBD}
Inc BYTE Ptr cs:[os_busy]
{$ENDIF}
CALL dword Ptr cs:[oldint9h]
{$IFDEF KEYBD}
Dec BYTE Ptr cs:[os_busy]
{$ENDIF}
sti
PUSH ax
PUSH ds
MOV ax,$40
MOV ds,ax
MOV ax,WORD Ptr cs:[user_hotkey]
AND ax,WORD Ptr ds:[$17]
CMP ax,WORD Ptr cs:[user_hotkey]
JNE @@no_hotkey
MOV BYTE Ptr cs:[popup_flag],TRUE
@@no_hotkey:
POP ds
POP ax
iret
END;
{$IFDEF KEYBD}
{$IFNDEF CRT}
FUNCTION KeyPressed:BOOLEAN;ASSEMBLER;
ASM
MOV ax,$100
OR [extended_key],al
jnz @@TRUE
int $16
MOV al,FALSE
jz @@FALSE
@@TRUE:
Inc ax
@@FALSE:
END;
FUNCTION ReadKey:CHAR;ASSEMBLER;
ASM
{$IFDEF DOS}
@@same_thing_once_more:
CALL KeyPressed
OR al,al
jnz @@cont
XOR ax,ax
int $28 {DOS Idle, alte Version}
MOV ax,$1680
int $2F {DOS Idle, neue Version}
JMP @@same_thing_once_more
@@cont:
{$ENDIF}
XOR ax,ax
XCHG al,[extended_key]
OR al,al
jnz @@Ok
int $16
OR al,al
jnz @@Ok
MOV [extended_key],ah
@@Ok:
END;
{$ENDIF}
PROCEDURE Wait4Ctrl;
BEGIN
StrgWrite(#13#10'Weiter ---> <Ctrl>-Taste '+
'(bzw. <Strg>-Taste) drücken...');
ASM
MOV ax,40H
MOV ES,ax
MOV di,17H
MOV bl,Ctrl
@@another_loop:
{$IFDEF DOS}
XOR ax,ax
int $28 {DOS Idle, alte Version}
MOV ax,$1680
int $2F {DOS Idle, neue Version}
{$ENDIF}
test bl,BYTE Ptr ES:[di]
jz @@another_loop
END
END;
{$ENDIF}
{$IFDEF SCRN}
PROCEDURE oldint10h;ASSEMBLER;
ASM
dw $9090
nop
END;
PROCEDURE newint10h;ASSEMBLER;
ASM
pushf
Inc BYTE Ptr cs:[os_busy]
CALL dword Ptr cs:[oldint10h]
Dec BYTE Ptr cs:[os_busy]
iret
END;
PROCEDURE oldint33h;ASSEMBLER;
ASM
dw $9090
nop
END;
PROCEDURE newint33h;ASSEMBLER;
ASM
pushf
Inc BYTE Ptr cs:[os_busy]
CALL dword Ptr cs:[oldint33h]
Dec BYTE Ptr cs:[os_busy]
iret
END;
{$ENDIF}
PROCEDURE oldint13h;ASSEMBLER;
ASM
dw $9090
nop
END;
PROCEDURE newint13h;ASSEMBLER;
ASM
PUSH bp
MOV bp,sp
PUSH WORD Ptr [bp+6] {Original-Flags}
Inc BYTE Ptr cs:[os_busy]
popf
POP bp
pushf
cli
CALL dword Ptr cs:[oldint13h]
pushf
Dec BYTE Ptr cs:[os_busy]
popf
retf 2 {ursprüngliche Flags raus}
END;
PROCEDURE newint23h;ASSEMBLER;
ASM
clc
retf 2
END;
{$IFDEF DOS}
PROCEDURE newint1Bh;ASSEMBLER;
ASM
iret
END;
PROCEDURE oldint25h;ASSEMBLER;
ASM
dw $9090
nop
END;
PROCEDURE newint25h;FAR;ASSEMBLER;
ASM
pushf
Inc BYTE Ptr cs:[os_busy]
popf
CALL dword Ptr cs:[oldint25h]
pushf
Dec BYTE Ptr cs:[os_busy]
popf
END;
PROCEDURE oldint26h;ASSEMBLER;
ASM
dw $9090
nop
END;
PROCEDURE newint26h;FAR;ASSEMBLER;
ASM
pushf
Inc BYTE Ptr cs:[os_busy]
popf
CALL dword Ptr cs:[oldint26h]
pushf
Dec BYTE Ptr cs:[os_busy]
popf
END;
{$IFNDEF NOSWAP}
PROCEDURE crit_dos_section;ASSEMBLER;
ASM
dw 0
END;
PROCEDURE oldint2ah;ASSEMBLER;
ASM
dw $9090
nop
END;
PROCEDURE newint2ah;ASSEMBLER;
ASM
pushf
CMP ah,$82
JE @@end_crit_sec0to7
CMP al,7
pushf
CMP ah,$80
JE @@begin_critical_section
CMP ah,$81
JE @@end_critical_section
popf
@@cont:
popf
JMP dword Ptr cs:[oldint2ah]
@@end_crit_sec0to7:
MOV BYTE Ptr cs:[crit_dos_section],0
JMP @@cont
@@begin_critical_section:
popf
ja @@inc_greater_7
Inc BYTE Ptr cs:[crit_dos_section]
JMP @@cont
@@inc_greater_7:
Inc BYTE Ptr cs:[crit_dos_section+1]
JMP @@cont
@@end_critical_section:
popf
ja @@dec_greater_7
Dec BYTE Ptr cs:[crit_dos_section]
JMP @@cont
@@dec_greater_7:
Dec BYTE Ptr cs:[crit_dos_section+1]
JMP @@cont
END;
{$ENDIF}
PROCEDURE get_error_info;ASSEMBLER;
ASM
PUSH bp {außer SS:SP wird alles zerstört!}
MOV ah,$59
XOR bx,bx
int $21
PUSH ES
PUSH di
PUSH ax
MOV ax,Seg @data
MOV ES,ax
lea di,error_info
CLD
POP ax
stosw
MOV ax,bx
stosw
MOV ax,cx
stosw
MOV ax,dx
stosw
MOV ax,si
stosw
POP ax {DI}
stosw
MOV ax,ds
stosw
POP ax {ES}
stosw
XOR ax,ax
stosw
stosw
stosw
POP bp
PUSH ES
POP ds
END;
PROCEDURE restore_error_info;ASSEMBLER;
ASM
lea dx,error_info {DS:DX}
MOV ax,$5D0A
int $21
END;
PROCEDURE swap_dta;ASSEMBLER;
ASM
PUSH ds
MOV ah,$2F {DTA-Addr. ---> ES:BX}
int $21
MOV dx,WORD Ptr [old_dta_add]
MOV WORD Ptr [old_dta_add],bx
MOV ax,WORD Ptr [old_dta_add+2]
MOV WORD Ptr [old_dta_add+2],ES
MOV ds,ax
MOV ah,$1A {DS:DX ---> DTA-Addr.}
int $21
POP ds
END;
PROCEDURE check_a20;ASSEMBLER;
ASM
CMP [dos_ver],$500 {ab DOS 5.0}
jb @@err_exit
XOR ax,ax
OR ax,WORD Ptr [xms_driver_add]
OR ax,WORD Ptr [xms_driver_add+2]
jz @@err_exit {Nullzeiger --> Ende}
MOV ah,07
CALL dword Ptr [xms_driver_add]
OR bl,bl
jz @@Exit
@@err_exit:
MOV al,$FF
@@Exit:
MOV [old_a20_state],al
END;
PROCEDURE restore_a20;ASSEMBLER;
ASM
MOV ah,[old_a20_state]
CMP ah,$FF
JE @@Exit
MOV al,1
AND ah,al
XOR ah,al
ADD ah,5
CALL dword Ptr [xms_driver_add]
@@Exit:
END;
PROCEDURE swap_psp;ASSEMBLER;
ASM
MOV ah,$51 {aktives PSP holen}
int $21
XCHG bx,[old_psp]
MOV ah,$50 {aktives PSP setzen}
int $21
END;
{$IFNDEF NOSWAP}
PROCEDURE copy_mem;ASSEMBLER;
ASM
CLD {Achtung: Parameter in CX,SI,DI,DS,ES!}
cli
SHR cx,1
jnc @@words_only
MOVSB
@@words_only:
REP movsw
sti
END;
PROCEDURE save_dos_context;ASSEMBLER;
ASM
PUSH ds
MOV cx,[swap_size]
MOV ax,[swapped_dos_seg]
MOV ES,ax
XOR di,di
LDS si,crit_err_ptr
CALL copy_mem
POP ds
MOV [dos_swapped],TRUE
END;
PROCEDURE restore_dos_context;ASSEMBLER;
ASM
CMP [dos_swapped],FALSE
JE @@ende
MOV cx,[swap_size]
LES di,crit_err_ptr
MOV ax,[swapped_dos_seg]
MOV [dos_swapped],FALSE
PUSH ds
MOV ds,ax
XOR si,si
CALL copy_mem
POP ds
@@ende:
END;
PROCEDURE int28h_busy;ASSEMBLER;
ASM
db 0
END;
{$ENDIF}
PROCEDURE dos_setup;
BEGIN
GetCBreak(save_cbreak);
SetCBreak(FALSE);
get_error_info;
swap_dta;
swap_psp;
GetIntVec($1B,Prog_Vec_1Bh);
{$IFDEF CRT}
SetIntVec($1B,SaveInt1B);
{$ELSE}
SetIntVec($1B,@newint1Bh);
{$ENDIF}
GetIntVec($23,Prog_Vec_23h);
SetIntVec($23,@newint23h);
GetIntVec($24,Prog_Vec_24h);
SetIntVec($24,SaveInt24);
{$IFDEF CRT}
CheckBreak:=FALSE
{$ENDIF}
END;
PROCEDURE dos_cleanup;
BEGIN
SetIntVec($1B,Prog_Vec_1Bh);
SetIntVec($23,Prog_Vec_23h);
SetIntVec($24,Prog_Vec_24h);
swap_psp;
swap_dta;
restore_error_info;
SetCBreak(save_cbreak)
END;
{$ENDIF}
PROCEDURE swap_stack;NEAR;ASSEMBLER;
ASM
POP bx {Rücksprungadresse}
MOV ax,ss
CMP ax,[savess]
JE @@do_not_swap
XCHG ax,[savess]
cli {keine Unterbrechungen
bei halb umgesetztem Stack}
MOV ss,ax
XCHG sp,[savesp]
@@do_not_swap:
PUSH bx
{sti folgt!}
END;
FUNCTION os_safe:BOOLEAN;ASSEMBLER;
ASM
XOR ax,ax
CMP BYTE Ptr cs:[os_busy],al
JNE @@unsafe
{$IFDEF DOS}
LES di,crit_err_ptr
CMP BYTE Ptr ES:[di],al
JNE @@unsafe
LES di,indos_ptr
CMP BYTE Ptr ES:[di],1
jb @@safe
{$IFNDEF UNSAFE}
ja @@unsafe
{$ENDIF}
{$IFNDEF NOSWAP}
{$IFNDEF UNSAFE}
CMP BYTE Ptr cs:[int28h_busy],1
JNE @@unsafe
{$ENDIF}
CMP [dos_ver],$400 {nicht für DOS 4.0}
JE @@unsafe
CMP WORD Ptr cs:[crit_dos_section],ax
JNE @@unsafe
CALL save_dos_context
{$ELSE}
JMP @@unsafe
{$ENDIF}
{$ENDIF}
@@safe:
Inc ax
@@unsafe:
END;
PROCEDURE timerint_busy;ASSEMBLER;
ASM
db 0
END;
PROCEDURE oldint8h;ASSEMBLER;
ASM
dw $9090
nop
END;
PROCEDURE activate_tsr;ASSEMBLER;
ASM
PUSH ax
PUSH bx
PUSH ds
MOV ax,Seg @data
MOV ds,ax {Turbo DS wiederherstellen}
CALL swap_stack {Turbo Stack wiederherstellen}
sti
PUSH cx
PUSH dx
PUSH si
PUSH di
PUSH ES
{$IFDEF DOS}
CALL check_a20
{$ENDIF}
CALL os_safe
OR al,al
jz @@not_activated
{$IFDEF DOS}
CALL dos_setup
{$ENDIF}
{$IFDEF SCRN}
CALL mouse_off
{$ENDIF}
CALL user_proc
XOR al,1
MOV BYTE Ptr cs:[popup_flag],al
{$IFDEF SCRN}
CALL mouse_on
{$ENDIF}
{$IFDEF DOS}
CALL dos_cleanup
{$IFNDEF NOSWAP}
CALL restore_dos_context
{$ENDIF}
CALL restore_a20
{$ENDIF}
@@not_activated:
POP ES
POP di
POP si
POP dx
POP cx
CALL swap_stack
POP ds
POP bx
POP ax
END;
PROCEDURE newint8h;ASSEMBLER;
ASM
pushf
CALL dword Ptr cs:[oldint8h]
cli
CMP BYTE Ptr cs:[popup_flag],0
JNE @@popup_requested
iret
@@popup_requested:
Inc BYTE Ptr cs:[timerint_busy]
CMP BYTE Ptr cs:[timerint_busy],1
JNE @@Exit
CALL activate_tsr
@@Exit:
Dec BYTE Ptr cs:[timerint_busy]
iret
END;
{$IFDEF DOS}
{$IFNDEF NOSWAP}
PROCEDURE oldint28h;ASSEMBLER;
ASM
dw $9090
nop
END;
PROCEDURE newint28h;ASSEMBLER;
ASM
pushf
CALL dword Ptr cs:[oldint28h]
cli
CMP BYTE Ptr cs:[popup_flag],0
JNE @@popup_requested
iret
@@popup_requested:
Inc BYTE Ptr cs:[timerint_busy]
CMP BYTE Ptr cs:[timerint_busy],1
JNE @@Exit
Inc BYTE Ptr cs:[int28h_busy]
CALL activate_tsr
Dec BYTE Ptr cs:[int28h_busy]
@@Exit:
Dec BYTE Ptr cs:[timerint_busy]
iret
END;
{$ENDIF}
{$ENDIF}
{$IFDEF SCRN}
PROCEDURE start_transient;ASSEMBLER;
ASM
{!!!ab hier wird der Code im TSR überschrieben!!!}
END;
{$ENDIF}
FUNCTION reserve_block(how_much:WORD):WORD;ASSEMBLER;
ASM
MOV ax,[PrefixSeg]
Dec ax
MOV ES,ax {MCB für PSP}
PUSH WORD Ptr ES:[3] {Paras Programm}
Inc ax
MOV ES,ax {PrefixSeg}
MOV ah,$4A
MOV bx,$FFFF
int $21 {max. Paras Programm in BX}
jnc @@error
CMP ax,8
JNE @@error
MOV dx,bx
MOV ah,$4A
int $21 {Speicher zu!}
jc @@error
MOV bx,[how_much]
ADD bx,15
MOV cl,4
SHR bx,cl
PUSH bx {Paras neuer Block}
MOV ah,$48 {Speicher-Fragment groß genug?}
int $21
POP cx
jnc @@Ok {...ja ---> dann o.k.}
MOV bx,dx {max. Blockgröße Programm}
SUB bx,cx {-neuer Block}
Dec bx {-1 Para (MCB)}
POP ax {Paras urspr. Programm}
PUSH ax
CMP bx,ax {kleiner als aktuell?}
jb @@error
MOV ah,$4A {PSP-Block schrumpfen}
int $21
jc @@error
MOV bx,cx
MOV ah,$48 {Speicher für auszulagernde DOS-Daten}
int $21
jc @@error
@@Ok:
POP bx
PUSH ax
MOV ah,$4A
int $21
POP ax
JMP @@terminate_proc
@@error:
XOR ax,ax
POP bx
@@terminate_proc:
END;
{$IFDEF DOS}
PROCEDURE get_flags_and_swap_area;ASSEMBLER;
ASM
PUSH ds
XOR ax,ax
MOV WORD Ptr [crit_err_ptr],ax
MOV WORD Ptr [crit_err_ptr+2],ax
XOR bx,bx
MOV ES,bx
MOV ah,$34
int $21 {InDos-Flag-Adresse holen}
MOV WORD Ptr [indos_ptr],bx
MOV WORD Ptr [indos_ptr+2],ES
Dec bx {ES:BX ---> critical error flag}
@@call_5d06:
MOV ax,$5D06 {crit.error flag+}
int $21 {DOS-Swapbereich holen}
jc @@error
PUSH ds
POP di
POP ds
PUSH ds
MOV ax,ES
CMP di,ax
JNE @@error
CMP bx,si
JNE @@error
{$IFNDEF NOSWAP}
CMP [dos_ver],$400
JE @@cannot_swap
MOV [swap_size],cx
PUSH di {eigentlich...}
PUSH si {...unnötig}
PUSH cx {Parameter}
CALL reserve_block
POP si {eigentlich...}
POP di {unnötig...}
OR ax,ax
jz @@error
MOV WORD Ptr [swapped_dos_seg],ax
@@cannot_swap:
{$ENDIF}
MOV WORD Ptr [crit_err_ptr],si
MOV WORD Ptr [crit_err_ptr+2],di
@@error:
POP ds
END;
PROCEDURE get_xms_driver_add;ASSEMBLER;
ASM
CMP [dos_ver],$500 {ab DOS 5.0}
jb @@Exit
MOV ax,$4300 {XMS-Treiber installiert?}
int $2F
XOR bx,bx
MOV ES,bx
CMP al,$80
JNE @@Exit
MOV ax,$4310 {Treiber-Adresse in ES:BX holen}
int $2F
@@Exit:
MOV WORD Ptr [xms_driver_add],bx
MOV WORD Ptr [xms_driver_add+2],ES
END;
{$ENDIF}
{$IFDEF SCRN}
FUNCTION true_DosVer:WORD;ASSEMBLER;
ASM
MOV ax,$3306 {DOS-Version holen (ab DOS 5.0)}
XOR bx,bx {BH:Hauptversion,BL:Nebenversion}
int $21
MOV ax,bx
CMP al,5 {DOS >=5.0?}
jnb @@dos_5_or_above
MOV ax,$3000 {entspr. DosVersion}
int $21
@@dos_5_or_above:
XCHG ah,al {Hauptversion höherwertig}
END;
PROCEDURE init_mouse;ASSEMBLER;
ASM
XOR ax,ax
int $33 {Maus da?}
Inc ax
PUSH ax
jnz @@end_routine
XOR bx,bx
MOV ax,$15
int $33
OR bx,bx {BX immer noch 0?}
jnz @@compatible {sonst uralter/inkompatibler Treiber}
@@no_mouse:
POP ax
Inc ax
PUSH ax
JMP @@end_routine
@@compatible:
MOV [mousebufsize],bx
lea ax,end_transient
lea di,start_transient
MOV WORD Ptr [mousebuffer],di {Mauszustand ab}
MOV WORD Ptr [mousebuffer+2],cs {start_transient puffern}
SUB ax,di
SUB ax,10 {sicherheitshalber}
CMP ax,bx {genügend Platz im Codesegment?}
JAE @@end_routine
CMP BYTE Ptr [dos_ver+1],3 {unter DOS 2.x...}
jb @@no_mouse {...geht reserve_block schief!}
PUSH bx
CALL reserve_block
OR ax,ax
jz @@no_mouse
MOV WORD Ptr [mousebuffer+2],ax
MOV WORD Ptr [mousebuffer],0
@@end_routine:
POP ax
MOV [mouse_not_found],al
END;
{$ENDIF}
FUNCTION Setup_TSR(popup_proc:TSR_Proc;hotkey,unused_stack:WORD):BOOLEAN;
BEGIN
{$IFDEF SCRN}
IF addr_6845=$3D4 THEN BEGIN
{farbfähige Grafikkarte}
screenptr:=Ptr($B800,0);
cursor:=$607;
Acceptable_Video_Mode:=3
END
ELSE IF addr_6845=$3B4 THEN BEGIN
{monochrom}
screenptr:=Ptr($B000,0);
cursor:=$A0B;
Acceptable_Video_Mode:=7
END
ELSE BEGIN
{????}
StrgWrite(#7#13#10'Grafikkarte '+
'nicht einzuordnen'#13#10);
Setup_TSR:=FALSE;
Exit
END;
dos_ver:=true_DosVer;
{$ENDIF}
ASM
MOV ax,[hotkey]
MOV WORD Ptr cs:[user_hotkey],ax
END;
user_proc:=popup_proc;
savesp:=SPtr-unused_stack;
savess:=SSeg;
SetIntVec($23,@newint23h); {Ctrl-C aus!!}
{$IFDEF DOS}
IF dos_ver<$30A THEN BEGIN
StrgWrite(#7#13#10'Dies Programm benötigt '+
'DOS-Versionen >=3.10'#13#10);
Setup_TSR:=FALSE;
Exit
END;
old_psp:=PrefixSeg;
old_dta_add:=Ptr(PrefixSeg,$80);
get_xms_driver_add;
get_flags_and_swap_area;
IF (crit_err_ptr=NIL) OR (indos_ptr=NIL) THEN BEGIN
StrgWrite(#7#13#10'Fehler bei '+
'der Initialisierung.'#13#10);
Setup_TSR:=FALSE;
Exit
END;
{$ENDIF}
GetCBreak(save_cbreak);
SetCBreak(FALSE);
SetIntVec(0,SaveInt00);
GetIntVec($8,POINTER(@oldint8h^));
SetIntVec($8,@newint8h);
GetIntVec($9,POINTER(@oldint9h^));
SetIntVec($9,@newint9h);
{$IFDEF SCRN}
GetIntVec($10,POINTER(@oldint10h^));
SetIntVec($10,@newint10h);
GetIntVec($33,POINTER(@oldint33h^));
IF POINTER(@oldint33h^)<>NIL THEN BEGIN
init_mouse;
SetIntVec($33,@newint33h)
END
ELSE
mouse_not_found:=TRUE; {evtl. bei DOS 2.x}
{$ENDIF}
GetIntVec($13,POINTER(@oldint13h^));
SetIntVec($13,@newint13h);
{$IFDEF INT16}
GetIntVec($16,POINTER(@oldint16h^));
SetIntVec($16,@newint16h);
{$ENDIF}
{$IFDEF DOS}
GetIntVec($24,SaveInt24);
GetIntVec($25,POINTER(@oldint25h^));
SetIntVec($25,@newint25h);
GetIntVec($26,POINTER(@oldint26h^));
SetIntVec($26,@newint26h);
{$IFNDEF NOSWAP}
GetIntVec($28,POINTER(@oldint28h^));
SetIntVec($28,@newint28h);
GetIntVec($2A,POINTER(@oldint2ah^));
SetIntVec($2A,@newint2ah);
{$ENDIF}
{$ENDIF}
GetIntVec($1B,Prog_Vec_1Bh);
SetIntVec($1B,SaveInt1B);
SaveInt1B:=Prog_Vec_1Bh;
SetCBreak(save_cbreak);
ASM
Dec BYTE Ptr cs:[os_busy]
END;
Setup_TSR:=TRUE
END;
PROCEDURE make_resident_without_heap;ASSEMBLER;
{Darf erst nach setup_tsr aufgerufen werden!}
{Heap und Overlay-Puffer werden freigegeben!}
ASM
MOV dx,[savess]
SUB dx,[PrefixSeg]
MOV ax,[savesp]
ADD ax,15
MOV cl,4
SHR ax,cl
ADD dx,ax
MOV ax,$3100 {keep(0)}
int $21
END;
{$IFDEF SCRN}
PROCEDURE end_transient;ASSEMBLER;
ASM
{globale Markierung für das Ende
des überschreibbaren Bereichs}
END;
{$ENDIF}
END.