home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / das_buch / tsr / popup.pas < prev    next >
Pascal/Delphi Source File  |  1993-06-04  |  24KB  |  1,336 lines

  1. UNIT PopUp;
  2.  
  3. {**************************************
  4. *        Autor : Robert Flogaus       *
  5. *       Sprache: Turbo Pascal 7.0     *
  6. *   Übersetzung: tpc popup [/DCRT]    *
  7. *                [/DSCRN] [/DKEYBD]   *
  8. *                [/DINT16] [/DDOS]    *
  9. *                [/DNOSWAP] [/DUNSAFE]*
  10. ***************************************
  11. *   Bedeutung der Compilerschalter:   *
  12. *               CRT:   Einbinden der  *
  13. *                      Unit Crt       *
  14. *               SCRN:  Benutzung von  *
  15. *                      Video-BIOS     *
  16. *                      (INT 10h)      *
  17. *                      und Bildschirm-*
  18. *                      ausgaben       *
  19. *                      (Bildschirm-   *
  20. *                      seite 0, 80*25)*
  21. *               KEYBD: Benutzung von  *
  22. *                      Tastatur       *
  23. *                      (INT 5,INT 9,  *
  24. *                      INT 16h,       *
  25. *                      INT 1Bh)       *
  26. *               INT16: Aufruf von     *
  27. *                      INT 16h        *
  28. *                      (Tastaturein-  *
  29. *                      gabe)          *
  30. *               DOS:   Benutzung von  *
  31. *                      DOS            *
  32. *               NOSWAP:kein Auslagern *
  33. *                      von DOS-Daten  *
  34. *               UNSAFE:Auslagerung    *
  35. *                      auch wenn InDos*
  36. *                      >1 und         *
  37. *                      ohne INT 28h   *
  38. *                    jeweils          *
  39. *                innerhalb der Popup- *
  40. *                    Routine          *
  41. *                                     *
  42. *         Zweck: zeitgesteuerter      *
  43. *                Aufruf von TSR-Popup *
  44. *                Routine mit Betriebs-*
  45. *                systemaufrufen       *
  46. *                ACHTUNG:             *
  47. *                Demo, bitte anpassen!*
  48. ***************************************}
  49.  
  50.  
  51. {$B-,R-,S-,Q-,I-}
  52.  
  53. {$IFDEF DOS}
  54.   {$DEFINE SCRN}
  55.   {$DEFINE KEYBD}
  56. {$ENDIF}
  57.  
  58. {$IFDEF INT16}
  59.   {$DEFINE KEYBD}
  60. {$ENDIF}
  61.  
  62. INTERFACE
  63.  
  64. USES Dos {$IFDEF CRT},Crt {$ENDIF};
  65.  
  66. TYPE
  67.   TSR_Proc=FUNCTION:BOOLEAN;
  68.  
  69. CONST
  70.   {BIOS-Statusbits im Word bei $40:$17}
  71.   ShiftRight=1;
  72.   ShiftLeft=2;
  73.   Ctrl=4;
  74.   Alt=8;
  75.   ScrollLockOn=16;
  76.   NumLockOn=32;
  77.   CapsLockOn=64;
  78.   InsertOn=128; {nicht so übersichtlich...}
  79.   CtrlLeft=$100;
  80.   AltLeft=$200;
  81.   SysReq=$400;
  82.   Break=$800; {besser nicht...}
  83.   ScrollLock=$1000;
  84.   NumLock=$2000;
  85.   CapsLock=$4000;
  86.   Insert=$8000;
  87.  
  88. VAR
  89.   Prog_Vec_1Bh,Prog_Vec_23h,
  90.   Prog_Vec_24h:POINTER;
  91. {$IFDEF SCRN}
  92.   Acceptable_Video_Mode:BYTE;
  93.   Video_Mode:BYTE ABSOLUTE $40:$49;
  94.   Active_Page:BYTE ABSOLUTE $40:$62;
  95.  
  96. {$IFNDEF CRT}
  97. FUNCTION WhereX:BYTE;
  98. FUNCTION WhereY:BYTE;
  99. PROCEDURE GotoXY(x,y:BYTE);
  100. PROCEDURE ClrScr;
  101. {$ENDIF}
  102. PROCEDURE Save_Screen;
  103. PROCEDURE Restore_Screen;
  104. PROCEDURE Swap_Cursor;
  105. PROCEDURE StrgWrite(s:STRING);
  106. {$ENDIF}
  107. {$IFDEF KEYBD}
  108. {$IFNDEF CRT}
  109. FUNCTION KeyPressed:BOOLEAN;
  110. FUNCTION ReadKey:CHAR;
  111. {$ENDIF}
  112. PROCEDURE Wait4Ctrl;
  113. {$ENDIF}
  114. FUNCTION Setup_TSR(popup_proc:TSR_Proc;hotkey,unused_stack:WORD):BOOLEAN;
  115. PROCEDURE make_resident_without_heap;
  116.  
  117. IMPLEMENTATION
  118.  
  119.  
  120. TYPE
  121.   screentype=ARRAY[1..2000] OF WORD;
  122.  
  123. {$IFDEF DOS}
  124. CONST
  125.   dos_swapped:BOOLEAN=FALSE;
  126. {$ENDIF}
  127. {$IFDEF SCRN}
  128. CONST
  129.   screen_swapped:BOOLEAN=FALSE;
  130. {$ENDIF}
  131. {$IFNDEF CRT}
  132. CONST
  133.   extended_key:CHAR=#0;
  134. {$ENDIF}
  135. VAR
  136.   user_proc:TSR_Proc;
  137.   {$IFDEF SCRN}
  138.   userscreen:screentype;
  139.   screenptr:^screentype;
  140.   x,y:BYTE;
  141.   mousebuffer:POINTER;
  142.   mousebufsize,dos_ver,cursor:WORD;
  143.   mouse_not_found:BOOLEAN;
  144.   {$ENDIF}
  145.   {$IFDEF DOS}
  146.   old_dta_add,xms_driver_add:POINTER;
  147.   crit_err_ptr,indos_ptr:^BYTE;
  148.   error_info:ARRAY[1..11] OF WORD;
  149.   old_psp
  150.   {$IFNDEF NOSWAP}
  151.   ,swap_size,swapped_dos_seg{$ENDIF}:WORD;
  152.   old_a20_state:BYTE;
  153.   {$ENDIF}
  154.   savess,savesp:WORD;
  155.   save_cbreak:BOOLEAN;
  156.   addr_6845:WORD ABSOLUTE $40:$63;
  157.  
  158.  
  159. {$IFDEF SCRN}
  160. PROCEDURE end_transient;FORWARD;
  161. {$ENDIF}
  162.  
  163. {$IFDEF DOS}
  164.  
  165. PROCEDURE StrgWrite(s:STRING);ASSEMBLER;
  166.  
  167. ASM
  168.   PUSH ds
  169.   LDS bx,s    {DS:BX-->Zeiger auf s}
  170.   XOR ch,ch
  171.   MOV cl,BYTE Ptr [bx] {CX: Anzahl Bytes}
  172.   MOV dx,bx
  173.   Inc dx    {DS:DX-->auszugebende Zeichen}
  174.   MOV bx,1 {Standardausgabe}
  175.   MOV ah,$40 {schreiben}
  176.   int $21
  177.   POP ds
  178. END;
  179. {$ELSE}
  180. PROCEDURE StrgWrite(s:STRING);ASSEMBLER;
  181.  
  182. ASM
  183.   PUSH ds
  184.   LDS si,s
  185.   CLD
  186.   LODSB {Längenbyte}
  187.   XOR cx,cx
  188.   MOV cl,al
  189.   XOR bx,bx
  190.   JCXZ @@schluss
  191. @@schleife:
  192.   MOV ah,$0E
  193.   CLD
  194.   LODSB
  195.   int $10
  196.   loop @@schleife
  197. @@schluss:
  198.   POP ds
  199. END;
  200. {$ENDIF}
  201.  
  202. {$IFDEF SCRN}
  203. {$IFNDEF CRT}
  204. PROCEDURE GotoXY(x,y:BYTE);ASSEMBLER;
  205.  
  206. {abgemagerte Form, ohne Fehlerchecks
  207. für gesamten 80*25-Bildschirm}
  208.  
  209. ASM
  210.   MOV ah,2
  211.   XOR bh,bh {Bildschirmseite 0}
  212.   MOV dh,[y]
  213.   MOV dl,[x]
  214.   Dec dh
  215.   Dec dx
  216.   int $10
  217. END;
  218.  
  219. FUNCTION WhereX:BYTE;ASSEMBLER;
  220.  
  221. {abgemagerte Version; vgl. GotoXY}
  222.  
  223. ASM
  224.   MOV ah,3
  225.   XOR bh,bh  {Bildschirmseite 0}
  226.   int $10
  227.   MOV ax,dx
  228.   Inc ax
  229. END;
  230.  
  231. FUNCTION WhereY:BYTE;ASSEMBLER;
  232.  
  233. {abgemagerte Version; vgl. GotoXY}
  234.  
  235. ASM
  236.   MOV ah,3
  237.   XOR bh,bh  {Bildschirmseite 0}
  238.   int $10
  239.   MOV al,dh
  240.   Inc ax
  241. END;
  242.  
  243. PROCEDURE ClrScr;
  244.  
  245. {nur 80*25-Bildschirm, durch
  246. Überschreiben von Bildschirmseite 1}
  247.  
  248. CONST
  249.   space=#32;  {damit wird Bildschirm überschrieben}
  250.   White=15;
  251.  
  252. BEGIN
  253.   {$IFDEF DOS}
  254.   GotoXY(1,1);
  255.   StrgWrite(space);  {korrekte DOS-Farbe links oben}
  256.   {$ENDIF}
  257.   ASM
  258.     CLD
  259.     LES di,screenptr
  260.     MOV cx,2000  {4000 Byte Bildschirmspeicher}
  261.     MOV ah,BYTE Ptr ES:[di+1] {Farbattribut links oben}
  262.     {$IFNDEF DOS}
  263.     OR ah,ah {schwarz auf schwarz?}
  264.     jnz @@colour_alright
  265.     MOV ah,White
  266. @@colour_alright:
  267.     {$ENDIF}
  268.     MOV al,space
  269.     REP stosw
  270.   END;
  271.   GotoXY(1,1);
  272. END;
  273. {$ENDIF}
  274.  
  275. PROCEDURE newmouseroutine;FAR;ASSEMBLER;
  276.  
  277. ASM
  278. END;
  279.  
  280. PROCEDURE mouse_off;ASSEMBLER;
  281.  
  282. ASM
  283.   CMP [mouse_not_found],TRUE
  284.   JE @@ende
  285.   MOV ax,$16 {Mauszustand sichern}
  286.   MOV bx,[mousebufsize]
  287.   LES dx,mousebuffer
  288.   int $33
  289.   MOV ax,$0C {neue Mausroutine}
  290.   lea dx,newmouseroutine
  291.   PUSH cs
  292.   POP ES
  293.   XOR cx,cx  {gar nicht aufrufen}
  294.   int $33
  295.   MOV ax,2 {Mauscursor aus}
  296.   int $33
  297. @@ende:
  298. END;
  299.  
  300. PROCEDURE mouse_on;ASSEMBLER;
  301.  
  302. ASM
  303.   CMP [mouse_not_found],TRUE
  304.   JE @@ende
  305.   MOV ax,$17 {Mauszustand wiederherstellen}
  306.   LES dx,mousebuffer
  307.   MOV bx,[mousebufsize]
  308.   int $33
  309. @@ende:
  310. END;
  311.  
  312. PROCEDURE Swap_Cursor;ASSEMBLER;
  313.  
  314. ASM
  315.   MOV ah,3
  316.   XOR bh,bh
  317.   int $10
  318.   XCHG cx,[cursor]
  319.   MOV ah,1
  320.   MOV al,[Acceptable_Video_Mode]
  321.   int $10
  322. END;
  323.  
  324. PROCEDURE Save_Screen;
  325.  
  326. {Bildschirmspeicher sichern (nur 80*25-Bildschirm)}
  327.  
  328. BEGIN
  329.   x:=WhereX;
  330.   y:=WhereY;
  331.   userscreen:=screenptr^; {Bildschirm sichern}
  332.   screen_swapped:=TRUE;
  333. END;
  334.  
  335. PROCEDURE Restore_Screen;
  336.  
  337. {Bildschirmspeicher wiederherstellen
  338.  (nur 80*25-Bildschirm)}
  339.  
  340. BEGIN
  341.   IF screen_swapped THEN BEGIN
  342.     GotoXY(x,y);
  343.     screenptr^:=userscreen
  344.   END
  345. END;
  346. {$ENDIF}
  347.  
  348. PROCEDURE popup_flag;ASSEMBLER;
  349.  
  350. ASM
  351.   db 0
  352. END;
  353.  
  354. PROCEDURE os_busy;ASSEMBLER;
  355.  
  356. ASM    {muß 0 sein bei popup}
  357.   db 1
  358. END;
  359.  
  360. {$IFDEF INT16}
  361.  
  362. PROCEDURE oldint16h;ASSEMBLER;
  363.  
  364. ASM
  365.   dw $9090
  366.   nop
  367. END;
  368.  
  369. PROCEDURE newint16h;ASSEMBLER;
  370.  
  371. ASM
  372.   PUSH bp
  373.   MOV bp,sp
  374.   PUSH WORD Ptr [bp+6] {Original-Flags}
  375.   Inc BYTE Ptr cs:[os_busy]
  376.   popf
  377.   POP bp
  378.   pushf
  379.   cli
  380.   CALL dword Ptr cs:[oldint16h]
  381.   pushf
  382.   Dec BYTE Ptr cs:[os_busy]
  383.   popf
  384.   retf 2  {ursprüngliche Flags raus}
  385. END;
  386.  
  387. {$ENDIF}
  388. PROCEDURE user_hotkey;ASSEMBLER;
  389. ASM
  390.   nop
  391. END;
  392.  
  393. PROCEDURE oldint9h;ASSEMBLER;
  394.  
  395. ASM
  396.   dw $9090
  397.   nop
  398. END;
  399.  
  400. PROCEDURE newint9h;ASSEMBLER;
  401.  
  402. ASM
  403.   pushf
  404.   {$IFDEF KEYBD}
  405.   Inc BYTE Ptr cs:[os_busy]
  406.   {$ENDIF}
  407.   CALL dword Ptr cs:[oldint9h]
  408.   {$IFDEF KEYBD}
  409.   Dec BYTE Ptr cs:[os_busy]
  410.   {$ENDIF}
  411.   sti
  412.   PUSH ax
  413.   PUSH ds
  414.   MOV ax,$40
  415.   MOV ds,ax
  416.   MOV ax,WORD Ptr cs:[user_hotkey]
  417.   AND ax,WORD Ptr ds:[$17]
  418.   CMP ax,WORD Ptr cs:[user_hotkey]
  419.   JNE @@no_hotkey
  420.   MOV BYTE Ptr cs:[popup_flag],TRUE
  421. @@no_hotkey:
  422.   POP ds
  423.   POP ax
  424.   iret
  425. END;
  426.  
  427. {$IFDEF KEYBD}
  428. {$IFNDEF CRT}
  429. FUNCTION KeyPressed:BOOLEAN;ASSEMBLER;
  430.  
  431. ASM
  432.   MOV ax,$100
  433.   OR [extended_key],al
  434.   jnz @@TRUE
  435.   int $16
  436.   MOV al,FALSE
  437.   jz @@FALSE
  438. @@TRUE:
  439.   Inc ax
  440. @@FALSE:
  441. END;
  442.  
  443. FUNCTION ReadKey:CHAR;ASSEMBLER;
  444.  
  445. ASM
  446. {$IFDEF DOS}
  447. @@same_thing_once_more:
  448.   CALL KeyPressed
  449.   OR al,al
  450.   jnz @@cont
  451.   XOR ax,ax
  452.   int $28 {DOS Idle, alte Version}
  453.   MOV ax,$1680
  454.   int $2F {DOS Idle, neue Version}
  455.   JMP @@same_thing_once_more
  456. @@cont:
  457. {$ENDIF}
  458.   XOR ax,ax
  459.   XCHG al,[extended_key]
  460.   OR al,al
  461.   jnz @@Ok
  462.   int $16
  463.   OR al,al
  464.   jnz @@Ok
  465.   MOV [extended_key],ah
  466. @@Ok:
  467. END;
  468. {$ENDIF}
  469. PROCEDURE Wait4Ctrl;
  470.  
  471. BEGIN
  472.   StrgWrite(#13#10'Weiter ---> <Ctrl>-Taste '+
  473.       '(bzw. <Strg>-Taste) drücken...');
  474.   ASM
  475.     MOV ax,40H
  476.     MOV ES,ax
  477.     MOV di,17H
  478.     MOV bl,Ctrl
  479. @@another_loop:
  480.     {$IFDEF DOS}
  481.     XOR ax,ax
  482.     int $28 {DOS Idle, alte Version}
  483.     MOV ax,$1680
  484.     int $2F {DOS Idle, neue Version}
  485.     {$ENDIF}
  486.     test bl,BYTE Ptr ES:[di]
  487.     jz @@another_loop
  488.   END
  489. END;
  490. {$ENDIF}
  491.  
  492. {$IFDEF SCRN}
  493. PROCEDURE oldint10h;ASSEMBLER;
  494.  
  495. ASM
  496.   dw $9090
  497.   nop
  498. END;
  499.  
  500. PROCEDURE newint10h;ASSEMBLER;
  501.  
  502. ASM
  503.   pushf
  504.   Inc BYTE Ptr cs:[os_busy]
  505.   CALL dword Ptr cs:[oldint10h]
  506.   Dec BYTE Ptr cs:[os_busy]
  507.   iret
  508. END;
  509.  
  510. PROCEDURE oldint33h;ASSEMBLER;
  511.  
  512. ASM
  513.   dw $9090
  514.   nop
  515. END;
  516.  
  517. PROCEDURE newint33h;ASSEMBLER;
  518.  
  519. ASM
  520.   pushf
  521.   Inc BYTE Ptr cs:[os_busy]
  522.   CALL dword Ptr cs:[oldint33h]
  523.   Dec BYTE Ptr cs:[os_busy]
  524.   iret
  525. END;
  526. {$ENDIF}
  527.  
  528. PROCEDURE oldint13h;ASSEMBLER;
  529.  
  530. ASM
  531.   dw $9090
  532.   nop
  533. END;
  534.  
  535. PROCEDURE newint13h;ASSEMBLER;
  536.  
  537. ASM
  538.   PUSH bp
  539.   MOV bp,sp
  540.   PUSH WORD Ptr [bp+6] {Original-Flags}
  541.   Inc BYTE Ptr cs:[os_busy]
  542.   popf
  543.   POP bp
  544.   pushf
  545.   cli
  546.   CALL dword Ptr cs:[oldint13h]
  547.   pushf
  548.   Dec BYTE Ptr cs:[os_busy]
  549.   popf
  550.   retf 2  {ursprüngliche Flags raus}
  551. END;
  552.  
  553. PROCEDURE newint23h;ASSEMBLER;
  554.  
  555. ASM
  556.   clc
  557.   retf 2
  558. END;
  559.  
  560. {$IFDEF DOS}
  561.  
  562. PROCEDURE newint1Bh;ASSEMBLER;
  563.  
  564. ASM
  565.   iret
  566. END;
  567.  
  568. PROCEDURE oldint25h;ASSEMBLER;
  569.  
  570. ASM
  571.   dw $9090
  572.   nop
  573. END;
  574.  
  575. PROCEDURE newint25h;FAR;ASSEMBLER;
  576.  
  577. ASM
  578.   pushf
  579.   Inc BYTE Ptr cs:[os_busy]
  580.   popf
  581.   CALL dword Ptr cs:[oldint25h]
  582.   pushf
  583.   Dec BYTE Ptr cs:[os_busy]
  584.   popf
  585. END;
  586.  
  587. PROCEDURE oldint26h;ASSEMBLER;
  588.  
  589. ASM
  590.   dw $9090
  591.   nop
  592. END;
  593.  
  594. PROCEDURE newint26h;FAR;ASSEMBLER;
  595.  
  596. ASM
  597.   pushf
  598.   Inc BYTE Ptr cs:[os_busy]
  599.   popf
  600.   CALL dword Ptr cs:[oldint26h]
  601.   pushf
  602.   Dec BYTE Ptr cs:[os_busy]
  603.   popf
  604. END;
  605.  
  606. {$IFNDEF NOSWAP}
  607. PROCEDURE crit_dos_section;ASSEMBLER;
  608.  
  609. ASM
  610.   dw 0
  611. END;
  612.  
  613. PROCEDURE oldint2ah;ASSEMBLER;
  614.  
  615. ASM
  616.   dw $9090
  617.   nop
  618. END;
  619.  
  620. PROCEDURE newint2ah;ASSEMBLER;
  621.  
  622. ASM
  623.   pushf
  624.   CMP ah,$82
  625.   JE @@end_crit_sec0to7
  626.   CMP al,7
  627.   pushf
  628.   CMP ah,$80
  629.   JE @@begin_critical_section
  630.   CMP ah,$81
  631.   JE @@end_critical_section
  632.   popf
  633. @@cont:
  634.   popf
  635.   JMP dword Ptr cs:[oldint2ah]
  636. @@end_crit_sec0to7:
  637.   MOV BYTE Ptr cs:[crit_dos_section],0
  638.   JMP @@cont
  639. @@begin_critical_section:
  640.   popf
  641.   ja @@inc_greater_7
  642.   Inc BYTE Ptr cs:[crit_dos_section]
  643.   JMP @@cont
  644. @@inc_greater_7:
  645.   Inc BYTE Ptr cs:[crit_dos_section+1]
  646.   JMP @@cont
  647. @@end_critical_section:
  648.   popf
  649.   ja @@dec_greater_7
  650.   Dec BYTE Ptr cs:[crit_dos_section]
  651.   JMP @@cont
  652. @@dec_greater_7:
  653.   Dec BYTE Ptr cs:[crit_dos_section+1]
  654.   JMP @@cont
  655. END;
  656. {$ENDIF}
  657.  
  658. PROCEDURE get_error_info;ASSEMBLER;
  659.  
  660. ASM
  661.   PUSH bp {außer SS:SP wird alles zerstört!}
  662.   MOV ah,$59
  663.   XOR bx,bx
  664.   int $21
  665.   PUSH ES
  666.   PUSH di
  667.   PUSH ax
  668.   MOV ax,Seg @data
  669.   MOV ES,ax
  670.   lea di,error_info
  671.   CLD
  672.   POP ax
  673.   stosw
  674.   MOV ax,bx
  675.   stosw
  676.   MOV ax,cx
  677.   stosw
  678.   MOV ax,dx
  679.   stosw
  680.   MOV ax,si
  681.   stosw
  682.   POP ax {DI}
  683.   stosw
  684.   MOV ax,ds
  685.   stosw
  686.   POP ax {ES}
  687.   stosw
  688.   XOR ax,ax
  689.   stosw
  690.   stosw
  691.   stosw
  692.   POP bp
  693.   PUSH ES
  694.   POP ds
  695. END;
  696.  
  697. PROCEDURE restore_error_info;ASSEMBLER;
  698.  
  699. ASM
  700.   lea dx,error_info {DS:DX}
  701.   MOV ax,$5D0A
  702.   int $21
  703. END;
  704.  
  705. PROCEDURE swap_dta;ASSEMBLER;
  706.  
  707. ASM
  708.   PUSH ds
  709.   MOV ah,$2F {DTA-Addr. ---> ES:BX}
  710.   int $21
  711.   MOV dx,WORD Ptr [old_dta_add]
  712.   MOV WORD Ptr [old_dta_add],bx
  713.   MOV ax,WORD Ptr [old_dta_add+2]
  714.   MOV WORD Ptr [old_dta_add+2],ES
  715.   MOV ds,ax
  716.   MOV ah,$1A {DS:DX ---> DTA-Addr.}
  717.   int $21
  718.   POP ds
  719. END;
  720.  
  721. PROCEDURE check_a20;ASSEMBLER;
  722.  
  723. ASM
  724.   CMP [dos_ver],$500 {ab DOS 5.0}
  725.   jb @@err_exit
  726.   XOR ax,ax
  727.   OR ax,WORD Ptr [xms_driver_add]
  728.   OR ax,WORD Ptr [xms_driver_add+2]
  729.   jz @@err_exit {Nullzeiger --> Ende}
  730.   MOV ah,07
  731.   CALL dword Ptr [xms_driver_add]
  732.   OR bl,bl
  733.   jz @@Exit
  734. @@err_exit:
  735.   MOV al,$FF
  736. @@Exit:
  737.   MOV [old_a20_state],al
  738. END;
  739.  
  740. PROCEDURE restore_a20;ASSEMBLER;
  741.  
  742. ASM
  743.   MOV ah,[old_a20_state]
  744.   CMP ah,$FF
  745.   JE @@Exit
  746.   MOV al,1
  747.   AND ah,al
  748.   XOR ah,al
  749.   ADD ah,5
  750.   CALL dword Ptr [xms_driver_add]
  751. @@Exit:
  752. END;
  753.  
  754. PROCEDURE swap_psp;ASSEMBLER;
  755.  
  756. ASM
  757.   MOV ah,$51 {aktives PSP holen}
  758.   int $21
  759.   XCHG bx,[old_psp]
  760.   MOV ah,$50 {aktives PSP setzen}
  761.   int $21
  762. END;
  763.  
  764. {$IFNDEF NOSWAP}
  765. PROCEDURE copy_mem;ASSEMBLER;
  766.  
  767. ASM
  768.   CLD {Achtung: Parameter in CX,SI,DI,DS,ES!}
  769.   cli
  770.   SHR cx,1
  771.   jnc @@words_only
  772.   MOVSB
  773. @@words_only:
  774.   REP movsw
  775.   sti
  776. END;
  777.  
  778. PROCEDURE save_dos_context;ASSEMBLER;
  779.  
  780. ASM
  781.   PUSH ds
  782.   MOV cx,[swap_size]
  783.   MOV ax,[swapped_dos_seg]
  784.   MOV ES,ax
  785.   XOR di,di
  786.   LDS si,crit_err_ptr
  787.   CALL copy_mem
  788.   POP ds
  789.   MOV [dos_swapped],TRUE
  790. END;
  791.  
  792. PROCEDURE restore_dos_context;ASSEMBLER;
  793.  
  794. ASM
  795.   CMP [dos_swapped],FALSE
  796.   JE @@ende
  797.   MOV cx,[swap_size]
  798.   LES di,crit_err_ptr
  799.   MOV ax,[swapped_dos_seg]
  800.   MOV [dos_swapped],FALSE
  801.   PUSH ds
  802.   MOV ds,ax
  803.   XOR si,si
  804.   CALL copy_mem
  805.   POP ds
  806. @@ende:
  807. END;
  808.  
  809. PROCEDURE int28h_busy;ASSEMBLER;
  810.  
  811. ASM
  812.   db 0
  813. END;
  814.  
  815. {$ENDIF}
  816.  
  817. PROCEDURE dos_setup;
  818.  
  819. BEGIN
  820.   GetCBreak(save_cbreak);
  821.   SetCBreak(FALSE);
  822.   get_error_info;
  823.   swap_dta;
  824.   swap_psp;
  825.   GetIntVec($1B,Prog_Vec_1Bh);
  826.   {$IFDEF CRT}
  827.   SetIntVec($1B,SaveInt1B);
  828.   {$ELSE}
  829.   SetIntVec($1B,@newint1Bh);
  830.   {$ENDIF}
  831.   GetIntVec($23,Prog_Vec_23h);
  832.   SetIntVec($23,@newint23h);
  833.   GetIntVec($24,Prog_Vec_24h);
  834.   SetIntVec($24,SaveInt24);
  835.   {$IFDEF CRT}
  836.   CheckBreak:=FALSE
  837.   {$ENDIF}
  838. END;
  839.  
  840. PROCEDURE dos_cleanup;
  841.  
  842. BEGIN
  843.   SetIntVec($1B,Prog_Vec_1Bh);
  844.   SetIntVec($23,Prog_Vec_23h);
  845.   SetIntVec($24,Prog_Vec_24h);
  846.   swap_psp;
  847.   swap_dta;
  848.   restore_error_info;
  849.   SetCBreak(save_cbreak)
  850. END;
  851.  
  852. {$ENDIF}
  853.  
  854. PROCEDURE swap_stack;NEAR;ASSEMBLER;
  855.  
  856. ASM
  857.   POP bx {Rücksprungadresse}
  858.   MOV ax,ss
  859.   CMP ax,[savess]
  860.   JE @@do_not_swap
  861.   XCHG ax,[savess]
  862.   cli  {keine Unterbrechungen
  863.        bei halb umgesetztem Stack}
  864.   MOV ss,ax
  865.   XCHG sp,[savesp]
  866. @@do_not_swap:
  867.   PUSH bx
  868.   {sti folgt!}
  869. END;
  870.  
  871. FUNCTION os_safe:BOOLEAN;ASSEMBLER;
  872.  
  873. ASM
  874.   XOR ax,ax
  875.   CMP BYTE Ptr cs:[os_busy],al
  876.   JNE @@unsafe
  877.   {$IFDEF DOS}
  878.   LES di,crit_err_ptr
  879.   CMP BYTE Ptr ES:[di],al
  880.   JNE @@unsafe
  881.   LES di,indos_ptr
  882.   CMP BYTE Ptr ES:[di],1
  883.   jb @@safe
  884.   {$IFNDEF UNSAFE}
  885.   ja @@unsafe
  886.   {$ENDIF}
  887.   {$IFNDEF NOSWAP}
  888.   {$IFNDEF UNSAFE}
  889.   CMP BYTE Ptr cs:[int28h_busy],1
  890.   JNE @@unsafe
  891.   {$ENDIF}
  892.   CMP [dos_ver],$400 {nicht für DOS 4.0}
  893.   JE @@unsafe
  894.   CMP WORD Ptr cs:[crit_dos_section],ax
  895.   JNE @@unsafe
  896.   CALL save_dos_context
  897.   {$ELSE}
  898.   JMP @@unsafe
  899.   {$ENDIF}
  900.   {$ENDIF}
  901. @@safe:
  902.   Inc ax
  903. @@unsafe:
  904. END;
  905.  
  906. PROCEDURE timerint_busy;ASSEMBLER;
  907.  
  908. ASM
  909.   db 0
  910. END;
  911.  
  912. PROCEDURE oldint8h;ASSEMBLER;
  913.  
  914. ASM
  915.   dw $9090
  916.   nop
  917. END;
  918.  
  919. PROCEDURE activate_tsr;ASSEMBLER;
  920.  
  921. ASM
  922.   PUSH ax
  923.   PUSH bx
  924.   PUSH ds
  925.   MOV ax,Seg @data
  926.   MOV ds,ax {Turbo DS wiederherstellen}
  927.   CALL swap_stack {Turbo Stack wiederherstellen}
  928.   sti
  929.   PUSH cx
  930.   PUSH dx
  931.   PUSH si
  932.   PUSH di
  933.   PUSH ES
  934.   {$IFDEF DOS}
  935.   CALL check_a20
  936.   {$ENDIF}
  937.   CALL os_safe
  938.   OR al,al
  939.   jz @@not_activated
  940.   {$IFDEF DOS}
  941.   CALL dos_setup
  942.   {$ENDIF}
  943.   {$IFDEF SCRN}
  944.   CALL mouse_off
  945.   {$ENDIF}
  946.   CALL user_proc
  947.   XOR al,1
  948.   MOV BYTE Ptr cs:[popup_flag],al
  949.   {$IFDEF SCRN}
  950.   CALL mouse_on
  951.   {$ENDIF}
  952.   {$IFDEF DOS}
  953.   CALL dos_cleanup
  954.   {$IFNDEF NOSWAP}
  955.   CALL restore_dos_context
  956.   {$ENDIF}
  957.   CALL restore_a20
  958.   {$ENDIF}
  959. @@not_activated:
  960.   POP ES
  961.   POP di
  962.   POP si
  963.   POP dx
  964.   POP cx
  965.   CALL swap_stack
  966.   POP ds
  967.   POP bx
  968.   POP ax
  969. END;
  970.  
  971. PROCEDURE newint8h;ASSEMBLER;
  972.  
  973. ASM
  974.   pushf
  975.   CALL dword Ptr cs:[oldint8h]
  976.   cli
  977.   CMP BYTE Ptr cs:[popup_flag],0
  978.   JNE @@popup_requested
  979.   iret
  980. @@popup_requested:
  981.   Inc BYTE Ptr cs:[timerint_busy]
  982.   CMP BYTE Ptr cs:[timerint_busy],1
  983.   JNE @@Exit
  984.   CALL activate_tsr
  985. @@Exit:
  986.   Dec BYTE Ptr cs:[timerint_busy]
  987.   iret
  988. END;
  989.  
  990. {$IFDEF DOS}
  991. {$IFNDEF NOSWAP}
  992.  
  993. PROCEDURE oldint28h;ASSEMBLER;
  994.  
  995. ASM
  996.   dw $9090
  997.   nop
  998. END;
  999.  
  1000. PROCEDURE newint28h;ASSEMBLER;
  1001.  
  1002. ASM
  1003.   pushf
  1004.   CALL dword Ptr cs:[oldint28h]
  1005.   cli
  1006.   CMP BYTE Ptr cs:[popup_flag],0
  1007.   JNE @@popup_requested
  1008.   iret
  1009. @@popup_requested:
  1010.   Inc BYTE Ptr cs:[timerint_busy]
  1011.   CMP BYTE Ptr cs:[timerint_busy],1
  1012.   JNE @@Exit
  1013.   Inc BYTE Ptr cs:[int28h_busy]
  1014.   CALL activate_tsr
  1015.   Dec BYTE Ptr cs:[int28h_busy]
  1016. @@Exit:
  1017.   Dec BYTE Ptr cs:[timerint_busy]
  1018.   iret
  1019. END;
  1020. {$ENDIF}
  1021. {$ENDIF}
  1022.  
  1023. {$IFDEF SCRN}
  1024. PROCEDURE start_transient;ASSEMBLER;
  1025.  
  1026. ASM
  1027. {!!!ab hier wird der Code im TSR überschrieben!!!}
  1028. END;
  1029. {$ENDIF}
  1030.  
  1031. FUNCTION reserve_block(how_much:WORD):WORD;ASSEMBLER;
  1032.  
  1033. ASM
  1034.   MOV ax,[PrefixSeg]
  1035.   Dec ax
  1036.   MOV ES,ax {MCB für PSP}
  1037.   PUSH WORD Ptr ES:[3] {Paras Programm}
  1038.   Inc ax
  1039.   MOV ES,ax  {PrefixSeg}
  1040.   MOV ah,$4A
  1041.   MOV bx,$FFFF
  1042.   int $21 {max. Paras Programm in BX}
  1043.   jnc @@error
  1044.   CMP ax,8
  1045.   JNE @@error
  1046.   MOV dx,bx
  1047.   MOV ah,$4A
  1048.   int $21 {Speicher zu!}
  1049.   jc @@error
  1050.   MOV bx,[how_much]
  1051.   ADD bx,15
  1052.   MOV cl,4
  1053.   SHR bx,cl
  1054.   PUSH bx {Paras neuer Block}
  1055.   MOV ah,$48 {Speicher-Fragment groß genug?}
  1056.   int $21
  1057.   POP cx
  1058.   jnc @@Ok {...ja ---> dann o.k.}
  1059.   MOV bx,dx {max. Blockgröße Programm}
  1060.   SUB bx,cx {-neuer Block}
  1061.   Dec bx    {-1 Para (MCB)}
  1062.   POP ax    {Paras urspr. Programm}
  1063.   PUSH ax
  1064.   CMP bx,ax {kleiner als aktuell?}
  1065.   jb @@error
  1066.   MOV ah,$4A {PSP-Block schrumpfen}
  1067.   int $21
  1068.   jc @@error
  1069.   MOV bx,cx
  1070.   MOV ah,$48 {Speicher für auszulagernde DOS-Daten}
  1071.   int $21
  1072.   jc @@error
  1073. @@Ok:
  1074.   POP bx
  1075.   PUSH ax
  1076.   MOV ah,$4A
  1077.   int $21
  1078.   POP ax
  1079.   JMP @@terminate_proc
  1080. @@error:
  1081.   XOR ax,ax
  1082.   POP bx
  1083. @@terminate_proc:
  1084. END;
  1085.  
  1086. {$IFDEF DOS}
  1087. PROCEDURE get_flags_and_swap_area;ASSEMBLER;
  1088.  
  1089. ASM
  1090.   PUSH ds
  1091.   XOR ax,ax
  1092.   MOV WORD Ptr [crit_err_ptr],ax
  1093.   MOV WORD Ptr [crit_err_ptr+2],ax
  1094.   XOR bx,bx
  1095.   MOV ES,bx
  1096.   MOV ah,$34
  1097.   int $21 {InDos-Flag-Adresse holen}
  1098.   MOV WORD Ptr [indos_ptr],bx
  1099.   MOV WORD Ptr [indos_ptr+2],ES
  1100.   Dec bx  {ES:BX ---> critical error flag}
  1101. @@call_5d06:
  1102.   MOV ax,$5D06 {crit.error flag+}
  1103.   int $21      {DOS-Swapbereich holen}
  1104.   jc @@error
  1105.   PUSH ds
  1106.   POP di
  1107.   POP ds
  1108.   PUSH ds
  1109.   MOV ax,ES
  1110.   CMP di,ax
  1111.   JNE @@error
  1112.   CMP bx,si
  1113.   JNE @@error
  1114.   {$IFNDEF NOSWAP}
  1115.   CMP [dos_ver],$400
  1116.   JE @@cannot_swap
  1117.   MOV [swap_size],cx
  1118.   PUSH di {eigentlich...}
  1119.   PUSH si {...unnötig}
  1120.   PUSH cx {Parameter}
  1121.   CALL reserve_block
  1122.   POP si  {eigentlich...}
  1123.   POP di  {unnötig...}
  1124.   OR ax,ax
  1125.   jz @@error
  1126.   MOV WORD Ptr [swapped_dos_seg],ax
  1127. @@cannot_swap:
  1128.   {$ENDIF}
  1129.   MOV WORD Ptr [crit_err_ptr],si
  1130.   MOV WORD Ptr [crit_err_ptr+2],di
  1131. @@error:
  1132.   POP ds
  1133. END;
  1134.  
  1135. PROCEDURE get_xms_driver_add;ASSEMBLER;
  1136.  
  1137. ASM
  1138.   CMP [dos_ver],$500 {ab DOS 5.0}
  1139.   jb @@Exit
  1140.   MOV ax,$4300 {XMS-Treiber installiert?}
  1141.   int $2F
  1142.   XOR bx,bx
  1143.   MOV ES,bx
  1144.   CMP al,$80
  1145.   JNE @@Exit
  1146.   MOV ax,$4310 {Treiber-Adresse in ES:BX holen}
  1147.   int $2F
  1148. @@Exit:
  1149.   MOV WORD Ptr [xms_driver_add],bx
  1150.   MOV WORD Ptr [xms_driver_add+2],ES
  1151. END;
  1152. {$ENDIF}
  1153.  
  1154. {$IFDEF SCRN}
  1155. FUNCTION true_DosVer:WORD;ASSEMBLER;
  1156.  
  1157. ASM
  1158.   MOV ax,$3306 {DOS-Version holen (ab DOS 5.0)}
  1159.   XOR bx,bx    {BH:Hauptversion,BL:Nebenversion}
  1160.   int $21
  1161.   MOV ax,bx
  1162.   CMP al,5 {DOS >=5.0?}
  1163.   jnb @@dos_5_or_above
  1164.   MOV ax,$3000 {entspr. DosVersion}
  1165.   int $21
  1166. @@dos_5_or_above:
  1167.   XCHG ah,al {Hauptversion höherwertig}
  1168. END;
  1169.  
  1170. PROCEDURE init_mouse;ASSEMBLER;
  1171.  
  1172. ASM
  1173.   XOR ax,ax
  1174.   int $33  {Maus da?}
  1175.   Inc ax
  1176.   PUSH ax
  1177.   jnz @@end_routine
  1178.   XOR bx,bx
  1179.   MOV ax,$15
  1180.   int $33
  1181.   OR bx,bx         {BX immer noch 0?}
  1182.   jnz @@compatible {sonst uralter/inkompatibler Treiber}
  1183. @@no_mouse:
  1184.   POP ax
  1185.   Inc ax
  1186.   PUSH ax
  1187.   JMP @@end_routine
  1188. @@compatible:
  1189.   MOV [mousebufsize],bx
  1190.   lea ax,end_transient
  1191.   lea di,start_transient
  1192.   MOV WORD Ptr [mousebuffer],di {Mauszustand ab}
  1193.   MOV WORD Ptr [mousebuffer+2],cs {start_transient puffern}
  1194.   SUB ax,di
  1195.   SUB ax,10 {sicherheitshalber}
  1196.   CMP ax,bx {genügend Platz im Codesegment?}
  1197.   JAE @@end_routine
  1198.   CMP BYTE Ptr [dos_ver+1],3 {unter DOS 2.x...}
  1199.   jb @@no_mouse       {...geht reserve_block schief!}
  1200.   PUSH bx
  1201.   CALL reserve_block
  1202.   OR ax,ax
  1203.   jz @@no_mouse
  1204.   MOV WORD Ptr [mousebuffer+2],ax
  1205.   MOV WORD Ptr [mousebuffer],0
  1206. @@end_routine:
  1207.   POP ax
  1208.   MOV [mouse_not_found],al
  1209. END;
  1210. {$ENDIF}
  1211.  
  1212. FUNCTION Setup_TSR(popup_proc:TSR_Proc;hotkey,unused_stack:WORD):BOOLEAN;
  1213.  
  1214. BEGIN
  1215. {$IFDEF SCRN}
  1216.   IF addr_6845=$3D4 THEN BEGIN
  1217.     {farbfähige Grafikkarte}
  1218.     screenptr:=Ptr($B800,0);
  1219.     cursor:=$607;
  1220.     Acceptable_Video_Mode:=3
  1221.   END
  1222.   ELSE IF addr_6845=$3B4 THEN BEGIN
  1223.     {monochrom}
  1224.     screenptr:=Ptr($B000,0);
  1225.     cursor:=$A0B;
  1226.     Acceptable_Video_Mode:=7
  1227.   END
  1228.   ELSE BEGIN
  1229.     {????}
  1230.     StrgWrite(#7#13#10'Grafikkarte '+
  1231.              'nicht einzuordnen'#13#10);
  1232.     Setup_TSR:=FALSE;
  1233.     Exit
  1234.   END;
  1235.   dos_ver:=true_DosVer;
  1236. {$ENDIF}
  1237.   ASM
  1238.     MOV ax,[hotkey]
  1239.     MOV WORD Ptr cs:[user_hotkey],ax
  1240.   END;
  1241.   user_proc:=popup_proc;
  1242.   savesp:=SPtr-unused_stack;
  1243.   savess:=SSeg;
  1244.   SetIntVec($23,@newint23h); {Ctrl-C aus!!}
  1245. {$IFDEF DOS}
  1246.   IF dos_ver<$30A THEN BEGIN
  1247.     StrgWrite(#7#13#10'Dies Programm benötigt '+
  1248.     'DOS-Versionen >=3.10'#13#10);
  1249.     Setup_TSR:=FALSE;
  1250.     Exit
  1251.   END;
  1252.   old_psp:=PrefixSeg;
  1253.   old_dta_add:=Ptr(PrefixSeg,$80);
  1254.   get_xms_driver_add;
  1255.   get_flags_and_swap_area;
  1256.   IF (crit_err_ptr=NIL) OR (indos_ptr=NIL) THEN BEGIN
  1257.     StrgWrite(#7#13#10'Fehler bei '+
  1258.     'der Initialisierung.'#13#10);
  1259.     Setup_TSR:=FALSE;
  1260.     Exit
  1261.   END;
  1262. {$ENDIF}
  1263.   GetCBreak(save_cbreak);
  1264.   SetCBreak(FALSE);
  1265.   SetIntVec(0,SaveInt00);
  1266.   GetIntVec($8,POINTER(@oldint8h^));
  1267.   SetIntVec($8,@newint8h);
  1268.   GetIntVec($9,POINTER(@oldint9h^));
  1269.   SetIntVec($9,@newint9h);
  1270. {$IFDEF SCRN}
  1271.   GetIntVec($10,POINTER(@oldint10h^));
  1272.   SetIntVec($10,@newint10h);
  1273.   GetIntVec($33,POINTER(@oldint33h^));
  1274.   IF POINTER(@oldint33h^)<>NIL THEN BEGIN
  1275.     init_mouse;
  1276.     SetIntVec($33,@newint33h)
  1277.   END
  1278.   ELSE
  1279.     mouse_not_found:=TRUE; {evtl. bei DOS 2.x}
  1280. {$ENDIF}
  1281.   GetIntVec($13,POINTER(@oldint13h^));
  1282.   SetIntVec($13,@newint13h);
  1283. {$IFDEF INT16}
  1284.   GetIntVec($16,POINTER(@oldint16h^));
  1285.   SetIntVec($16,@newint16h);
  1286. {$ENDIF}
  1287. {$IFDEF DOS}
  1288.   GetIntVec($24,SaveInt24);
  1289.   GetIntVec($25,POINTER(@oldint25h^));
  1290.   SetIntVec($25,@newint25h);
  1291.   GetIntVec($26,POINTER(@oldint26h^));
  1292.   SetIntVec($26,@newint26h);
  1293.   {$IFNDEF NOSWAP}
  1294.   GetIntVec($28,POINTER(@oldint28h^));
  1295.   SetIntVec($28,@newint28h);
  1296.   GetIntVec($2A,POINTER(@oldint2ah^));
  1297.   SetIntVec($2A,@newint2ah);
  1298.   {$ENDIF}
  1299. {$ENDIF}
  1300.   GetIntVec($1B,Prog_Vec_1Bh);
  1301.   SetIntVec($1B,SaveInt1B);
  1302.   SaveInt1B:=Prog_Vec_1Bh;
  1303.   SetCBreak(save_cbreak);
  1304.   ASM
  1305.     Dec BYTE Ptr cs:[os_busy]
  1306.   END;
  1307.   Setup_TSR:=TRUE
  1308. END;
  1309.  
  1310. PROCEDURE make_resident_without_heap;ASSEMBLER;
  1311.  
  1312. {Darf erst nach setup_tsr aufgerufen werden!}
  1313. {Heap und Overlay-Puffer werden freigegeben!}
  1314.  
  1315. ASM
  1316.   MOV dx,[savess]
  1317.   SUB dx,[PrefixSeg]
  1318.   MOV ax,[savesp]
  1319.   ADD ax,15
  1320.   MOV cl,4
  1321.   SHR ax,cl
  1322.   ADD dx,ax
  1323.   MOV ax,$3100 {keep(0)}
  1324.   int $21
  1325. END;
  1326.  
  1327. {$IFDEF SCRN}
  1328. PROCEDURE end_transient;ASSEMBLER;
  1329. ASM
  1330. {globale Markierung für das Ende
  1331. des überschreibbaren Bereichs}
  1332. END;
  1333. {$ENDIF}
  1334.  
  1335. END.
  1336.