home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / pcmag / vol5n20.zip / SUGGEST.ASM next >
Assembly Source File  |  1987-12-13  |  12KB  |  236 lines

  1. CODE SEGMENT                           ;*************************
  2. ASSUME CS:CODE,DS:CODE                 ;*                       *
  3. ORG 100H                               ;*  REMEMBER TO EXE2BIN  *
  4.                                        ;*                       *
  5. START:         JMP    INITIALIZE       ;*************************
  6.  
  7. ;              DATA AREA
  8. ;              ---------
  9. COPY_RIGHT     DB      'Copyright 1986 Ziff-Davis Publishing Co.'
  10. SCREEN_SEG     DW  0B000H
  11. OLD_TIMER      DD  ?
  12. STATUS_REG     DW  ?
  13.  
  14. COUNTER        DW  0
  15. TIME_OUT       DW  1
  16. FREQUENCY      DW  7387H                     ;Twenty seven minutes
  17.  
  18. FREQ_CONSTANT  EQU 3276                      ;Three minutes
  19. DURA_CONSTANT  EQU 4205                      ;17/1000 sec.
  20.  
  21. ;              CODE AREA
  22. ;              ---------
  23. SUGGEST:       STI                           ;Turn the interrupts back on
  24.                PUSHF                         ; and save the flags
  25.                PUSH   AX                     ; and all registers we will
  26.                PUSH   CX                     ; be using.
  27.                PUSH   DX
  28.                PUSH   DS
  29.                PUSH   ES
  30.                PUSH   SI
  31.                PUSH   DI
  32.  
  33.                PUSH   CS                     ;Retrieve our data segment.
  34.                POP    DS
  35.                INC    WORD PTR COUNTER       ;Increment the counter.
  36.                MOV    DX,COUNTER
  37.                CMP    DX,FREQUENCY           ;Is it time to display?
  38.                JNZ    EXIT                   ;If no, exit
  39.                MOV    WORD PTR COUNTER,0     ; else, reset counter
  40.                MOV    AX,40H                 ;Point to ROM BIOS data area.
  41.                MOV    ES,AX
  42.                MOV    AL,ES:[49H]            ;Get current CRT_MODE
  43.                CMP    AL,1                   ;Is it 40 column?
  44.                JBE    EXIT                   ;If yes, exit
  45.                CMP    AL,3                   ;Is it color card in text?
  46.                JBE    DISPLAY                ;If yes, display.
  47.                CMP    AL,7                   ;Is it mono card?
  48.                JNZ    EXIT                   ;If no, exit.
  49.  
  50. DISPLAY:       MOV    DX,STATUS_REG          ;Retrieve status register and
  51.                MOV    AX,SCREEN_SEG          ; retrieve screen buffer segment.
  52.                PUSH   DS                     ;ES points to data
  53.                POP    ES
  54.                MOV    DS,AX                  ; and DS points to screen buffer.
  55.                MOV    SI,160*11              ;Source is 11th row of screen
  56.                MOV    DI,OFFSET SCREEN       ; and destination end of code.
  57.                CLD                           ;Set direction forward.
  58.                CALL   READ                   ;Go read the screen.
  59.  
  60.                PUSH   DS                     ;Switch source
  61.                PUSH   ES                     ; and destination segments.
  62.                POP    DS
  63.                POP    ES
  64.                MOV    SI,OFFSET MSG          ;Point to message
  65.                CALL   WRITE                  ; and go write it.
  66.  
  67.                MOV    CX,TIME_OUT            ;Get the duration time out
  68. DELAY:         DEC    CX                     ; and delay here while monitor
  69.                JNZ    DELAY                  ; displays message.
  70.  
  71.                MOV    SI,OFFSET SCREEN       ;Point to data and replace
  72.                CALL   WRITE                  ; it on the screen.
  73.  
  74. EXIT:          POP    DI                     ;Restore registers
  75.                POP    SI                     ; and flags.
  76.                POP    ES
  77.                POP    DS
  78.                POP    DX
  79.                POP    CX
  80.                POP    AX
  81.                POPF
  82.  
  83.                JMP    CS:OLD_TIMER           ;Goto old timer interrupt.
  84.  
  85. ;--------------------------------------------------------;
  86. ; This subroutine will read three lines in the middle    ;
  87. ; of the screen and store them at the end of code so the ;
  88. ; display can be restored after we display our message.  ;
  89. ;--------------------------------------------------------;
  90.  
  91. READ:          MOV    CX,3*80                ;Set count to three lines.
  92. HORZ_RET1:     IN     AL,DX                  ;Get status.
  93.                TEST   AL,1                   ;Is it low?
  94.                JNZ    HORZ_RET1              ;If no, wait until it is.
  95.                CLI                           ;No more interrupts.
  96.  
  97. WAIT1:         IN     AL,DX                  ;Get status
  98.                TEST   AL,1                   ;Is it high?
  99.                JZ     WAIT1                  ;If no, wait until it is.
  100.                LODSB                         ;Retrieve a byte.
  101.                STI                           ;Interrupts back on.
  102.                STOSB                         ;Store the byte.
  103.                INC    SI                     ;Bump the point past attribute.
  104.                LOOP   HORZ_RET1              ;Get next byte.
  105.                RET                           ;Return.
  106.  
  107. ;----------------------------------------------------------;
  108. ; This subroutine writes three lines to the screen buffer. ;
  109. ;----------------------------------------------------------;
  110.  
  111. WRITE:         MOV    DI,160*11              ;Point to the 11th row.
  112.                MOV    CX,3*80                ;Count of three rows.
  113. PUT_BYTE:      LODSB                         ;Get a byte.
  114.                MOV    AH,AL                  ;Store it in AH.
  115. HORZ_RET2:     IN     AL,DX                  ;Get status.
  116.                TEST   AL,1                   ;Is it low?
  117.                JNZ    HORZ_RET2              ;If no, wait until it is.
  118.                CLI                           ;No more interrupts.
  119.  
  120. WAIT2:         IN     AL,DX                  ;Get status.
  121.                TEST   AL,1                   ;Is it high?
  122.                JZ     WAIT2                  ;If no, wait until it is.
  123.                MOV    AL,AH                  ;Retrieve the byte
  124.                STOSB                         ; and store it.
  125.                STI                           ;Interrupts back on.
  126.                INC    DI                     ;Bump pointer past attribute.
  127.                LOOP   PUT_BYTE               ;Write next byte.
  128.                RET                           ;Return.
  129.  
  130. ;---------------------------------------------------------------------;
  131. ; This is the start of the install. We will need the port of status   ;
  132. ; register and the video card address. Then we will parse the command ;
  133. ; line and store. Check for frequency and duration switches. Take the ;
  134. ; the timer tick interrupt and terminate but stay resident.           ;
  135. ;---------------------------------------------------------------------;
  136.  
  137. INITIALIZE:    MOV    AL,32                  ;First pad the message
  138.                MOV    DI,OFFSET MSG          ;storage area with three
  139.                MOV    CX,80*3                ;lines of spaces.
  140.                REP    STOSB
  141.  
  142. PARSE:         XOR    CX,CX                  ;Zero in string counter.
  143.                MOV    SI,82H                 ;Point to string.
  144.                CMP    BYTE PTR[SI-2],1       ;Is there a string?
  145.                JA     GET_MSG                ;If yes, get the message length
  146.                INT    20H                    ; else terminate.
  147.  
  148. GET_MSG:       LODSB                         ;Get a byte.
  149.                INC    CX                     ;Increment counter.
  150.                CMP    AL,13                  ;Is it carriage return?
  151.                JZ     MESSAGE                ;If yes, end of message.
  152.                CMP    AL,'/'                 ;Is it switch character?
  153.                JNZ    GET_MSG                ;If no, get next byte.
  154.  
  155. GET_SWITCH:    LODSB                         ;Get a byte.
  156.                CMP    AL,13                  ;Is it carriage return?
  157.                JZ     MESSAGE                ;If yes, end of switches.
  158.                AND    AL,5FH                 ;Capitalize.
  159.                CMP    AL,'F'                 ;Is it frequency switch?
  160.                JNZ    DURATION               ;If no, check duration switch
  161.                CALL   CONVERT                ; else convert number to hex
  162.                MOV    BX,FREQ_CONSTANT       ; get frequency constant
  163.                MUL    BX                     ; and multiply.
  164.                SUB    FREQUENCY,AX           ;Subtract from frequency default.
  165.                JMP    SHORT GET_SWITCH       ;Get next character.
  166.  
  167. DURATION:      CMP    AL,'D'                 ;Is it duration switch?
  168.                JNZ    GET_SWITCH             ;If no, get next character
  169.                CALL   CONVERT                ; else convert number to hex
  170.                MOV    BX,DURA_CONSTANT       ; get duration constant
  171.                MUL    BX                     ; and multiply.
  172.                ADD    TIME_OUT,AX            ;Add to time out default.
  173.                JMP    SHORT GET_SWITCH       ;Get next character.
  174.  
  175. MESSAGE:       MOV    SI,82H                 ;Point to message.
  176.                MOV    DI,OFFSET MSG+80       ;Point to storage.
  177.                DEC    CX                     ;Adjust counter.
  178.                CMP    CX,80                  ;Is it more than one line?
  179.                JB     CENTER                 ;If no, center
  180.                MOV    CX,80                  ; else, truncate to one line
  181.                JMP    SHORT STORE            ; and store.
  182.  
  183. CENTER:        MOV    BX,80                  ;Take 80
  184.                SUB    BX,CX                  ; and subtract message length
  185.                SHR    BX,1                   ; divide by two
  186.                ADD    DI,BX                  ; and add to storage offset.
  187. STORE:         REP    MOVSB                  ;Store.
  188.  
  189. CARD:          MOV    AX,40H                 ;Point to ROM BIOS data area
  190.                MOV    ES,AX
  191.                MOV    AX,ES:[63H]            ;Get base address of video card.
  192.                ADD    AX,6                   ;Convert to status register
  193.                MOV    STATUS_REG,AX          ; and store.
  194.                CMP    AX,3BAH                ;Is it mono card?
  195.                JZ     INTERRUPT                    ;If yes, go to interrupt
  196.                ADD    WORD PTR SCREEN_SEG,800H     ; else point to color card.
  197.  
  198. INTERRUPT:     MOV    AX,351CH                     ;Get timer tick vector
  199.                INT    21H
  200.                MOV    WORD PTR OLD_TIMER,BX        ; and store offset
  201.                MOV    WORD PTR OLD_TIMER[2],ES     ; and segment.
  202.  
  203.                MOV    DX,OFFSET SUGGEST            ;Replace with our
  204.                MOV    AX,251CH                     ; offset and segment.
  205.                INT    21H
  206.  
  207.                MOV    DX,OFFSET SCREEN+80*3+1      ;Terminate but
  208.                INT    27H                          ; stay resident.
  209.  
  210. ;---------------------------------------------;
  211. ; This subroutine will convert decimal to hex ;
  212. ;---------------------------------------------;
  213.  
  214. CONVERT:       XOR    AH,AH                  ;Zero in high half.
  215.                LODSB                         ;Get a byte.
  216.                CMP    AL,'1'                 ;Is it less than one
  217.                JB     IGNORE                 ; or more than nine?
  218.                CMP    AL,'9'
  219.                JA     IGNORE                 ;If yes, ignore
  220.                SUB    AL,30H                 ; else convert to decimal
  221.                RET                           ; and return.
  222. IGNORE:        MOV    AL,0                   ;Default is zero.
  223.                RET                           ;Return.
  224.  
  225. ;------------------------------------------------------------;
  226. ; Message and screen storage is placed here instead of in    ;
  227. ; the data area to save 480 bytes in the BASIC data listing. ;
  228. ;------------------------------------------------------------;
  229.  
  230. MSG:
  231. ORG  OFFSET MSG+80*3
  232. SCREEN:
  233.  
  234. CODE ENDS
  235. END  START
  236.