home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 September / Simtel20_Sept92.cdr / msdos / pcmag / vol8n17.arc / DIMMER.ASM < prev    next >
Assembly Source File  |  1989-06-20  |  33KB  |  716 lines

  1.                 page    66,132
  2. ;============================================================================
  3. ; DIMMER.COM allows VGA users to interactively brighten or dim the screen.
  4. ; Syntax is:
  5. ;
  6. ;       DIMMER [/U] [/V[+|-]] [/D mmm [+|-]xx] [[+|-]xx]
  7. ;
  8. ; where /U = Uninstall the program
  9. ;       /D = Adjust intensity by xx after mmm minutes of inactivity
  10. ;       xx = Numeric code from -63 to +63 representing relative
  11. ;            amount by which to adjust the intensity
  12. ;       /V = Reset delay timer on call to BIOS video interrupt. The
  13. ;         default is V-.
  14. ;
  15. ; COMMAND LINE INTENSITY CONTROL
  16. ;
  17. ;       DIMMER /D 1 -63 causes the screen to blank after 1 minute of
  18. ;       inactivity.  DIMMER /D 0 cancels any time delay previously entered.
  19. ;       DIMMER -20 causes the screen to immediately dim 20 intensity levels.
  20. ;       DIMMER 0 restores the screen intensity to what it was when DIMMER
  21. ;       was installed.  In all cases, DIMMER becomes RAM-resident so that
  22. ;       intensity levels can also be adjusted interactively.
  23. ;       DIMMER /D 1 -63 /V causes the screen to blank after 1 minute of
  24. ;       inactivity.  If a program calls any BIOS video routines, the
  25. ;       screen is reset to its original brightness.
  26. ;
  27. ; INTERACTIVE INTENSITY CONTROL
  28. ;
  29. ;       With DIMMER installed, Alt-UpArrow increases the display intensity
  30. ;       by 1 level, Alt-DnArrow decreases the intensity by 1 level, and
  31. ;       Alt-Home restores the screen intensity to what it was when DIMMER
  32. ;       was installed.
  33. ;============================================================================
  34.  
  35.                 code    segment
  36.                 assume  cs:code
  37.  
  38.                 org     2Ch
  39. env_segment     dw      ?                       ;Address of environment block
  40.                 org     80h
  41. command_tail    dw      ?                       ;Address of command tail
  42.  
  43.                 org     100h
  44. main:           jmp     initialize              ;Go to initialization code
  45.  
  46. program         db      "Dimmer 1.0 "
  47. copyright       db      "(c) 1989 Ziff Communications Co.",13,10
  48. authors         db      "PC Magazine ",254," Doug Boling and Jeff Prosise"
  49.                 db      "$",1Ah
  50.  
  51. dimmer_val      db      0                       ;Relative dimmer value
  52. delaydimval     db      0                       ;Delayed dimmer value
  53. wait_time       dw      -1                      ;Delay until screen blank
  54. dim_counter     dw      -1                      ;Number of minutes to delay
  55. second_cnt      dw      1092                    ;Timer ticks per minute
  56. restorebyvid    db    0            ;1 = delay reset by video call
  57. vid_function    dw      0                       ;Saved video function
  58. int08h          dd      ?                       ;Int 8 vector (Timer)
  59. int09h          dd      ?                       ;Int 9 vector (Keyboard)
  60. int10h          dd      ?                       ;Int 10 vector (Video)
  61.  
  62. ;============================================================================
  63. ; TIMERINT services the BIOS timer interrupt.
  64. ;============================================================================
  65. timerint        proc    far
  66.                 pushf                           ;Push flags
  67.                 call    int08h                  ;Call BIOS timer routine
  68.                 sti                             ;Enable interrupts
  69.  
  70.                 push    ax                      ;Save AX
  71.                 mov     ax,cs:[dim_counter]     ;Get delay counter
  72.                 cmp     ax,0FFFFh               ;See if timer enabled
  73.                 je      timer_exit              ;Exit if not enabled
  74.         or    ax,ax            ;Exit if timer at 0 to
  75.         je    timer_exit        ;  prevent rollover.
  76.  
  77.                 dec     cs:[second_cnt]         ;Decrement seconds and exit
  78.                 jnz     timer_exit              ;  if not zero
  79.                 mov     word ptr cs:[second_cnt],1092
  80.                 dec     ax                      ;Decrement minute counter
  81.                 mov     cs:[dim_counter],ax     ;Update delay counter
  82.                 or      ax,ax                   ;Exit if timer hasn't
  83.                 jne     timer_exit              ;  reached zero
  84.  
  85.                 mov     ah,cs:[delaydimval]     ;Get dimmer value
  86.                 call    adj_palette_2           ;Modify color registers
  87. timer_exit:
  88.                 pop     ax                      ;Restore AX and exit
  89.                 iret
  90. timerint        endp
  91.  
  92. ;============================================================================
  93. ; KBINT services the keyboard interrupt.
  94. ;============================================================================
  95. kbint           proc    far
  96.                 sti                             ;Enable interrupts
  97.                 push    ax                      ;Save AX
  98.                 mov     cs:[second_cnt],1092    ;Reset delay counters
  99.                 mov     ax,cs:[wait_time]
  100.                 xchg    cs:[dim_counter],ax
  101.                 or      ax,ax                   ;If counter was 0, reset the
  102.                 jne     kbint0                  ;  screen intensity
  103.  
  104.                 mov     ah,cs:[dimmer_val]
  105.                 call    adj_palette_2
  106. kbint0:
  107.                 push    ds                      ;Save DS
  108.                 mov     ax,40h                  ;Point DS to BIOS data area
  109.                 mov     ds,ax
  110.                 mov     al,ds:[17h]             ;Get keyboard shift status
  111.                 pop     ds                      ;Restore DS
  112.                 and     al,0Fh                  ;Mask upper 4 bits
  113.                 cmp     al,8                    ;Check for Alt key
  114.                 je      alt_found               ;Continue if Alt is pressed
  115.  
  116. goto_bios:
  117.                 pop     ax                      ;Restore AX and exit to
  118.                 jmp     int09h                  ;  BIOS keyboard handler
  119.  
  120. alt_found:
  121.                 in      al,60h                  ;Get key pressed
  122.                 cmp     al,72                   ;Check for UpArrow
  123.                 jne     kbint1
  124.                 cmp     cs:[dimmer_val],63      ;Increment color registers
  125.                 jge     kbint3                  ;  by 1 if dimmer value
  126.                 inc     cs:[dimmer_val]         ;  isn't maxed out
  127.                 jmp     short kbint3
  128. kbint1:
  129.                 cmp     al,80                   ;Check for DnArrow
  130.                 jne     kbint2
  131.                 cmp     cs:[dimmer_val],-63     ;Decrement color registers
  132.                 jle     kbint3                  ;  by 1 if dimmer value
  133.                 dec     cs:[dimmer_val]         ;  isn't zeroed out
  134.                 jmp     short kbint3
  135. kbint2:
  136.                 cmp     al,71                   ;Reset color registers if
  137.                 jne     goto_bios               ;  Alt-Home was pressed
  138.                 mov     cs:[dimmer_val],0
  139. kbint3:
  140.                 mov     ah,cs:[dimmer_val]      ;Get dimmer value
  141.                 call    adj_palette_2           ;Modify color registers
  142.  
  143.                 cli                             ;Disable interrupts
  144.                 in      al,61h                  ;Reset the keyboard
  145.                 mov     ah,al                   ;  controller
  146.                 or      al,80h
  147.                 out     61h,al
  148.                 mov     al,ah
  149.                 out     61h,al
  150.  
  151.                 mov     al,20h                  ;Signal end-of-interrupt to
  152.                 out     20h,al                  ;  the interrupt controller
  153.                 sti                             ;Enable interrupts
  154.  
  155.                 pop     ax                      ;Restore AX and exit
  156.                 iret
  157. kbint           endp
  158.  
  159. ;============================================================================
  160. ; VIDEOINT services the BIOS video interrupt.
  161. ;============================================================================
  162. videoint        proc    far
  163.                 mov     cs:[vid_function],ax    ;Save function number
  164.                 pushf                           ;Push flags
  165.                 call    int10h                  ;Call video BIOS routine
  166.                 sti                             ;Enable interrupts
  167.                 push    ax                      ;Save AX
  168.  
  169.         cmp    cs:[restorebyvid],0     ;If video checking enabled,
  170.         je    video_1            ;  check delay counter.
  171.                 cmp     word ptr cs:[dim_counter],0
  172.                 jne     video_1                 ;Restore color register
  173.                 mov     ah,cs:[dimmer_val]      ;  values if timed delay
  174.                 call    adj_palette_2           ;  has dimmed the screen
  175.                 mov     cs:[second_cnt],1092    ;Reset delay counters
  176.                 mov     ax,cs:[wait_time]
  177.                 mov     cs:[dim_counter],ax
  178.  
  179. video_1:
  180.                 mov     ax,cs:[vid_function]    ;See what function was called
  181.                 or      ah,ah                   ;Check for mode change
  182.                 je      refresh_palette
  183.                 cmp     ah,11h                  ;Check for mode reset
  184.                 je      refresh_palette
  185.  
  186.                 cmp     ax,1010h                ;Check for changes to the
  187.                 je      refresh_buffer          ;  VGA color registers
  188.                 cmp     ax,1012h                ;  made thru the video
  189.                 je      refresh_buffer          ;  BIOS
  190.                 cmp     ax,101Bh
  191.                 jne     video_exit
  192. refresh_buffer:
  193.                 call    get_palette             ;Reload register array
  194.                 jmp     short video_exit
  195.  
  196. refresh_palette:
  197.                 mov     ah,cs:[dimmer_val]      ;Get dimmer adjust value
  198.                 call    adj_palette_2           ;Modify palette
  199. video_exit:
  200.                 pop     ax                      ;Restore AX and exit
  201.                 iret
  202. videoint        endp
  203.  
  204. ;----------------------------------------------------------------------------
  205. ; ADJ_PALETTE_1 adjusts the VGA color registers to their original values
  206. ; plus the current dimmer value.
  207. ;   Entry:  AH - Dimmer value
  208. ;           DS - Segment where color register values are stored
  209. ;----------------------------------------------------------------------------
  210. adj_palette_1   proc    near
  211.                 cld                             ;Clear direction flag
  212.                 push    cx                      ;Save registers
  213.                 push    dx
  214.                 push    si
  215.  
  216.                 mov     si,offset end_res       ;Point SI to buffer
  217.                                                 ;  containing original values
  218.                 mov     dx,03C8h                ;Write address register
  219.                 xor     al,al                   ;Set beginning address
  220.         cli                ;Disable interrupts
  221.                 out     dx,al
  222.                 mov     cx,256 * 3              ;256 color registers
  223.                 mov     dx,03C9h                ;Write data register
  224. adj_loop1:
  225.                 lodsb                           ;Get color value
  226.                 call    mod64_add               ;Add dimmer value
  227.                 out     dx,al                   ;Write data to color register
  228.                 loop    adj_loop1               ;Loop until done
  229.  
  230.         sti                ;Enable interrupts
  231.                 pop     si                      ;Restore registers and exit
  232.                 pop     dx
  233.                 pop     cx
  234.                 ret
  235. adj_palette_1   endp
  236.  
  237. ;----------------------------------------------------------------------------
  238. ; ADJ_PALETTE_2 adjusts the VGA color registers to their original values
  239. ; plus the current dimmer value.
  240. ;   Entry:  AH - Dimmer value
  241. ;----------------------------------------------------------------------------
  242. adj_palette_2   proc    near
  243.                 push    ds                      ;Save DS
  244.                 push    cs                      ;Point DS to code segment
  245.                 pop     ds
  246.                 call    adj_palette_1           ;Modify color registers
  247.                 pop     ds                      ;Restore DS and exit
  248.                 ret
  249. adj_palette_2   endp
  250.  
  251. ;----------------------------------------------------------------------------
  252. ; MOD64_ADD adds AH to AL using modulo 64 math.
  253. ;----------------------------------------------------------------------------
  254. mod64_add       proc    near
  255.                 or      al,al                   ;If 0, don't brighten
  256.                 je      mod2
  257.                 add     al,ah
  258.                 cmp     al,0                    ;See if underflow
  259.                 jg      mod1
  260.                 mov     al,0                    ;If so, set at minimum
  261.                 jmp     short mod2
  262. mod1:
  263.                 cmp     al,63                   ;See if overflow
  264.                 jbe     mod2
  265.                 mov     al,63                   ;If so, set at maximum
  266. mod2:
  267.                 ret
  268. mod64_add       endp
  269.  
  270. ;----------------------------------------------------------------------------
  271. ; GET_PALETTE buffers the current values of the VGA color registers.
  272. ;----------------------------------------------------------------------------
  273. get_palette     proc    near
  274.                 cld                             ;Clear direction flag
  275.                 push    ax                      ;Save registers
  276.                 push    cx
  277.                 push    dx
  278.                 push    di
  279.                 push    es
  280.  
  281.                 mov     cx,cs                   ;Point ES to the code segment
  282.                 mov     es,cx
  283.                 mov     di,offset end_res       ;Point DI to save buffer
  284.                 mov     dx,03C7h                ;Read address register
  285.                 xor     al,al                   ;Begin with register 0
  286.         cli                ;Disable interrupts
  287.                 out     dx,al
  288.                 mov     cx,256 * 3              ;256 color registers
  289.                 mov     dx,03C9h                ;Read data register
  290. getp_loop1:
  291.                 in      al,dx                   ;Get color register value
  292.                 and     al,3Fh                  ;Mask off the upper 2 bits
  293.                 stosb                           ;Store it
  294.                 loop    getp_loop1              ;Loop until done
  295.  
  296.         sti                ;Enable interrupts
  297.                 pop     es                      ;Restore registers and exit
  298.                 pop     di
  299.                 pop     dx
  300.                 pop     cx
  301.                 pop     ax
  302.                 ret
  303. get_palette     endp
  304.  
  305. ;----------------------------------------------------------------------------
  306. ; FINAL_INSTALL is the last of the resident code.
  307. ;----------------------------------------------------------------------------
  308. final_install:
  309.                 assume  ds:code
  310.                 call    get_palette             ;Get color register values
  311.                 mov     ah,dimmer_val           ;Adjust color registers and
  312.                 call    adj_palette_2           ;  terminate
  313.                 mov     dx,(offset end_res-offset code+768+15) SHR 4
  314.                 mov     ax,3100h
  315.                 int     21h
  316. end_res         =       $                       ;End of resident code
  317.  
  318. ;============================================================================
  319. ; Start of non-resident section.
  320. ;============================================================================
  321.  
  322. alrdy_installed db      0                       ;Installed flag
  323. other_seg       dw      0                       ;Segment of installed code
  324. change_flag     db      0                       ;Set if dimmer or delay
  325.                                                 ;  value is modified
  326. infomsg1        db      "Program uninstalled$"
  327. errmsg1         db      "Program not installed$"
  328. errmsg2         db      "Syntax: DIMMER [/U] [/V[+|-]] [/D mmm [+|-]xx]"
  329.         db    " [[+|-]xx]$"
  330. errmsg3         db      "Can",39,"t uninstall$"
  331. errmsg4         db      "VGA required$"
  332. errmsg5         db      "Intensity value must be between -63 and +63$"
  333. errmsg6         db      "Invalid delay value$"
  334. errmsg7         db      "Program already installed$"
  335. errmsg8         db      "Invalid intensity value$"
  336.  
  337. initialize      proc    near
  338.                 assume  cs:code,ds:code
  339. ;
  340. ;See if a copy of DIMMER is already resident in memory.
  341. ;
  342.                 cld                             ;Clear direction flag
  343.                 mov     word ptr [main],0       ;Initialize fingerprint
  344.                 xor     bx,bx                   ;Zero BX for start
  345.                 mov     ax,cs                   ;Keep CS value in AX
  346. find_copy:
  347.                 inc     bx                      ;Increment search segment
  348.                 mov     es,bx
  349.                 cmp     ax,bx                   ;Not installed if current
  350.                 je      find_copy1              ;  segment is found
  351.                 mov     si,offset main          ;Search this segment for ASCII
  352.                 mov     di,si                   ;  fingerprint.
  353.                 mov     cx,16
  354.                 repe    cmpsb
  355.                 jne     find_copy               ;Loop back if not found
  356.                 inc     alrdy_installed         ;Set installed flag
  357. find_copy1:
  358.                 mov     other_seg,es            ;Save segment value
  359. ;
  360. ;Verify that a VGA is installed.
  361. ;
  362.                 mov     ax,1A00h                ;BIOS read display function
  363.                 int     10h
  364.                 mov     dx,offset errmsg4
  365.                 cmp     al,1Ah                  ;See if VGA present
  366.                 jne     disp_error              ;Exit on error if no VGA
  367. ;
  368. ;Parse the command line for switches.
  369. ;
  370.                 mov     si,offset command_tail+1        ;Point SI to command
  371. parse_line_loop:                                        ;  tail in PSP
  372.                 lodsb                           ;Scan command line for / or a
  373.                 cmp     al,32                   ;  number.  Continue scanning
  374.                 je      parse_line_loop         ;  until a carriage return is
  375.                 cmp     al,13                   ;  found.
  376.                 je      parse_line_end
  377.  
  378.                 cmp     al,"/"                  ;Is this a / character?
  379.                 jne     check_numeric           ;No, then check for numeric
  380.                 lodsb                           ;Get next character
  381.                 or      al,20h                  ;Convert to lower case
  382.                 cmp     al,"u"                  ;Check for uninstall switch
  383.                 je      uninstall_found
  384.                 cmp     al,"d"                  ;Check for delay switch
  385.                 je      delay_found
  386.                 cmp     al,"v"                  ;Check for reset delay by
  387.                 je      vidflag_found        ;  video call switch.
  388. parse_line_error:
  389.                 mov     dx,offset errmsg2       ;Syntax error
  390.                 jmp     short disp_error        ;Display message and exit
  391. ;
  392. ;Read the dimmer value from the command line if entry is numeric.
  393. ;
  394. check_numeric:
  395.                 cmp     al,"-"                  ;Convert ASCII number into
  396.                 je      numeric_start           ;  binary.  Check for leading
  397.                 cmp     al,"+"                  ;  sign.
  398.                 je      numeric_start
  399.                 cmp     al,"0"
  400.                 jb      parse_line_error
  401.                 cmp     al,"9"
  402.                 ja      parse_line_error
  403.                 dec     si
  404. numeric_start:
  405.                 or      change_flag,1           ;Set bit 0 in change flag
  406.                 call    setdim                  ;Read and set dimmer value
  407.                 jmp     short chk_err_and_loop  ;Check for error return
  408. ;
  409. ;Read the time delay and dimmer values from the command line.
  410. ;
  411. vidflag_found:
  412.                 call    setvidflag              ;Modify the state of video flg
  413.                 jmp     short chk_err_and_loop  ;Check for error return
  414. delay_found:
  415.                 or      change_flag,2           ;Set bit 1 in change flag
  416.                 call    setdelay                ;Read and set delay value
  417. chk_err_and_loop:
  418.                 jc      disp_error
  419.                 jmp     short parse_line_loop
  420. ;
  421. ;Uninstall the program from memory.
  422. ;
  423. uninstall_found:
  424.                 mov     dx,offset errmsg1       ;Make sure program is
  425.                 cmp     alrdy_installed,0       ;  installed and signal
  426.                 je      disp_error              ;  error if it is not
  427.                 call    remove                  ;Remove program from memory
  428.                 mov     dx,offset errmsg3
  429.                 jc      disp_error              ;Error if can't remove
  430.                 mov     dx,offset infomsg1      ;Acknowledge if removed
  431.                 call    print_string
  432. exit:
  433.                 mov     ax,4C00h                ;Exit with RC = 0
  434.                 int     21h
  435. ;
  436. ;Process new dimmer and/or delay values now if DIMMER is already resident.
  437. ;
  438. parse_line_end:
  439.                 cmp     alrdy_installed,0       ;Program already installed?
  440.                 je      install                 ;No, then install it
  441.                 cmp     change_flag,0           ;Changes to resident copy?
  442.                 jne     check_dimmer_change     ;Yes, then process them
  443.                 mov     dx,offset errmsg7
  444. disp_error:
  445.                 call    print_string            ;No, then display error
  446.                 mov     ax,4C01h                ;  message and exit
  447.                 int     21h                     ;  with RC = 1
  448. check_dimmer_change:
  449.                 test    change_flag,1           ;Adjust color registers if
  450.                 jz      check_delay_change      ;  dimmer value was changed
  451.                 push    ds
  452.                 mov     ds,other_seg            ;Point DS to installed
  453.                 assume  ds:nothing              ;  segment
  454.                 mov     ah,ds:[dimmer_val]
  455.                 call    adj_palette_1
  456.                 pop     ds
  457.                 assume  ds:code
  458.                 jmp     exit                    ;Terminate
  459. check_delay_change:
  460.                 test    change_flag,2           ;Exit now if delay value
  461.                 jnz     exit                    ;  was modified
  462. ;
  463. ;Install a copy of DIMMER.
  464. ;
  465. install:
  466.                 mov     ax,3508h                ;Hook into interrupt 8
  467.                 int     21h
  468.                 mov     word ptr int08h,bx
  469.                 mov     word ptr int08h[2],es
  470.                 mov     ax,2508h
  471.                 mov     dx,offset timerint
  472.                 int     21h
  473.  
  474.                 mov     ax,3509h                ;Hook into interrupt 9
  475.                 int     21h
  476.                 mov     word ptr int09h,bx
  477.                 mov     word ptr int09h[2],es
  478.                 mov     ax,2509h
  479.                 mov     dx,offset kbint
  480.                 int     21h
  481.  
  482.                 mov     ax,3510h                ;Hook into interrupt 10h
  483.                 int     21h
  484.                 mov     word ptr int10h,bx
  485.                 mov     word ptr int10h[2],es
  486.                 mov     ax,2510h
  487.                 mov     dx,offset videoint
  488.                 int     21h
  489.  
  490.                 mov     dx,offset program       ;Display copyright notice
  491.                 call    print_string            ;  and jump to final
  492.                 jmp     final_install           ;  install code
  493. initialize      endp
  494.  
  495. ;-----------------------------------------------------------------------------
  496. ; PRINT_STRING displays a DOS "$"-delimited text string with leading and
  497. ; trailing CRLFs.
  498. ;   Entry: DS:DX - String address
  499. ;-----------------------------------------------------------------------------
  500. crlf            db      13,10,"$"
  501.  
  502. print_string    proc    near
  503.                 push    dx                      ;Save entry-level value of DX
  504.                 mov     ah,9                    ;Print leading CRLF
  505.                 mov     dx,offset crlf
  506.                 int     21h
  507.                 mov     ah,9                    ;Print text string
  508.                 pop     dx
  509.                 int     21h
  510.                 mov     ah,9                    ;Print trailing CRLF
  511.                 mov     dx,offset crlf
  512.                 int     21h
  513.                 ret                             ;Exit to caller
  514. print_string    endp
  515.  
  516. ;-----------------------------------------------------------------------------
  517. ; SETVIDFLAG modifies the video reset flag.
  518. ;   Entry: DS:SI - Address of optional sign value.
  519. ;-----------------------------------------------------------------------------
  520. setvidflag      proc    near
  521.                 mov     al,1                    ;Assume video flag enable
  522.                 cmp     byte ptr [si],"-"       ;Check for video flag disable
  523.                 jne     setvidflag_1
  524.                 dec     al
  525. setvidflag_1:
  526.                 mov     es,other_seg            ;Point ES to installed seg
  527.                 mov     es:[restorebyvid],al    ;Set/Reset video flag
  528.                 clc
  529.                 ret
  530. setvidflag      endp
  531.  
  532. ;-----------------------------------------------------------------------------
  533. ; SETDIM sets the dimmer value.
  534. ;   Entry: DS:SI - Address of first digit
  535. ;   Exit:  CF set on error (DX points to error message text)
  536. ;-----------------------------------------------------------------------------
  537. setdim          proc    near
  538.                 mov     di,si                   ;Copy command line pointer
  539.                 call    asc2bin                 ;Convert ASCII to binary
  540.                 mov     dx,offset errmsg8       ;Exit on error
  541.                 jc      setdim_error
  542.                 cmp     byte ptr [di-1],"-"     ;Negate value if negative
  543.                 jne     setdim_1
  544.                 neg     ax
  545. setdim_1:
  546.                 mov     dx,offset errmsg5
  547.                 cmp     ax,63                   ;Error if value is less than
  548.                 jg      setdim_error            ;  -63 or greater than +63
  549.                 cmp     ax,-63
  550.                 jl      setdim_error
  551.  
  552.                 mov     es,other_seg            ;Point ES to installed seg
  553.                 mov     es:[dimmer_val],al      ;Record dimmer value
  554.                 clc
  555. setdim_exit:
  556.                 ret
  557. setdim_error:
  558.                 stc
  559.                 jmp     short setdim_exit
  560. setdim          endp
  561.  
  562. ;-----------------------------------------------------------------------------
  563. ; SETDELAY sets the delay counter.
  564. ;   Entry: DS:SI - Address of first character past /D switch
  565. ;   Exit:  CF set on error (DX points to error message text)
  566. ;-----------------------------------------------------------------------------
  567. setdelay        proc    near
  568. setdelay_l1:
  569.                 lodsb
  570.                 cmp     al,32                   ;Skip spaces
  571.                 je      setdelay_l1
  572.                 mov     dx,offset errmsg2       ;Error if no delay value
  573.                 cmp     al,13                   ;  was specified
  574.                 je      setdelay_error
  575.  
  576.                 dec     si                      ;Back up to first character
  577.                 call    asc2bin                 ;Convert ASCII to binary
  578.                 mov     dx,offset errmsg6       ;Exit on error
  579.                 jc      setdelay_error
  580.                 mov     bx,0FFFFh               ;If delay value 0, disable
  581.                 or      ax,ax                   ;  delay counter with FFFFh
  582.                 je      delay_2
  583.                 mov     bx,ax                   ;Save delay value
  584. setdelay_l2:
  585.                 lodsb                           ;Get next character
  586.                 cmp     al,32                   ;Skip spaces
  587.                 je      setdelay_l2
  588.                 mov     dx,offset errmsg2       ;Error if no delay value
  589.                 cmp     al,13                   ;  was specified
  590.                 je      setdelay_error
  591.  
  592.                 mov     di,si                   ;Copy pointer to number
  593.                 cmp     al,"-"                  ;Check for leading sign
  594.                 je      setdelay_1              ;  identifier
  595.                 cmp     al,"+"
  596.                 je      setdelay_1
  597.                 dec     si                      ;Back up to first character
  598. setdelay_1:
  599.                 push    bx                      ;Save delay value
  600.                 call    asc2bin                 ;ASCII --> binary
  601.                 pop     bx                      ;Retrieve delay value
  602.                 mov     dx,offset errmsg8       ;Exit on error
  603.                 jc      setdelay_error
  604.                 cmp     byte ptr [di-1],"-"     ;Negate value if negative
  605.                 jne     delay_1
  606.                 neg     ax
  607. delay_1:
  608.                 mov     dx,offset errmsg5       ;Check to see if the value
  609.                 cmp     ax,63                   ;  is out of range
  610.                 jg      setdelay_error
  611.                 cmp     ax,-63
  612.                 jl      setdelay_error
  613. delay_2:
  614.                 mov     es,other_seg            ;Load new delay and dimmer
  615.                 mov     es:[delaydimval],al     ;  values into the
  616.                 mov     es:[wait_time],bx       ;  program
  617.                 mov     es:[dim_counter],bx
  618.                 mov     es:[second_cnt],1092
  619.                 clc
  620. setdelay_exit:
  621.                 ret
  622. setdelay_error:
  623.                 stc
  624.                 jmp     short setdelay_exit
  625. setdelay        endp
  626.  
  627. ;-----------------------------------------------------------------------------
  628. ; REMOVE removes a resident copy of the program from memory.
  629. ;   Exit: CF set on error
  630. ;-----------------------------------------------------------------------------
  631. remove          proc    near
  632.                 cmp     alrdy_installed,0       ;See if installed
  633.                 je      remove_error            ;No, error
  634.                 mov     ax,3508h                ;Get timer vector
  635.                 int     21h
  636.                 mov     ax,es                   ;Check to make sure timer
  637.                 cmp     ax,other_seg            ;  vector not modified
  638.                 jne     remove_error
  639.  
  640.                 mov     ax,3509h                ;Get keyboard vector
  641.                 int     21h
  642.                 mov     ax,es                   ;Check to make sure keyboard
  643.                 cmp     ax,other_seg            ;  vector not modified
  644.                 jne     remove_error
  645.  
  646.                 mov     ax,3510h                ;Get video vector
  647.                 int     21h
  648.                 mov     ax,es                   ;Check to make sure video
  649.                 cmp     ax,other_seg            ;  vector not modified
  650.                 jne     remove_error
  651.  
  652.                 push    ds
  653.                 lds     dx,es:[int08h]          ;Get old interrupt 8 vector
  654.                 mov     ax,2508h                ;Set interrupt
  655.                 int     21h
  656.                 lds     dx,es:[int09h]          ;Get old interrupt 9 vector
  657.                 mov     ax,2509h                ;Set interrupt
  658.                 int     21h
  659.                 lds     dx,es:[int10h]          ;Get old interrupt 10 vector
  660.                 mov     ax,2510h                ;Set interrupt
  661.                 int     21h
  662.                 pop     ds
  663.  
  664.                 mov     cx,es:[env_segment]
  665.                 mov     ah,49h                  ;Free PSP block
  666.                 int     21h
  667.                 mov     es,cx                   ;Free environment block
  668.                 mov     ah,49h
  669.                 int     21h
  670. remove_exit:    
  671.                 clc
  672. remove_exit1:
  673.                 ret
  674. remove_error:
  675.                 stc
  676.                 jmp     remove_exit1
  677. remove          endp
  678.  
  679. ;-----------------------------------------------------------------------------
  680. ; ASC2BIN Converts an ASCII number pointed to by SI to a hex value.
  681. ;   Entry: SI = pointer to ASCII number
  682. ;   Exit:  AX = binary value
  683. ;          CF set on error
  684. ;-----------------------------------------------------------------------------
  685. ten             dw      10
  686.  
  687. asc2bin         proc near
  688.                 xor     ax,ax                   ;Clear accumulator
  689.                 xor     bx,bx                   ;Clear BX
  690. asc_loop:
  691.                 mov     bl,[si]                 ;Get ASCII character
  692.                 cmp     bl,13                   ;Done if carriage return or
  693.                 je      asc_exit                ;  space encountered
  694.                 cmp     bl,32
  695.                 je      asc_exit
  696.                 inc     si
  697.                 sub     bl,"0"                  ;ASCII --> binary
  698.                 jb      asc_error               ;Error if binary value is
  699.                 cmp     bl,9                    ;  less than 0 or greater
  700.                 ja      asc_error               ;  than 9
  701.                 mul     ten                     ;Multiply accumulator by 10
  702.                 add     ax,bx                   ;Add last digit to sum
  703.                 jmp     short asc_loop          ;Loop until done
  704. asc_exit:
  705.                 clc
  706. asc_exit1:
  707.                 ret
  708. asc_error:
  709.                 stc
  710.                 jmp     short asc_exit1
  711. asc2bin         endp
  712.  
  713. code            ends
  714.  
  715.                 end     main
  716.