home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / buffy / buffy.asm
Assembly Source File  |  1994-02-14  |  34KB  |  969 lines

  1. TITLE   BUFFY.ASM
  2. PAGE    60,132
  3. ;
  4. ;
  5. ;               
  6. ;
  7. ;
  8. ;
  9. ;
  10. ;
  11. ;
  12. ;
  13. ;
  14. ;
  15. ;----------------------------------------------------------------------------
  16. PUBLIC  initialize
  17. max_value = 36
  18.  
  19. ;----------------------------------------------------------------------------
  20. ;----------------------------------------------------------------------------
  21. ;----------------------------------------------------------------------------
  22. ;
  23. ; This data is used by both interupt service routines (ISR's)
  24. ;
  25. ;----------------------------------------------------------------------------
  26.  
  27. BUFFY_DATA      SEGMENT PARA    PUBLIC  'DATA'
  28.                 db      "Unique StringXYZ"
  29. psp_pointer     dw      (?)
  30. isr_2f_seg      dw      (?)
  31. int_2f_id       db      (?)
  32. error_code      db      (?)
  33. counter         dw      (?)
  34. screen_buffer   dw      (?)
  35. org_screen      dw      80 * 25         dup     (?)
  36. display_lines   label   word
  37.  
  38. db "    WW       WW  EEEEEEE   LL       CCCCCC   OOOOO    MMM   MMM   EEEEEEE       "
  39. db "    WW       WW  EE        LL      CC       OO   OO  MM  M M  MM  EE            "
  40. db "    WW   W   WW  EEEE      LL      CC       OO   OO  MM   M   MM  EEEE          "
  41. db "    WW  W W  WW  EE        LL      CC       OO   OO  MM       MM  EE            "
  42. db "     WWW   WWW   EEEEEEE   LLLLLLL  CCCCCC   OOOOO   MM       MM  EEEEEEE       "
  43. db "                                                                                "
  44. db "                          TTTTTTTTT   OOOOO                                     "
  45. db "                             TT      OO   OO                                    "
  46. db "                             TT      OO   OO                                    "
  47. db "                             TT      OO   OO                                    "
  48. db "                             TT       OOOOO                                     "
  49. db "                                                                                "
  50. db "         BBBBBB    UU   UU  FFFFFFF  FFFFFFF  YY    YY   ''   SSSSSS            "
  51. db "         BB   BB   UU   UU  FF       FF        YY  YY   ''    SS    S           "
  52. db "         BB  BB    UU   UU  FFFFF    FFFFF       YY             SS              "
  53. db "         BB   BB   UU   UU  FF       FF          YY          S    SS            "
  54. db "         BBBBBB     UUUUU   FF       FF          YY           SSSSSS            "
  55. db "                                                                                "
  56. db "             WW       WW    OOOOO    RRRRRR     LL        DDDDDD                "
  57. db "             WW       WW   OO   OO   RR   RR    LL        DD   DD               "
  58. db "             WW   W   WW   OO   OO   RRRRRR     LL        DD   DD               "
  59. db "             WW  W W  WW   OO   OO   RR   RR    LL        DD   DD               "
  60. db "              WWW   WWW     OOOOO    RR    RR   LLLLLLL   DDDDDD                "
  61. db "                                                                                "
  62. db "                       Press any key to return to reality                       "
  63.  
  64. screen_length = $ - display_lines
  65.  
  66.  
  67. BUFFY_DATA      ENDS
  68.  
  69. ;----------------------------------------------------------------------------
  70. ;----------------------------------------------------------------------------
  71. ;----------------------------------------------------------------------------
  72.  
  73. MULTIPLEX_RTN   SEGMENT PARA    PUBLIC  'CODE'
  74.         ASSUME CS:MULTIPLEX_RTN, DS:NOTHING, ES:NOTHING
  75. int_2f_rtn      PROC    FAR
  76.         push    bx
  77.         push    ds     
  78.  
  79. ;----------------------------------------------------------------------------
  80. ; Check to see if the multiplex id is ours.
  81. ; If it is, set ES to point to our copy of BUFFY_DATA, AL=FF and return.
  82. ; If not, restore registers and call next interupt vector in line.
  83. ;----------------------------------------------------------------------------
  84.         mov     bx,BUFFY_DATA
  85.         mov     ds,bx
  86.         ASSUME  DS:BUFFY_DATA, ES:NOTHING
  87.         cmp     ah,int_2f_id
  88.         jne     exit_multiplex_rtn
  89.  
  90.         mov     es,bx
  91.         pop     ds
  92.         pop     bx
  93.         mov     al,0FFh
  94.         iret
  95.  
  96. exit_multiplex_rtn:
  97.         pop     ds
  98.         pop     bx
  99.         ASSUME DS:NOTHING, ES:NOTHING
  100.         jmp     DWORD PTR cs:next_int_2f
  101.  
  102. next_int_2f     dd      (?)
  103.  
  104. int_2f_rtn      ENDP
  105. MULTIPLEX_RTN   ENDS
  106. ;----------------------------------------------------------------------------
  107. ;----------------------------------------------------------------------------
  108. ;----------------------------------------------------------------------------
  109.  
  110. KEYB_INTR_RTN   SEGMENT PARA    PUBLIC  'CODE'
  111.         ASSUME CS:KEYB_INTR_RTN, DS:NOTHING, ES:NOTHING
  112. keyb_isr        PROC    FAR
  113.         push    ax
  114.         push    ds
  115.         pushf
  116.  
  117.         mov     ax,BUFFY_DATA
  118.         mov     ds,ax
  119.         ASSUME  DS:BUFFY_DATA, ES:NOTHING
  120.  
  121.         cmp     counter,max_value
  122.         jng     exit_keyb_rtn
  123.         call    NEAR PTR restore_screen
  124.  
  125. exit_keyb_rtn:
  126.         mov     counter,0
  127.         popf
  128.         pop     ds
  129.         pop     ax
  130.         ASSUME  DS:NOTHING, ES:NOTHING
  131.  
  132.         jmp     DWORD PTR cs:org_keyb_vector
  133.  
  134. keyb_isr        ENDP
  135. ;----------------------------------------------------------------------------
  136. ; Copy the screen into the screen buffer.
  137. ;----------------------------------------------------------------------------
  138.  
  139. restore_screen  PROC    NEAR
  140.         ASSUME  DS:BUFFY_DATA
  141.         push    cx
  142.         push    si
  143.         push    di
  144.         push    es
  145.  
  146. ;----------------------------------------------------------------------------
  147. ; Set the destination pointer (ES:DI) to B000:screen_buffer
  148. ;----------------------------------------------------------------------------
  149.         mov     di,0B000h
  150.         mov     es,di
  151.         mov     di,screen_buffer
  152.  
  153. ;----------------------------------------------------------------------------
  154. ; Set the source pointer (DS:SI) to BUFFY_DATA:org_screen
  155. ;----------------------------------------------------------------------------
  156.         mov     si,OFFSET org_screen
  157.  
  158. ;----------------------------------------------------------------------------
  159. ; Copy the original screen back onto the display.
  160. ;----------------------------------------------------------------------------
  161.         mov     cx,80 * 25
  162.         cld
  163.         rep     movsw
  164.  
  165.         pop     es
  166.         pop     di
  167.         pop     si
  168.         pop     cx
  169.  
  170.         ret
  171.  
  172. restore_screen  ENDP
  173.  
  174. org_keyb_vector dd      (?)
  175. KEYB_INTR_RTN   ENDS
  176.  
  177. ;----------------------------------------------------------------------------
  178. ;----------------------------------------------------------------------------
  179. ;----------------------------------------------------------------------------
  180.  
  181. CLK_INTR_RTN    SEGMENT PARA    PUBLIC  'CODE'
  182.         ASSUME CS:CLK_INTR_RTN, DS:NOTHING, ES:NOTHING
  183. clk_isr         PROC    FAR
  184.         push    ax
  185.         push    ds
  186.         pushf
  187.  
  188.         mov     ax,BUFFY_DATA
  189.         mov     ds,ax
  190.         ASSUME DS:BUFFY_DATA, ES:NOTHING
  191.  
  192. ;----------------------------------------------------------------------------
  193. ; Check the counter value.
  194. ; If the counter > max_value the screen has already been swapped.
  195. ; If the counter = max_value then try to swap the screen.
  196. ; If the counter < max_value then increment the counter.
  197. ;----------------------------------------------------------------------------
  198.         cmp     counter,max_value
  199.         je      attempt_swap
  200.         jl      increment_and_exit      ; Still counting up to screen swap.
  201.         jg      no_action               ; Screen has already been swapped.
  202.  
  203. increment_and_exit:
  204.         inc     counter
  205.  
  206. no_action:
  207.         popf
  208.         pop     ds
  209.         pop     ax
  210.         ASSUME DS:NOTHING, ES:NOTHING
  211.  
  212.         jmp     DWORD PTR cs:org_clk_vector
  213.  
  214. ;----------------------------------------------------------------------------
  215. ; At this point the counter = max_value.
  216. ; Check the video mode to make sure that it is one of 2,3 or 7.
  217. ; If it is then save the screen buffer start position and
  218. ; swap the screen and increment the counter variable.
  219. ;----------------------------------------------------------------------------
  220.         ASSUME DS:BUFFY_DATA, ES:NOTHING
  221. attempt_swap:
  222.         call    NEAR PTR get_current_video_mode  ; Returns BIOS video mode in AL
  223.         mov     screen_buffer,0000
  224.         cmp     al,7
  225.         je      swap_screen             ; can swap in mode 7
  226.         mov     screen_buffer,8000h
  227.         cmp     al,3
  228.         je      swap_screen             ; can swap in mode 3
  229.         cmp     al,2
  230.         je      swap_screen             ; can swap in mode 2
  231.         jmp     SHORT no_action
  232.  
  233. swap_screen:
  234.         call    NEAR PTR screen_save
  235.         call    NEAR PTR screen_clear
  236.         call    NEAR PTR buffy_screen
  237.  
  238.         jmp     SHORT increment_and_exit
  239.  
  240. clk_isr         ENDP
  241.  
  242. ;----------------------------------------------------------------------------
  243. ;----------------------------------------------------------------------------
  244. ;----------------------------------------------------------------------------
  245. ;
  246. ; Return the BIOS video mode in the AL register.
  247. ;
  248. ;----------------------------------------------------------------------------
  249.  
  250. get_current_video_mode  PROC    NEAR
  251.         ASSUME  DS:NOTHING, ES:NOTHING
  252.  
  253.         push    ds
  254.         mov     ax,40h
  255.         mov     ds,ax
  256.         mov     al,ds:[49h]                 ; get display mode variable.
  257.         pop     ds
  258.  
  259.         ret
  260.  
  261. get_current_video_mode  ENDP
  262.  
  263. ;----------------------------------------------------------------------------
  264. ;----------------------------------------------------------------------------
  265. ;----------------------------------------------------------------------------
  266. ; Copy the screen into the screen buffer.
  267. ;----------------------------------------------------------------------------
  268. screen_save     PROC    NEAR
  269.         ASSUME  DS:NOTHING, ES:NOTHING
  270.         push    ax
  271.         push    cx
  272.         push    di
  273.         push    si
  274.         push    ds
  275.         push    es
  276.         pushf
  277.  
  278. ;----------------------------------------------------------------------------
  279. ; Set up DS to point to B000 and ES to point to BUFFY_DATA
  280. ;----------------------------------------------------------------------------
  281.         mov     ax,0B000h
  282.         mov     ds,ax
  283.         mov     ax,BUFFY_DATA
  284.         mov     es,ax
  285.         ASSUME DS:NOTHING, ES:BUFFY_DATA
  286.  
  287. ;----------------------------------------------------------------------------
  288. ; Set up SI to point to start of screen buffer, DI to <org_screen>
  289. ;----------------------------------------------------------------------------
  290.         mov     si,es:screen_buffer
  291.         mov     di,OFFSET BUFFY_DATA:org_screen
  292.  
  293. ;----------------------------------------------------------------------------
  294. ; Copy display screen (DS:SI) to screen save buffer (BUFFY_DATA:org_screen)
  295. ;----------------------------------------------------------------------------
  296.         mov     cx,80 * 25
  297.         cld
  298.         rep     movsw
  299.  
  300.         popf
  301.         pop     es
  302.         pop     ds
  303.         pop     si
  304.         pop     di
  305.         pop     cx
  306.         pop     ax
  307.  
  308.         ret
  309.  
  310. screen_save     ENDP
  311.  
  312. ;----------------------------------------------------------------------------
  313. ;----------------------------------------------------------------------------
  314. ;----------------------------------------------------------------------------
  315. ;
  316. ;  Clear the screen.  Use attribute 7 (normal) and character 'space'.
  317. ;
  318. ;----------------------------------------------------------------------------
  319.  
  320. screen_clear    PROC    NEAR
  321.         ASSUME DS:NOTHING, ES:NOTHING
  322.  
  323.         push    ax
  324.         push    cx
  325.         push    di
  326.         push    es
  327.         pushf
  328.  
  329.         mov     ax,BUFFY_DATA
  330.         mov     es,ax
  331.         ASSUME DS:NOTHING, ES:BUFFY_DATA
  332.         mov     di,es:screen_buffer
  333.  
  334.         mov     ax,0B000h
  335.         mov     es,ax
  336.         ASSUME DS:NOTHING, ES:NOTHING
  337.         mov     cx,80 * 25
  338.         mov     ax,720h
  339.         cld
  340.         rep     stosw
  341.  
  342.         popf
  343.         pop     es
  344.         pop     di
  345.         pop     cx
  346.         pop     ax
  347.  
  348.         ret
  349.  
  350. screen_clear    ENDP
  351.  
  352. ;----------------------------------------------------------------------------
  353. ;----------------------------------------------------------------------------
  354. ;----------------------------------------------------------------------------
  355.  
  356. buffy_screen    PROC    NEAR
  357.         ASSUME DS:NOTHING, ES:NOTHING
  358.  
  359.         push    ax
  360.         push    cx
  361.         push    di
  362.         push    si
  363.         push    ds
  364.         push    es
  365.         pushf
  366.  
  367.         mov     ax,BUFFY_DATA
  368.         mov     ds,ax
  369.         ASSUME DS:BUFFY_DATA, ES:NOTHING
  370.  
  371.         mov     di,screen_buffer                ; Offset of screen buffer.
  372.         mov     si,OFFSET display_lines         ; BX points to current display item
  373.  
  374.         mov     ax,0B000h                       ; Segment of screen buffer.
  375.         mov     es,ax
  376.  
  377.         mov     ah,07                           ; This is the characters attribute
  378.         mov     cx,screen_length
  379. next_character:
  380.         lodsb
  381.         stosw
  382.         loop next_character
  383.  
  384. exit_buffy_screen:
  385.         popf
  386.         pop     es
  387.         pop     ds
  388.         pop     si
  389.         pop     di
  390.         pop     cx
  391.         pop     ax
  392.  
  393.         ret
  394.  
  395. buffy_screen    ENDP
  396.  
  397. ;----------------------------------------------------------------------------
  398. ;----------------------------------------------------------------------------
  399. ;----------------------------------------------------------------------------
  400. ; Data area in same segment.
  401. ;----------------------------------------------------------------------------
  402.  
  403. org_clk_vector  dd      (?)
  404. CLK_INTR_RTN    ENDS
  405.  
  406. ;----------------------------------------------------------------------------
  407. ;----------------------------------------------------------------------------
  408. ;----------------------------------------------------------------------------
  409.  
  410. BUFFY_CODE      SEGMENT PARA    PUBLIC  'CODE'
  411.  
  412.         ASSUME CS:BUFFY_CODE, DS:NOTHING, ES:NOTHING
  413.  
  414. initialize      PROC    FAR
  415.  
  416.         mov     ax,BUFFY_DATA
  417.         mov     ds,ax
  418.         ASSUME  DS:BUFFY_DATA, ES:NOTHING
  419.  
  420. ;----------------------------------------------------------------------------
  421. ; Save the PSP in the BUFFY_DATA segment for possible use later.
  422. ;----------------------------------------------------------------------------
  423.         mov     psp_pointer,es                  ; Save the segment of the PSP.
  424.         mov     counter,0                       ; Set the counter to 0
  425.         mov     error_code,0                    ; Set the error code to 0
  426.  
  427. ;----------------------------------------------------------------------------
  428. ; Get the original multiplex interupt vector and save it in a memory
  429. ; variable in the MULTIPLEX_RTN segment.
  430. ;----------------------------------------------------------------------------
  431.  
  432.         mov     ah,35h                          ; Get the interupt 2Fhex vector
  433.         mov     al,2Fh                          ; returned in ES:BX
  434.         int     21h
  435.  
  436.         mov     ax,MULTIPLEX_RTN                ; Store original vector
  437.         mov     ds,ax
  438.         ASSUME  DS:MULTIPLEX_RTN, ES:NOTHING
  439.  
  440.         mov     WORD PTR next_int_2f[2], es
  441.         mov     WORD PTR next_int_2f[0], bx
  442.  
  443. ;----------------------------------------------------------------------------
  444. ; Get the original keyboard interupt vector and save it in a memory
  445. ; variable in the KEYB_INTR_RTN segment.
  446. ;----------------------------------------------------------------------------
  447.  
  448.         mov     ah,35h                          ; Get the interupt 9 vector
  449.         mov     al,09h                          ; returned in ES:BX
  450.         int     21h
  451.  
  452.         mov     ax,KEYB_INTR_RTN                ; Store original vector
  453.         mov     ds,ax
  454.         ASSUME  DS:KEYB_INTR_RTN, ES:NOTHING
  455.  
  456.         mov     WORD PTR org_keyb_vector[2], es
  457.         mov     WORD PTR org_keyb_vector[0], bx
  458.  
  459. ;----------------------------------------------------------------------------
  460. ; Get the original clock (1Chex) interupt vector and save it in a memory
  461. ; variable in the CLK_INTR_RTN segment.
  462. ;----------------------------------------------------------------------------
  463.         mov     ah,35h                  ; Get the interupt 1Chex vector
  464.         mov     al,1Ch                  ; returned in ES:BX
  465.         int     21h
  466.  
  467.         mov     ax,CLK_INTR_RTN        ; Store original vector
  468.         mov     ds,ax
  469.         ASSUME  DS:CLK_INTR_RTN, ES:NOTHING
  470.  
  471.         mov     WORD PTR org_clk_vector[2], es
  472.         mov     WORD PTR org_clk_vector[0], bx
  473.  
  474. ;----------------------------------------------------------------------------
  475. ;----------------------------------------------------------------------------
  476. ;----------------------------------------------------------------------------
  477. ;        call    NEAR PTR debug_proc
  478.  
  479.  
  480. ;----------------------------------------------------------------------------
  481. ;----------------------------------------------------------------------------
  482. ;----------------------------------------------------------------------------
  483.  
  484. ;----------------------------------------------------------------------------
  485. ; Check to see if a copy is already installed.
  486. ; If a copy is already installed, check for a command line option to
  487. ; uninstall it "/U", otherwise print error message and exit.
  488. ; If no copy is currently running then install this copy.
  489. ;----------------------------------------------------------------------------
  490.         mov     ax,BUFFY_DATA
  491.         mov     ds,ax
  492.         ASSUME  DS:BUFFY_DATA, ES:NOTHING
  493.  
  494.         call    NEAR PTR check_for_existing_copy
  495.         jnc     install_buffy
  496.  
  497.         call    NEAR PTR check_for_uninstall
  498.         jnc     @F
  499.         push    ds
  500.         push    cs
  501.         pop     ds
  502.         mov     dx,OFFSET CS:msg_already_installed
  503.         mov     ah,9
  504.         int     21h
  505.         pop     ds
  506.         jmp     SHORT exit_with_error
  507.  
  508. @@:     call    NEAR PTR uninstall
  509.         mov     error_code,0
  510.         jmp     SHORT exit_no_error
  511.  
  512. ;----------------------------------------------------------------------------
  513. ; After uninstalling or issuing error message, exit without installing.
  514. ;----------------------------------------------------------------------------
  515. exit_with_error:
  516.         mov     error_code,1
  517.  
  518. exit_no_error:
  519.         mov     ah,4Ch
  520.         mov     al,error_code
  521.         int     21h
  522.  
  523.  
  524. install_buffy:
  525.         call    NEAR PTR set_int_2f_id
  526.  
  527. ;----------------------------------------------------------------------------
  528. ; Set the keyboard interupt vector to the new routine
  529. ;----------------------------------------------------------------------------
  530.         mov     ax,KEYB_INTR_RTN
  531.         mov     ds,ax
  532.         ASSUME  DS:KEYB_INTR_RTN, ES:NOTHING
  533.  
  534.         mov     dx,OFFSET KEYB_INTR_RTN:keyb_isr
  535.         mov     ah,25h                  ; Set the interupt 9 vector
  536.         mov     al,09h                  ; set to DS:DX
  537.         int     21h
  538.  
  539. ;----------------------------------------------------------------------------
  540. ; Set the clock interupt vector to the new routine
  541. ;----------------------------------------------------------------------------
  542.         mov     ax,CLK_INTR_RTN
  543.         mov     ds,ax
  544.         ASSUME  DS:CLK_INTR_RTN, ES:NOTHING
  545.  
  546.         mov     dx,OFFSET CLK_INTR_RTN:clk_isr
  547.         mov     ah,25h                  ; Set the interupt 1Chex vector
  548.         mov     al,1Ch                  ; set to DS:DX
  549.         int     21h
  550.  
  551. ;----------------------------------------------------------------------------
  552. ; Set the multiplex interupt vector to the new routine
  553. ;----------------------------------------------------------------------------
  554.         mov     ax,MULTIPLEX_RTN
  555.         mov     ds,ax
  556.         ASSUME  DS:MULTIPLEX_RTN, ES:NOTHING
  557.  
  558.         mov     dx,OFFSET MULTIPLEX_RTN:int_2f_rtn
  559.         mov     ah,25h                  ; Set the interupt 2Fhex vector
  560.         mov     al,2Fh                  ; set to DS:DX
  561.         int     21h
  562.  
  563. ;----------------------------------------------------------------------------
  564. ; Release environment block.
  565. ;----------------------------------------------------------------------------
  566.         mov     ax,BUFFY_DATA           ; Make data segment addressable
  567.         mov     ds,ax
  568.         ASSUME  DS:BUFFY_DATA, ES:NOTHING
  569.         
  570.         mov     ax,psp_pointer          ; Load pointer to PSP into DS
  571.         mov     ds,ax
  572.         ASSUME  DS:NOTHING, ES:NOTHING
  573.  
  574.         mov     es,ds:[2Ch]             ; Get segment of Environment from PSP
  575.  
  576.         mov     ah,49h                  ; Release segment of Environment.
  577.         int     21h
  578.  
  579. ;----------------------------------------------------------------------------
  580. ; Terminate and stay resident, leaving enough memory to hold the 
  581. ; interupt service routines and the screen buffers.
  582. ;----------------------------------------------------------------------------
  583.         mov     ax,BUFFY_DATA
  584.         mov     ds,ax
  585.         ASSUME  DS:BUFFY_DATA
  586.  
  587.         mov     dx,BUFFY_CODE
  588.         sub     dx,ax
  589.         add     dx,16
  590.         mov     ah,31h
  591.         mov     al,error_code
  592.         int     21h
  593.  
  594. initialize      ENDP
  595.  
  596. ;----------------------------------------------------------------------------
  597. ;----------------------------------------------------------------------------
  598. ;----------------------------------------------------------------------------
  599. debug_proc      PROC    NEAR
  600.  
  601.         push    ax
  602.         push    ds
  603.  
  604.         mov     ax,BUFFY_DATA
  605.         mov     ds,ax
  606.         call    NEAR PTR uninstall
  607.  
  608.         pop     ds
  609.         pop     ax
  610.         ret
  611.  
  612. debug_proc      ENDP
  613.  
  614. ;----------------------------------------------------------------------------
  615. ;----------------------------------------------------------------------------
  616. ;----------------------------------------------------------------------------
  617.  
  618. check_for_existing_copy PROC    NEAR
  619.         ASSUME  DS:BUFFY_DATA, ES:NOTHING
  620.  
  621.         push    ax
  622.         push    cx
  623.         push    di
  624.         push    si
  625.         push    es
  626.  
  627.         mov     ah,80h
  628.  
  629. next_check:
  630.         xor     al,al
  631.         int     2fh
  632.  
  633.         cmp     al,0FFh
  634.         je      check_16_bytes
  635.         or      al,al
  636.         je      could_not_find
  637. failed_check:
  638.         inc     ah
  639.         jnz     next_check
  640.         jmp     SHORT could_not_find
  641.         
  642. check_16_bytes:
  643.         xor     si,si
  644.         xor     di,di
  645.         cld
  646.         mov     cx,16
  647.         repe    cmpsb
  648.         jne     failed_check
  649.  
  650.         mov     isr_2f_seg,es
  651.         stc
  652.         jmp     SHORT exit_check
  653.  
  654. could_not_find:
  655.         clc
  656.  
  657. exit_check:
  658.         pop     es
  659.         pop     si
  660.         pop     di
  661.         pop     cx
  662.         pop     ax
  663.         ret
  664.  
  665. check_for_existing_copy ENDP
  666.  
  667. ;----------------------------------------------------------------------------
  668. ;----------------------------------------------------------------------------
  669. ;----------------------------------------------------------------------------
  670.  
  671. check_for_uninstall     PROC    NEAR
  672.         ASSUME  DS:BUFFY_DATA, ES:NOTHING
  673.         push    ds
  674.  
  675.         mov     ds,psp_pointer
  676.         ASSUME  DS:NOTHING, ES:NOTHING
  677.  
  678.         or      BYTE PTR ds:[80h],0
  679.         je      error_exit_check_for_uninstall
  680.  
  681. check_parameter_value:
  682.         cmp     BYTE PTR ds:[82h], '/'
  683.         jne     error_exit_check_for_uninstall
  684.         cmp     BYTE PTR ds:[83h], 'U'
  685.         jne     error_exit_check_for_uninstall
  686.         clc
  687.         jmp     SHORT exit_check_for_uninstall
  688.  
  689. error_exit_check_for_uninstall:
  690.         stc
  691.  
  692. exit_check_for_uninstall:
  693.         pop     ds
  694.  
  695.         ret
  696.  
  697. check_for_uninstall     ENDP
  698.  
  699. ;----------------------------------------------------------------------------
  700. ;----------------------------------------------------------------------------
  701. ;----------------------------------------------------------------------------
  702.  
  703. uninstall               PROC    NEAR
  704.  
  705.         push    ax
  706.         push    bx
  707.         push    dx
  708.         push    si
  709.         push    ds
  710.         push    es
  711.  
  712. ;----------------------------------------------------------------------------
  713. ; Switch active PSP to the copy of BUFFY that was found.
  714. ; 1) Unlink all interupt vectors from found copy of BUFFY.
  715. ; 2) get current PSP address from DOS
  716. ; 3) get PSP from found copy of BUFFY
  717. ; 4) call DOS 'Set psp' with found copy
  718. ; 5) release memory starting at found copy of PSP
  719. ; 6) reset to current PSP
  720. ;----------------------------------------------------------------------------
  721.  
  722. ;----------------------------------------------------------------------------
  723. ; Set DS to point to the found copy of BUFFY_DATA
  724. ; We can let the assembler think that we are still pointing to the current
  725. ; copy of BUFFY_DATA because the assembler just uses this for segment 
  726. ; overrides and offset calculations (both of which will be the same).
  727. ;----------------------------------------------------------------------------
  728.         mov     ax,BUFFY_DATA
  729.         mov     ds,ax
  730.         ASSUME DS:BUFFY_DATA, ES:NOTHING
  731.  
  732.         mov     ax,isr_2f_seg
  733.         mov     es,ax
  734.         ASSUME DS:NOTHING, ES:BUFFY_DATA
  735.  
  736. ;----------------------------------------------------------------------------
  737. ; ES now points to found copy of BUFFY_DATA.
  738. ; Calculate the position of the original int 2F vector and reset the
  739. ; vector via DOS.
  740. ;----------------------------------------------------------------------------
  741.         mov     ax,MULTIPLEX_RTN
  742.         sub     ax,BUFFY_DATA
  743.         mov     bx,es
  744.         add     ax,bx
  745.         mov     ds,ax
  746.         ASSUME DS:MULTIPLEX_RTN, ES:BUFFY_DATA
  747.  
  748. ;----------------------------------------------------------------------------
  749. ; DS now points to the found copy of MULTIPLEX_RTN.
  750. ; ES points to the found copy of BUFFY_DATA,
  751. ; Save a copy of the segment address of the original int_2f_isr
  752. ; Get the current vector from DOS
  753. ; Compare the current vector with the address of found copy,
  754. ;   If they are the same they can be unlinked
  755. ;   otherwise they cannot be unlinked (chain would be cut)
  756. ;----------------------------------------------------------------------------
  757.         mov     si,es
  758.  
  759.         mov     ah,35h                  ; Get vector to current int 2F handler
  760.         mov     al,2Fh
  761.         int     21h                     ; Returns ES:BX
  762.  
  763.         mov     ax,ds
  764.         mov     bx,es
  765.         sub     ax,bx                   ; Compare found segment with INT 2F segment
  766.         jz      @F
  767.         jmp     could_not_unlink
  768.  
  769. @@:     mov     es,si                   ; Restore segment of BUFFY_DATA
  770.         mov     dx,WORD PTR next_int_2f[0]
  771.         mov     ds,WORD PTR next_int_2f[2]
  772.         ASSUME  DS:NOTHING, ES:BUFFY_DATA
  773.  
  774.         mov     ah,25h                  ; Reset int 2F vector to previous vector
  775.         mov     al,2Fh
  776.         int     21h
  777.         
  778. ;----------------------------------------------------------------------------
  779. ; ES now points to found copy of BUFFY_DATA.
  780. ; Calculate the position of the original int 9 vector and reset the
  781. ; vector via DOS.
  782. ;----------------------------------------------------------------------------
  783.         mov     ax,KEYB_INTR_RTN
  784.         sub     ax,BUFFY_DATA
  785.         mov     bx,es
  786.         add     ax,bx
  787.         mov     ds,ax
  788.         ASSUME DS:KEYB_INTR_RTN, ES:BUFFY_DATA
  789.  
  790. ;----------------------------------------------------------------------------
  791. ; DS now points to the found copy of KEYB_INTR_RTN
  792. ; ES points to the found copy of BUFFY_DATA,
  793. ; Save a copy of the segment address of the original keyb_isr
  794. ; Get the current vector from DOS
  795. ; Compare the current vector with the address of found copy,
  796. ;   If they are the same they can be unlinked
  797. ;   otherwise they cannot be unlinked (chain would be cut)
  798. ;----------------------------------------------------------------------------
  799.         mov     si,es
  800.  
  801.         mov     ah,35h                  ; Get vector to current int 9 handler
  802.         mov     al,9
  803.         int     21h                     ; Returns ES:BX
  804.  
  805.         mov     ax,ds
  806.         mov     bx,es
  807.         sub     ax,bx                   ; Compare found segment with int 9 segment
  808.         jz      @F
  809.         jmp     could_not_unlink
  810.  
  811. @@:     mov     es,si                   ; Restore segment of BUFFY_DATA
  812.         mov     dx,WORD PTR org_keyb_vector[0]
  813.         mov     ds,WORD PTR org_keyb_vector[2]
  814.         ASSUME  DS:NOTHING, ES:BUFFY_DATA
  815.  
  816.         mov     ah,25h                  ; Reset int 9 vector to previous vector
  817.         mov     al,9                    ; Vector in DS:DX
  818.         int     21h
  819.  
  820. ;----------------------------------------------------------------------------
  821. ; ES now points to found copy of BUFFY_DATA.
  822. ; Calculate the position of the original int 1C vector and reset the
  823. ; vector via DOS.
  824. ;----------------------------------------------------------------------------
  825.         mov     ax,CLK_INTR_RTN
  826.         sub     ax,BUFFY_DATA
  827.         mov     bx,es
  828.         add     ax,bx
  829.         mov     ds,ax
  830.         ASSUME DS:CLK_INTR_RTN, ES:BUFFY_DATA
  831.  
  832. ;----------------------------------------------------------------------------
  833. ; DS now points to the found copy of CLK_INTR_RTN
  834. ; ES points to the found copy of BUFFY_DATA,
  835. ; Save a copy of the segment address of the original clk_isr
  836. ; Get the current vector from DOS
  837. ; Compare the current vector with the address of found copy,
  838. ;   If they are the same they can be unlinked
  839. ;   otherwise they cannot be unlinked (chain would be cut)
  840. ;----------------------------------------------------------------------------
  841.         mov     si,es
  842.  
  843.         mov     ah,35h                  ; Get vector to current int 1C handler
  844.         mov     al,1Ch
  845.         int     21h                     ; Returns ES:BX
  846.  
  847.         mov     ax,ds
  848.         mov     bx,es
  849.         sub     ax,bx                   ; Compare found segment with int 1C segment
  850.         jz      @F
  851.         jmp     could_not_unlink
  852.  
  853. @@:     mov     es,si                   ; Restore segment of BUFFY_DATA
  854.         mov     dx,WORD PTR org_clk_vector[0]
  855.         mov     ds,WORD PTR org_clk_vector[2]
  856.         ASSUME  DS:NOTHING, ES:BUFFY_DATA
  857.  
  858.         mov     ah,25h                  ; Reset int 1C vector to previous vector
  859.         mov     al,1Ch                  ; Vector in DS:DX
  860.         int     21h
  861.  
  862. ;----------------------------------------------------------------------------
  863. ; The interupt service routines have now been unlinked.
  864. ; Now we get our PSP and save it.
  865. ; Get the found copies PSP and make it active.
  866. ;----------------------------------------------------------------------------
  867.  
  868.         mov     ah,51h                          ; Get our PSP
  869.         int     21h                             ; Returned in BX
  870.  
  871.         push    bx                              ; Save this so we can reset later.
  872.  
  873.         mov     bx,psp_pointer                  ; Set found PSP to be active
  874.         mov     ah,50h
  875.         int     21h
  876.  
  877. ;----------------------------------------------------------------------------
  878. ; Release the memory originally consumed by the found copy of BUFFY.
  879. ;----------------------------------------------------------------------------
  880.         mov     es,psp_pointer
  881.         mov     ah,49h
  882.         int     21h
  883.  
  884.         jnc     @F
  885.         mov     ax,cs
  886.         mov     ds,ax
  887.         mov     dx,OFFSET cs:msg_memory_failure
  888.         int     21h
  889.         add     sp,2
  890.         stc
  891.         jmp     SHORT exit_uninstall
  892.  
  893. ;----------------------------------------------------------------------------
  894. ; Reset PSP back to current process.
  895. ;----------------------------------------------------------------------------
  896. @@:     pop     bx
  897.         mov     ah,50h
  898.         int     21h
  899.         jmp     SHORT exit_uninstall
  900.  
  901. could_not_unlink:
  902.         mov     ax,cs
  903.         mov     ds,ax
  904.         mov     dx,OFFSET cs:msg_interupt_taken
  905.         int     21h
  906.         stc
  907.  
  908. exit_uninstall:
  909.         pop     es
  910.         pop     ds
  911.         pop     si
  912.         pop     dx
  913.         pop     bx
  914.         pop     ax
  915.  
  916.         ret
  917.  
  918. uninstall               ENDP
  919.  
  920. ;----------------------------------------------------------------------------
  921. ;----------------------------------------------------------------------------
  922. ;----------------------------------------------------------------------------
  923.  
  924. set_int_2f_id           PROC    NEAR
  925.         ASSUME  DS:BUFFY_DATA, ES:NOTHING
  926.  
  927.         push    ax
  928.  
  929.         mov     ah,80h
  930.         xor     al,al
  931.  
  932. set_check:
  933.         int     2fh
  934.         or      al,al
  935.         je      set_2f_id
  936.         inc     ah
  937.         jnz     set_check
  938.         stc
  939.         jmp     exit_set_2f_id
  940.  
  941. set_2f_id:
  942.         mov     int_2f_id,ah
  943.         clc
  944.  
  945. exit_set_2f_id:
  946.         pop     ax
  947.         ret
  948.  
  949. set_int_2f_id           ENDP
  950.  
  951. msg_already_installed   db      13,10,'TSR is already installed',13,10,'$'
  952. msg_interupt_taken      db      13,10,'Could not uninstall',13,10,'$'
  953. msg_memory_failure      db      13,10,'Memory deallocation failure - Reboot',13,10,'$'
  954. BUFFY_CODE      ENDS
  955.  
  956. ;----------------------------------------------------------------------------
  957. ;----------------------------------------------------------------------------
  958. ;----------------------------------------------------------------------------
  959.  
  960. STACK   SEGMENT STACK  'STACK'
  961.  
  962.         db      64      dup     ('stack...')
  963.  
  964. STACK   ENDS
  965.  
  966. END     initialize
  967.  
  968. 
  969.