home *** CD-ROM | disk | FTP | other *** search
/ Piper's Pit BBS/FTP: ibm 0010 - 0019 / ibm0010-0019 / ibm0010.tar / ibm0010 / QC25-10.ZIP / SAMPLES / MISC.AS$ / MISC.bin
Encoding:
Text File  |  1989-04-28  |  30.8 KB  |  1,066 lines

  1.     .MODEL small, c
  2.     INCLUDE demo.inc
  3.     .CODE
  4.  
  5.  
  6. ;* DisableCGA - Disables CGA video by reprogramming the control register.
  7. ;*
  8. ;* Shows:   Instructions - cli     sti     loopz     loopnz
  9. ;*
  10. ;* Uses:    vconfig - Video configuration structure, declared in the
  11. ;*        DEMO.INC include file. The structure must first be
  12. ;*        initialized by calling the GetVidConfig procedure.
  13. ;*
  14. ;* Params:  None
  15. ;*
  16. ;* Return:  None
  17.  
  18. DisableCGA PROC \
  19.     USES ax cx dx            ; Preserve registers
  20.  
  21.     mov    cx, -1            ; Set maximum loop count
  22.     mov    dx, 03DAh        ; Address of status register
  23. wait1:    in    al, dx            ; Get video status
  24.     test    al, 8            ; Vertical retrace active?
  25.     loopnz    wait1            ; Yes?    Wait for end/timeout
  26.     cli                ; Disallow interruptions
  27.     mov    cx, -1            ; Reset loop count
  28. wait2:    in    al, dx            ; Get video status
  29.     test    al, 8            ; Start of vertical retrace?
  30.     loopz    wait2            ; No?  Wait for start/timeout
  31.     sub    dx, 2            ; DX = address of control reg
  32.     mov    al, 1            ; Value to disable CGA video
  33.     out    dx, al            ; Disable video
  34.     sti                ; Reenable interrupts
  35.     ret
  36.  
  37. DisableCGA ENDP
  38.  
  39.  
  40. ;* EnableCGA - Enables CGA video by reprogramming the control register.
  41. ;*
  42. ;* Uses:    vconfig - Video configuration structure, declared in the
  43. ;*        DEMO.INC include file. The structure must first be
  44. ;*        initialized by calling the GetVidConfig procedure.
  45. ;*
  46. ;* Params:  None
  47. ;*
  48. ;* Return:  None
  49.  
  50. EnableCGA PROC \
  51.     USES ax dx            ; Preserve registers
  52.  
  53.     mov    dx, 03D8h        ; Address of control register
  54.     mov    al, vconfig.CGAvalue    ; Reprogram with proper value
  55.     out    dx, al            ; Enable video
  56.     ret
  57.  
  58. EnableCGA ENDP
  59.  
  60.  
  61. ;* WinOpen - Saves portion of screen to allocated memory, then opens a window
  62. ;* with specified fill attribute. See also the WinClose procedure.
  63. ;*
  64. ;* Shows:   DOS Function - 48h (Allocate Memory Block)
  65. ;*        BIOS Interrupt - 10h, Function 6 (Initialize or Scroll Up Window)
  66. ;*        Instructions - movsw    stosw      rep
  67. ;*
  68. ;* Uses:    vconfig - Video configuration structure, declared in the
  69. ;*        DEMO.INC include file. The structure must first be
  70. ;*        initialized by calling the GetVidConfig procedure.
  71. ;*
  72. ;* Params:  row1 - Row at top of window
  73. ;*        col1 - Column at left edge of window
  74. ;*        row2 - Row at bottom of window
  75. ;*        col2 - Column at right edge of window
  76. ;*        attr - Fill attribute for window
  77. ;*
  78. ;* Return:  Short integer with segment address of allocated buffer, or
  79. ;*        0 if unable to allocate memory
  80.  
  81. WinOpen PROC \
  82.     USES ds di si, \
  83.     row1:WORD, col1:WORD, row2:WORD, col2:WORD, attr:WORD
  84.  
  85.     GetVidOffset row1, col1     ; Get offset in video segment
  86.     mov    si, ax            ; SI = video offset for window
  87.     mov    bx, row2
  88.     sub    bx, row1
  89.     inc    bx            ; BX = number of window rows
  90.     mov    cx, col2
  91.     sub    cx, col1
  92.     inc    cx            ; CX = number of columns
  93.  
  94.     mov    ax, cx            ; Compute number of video
  95.     mul    bl            ;   cells in window
  96.     add    ax, 3            ; Plus 3 additional entries
  97.     shr    ax, 1            ; Shift right 3 times to
  98.     shr    ax, 1            ;   multiply by 2 bytes/cell,
  99.     shr    ax, 1            ;   divide by 16 bytes/para
  100.     inc    ax            ; Add a paragraph
  101.     push    bx            ; Save number of rows
  102.     mov    bx, ax            ; BX = number of paragraphs
  103.     mov    ah, 48h         ; Request DOS Function 48h
  104.     int    21h            ; Allocate Memory Block
  105.     pop    bx
  106.     jnc    @F            ; If successful, continue
  107.     sub    ax, ax            ; Else return null pointer
  108.     jmp    SHORT exit
  109.  
  110. @@:    mov    es, ax            ; Point ES:DI to allocated
  111.     sub    di, di            ;   buffer
  112.     mov    ax, si
  113.     stosw                ; Copy video offset to buffer
  114.     mov    ax, bx
  115.     stosw                ; Number of rows to buffer
  116.     mov    ax, cx
  117.     stosw                ; Number of cols to buffer
  118.     mov    ax, 160         ; Number of video cells/row
  119.     mov    ds, vconfig.sgmnt    ; DS = video segment
  120. loop1:    push    si            ; Save ptr to start of line
  121.     push    cx            ;   and number of columns
  122.     cmp    vconfig.adapter, CGA    ; CGA adapter?
  123.     jne    @F            ; No?  Skip video disable
  124.  
  125. ; For CGA adapters, WinOpen avoids screen "snow" by disabling the video prior
  126. ; to block memory moves, then reenabling it. Although this technique can
  127. ; result in brief flickering, it demonstrates the fastest way to access a
  128. ; block in the CGA video buffer without causing display snow. See also the
  129. ; StrWrite procedure for another solution to the problem of CGA snow.
  130.  
  131.     call    DisableCGA        ; Yes?    Disable video
  132. @@:    rep    movsw            ; Copy one row to buffer
  133.     cmp    vconfig.adapter, CGA
  134.     jne    @F
  135.     call    EnableCGA        ; Reenable CGA video
  136. @@:    pop    cx            ; Recover number of columns
  137.     pop    si            ;   and start of line
  138.     add    si, ax            ; Point to start of next line
  139.     dec    bx            ; Decrement row counter
  140.     jnz    loop1            ; Loop while rows remain
  141.  
  142.  
  143. ; Screen contents (including display attributes) are now copied to buffer.
  144. ; Next open window, overwriting the screen portion just saved.
  145.  
  146.     mov    ax, 0600h        ; Scroll service
  147.     mov    bh, BYTE PTR attr    ; Fill attribute
  148.     mov    cx, col1        ; CX = row/col for upper left
  149.     mov    ch, BYTE PTR row1
  150.     mov    dx, col2        ; DX = row/col for lower right
  151.     mov    dh, BYTE PTR row2
  152.     int    10h            ; Blank window area on screen
  153.     mov    ax, es            ; Return address of allocated
  154. exit:    ret                ;   segment
  155.  
  156. WinOpen ENDP
  157.  
  158.  
  159. ;* WinClose - "Closes" a window previously opened by the WinOpen procedure.
  160. ;* See also the WinOpen procedure.
  161. ;*
  162. ;* Shows:   DOS Function - 49h (Release Memory Block)
  163. ;*        Instructions - lodsw
  164. ;*        Operators - : (segment override)     SEG
  165. ;*
  166. ;* Uses:    vconfig - Video configuration structure, declared in the
  167. ;*        DEMO.INC include file. The structure must first be
  168. ;*        initialized by calling the GetVidConfig procedure.
  169. ;*
  170. ;* Params:  addr - Segment address of buffer that holds screen contents
  171. ;*           saved in WinOpen procedure
  172. ;*
  173. ;* Return:  None
  174.  
  175. WinClose PROC \
  176.     USES ds di si, \
  177.     addr:WORD
  178.  
  179.     mov    ds, addr        ; DS:SI points to buffer
  180.     sub    si, si
  181.     lodsw
  182.     mov    di, ax            ; DI = video offset of window
  183.     lodsw
  184.     mov    bx, ax            ; BX = number of window rows
  185.     lodsw
  186.     mov    cx, ax            ; CX = number of columns
  187.  
  188.     mov    ax, SEG vconfig.sgmnt
  189.     mov    es, ax            ; Point ES to data segment
  190.     push    es:vconfig.sgmnt
  191.     pop    es            ; ES = video segment
  192.     mov    ax, 160         ; Number of video cells/row
  193. loop1:    push    di            ; Save ptr to start of line
  194.     push    cx            ;   and number of columns
  195.     cmp    vconfig.adapter, CGA    ; CGA adapter?
  196.     jne    @F            ; No?  Skip video disable
  197.  
  198. ; Disable CGA video prior to memory move to avoid screen snow. (See the
  199. ; WinOpen and StrWrite procedures for further discussions on CGA snow.)
  200.  
  201.     call    DisableCGA        ; Yes?    Disable video
  202. @@:    rep    movsw            ; Copy one row to buffer
  203.     cmp    vconfig.adapter, CGA
  204.     jne    @F
  205.     call    EnableCGA        ; Reenable CGA video
  206. @@:    pop    cx            ; Recover number of columns
  207.     pop    di            ;   and start of line
  208.     add    di, ax            ; Point to start of next line
  209.     dec    bx            ; Decrement row counter
  210.     jnz    loop1            ; Loop while rows remain
  211.  
  212.     mov    ah, 49h         ; Request DOS Function 49h
  213.     mov    es, addr
  214.     int    21h            ; Release Memory Block
  215.     ret
  216.  
  217. WinClose ENDP
  218.  
  219.  
  220. ;* SetCurSize - Sets cursor size.
  221. ;*
  222. ;* Shows:   BIOS Interrupt - 10h, Function 1 (Set Cursor Type)
  223. ;*
  224. ;* Params:  scan1 - Starting scan line
  225. ;*        scan2 - Ending scan line
  226. ;*
  227. ;* Return:  None
  228.  
  229. SetCurSize PROC \
  230.     scan1:WORD, scan2:WORD
  231.  
  232.     mov    cx, scan2        ; CL = ending scan line
  233.     mov    ch, BYTE PTR scan1    ; CH = starting scan line
  234.     mov    ah, 1            ; Function 1
  235.     int    10h            ; Set Cursor Type
  236.     ret
  237.  
  238. SetCurSize ENDP
  239.  
  240.  
  241. ;* GetCurSize - Gets current cursor size.
  242. ;*
  243. ;* Shows:   BIOS Interrupt - 10h, Function 3 (Get Cursor Position)
  244. ;*
  245. ;* Uses:    vconfig - Video configuration structure, declared in the
  246. ;*        DEMO.INC include file. The structure must first be
  247. ;*        initialized by calling the GetVidConfig procedure.
  248. ;*
  249. ;* Params:  None
  250. ;*
  251. ;* Return:  Short integer with high byte = top scan line,
  252. ;*                   low byte  = bottom scan line
  253.  
  254. GetCurSize PROC
  255.  
  256.     mov    ah, 3            ; Function 3
  257.     mov    bh, vconfig.dpage
  258.     int    10h            ; Get Cursor Position
  259.     mov    ax, cx            ; Return cursor size
  260.     ret
  261.  
  262. GetCurSize ENDP
  263.  
  264.  
  265. ;* GetCurPos - Gets current cursor position.
  266. ;*
  267. ;* Shows:   BIOS Interrupt - 10h, Function 3 (Get Cursor Position)
  268. ;*
  269. ;* Uses:    vconfig - Video configuration structure, declared in the
  270. ;*        DEMO.INC include file. The structure must first be
  271. ;*        initialized by calling the GetVidConfig procedure.
  272. ;*
  273. ;* Params:  None
  274. ;*
  275. ;* Return:  Short integer with high byte = row, low byte = column
  276.  
  277. GetCurPos PROC
  278.  
  279.     mov    ah, 3            ; Function 3
  280.     mov    bh, vconfig.dpage
  281.     int    10h            ; Get cursor position
  282.     mov    ax, dx            ; Return cursor row/column
  283.     ret
  284.  
  285. GetCurPos ENDP
  286.  
  287.  
  288. ;* GetShift - Gets current shift status. Checks for extended keyboard,
  289. ;* and if available returns additional shift information.
  290. ;*
  291. ;* Shows:   BIOS Interrupt - 16h, Functions 2 and 12h (Get Keyboard Flags)
  292. ;*
  293. ;* Params:  None
  294. ;*
  295. ;* Return:  Long integer
  296. ;*        high word = 0 for non-extended keyboard
  297. ;*            1 for extended keyboard
  298. ;*        low word has following bits set when indicated keys are pressed:
  299. ;*        0 - Right shift              8 - Left Ctrl
  300. ;*        1 - Left shift              9 - Left Alt
  301. ;*        2 - Ctrl                 10 - Right Ctrl
  302. ;*        3 - Alt                 11 - Right Alt
  303. ;*        4 - Scroll Lock active         12 - Scroll Lock pressed
  304. ;*        5 - Num Lock active          13 - Num Lock pressed
  305. ;*        6 - Caps Lock active         14 - Caps Lock pressed
  306. ;*        7 - Insert toggled             15 - Sys Req pressed
  307.  
  308. GetShift PROC
  309.  
  310.     sub    dx, dx            ; Assume non-extended keyboard
  311.     mov    ah, 2            ;   and use Function 2
  312.     mov    es, dx            ; Point ES to low memory
  313.     test    BYTE PTR es:[496h], 16    ; Extended keyboard installed?
  314.     jz    @F            ; No?    Leave AH as Function 2
  315.     inc    dx            ; Yes?    Set high word of return code
  316.     mov    ah, 12h         ;   and use Function 12h
  317. @@:    int    16h            ; Get Keyboard Flags
  318.     ret
  319.  
  320. GetShift ENDP
  321.  
  322.  
  323. ;* GetKeyClock - Waits for keypress while updating time at specified location
  324. ;* on screen.
  325. ;*
  326. ;* Shows:   BIOS Interrupt - 16h, Functions 0 and 10h (Read Character)
  327. ;*                 16h, Functions 1 and 11h (Get Keyboard Status)
  328. ;*        DOS Functions - 2Ah (Get Date)
  329. ;*                2Ch (Get Time)
  330. ;*
  331. ;* Uses:    vconfig - Video configuration structure, declared in the
  332. ;*        DEMO.INC include file. The structure must first be
  333. ;*        initialized by calling the GetVidConfig procedure.
  334. ;*
  335. ;* Params:  row - Screen row for clock display
  336. ;*        col - Screen column for clock display
  337. ;*
  338. ;* Return:  Short integer with key scan code in high byte and ASCII
  339. ;*        character code in low byte. Low byte is 0 for special
  340. ;*        keys (such as the "F" keys) which don't generate characters.
  341.  
  342.     .DATA
  343.     PUBLIC datestr
  344. datestr DB    '  -  -     :  :  ', 0    ; Date/time string
  345.     .CODE
  346.  
  347.     EXTRN StrWrite:PROC
  348.  
  349. GetKeyClock PROC \
  350.     row:WORD, col:WORD
  351.  
  352.     LOCAL    service:BYTE
  353.  
  354.     call    GetShift        ; Check for extended keyboard
  355.     mov    service, 11h        ; Request for Function 11h
  356.     cmp    dx, 1            ; Extended keyboard available?
  357.     je    key1            ; Yes?    Set AH appropriately
  358.     mov    service, 1        ; No? Set AH for Function 1
  359. key1:    mov    ah, service
  360.     int    16h            ; Get Keyboard Status
  361.     jnz    exit            ; Ready?  Exit procedure
  362.                     ; Not ready?  Check text mode
  363.     cmp    vconfig.mode, 7     ; Monochrome text mode?
  364.     je    @F            ; Yes?    Continue
  365.     cmp    vconfig.mode, 3     ; Color text mode?
  366.     je    @F            ; Yes?    Continue
  367.     cmp    vconfig.mode, 2     ; Black/white?
  368.     jne    key1            ; No?  Skip clock update and
  369.                     ;   poll keyboard again
  370.  
  371. ; If 80-column text, get date and time from DOS before again polling keyboard,
  372. ; and display at upper right corner of screen.
  373.  
  374. @@:    mov    ah, 2Ch         ; Request time
  375.     int    21h            ; Get Time
  376.     mov    dl, dh
  377.     push    dx            ; Save seconds,
  378.     push    cx            ;   minutes,
  379.     mov    cl, ch            ;   and
  380.     push    cx            ;   hours
  381.     mov    ah, 2Ah         ; Request date
  382.     int    21h            ; Get Date
  383.     sub    cx, 1900        ; Subtract century, CL = year
  384.     push    cx            ; Save year,
  385.     push    dx            ;   day,
  386.     mov    dl, dh            ;   and
  387.     push    dx            ;   month
  388.  
  389.     mov    cx, 6
  390.     sub    bx, bx
  391. loop1:    pop    ax            ; Recover all 6 numbers in AL
  392.     aam                ; Convert to unpacked BCD
  393.     xchg    al, ah            ; Switch bytes for word move
  394.     or    ax, '00'        ; Make ASCII numerals
  395.     mov    WORD PTR datestr[bx], ax; Copy to string
  396.     add    bx, 3            ;   at every third byte
  397.     loop    loop1
  398.  
  399.     DispText row, col, <OFFSET datestr>
  400.     jmp    key1            ; Loop again for keypress
  401.  
  402. exit:    mov    ah, service        ; 1 or 11h, depending on keybd
  403.     dec    ah            ; Set AH to 0 or 10h
  404.     int    16h            ; Get key to remove it from
  405.     ret                ;   keyboard buffer
  406.  
  407. GetKeyClock ENDP
  408.  
  409.  
  410. ;* GetPSP - Gets address of Program Segment Prefix. For DOS 3.0 or higher.
  411. ;*
  412. ;* Shows:   DOS Function - 62h (Get PSP Address)
  413. ;*        Instruction - call (See the MISCDEMO.ASM example program
  414. ;*              for an example of a call dispatch table)
  415. ;*
  416. ;* Params:  None
  417. ;*
  418. ;* Return:  Short integer with PSP segment address
  419. ;*        or 0 if DOS version below 3.0
  420.  
  421.     EXTRN GetVer:PROC
  422.  
  423. GetPSP    PROC
  424.  
  425.     call    GetVer            ; Get DOS version number
  426.     cmp    ax, 300         ; Version 3.0 or higher?
  427.     jb    dos2            ; No?  Return error code
  428.     mov    ah, 62h         ; Yes?    Query DOS for PSP
  429.     int    21h            ; Get PSP Address
  430.     mov    ax, bx            ; Put in AX
  431.     jmp    SHORT exit        ; Exit
  432. dos2:    sub    ax, ax            ; For version 2, return 0
  433. exit:    ret
  434.  
  435. GetPSP    ENDP
  436.  
  437.  
  438. ;* GetMem - Gets total size of memory and determines the largest amount of
  439. ;* unallocated memory available. GetMem invokes DOS Function 48h (Allocate
  440. ;* Memory) to request an impossibly large memory block. DOS denies the re-
  441. ;* quest, but returns instead the size of the largest block available. This
  442. ;* is the amount that GetMem returns to the calling program. See the WinOpen
  443. ;* procedure for an example of calling Function 48h to allocate unused memory.
  444. ;*
  445. ;* Shows:   BIOS Interrupt - 12h (Get Conventional Memory Size)
  446. ;*
  447. ;* Params:  None
  448. ;*
  449. ;* Return:  Long integer, high word = total memory in kilobytes (KB)
  450. ;*              low word  = largest block of available memory (KB)
  451.  
  452. GetMem    PROC
  453.  
  454.     int    12h            ; Get total memory in K
  455.     push    ax            ; Save size of memory
  456.     mov    ah, 48h         ; Request memory allocation
  457.     mov    bx, 0FFFFh        ; Ensure request is denied for
  458.                     ;   impossibly large block
  459.     int    21h            ; Get largest available block in BX
  460.     mov    ax, bx            ; Copy to AX
  461.     mov    cl, 6            ; Convert paragraphs to kilobytes by
  462.     shr    ax, cl            ;   dividing by 64
  463.     pop    dx            ; Recover total in DX
  464.     ret                ; Return long integer DX:AX
  465.  
  466. GetMem    ENDP
  467.  
  468.  
  469. ;* VeriPrint - Checks if LPT1 (PRN) is available.
  470. ;*
  471. ;* Shows:   BIOS Interrupt - 17h (Parallel Port Printer Driver)
  472. ;*
  473. ;* Params:  None
  474. ;*
  475. ;* Return:  Short integer, 1 for yes or 0 for no
  476.  
  477. VeriPrint PROC
  478.  
  479.     mov    ah, 2            ; Check printer status for 
  480.     sub    dx, dx            ;   parallel printer (port 0)
  481.     int    17h
  482.     xchg    dx, ax            ; Put 0 (for error) in AX
  483.     test    dh, 00101001b        ; Are any error bits on?
  484.     jne    exit            ; Yes?    Leave 0
  485.     test    dh, 10010000b        ; Are both operation bits on?
  486.     jz    exit            ; No?  Leave 0
  487.     inc    ax            ; Yes?    Return 1
  488. exit:    ret
  489.  
  490. VeriPrint ENDP
  491.  
  492.  
  493. ;* IntToAsc - Converts integer to ASCII string. This procedure is useful
  494. ;* only for assembly language, and is not intended to be C-callable.
  495. ;*
  496. ;* Shows:   Instructions - cwd       aam     xchg
  497. ;*
  498. ;* Entry:   AX = integer (9999 max)
  499. ;*
  500. ;* Return:  DX:AX = 4-digit ASCII number
  501.  
  502. IntToAsc PROC
  503.  
  504.     cwd                ; Zero DX register
  505.     mov    cx, 100         ; Divide AX by 100, yields
  506.     div    cx            ;   AX=quotient, DX=remainder
  507.     aam                ; Make digits unpacked BCD
  508.     or    ax, '00'        ; Convert to ASCII
  509.     xchg    ax, dx            ; Do same thing for DX
  510.     aam
  511.     or    ax, '00'
  512.     ret                ; Return DX:AX = ASCII number
  513.  
  514. IntToAsc ENDP
  515.  
  516.  
  517. ;* VeriAnsi - Checks for ANSI driver by writing ANSI sequence to report
  518. ;* cursor position. If report compares with position returned from
  519. ;* GetCurPos procedure, then ANSI driver is operating.
  520. ;*
  521. ;* Shows:   DOS Functions - 06h (Direct Console I/O)
  522. ;*                0Ch (Flush Input Buffer and then Input)
  523. ;*
  524. ;* Params:  None
  525. ;*
  526. ;* Return:  Short integer, 1 for yes or 0 for no
  527.  
  528.     .DATA
  529.     PUBLIC report
  530. report    DB    ESCAPE, '[6n$'        ; ANSI Report Cursor sequence
  531.     .CODE
  532.  
  533. VeriAnsi PROC
  534.  
  535.     call    GetCurPos        ; Cursor position from BIOS
  536.     mov    cx, ax            ; Save it in CX
  537.     mov    dx, OFFSET report    ; ANSI string to get position
  538.     mov    ah, 9            ; Request DOS String Output
  539.     int    21h            ; Write ANSI escape sequence
  540.  
  541.     mov    ah, 6            ; Skip Esc character in
  542.     mov    dl, 0FFh        ;   keyboard buffer
  543.     int    21h
  544.     jz    e_exit            ; If no key, ANSI not loaded
  545.     mov    ah, 6            ; Skip '[' character
  546.     int    21h
  547.     jz    e_exit            ; If no key, ANSI not loaded
  548.     mov    ah, 6            ; Get 1st digit of cursor row
  549.     int    21h
  550.     jz    e_exit            ; If no key, ANSI not loaded
  551.     mov    bh, al            ; Store in BH
  552.     mov    ah, 6            ; Get 2nd digit of cursor row
  553.     int    21h
  554.     jz    e_exit            ; If no key, ANSI not loaded
  555.     mov    bl, al            ; Store in BL
  556.     mov    al, ch            ; Get original row # in AL
  557.     cbw                ; AX = row # from GetCurPos
  558.     inc    ax            ; Add 1 to it
  559.     call    IntToAsc        ; Make ASCII digits
  560.     cmp    ax, bx            ; ANSI and BIOS reports match?
  561.     jne    e_exit            ; No?  Then ANSI not loaded
  562.  
  563.     mov    ax, 0C06h        ; Flush remaining ANSI keys
  564.     mov    dl, 0FFh        ;   from buffer
  565.     int    21h
  566.     mov    ax, 1            ; Set 1 for true
  567.     jmp    SHORT exit        ;   and exit
  568.  
  569. e_exit: sub    ax, ax            ; Set 0 return code if no
  570. exit:    ret                ;   ANSI driver installed
  571.  
  572. VeriAnsi ENDP
  573.  
  574.  
  575. ;* VeriCop - Checks for coprocessor.
  576. ;*
  577. ;* Shows:   BIOS Interrupt - 11h (Get Equipment Configuration)
  578. ;*
  579. ;* Params:  None
  580. ;*
  581. ;* Return:  Short integer, 1 for yes or 0 for no
  582.  
  583. VeriCop PROC
  584.  
  585.     int    11h            ; Check peripherals
  586.     test    al, 2            ; Coprocessor?
  587.     mov    ax, 0            ; Assume no, don't alter flags
  588.     jz    exit            ; No?  Done
  589.     inc    ax            ; Yes?    Set to 1
  590. exit:    ret
  591.  
  592. VeriCop ENDP
  593.  
  594.  
  595. ;* SetLineMode - Sets line mode for EGA or VGA.
  596. ;*
  597. ;* Shows:   BIOS Interrupt - 10h, Function 11h (Character Generator Interface)
  598. ;*                 10h, Function 12h (Video Subsystem Configuration)
  599. ;*        Instruction - cmp
  600. ;*
  601. ;* Uses:    vconfig - Video configuration structure, declared in the
  602. ;*        DEMO.INC include file. The structure must first be
  603. ;*        initialized by calling the GetVidConfig procedure.
  604. ;*
  605. ;* Params:  line - Requested line mode (25, 43, or 50)
  606. ;*
  607. ;* Return:  Short integer with error code
  608. ;*        0 if successful
  609. ;*        1 if error
  610.  
  611. SetLineMode PROC \
  612.     line:WORD
  613.  
  614.     cmp    vconfig.adapter, EGA    ; EGA or VGA?
  615.     jge    @F            ; Yes?    Continue
  616.     jmp    e_exit            ; No?  Exit with error
  617. @@:    mov    ax, line        ; Check for valid parameter
  618.     cmp    al, 25
  619.     je    line25
  620.     cmp    al, 43
  621.     je    line43
  622.     cmp    al, 50
  623.     je    line50
  624.     jmp    SHORT e_exit        ; If not 25, 43, or 50, exit w/ error
  625.  
  626. line25: mov    al, 11h         ; Set for EGA 25-line mode
  627.     cmp    vconfig.adapter, EGA    ; EGA?
  628.     je    lmode            ; Yes?    Continue
  629.     mov    ax, 1202h        ; No?  Function 12h for VGA
  630.     mov    bl, 30h         ; AL = 2 for 400 scan lines
  631.     int    10h            ; Reset to 400 scan lines
  632.     mov    ax, 0003        ; Reset mode (Function 0)
  633.     int    10h            ;   to mode 3 (80-col text)
  634.     mov    al, 14h         ; Request 8x16 char matrix
  635.     jmp    SHORT lmode
  636.  
  637. line43: mov    al, 12h         ; Set for EGA 43-line mode
  638.     cmp    vconfig.adapter, EGA    ; EGA?
  639.     je    lmode            ; Yes?    Continue
  640.     mov    ax, 1201h        ; No?  Function 12h for VGA
  641.     mov    bl, 30h         ; AL = 1 for 350 scan lines
  642.     int    10h            ; Reset to 350 scan lines
  643.     mov    ax, 0003        ; Reset mode (Function 0)
  644.     int    10h            ;   to mode 3 (80-col text)
  645.     mov    al, 12h         ; Request 8x8 character matrix
  646.     jmp    SHORT lmode
  647.  
  648. line50: cmp    vconfig.adapter, VGA    ; VGA?
  649.     jne    e_exit            ; No?  Exit with error
  650.     mov    ax, 1202h        ; Yes?    Function 12h
  651.     mov    bl, 30h         ; AL = 2 for 400 scan lines
  652.     int    10h            ; Reset to 400 scan lines
  653.     mov    ax, 0003        ; Reset mode (Function 0)
  654.     int    10h            ;   to mode 3 (80-col text)
  655.     mov    al, 12h         ; Request 8x8 character matrix
  656.  
  657. lmode:    sub    bl, bl            ; Use table 0
  658.     mov    ah, 11h         ; Request Function 11h
  659.     int    10h            ; Set new line mode
  660.  
  661.     mov    ah, 12h         ; Select alternate print
  662.     mov    bl, 20h         ;    screen for EGA and VGA
  663.     int    10h
  664.  
  665.     cmp    vconfig.adapter, VGA    ; VGA?
  666.     je    exit            ; Yes?    Then exit
  667.     cmp    line, 12h        ; If EGA 43-line mode, set
  668.     je    port            ;   cursor through port to
  669.                     ;   avoid cursor emulation bug 
  670.     mov    al, 7            ; Else use BIOS to set cursor
  671.     push    ax            ; Pass bottom scan line
  672.     mov    al, 6
  673.     push    ax            ; Pass top scan line
  674.     call    SetCurSize        ; Set normal cursor
  675.     add    sp, 4            ; Clean stack
  676.     jmp    SHORT exit        ; Exit
  677.  
  678. port:    mov    dx, 03D4h        ; Video controller address
  679.     mov    ax, 060Ah        ; Set AH = 06h (cursor start)
  680.                     ;     AL = 0Ah (register #)
  681.     out    dx, ax            ; Update port
  682.     mov    ax, 000Bh        ; Set AH = 00h (cursor end)
  683.                     ;     AL = 0Bh (register #)
  684.     out    dx, ax            ; Update port
  685.     jmp    SHORT exit        ; Normal exit
  686.  
  687. e_exit: mov    ax, 1            ; Set error code
  688.     jmp    SHORT @F
  689. exit:    sub    ax, ax            ; Clear error code
  690. @@:    ret
  691.  
  692. SetLineMode ENDP
  693.  
  694.  
  695. ;* Pause - Waits for specified number of clocks to elapse, then returns.
  696. ;*
  697. ;* Shows:   BIOS Interrupt - 1Ah, Function 0 (Real-Time Clock Driver)
  698. ;*        Operators - LOCAL      []
  699. ;*
  700. ;* Params:  duration - Desired duration in clocks, where
  701. ;*               18 clocks = approx 1 second
  702. ;*
  703. ;* Return:  None
  704.  
  705. Pause    PROC \
  706.     duration:WORD
  707.  
  708.     LOCAL time:DWORD
  709.  
  710.     sub    ah, ah
  711.     int    1Ah            ; Get Clock Count in CX:DX
  712.     add    dx, duration        ; Add pause time to it
  713.     adc    cx, 0
  714.     mov    WORD PTR time[0], dx    ; Result is target time;
  715.     mov    WORD PTR time[2], cx    ;   keep in local variable
  716. loop1:    int    1AH            ; Now repeatedly poll clock
  717.     cmp    dx, WORD PTR time[0]    ;   count until the target
  718.     jb    loop1            ;   time is reached
  719.     cmp    cx, WORD PTR time[2]
  720.     jb    loop1
  721.     ret
  722.  
  723. Pause    ENDP
  724.  
  725.  
  726. ;* Sound - Sounds speaker with specified frequency and duration.
  727. ;*
  728. ;* Shows:   Instructions - in        out
  729. ;*
  730. ;* Params:  freq - Desired frequency of sound in Hertz
  731. ;*        duration - Desired duration in clocks, where
  732. ;*               18 clocks = approx 1 second
  733. ;*
  734. ;* Return:  None
  735.  
  736. Sound    PROC \
  737.     freq:WORD, duration:WORD
  738.  
  739.     mov    al, 0B6h        ; Initialize channel 2 of
  740.     out    43h, al         ;   timer chip
  741.     mov    dx, 12h         ; Divide 1,193,182 Hertz
  742.     mov    ax, 34DEh        ;   (clock frequency) by
  743.     div    freq            ;   desired frequency
  744.                     ; Result is timer clock count
  745.     out    42h, al         ; Low byte of count to timer
  746.     mov    al, ah
  747.     out    42h, al         ; High byte of count to timer
  748.     in    al, 61h         ; Read value from port 61h
  749.     or    al, 3            ; Set first two bits
  750.     out    61h, al         ; Turn speaker on
  751.     push    duration
  752.     call    Pause            ; Pause for specified time
  753.     add    sp, 2            ; Clean stack on return
  754.     in    al, 61h         ; Get port value
  755.     xor    al, 3            ; Kill bits 0-1 to turn
  756.     out    61h, al         ;   speaker off
  757.     ret
  758.  
  759. Sound    ENDP
  760.  
  761.  
  762. ;* WriteTTY - Displays ASCIIZ string at cursor position, in either text
  763. ;* or graphics mode.
  764. ;*
  765. ;* Shows:   BIOS Interrupt - 10h, Function 0Eh (Write Character in TTY Mode)
  766. ;*        Instruction - loop
  767. ;*
  768. ;* Uses:    vconfig - Video configuration structure, declared in the
  769. ;*        DEMO.INC include file. The structure must first be
  770. ;*        initialized by calling the GetVidConfig procedure.
  771. ;*
  772. ;* Params:  str - Pointer to ASCIIZ string
  773. ;*        icolor - Color index (for graphics mode only)
  774. ;*
  775. ;* Return:  None
  776.  
  777. WriteTTY PROC \
  778.     USES ds si, \
  779.     str:PTR BYTE, icolor:WORD
  780.  
  781.     mov    bx, icolor        ; BL = color index
  782.     mov    bh, vconfig.dpage    ; BH = current display page
  783.     LoadPtr ds, si, str
  784.     mov    cx, -1            ; Set loop counter to maximum
  785.     mov    ah, 14            ; Function 14
  786. loop1:    lodsb                ; Get character from string
  787.     or    al, al            ; NULL string terminator?
  788.     jz    exit            ; Yes?    Exit
  789.     int    10h            ; No?  Display, advance cursor
  790.     loop    loop1            ; Loop to get next character
  791. exit:    ret
  792.  
  793. WriteTTY ENDP
  794.  
  795.  
  796. ;* Colors - Alters screen colors within a specified area by using bit
  797. ;* or move operations on display attribute bytes in video memory.
  798. ;*
  799. ;* Shows:   Instructions - not     rol     ror     and     xor     or
  800. ;*
  801. ;* Params:  logic - Code number, 0 = NOT    2 = ROR     4 = XOR    6 = MOV   
  802. ;*                 1 = ROL    3 = AND     5 = OR
  803. ;*        attr - Attribute mask
  804. ;*        row1 - Row at top of window
  805. ;*        col1 - Column at left edge of window
  806. ;*        row2 - Row at bottom of window
  807. ;*        col2 - Column at right edge of window
  808. ;*
  809. ;* Return:  None
  810.  
  811. Colors    PROC \
  812.     USES ds si, \
  813.     logic:WORD, attr:WORD, row1:WORD, col1:WORD, row2:WORD, col2:WORD
  814.  
  815.     GetVidOffset row1, col1     ; Get offset in video segment
  816.     inc    ax
  817.     mov    si, ax            ; SI = offset for 1st attr byte
  818.     mov    bx, row2
  819.     sub    bx, row1
  820.     inc    bx            ; BX = number of window rows
  821.     mov    cx, col2
  822.     sub    cx, col1
  823.     inc    cx            ; CX = number of columns
  824.  
  825.     mov    ds, vconfig.sgmnt    ; DS = video segment
  826.     mov    ax, attr        ; AL = mask for and, xor, and or
  827. loop1:    push    si            ; Save ptr to start of line
  828.     push    cx            ;   and number of columns
  829.     cmp    vconfig.adapter, CGA    ; CGA adapter?
  830.     jne    @F            ; No?  Skip video disable
  831.  
  832. ; Disable CGA video prior to memory access to avoid screen snow. (See the
  833. ; WinOpen and StrWrite procedures for further discussions on CGA snow.)
  834.  
  835.     call    DisableCGA        ; Yes?    Disable video
  836. @@:    cmp    logic, 1        ; Rotate left?
  837.     jl    c_not            ; If less, do NOT
  838.     je    c_rol            ; If equal, do ROL
  839.     cmp    logic, 3        ; And?
  840.     jl    c_ror            ; If less, do ROR
  841.     je    c_and            ; If equal, do AND
  842.     cmp    logic, 5        ; Or?
  843.     jl    c_xor            ; If less, do XOR
  844.     je    c_or            ; If equal, do OR
  845.                     ; Otherwise, do MOV
  846. c_mov:    mov    BYTE PTR [si], al    ; MOV attr parameter
  847.     add    si, 2            ;   into attribute byte
  848.     loop    c_mov
  849.     jmp    SHORT c_done
  850. c_or:    or    BYTE PTR [si], al    ; OR with attr parameter
  851.     add    si, 2
  852.     loop    c_or
  853.     jmp    SHORT c_done
  854. c_xor:    xor    BYTE PTR [si], al    ; XOR with attr parameter
  855.     add    si, 2
  856.     loop    c_xor
  857.     jmp    SHORT c_done
  858. c_and:    and    BYTE PTR [si], al    ; AND with attr parameter
  859.     add    si, 2
  860.     loop    c_and
  861.     jmp    SHORT c_done
  862. c_ror:    ror    BYTE PTR [si], 1    ; Rotate right 1 bit
  863.     add    si, 2
  864.     loop    c_ror
  865.     jmp    SHORT c_done
  866. c_rol:    rol    BYTE PTR [si], 1    ; Rotate left 1 bit
  867.     add    si, 2
  868.     loop    c_rol
  869.     jmp    SHORT c_done
  870. c_not:    not    BYTE PTR [si]        ; Flip bits
  871.     add    si, 2
  872.     loop    c_not
  873.  
  874. c_done: cmp    vconfig.adapter, CGA
  875.     jne    @F
  876.     call    EnableCGA        ; Reenable CGA video
  877. @@:    pop    cx            ; Recover number of columns
  878.     pop    si            ; Recover offset for start of line
  879.     add    si, 160         ; Point to start of next line
  880.     dec    bx            ; Decrement row counter
  881.     jnz    loop1            ; Loop while rows remain
  882.     ret                ; Exit when all lines complete
  883.  
  884. Colors    ENDP
  885.  
  886.  
  887. ;* Exec - Executes a child process.  Exec handles the usual chores associated
  888. ;* with spawning a process:  (1) parsing the command line tail and loading the
  889. ;* FCBs with the first two arguments; (2) setting and restoring the vectors
  890. ;* for Interrupts 1Bh, 23h, and 24h; and (3) querying DOS for the child's
  891. ;* return code.
  892. ;*
  893. ;* Shows:   DOS Functions - 29h (Parse Filename)
  894. ;*                25h (Set Interrupt Vector)
  895. ;*                35h (Get Interrupt Vector)
  896. ;*                4Bh (Execute Program)
  897. ;*                4Dh (Get Return Code)
  898. ;*
  899. ;* Params:  spec - Pointer to ASCIIZ specification for program file
  900. ;*           (must include .COM or .EXE extension)
  901. ;*        block - Pointer to parameter block structure
  902. ;*        break - Pointer to new Ctrl-Break (Interrupt 1Bh) handler
  903. ;*        ctrlc - Pointer to new Ctrl-C (Interrupt 23h) handler
  904. ;*        criterr - Pointer to new Critical Error (Interrupt 24h) handler
  905. ;*
  906. ;* Return:  Short integer with child return code, or -1 for EXEC error
  907.  
  908. Exec    PROC \
  909.     USES ds si di, \
  910.     spec:PTR BYTE, block:PTR parmblk, break:PTR BYTE, \
  911.     ctrlc:PTR BYTE, criterr:PTR BYTE
  912.  
  913.     jmp    SHORT @F        ; Jump over data area
  914.  
  915. old_1Bh DD    WORD PTR ?        ; Keep vectors for Interrupts
  916. old_23h DD    WORD PTR ?        ;   1Bh, 23h, and 24h in
  917. old_24h DD    WORD PTR ?        ;   code segment
  918. old_stk DD    WORD PTR ?        ; Keep stack pointer
  919.  
  920. @@:    Vector 1Bh, cs:old_1Bh, break    ; Save, replace Int 1Bh vector
  921.     Vector 23h, cs:old_23h, ctrlc    ; Save, replace Int 23h vector
  922.     Vector 24h, cs:old_24h, criterr ; Save, replace Int 24h vector
  923.  
  924.     LoadPtr ds, bx, block        ; Point DS:BX to parameter block
  925.     push    ds            ; Save segment address
  926.     les    di, [bx].fcb1        ; Point ES:DI to first FCB
  927.     lds    si, [bx].taddr        ; Point DS:SI to command line tail
  928.     inc    si            ; Skip over count byte
  929.  
  930.     mov    ax, 2901h        ; Set AH to request Function 29h
  931.                     ; AL = flag to skip leading blanks
  932.     int    21h            ; Parse command-line into first FCB
  933.     pop    es            ; Recover seg addr of parameter block
  934.     les    di, es:[bx].fcb2    ; Point ES:DI to second FCB
  935.     mov    ax, 2901h        ; Request DOS Function #29h again
  936.     int    21h            ; Parse command-line into second FCB
  937.  
  938.     push    bp            ; Save only important register
  939.     mov    WORD PTR cs:old_stk[0], sp
  940.     mov    WORD PTR cs:old_stk[2], ss
  941.     LoadPtr es, bx, block        ; ES:BX points to param block
  942.     LoadPtr ds, dx, spec        ; DS:DX points to path spec
  943.     mov    ax, 4B00h        ; AH = DOS Function 4Bh
  944.                     ; AL = 0 for load and execute
  945.     int    21h            ; Execute Program
  946.     mov    sp, WORD PTR cs:old_stk[0] ; Reset stack pointers
  947.     mov    ss, WORD PTR cs:old_stk[2]
  948.     pop    bp            ; Recover saved register
  949.  
  950. ; Restore vectors for Interrupts 1Bh, 23h, and 24h.
  951.  
  952.     mov    ax, 251Bh        ; AH = DOS Function 25h
  953.                     ; AL = interrupt number
  954.     lds    dx, cs:old_1Bh        ; DS:DX = original vector
  955.     int    21h            ; Set Interrupt 1Bh Vector
  956.     mov    al, 23h         ; AL = interrupt number
  957.     lds    dx, cs:old_23h        ; DS:DX = original vector
  958.     int    21h            ; Set Interrupt 23h Vector
  959.     mov    al, 24h         ; AL = interrupt number
  960.     lds    dx, cs:old_24h        ; DS:DX = original vector
  961.     int    21h            ; Set Interrupt 24h Vector
  962.  
  963.     mov    ax, -1            ; Set error code
  964.     jc    exit            ; If EXEC error, exit
  965.     mov    ah, 4Dh         ; Else request child's code
  966.     int    21h            ; Get Return Code
  967.     sub    ah, ah            ; Make short integer
  968. exit:    ret
  969.  
  970. Exec    ENDP
  971.  
  972.  
  973. ;* BinToHex - Converts binary word to 6-byte hexadecimal number in
  974. ;* ASCIIZ string. String is right-justified and includes "h" radix.
  975. ;*
  976. ;* Shows:   Instruction - xlat
  977. ;*
  978. ;* Params:  num - Number to convert to hex string
  979. ;*        str - Pointer to 6-byte string
  980. ;*
  981. ;* Return:  None
  982.  
  983.     .DATA
  984. hex    DB    '0123456789ABCDEF'    ; String of hex numbers
  985.     .CODE
  986.  
  987. BinToHex PROC \
  988.     USES di, \
  989.     num:WORD, str:PTR BYTE
  990.  
  991.     LoadPtr es, di, str        ; Point ES:DI to 6-byte string
  992.     mov    bx, OFFSET hex        ; Point DS:BX to hex numbers
  993.     mov    ax, num         ; Number in AX
  994.     mov    cx, 2            ; Loop twice for two bytes
  995.  
  996. loop1:    xchg    ah, al            ; Switch bytes
  997.     push    ax            ; Save number
  998.     shr    al, 1            ; Shift high nibble to low
  999.     shr    al, 1
  1000.     shr    al, 1
  1001.     shr    al, 1
  1002.     xlat                ; Get equivalent ASCII number in AL
  1003.     stosb                ; Copy to 6-byte string, increment DI
  1004.     pop    ax            ; Recover number
  1005.     push    ax            ; Save it again
  1006.     and    al, 00001111b        ; Mask out high nibble
  1007.     xlat                ; Get equivalent ASCII number in AL
  1008.     stosb                ; Copy to 6-byte string, increment DI
  1009.     pop    ax            ; Recover number
  1010.     loop    loop1            ; Do next byte
  1011.     mov    ax, 'h'         ; Put null, 'h' radix in AX
  1012.     stosw                ; Copy to last two bytes in string
  1013.     ret
  1014.  
  1015. BinToHex ENDP
  1016.  
  1017.  
  1018. ;* NewBlockSize - Adjusts size of allocated memory block.
  1019. ;*
  1020. ;* Shows:   DOS Function - 4Ah (Resize Memory Block)
  1021. ;*
  1022. ;* Params:  addr - Segment address of block
  1023. ;*        resize - Requested block size in paragraphs
  1024. ;*
  1025. ;* Return:  Short integer error code
  1026. ;*        0 if successful
  1027. ;*        1 if error
  1028.  
  1029. NewBlockSize PROC \
  1030.     addr:WORD, resize:WORD
  1031.  
  1032.     mov    ax, addr        ; Get block address
  1033.     mov    es, ax            ; Point ES to block
  1034.     mov    bx, resize        ; New block size
  1035.     mov    ah, 4Ah         ; Function number
  1036.     int    21h            ; Resize Memory Block
  1037.     ret
  1038.  
  1039. NewBlockSize ENDP
  1040.  
  1041.  
  1042. ;* Initialize - Initializes global variables _psp and _env, which are defined
  1043. ;* in the DEMO.INC include file. If used with a DOS version less than 3.0,
  1044. ;* this procedure will not produce valid results unless it is called before
  1045. ;* changing the ES register. This is because at program entry ES points to
  1046. ;* the Program Segment Prefix (PSP).
  1047. ;*
  1048. ;* Params:  None
  1049. ;*
  1050. ;* Return:  None
  1051.  
  1052. Initialize PROC
  1053.  
  1054.     call    GetPSP            ; Get segment address of PSP
  1055.     or    ax, ax            ; DOS version less than 3.0?
  1056.     jz    @F            ; Yes?    Assume ES points to PSP
  1057.     mov    es, ax            ; No?  Reload ES with PSP address
  1058. @@:    mov    _psp, es        ; Initialize variable with PSP address
  1059.     mov    ax, es:[2Ch]        ; Get environment seg from PSP
  1060.     mov    _env, ax        ; Store it
  1061.     ret
  1062.  
  1063. Initialize ENDP
  1064.  
  1065.     END
  1066.