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

  1. ;* MISCDEMO - Invokes many of the QuickAssembler example procedures, most of
  2. ;* them demonstrating assembly language instructions and calls to the system
  3. ;* BIOS. MISCDEMO demonstrates how to:
  4. ;*
  5. ;*       -   determine hardware information
  6. ;*       -   display time and date while waiting for keystrokes
  7. ;*       -   play notes of any frequency on the speaker
  8. ;*       -   change the line mode for EGA or VGA systems
  9. ;*       -   create non-destructive pop-up windows
  10. ;*       -   execute another program as a child process
  11. ;*       -   create primitive handlers for Interrupts 1Bh, 23h, and 24h
  12. ;*       -   use C-callable procedures in assembly programs
  13. ;*       -   use simplified segment directives
  14. ;*       -   write model-independent procedures
  15. ;*       -   declare and initialize data with DUP, DB, DW, and DD
  16. ;*       -   create structures with the STRUCT directive
  17. ;*       -   declare macros
  18. ;*       -   set up a dispatch table
  19. ;*
  20. ;* MISCDEMO.EXE is built from the following files:
  21. ;*    MISCDEMO.ASM - Main program
  22. ;*    MISC.ASM       - QuickAssembler procedures for MISCDEMO
  23. ;*    COMMON.ASM   - QuickAssembler procedures shared by other example programs
  24. ;*    DEMO.INC       - Include file with macros, structure declarations
  25. ;*
  26. ;* Procedures:    GetVidConfig    GetCurPos    VeriPrint    GetPSP
  27. ;*        WinOpen     VeriAnsi    VeriCop     GetVer
  28. ;*        WinClose    StrWrite    SetLineMode    NewBlockSize
  29. ;*        SetCurSize    GetKeyClock    BinToHex    IntToAsc
  30. ;*        SetCurPos    GetShift    Sound        Colors
  31. ;*        GetCurSize    GetMem        Pause        Exec
  32. ;*        WriteTTY    Initialize
  33.  
  34.     DOSSEG
  35.     .MODEL small, c
  36.     INCLUDE demo.inc
  37.  
  38. PGMSIZE EQU    500h            ; Maximum program size in paragraphs
  39. F1    EQU    59            ; Extended code for first option key
  40. F7    EQU    65            ; Extended code for last option key
  41. CLKRW    EQU    0            ; Row for on-screen clock
  42. CLKCL    EQU    62            ; Column for on-screen clock
  43.  
  44. ;* Box - Macro to color portion of screen for effect. Not to be confused with
  45. ;* the WinOpen procedure, which is far more capable.
  46. ;*
  47. ;* Params:  row1 - Screen row at top of box
  48. ;*        col1 - Screen column at left side of box
  49. ;*        row2 - Screen row at bottom of box
  50. ;*        col2 - Screen column at right side of box
  51.  
  52. Box MACRO row1, col1, row2, col2
  53.     LOCAL sk
  54.     mov ax, 0600h            ;; Scroll service
  55.     mov bh, filmono            ;; Fill attribute
  56.     cmp vconfig.adapter, MDA        ;; Monochrome?
  57.     je    sk                ;; Yes?  Continue
  58.     mov bh, filcolr            ;; No?    Use color fill attribute
  59. sk: mov ch, row1
  60.     mov cl, col1            ;; CX = row/col for upper left
  61.     mov dh, row2
  62.     mov dl, col2            ;; DX = row/col for lower right
  63.     int 10h                ;; Blank window area on screen
  64. ENDM
  65.  
  66.     .STACK
  67.     .DATA
  68.  
  69. oldmode DB    ?            ; Original video mode
  70. oldcurs DW    ?            ; Original cursor coordinates
  71. keepseg DW    ?            ; Segment addr, orig screen
  72. buffer    DB    BUFFER_SIZE DUP(?)    ; Buffer for diskette read
  73. filcolr DB    1Fh, 20h, 3Bh, 4Eh    ; Color fill attributes
  74. filmono DB    70h, 89h, 78h, 1    ; Monochrome fill attributes
  75. fill    DB    7            ; Default attribute for menu
  76. filsub    DB    ?            ; Fore/background colors in submenu
  77.  
  78. presmsg DB    '. . . press a key to continue', 0
  79. yes    DB    'yes'
  80. no    DB    'no '
  81.  
  82. ; Main menu text
  83.  
  84. menu1    DB    '***  QuickAssembler Misc Demonstration Program  ***', 0
  85. menu2    DB    'F1  System Configuration', 0
  86. menu3    DB    'F2  Speaker Test', 0
  87. menu4    DB    'F3  Toggle Line Mode', 0
  88. menu5    DB    'F4  Windows', 0
  89. menu6    DB    'F5  Screen Colors', 0
  90. menu7    DB    'F6  Exec Program', 0
  91. menu8    DB    'Select an option, or press ESC to quit:', 0
  92.  
  93. ; Option F1 - System Configuration
  94.  
  95. monostr DB    'monochrome'
  96. clrstr    DB    'color     '
  97. adapstr DB    'MDA CGA MCGAEGA VGA '
  98. vidmsg1 DB    'Adapter:                 xxxx', 0
  99. vidmsg2 DB    'Display:                 xxxxxxxxxx', 0
  100. vidmsg3 DB    'Mode:                    xx', 0
  101. vidmsg4 DB    'Rows:                    xx', 0
  102. memmsg1 DB    'Total memory:            xxxx Kb', 0
  103. memmsg2 DB    'Available memory:        xxxx Kb', 0
  104. prnmsg    DB    'Printer ready:           xxx', 0
  105. ansimsg DB    'ANSI driver installed:   xxx', 0
  106. copmsg    DB    'Coprocessor installed:   xxx', 0
  107. LEN1    EQU    $ - copmsg - 4
  108.  
  109. ; Option F3 - Toggle Line Mode
  110.  
  111. linemsg DB    'Line mode reset available only for EGA or VGA', 0
  112.  
  113. ; Option F4 - Windows
  114.  
  115. winmsg    DB    'WINDOW x', 0
  116. LEN3    EQU    $ - winmsg - 2
  117.  
  118. ; Option F5  Screen Colors
  119.  
  120. cmsg1    DB    'Toggle                   Step', 0
  121. cmsg2    DB    '────────────────         ──────────────────', 0
  122. cmsg3    DB    'B  blink                 ', 27, 26, '  foreground', 0
  123. cmsg4    DB    'I  intensity             ', 24, 25, '  background', 0
  124. cmsg5    DB    'Foreground:  press F, then color number 0-7', 0
  125. cmsg6    DB    'Background:  press A, then color number 0-7', 0
  126. cmsg7    DB    'Color Numbers', 0
  127. cmsg8    DB    '───────────────────────────────────────────', 0
  128. cmsg9    DB    '0  black                     4  red', 0
  129. cmsg10    DB    '1  blue                      5  magenta', 0
  130. cmsg11    DB    '2  green                     6  brown', 0
  131. cmsg12    DB    '3  cyan                      7  white', 0
  132. cmsg13    DB    'Toggle', 0
  133. cmsg14    DB    '───────────────', 0
  134. cmsg15    DB    'B  blink', 0
  135. cmsg16    DB    'I  intensity', 0
  136. cmsg17    DB    'U  underline', 0
  137. cmsg18    DB    'R  reverse', 0
  138.  
  139. ; Option F6 - Exec Program
  140.  
  141. retmsg    DB    'Return code:  '
  142. recode    DB    6 DUP (?)        ; ASCII string for return code
  143. execmsg DB    'Enter program file spec (including .COM or .EXE):', 0
  144. tailmsg DB    'Enter command-line argument(s):', 0
  145. fspec    DB    50, 50 DUP (?)        ; File specification (max length = 50)
  146. tail    DB    50, 50 DUP (?)        ; Command-line tail (max length = 50)
  147. fcblk1    DB    0            ; Allocate space for 1st FCB
  148.     DB    11 DUP (?)
  149.     DB    25 DUP (0)
  150. fcblk2    DB    0            ; Allocate space for 2nd FCB
  151.     DB    11 DUP (?)
  152.     DB    25 DUP (0)
  153. pb    parmblk <>            ; Parameter block structure
  154.  
  155. ; Initialize dispatch table with offsets for internal procedures.
  156.  
  157. table    DW    get_config, speaker, set_lines
  158.     DW    pop_windows, set_attrs, exec_pgm
  159.  
  160.  
  161.     .CODE
  162.  
  163.     EXTRN GetVidConfig:PROC,  GetCurPos:PROC,    VeriPrint:PROC
  164.     EXTRN GetPSP:PROC,        WinOpen:PROC,      VeriAnsi:PROC
  165.     EXTRN VeriCop:PROC,       WinClose:PROC,     WriteTTY:PROC
  166.     EXTRN StrWrite:PROC,      SetLineMode:PROC,  NewBlockSize:PROC
  167.     EXTRN SetCurSize:PROC,    GetKeyClock:PROC,  BinToHex:PROC
  168.     EXTRN SetCurPos:PROC,     GetShift:PROC,     Sound:PROC
  169.     EXTRN GetCurSize:PROC,    GetMem:PROC,       Pause:PROC
  170.     EXTRN IntToAsc:PROC,      Colors:PROC,       GetVer:PROC
  171.     EXTRN Exec:PROC,          Initialize:PROC
  172.  
  173.  
  174.     .STARTUP
  175.  
  176.     call    Initialize        ; Initialize _psp and _env variables
  177.     mov    ax, PGMSIZE        ; Shrink memory block
  178.     push    ax            ;   allocated to program
  179.     push    _psp            ; Push PSP segment address
  180.     call    NewBlockSize        ; Return unused memory to DOS
  181.     add    sp, 4            ; Clean stack
  182.     call    GetVidConfig        ; Initialize variables
  183.     mov    al, vconfig.rows
  184.     mov    oldmode, al        ; Preserve original line mode
  185.     call    GetCurPos        ; Get current cursor position
  186.     mov    oldcurs, ax        ; Store it
  187.     mov    ax, 7
  188.     push    ax            ; Pass display attribute = 7
  189.     mov    al, 79
  190.     push    ax            ; Pass right column
  191.     mov    al, vconfig.rows
  192.     push    ax            ; Pass bottom row
  193.     sub    al, al
  194.     push    ax            ; Pass left column
  195.     push    ax            ;   and top row
  196.     call    WinOpen         ; Preserve original screen
  197.     add    sp, 10            ; Clean stack
  198.     mov    keepseg, ax        ; Keep segment address
  199.     or    ax, ax            ; Window opened successfully?
  200.     jnz    renew            ; Yes?    Continue
  201.     .EXIT    1            ; No?  Exit with return code = 1
  202.  
  203. renew:    call    disp_menu        ; Display main menu
  204.     Box CLKRW, CLKCL-1, CLKRW, CLKCL+17 ; Highlight on-screen clock
  205.     mov    ax, CLKCL        ; Column for clock
  206.     push    ax
  207.     mov    ax, CLKRW        ; Row for clock
  208.     push    ax
  209.     call    GetKeyClock        ; Poll for keyboard selection
  210.     add    sp, 4            ; Clean stack
  211.     cmp    al, ESCAPE        ; Esc key?
  212.     je    restr            ; Yes?    Quit
  213.     cmp    ah, F1            ; No?  Then is scan code for
  214.     jb    renew            ;   one of the function keys
  215.     cmp    ah, F7            ;   between F1 and F7?
  216.     ja    renew            ; No?  Try again
  217.     xchg    al, ah            ; Yes?    Make AX = AH
  218.     sub    al, F1            ; Normalize to 0
  219.     shl    al, 1            ; Double to make word index
  220.     mov    bx, ax            ; BX = index to table
  221.     call    table[bx]        ; Call procedure
  222.     jmp    SHORT renew        ; Loop for another key
  223.  
  224. restr:    mov    al, oldmode        ; Get original line mode
  225.     cmp    al, vconfig.rows    ; Same as current mode?
  226.     je    @F            ; Yes?    Continue
  227.     inc    ax            ; No?  Increment to 25/43/50
  228.     push    ax            ; Pass to procedure
  229.     call    SetLineMode        ; Restore line mode
  230.     add    sp, 2            ; Clean stack
  231. @@:    push    keepseg         ; Segment with screen contents
  232.     call    WinClose        ; Restore original screen
  233.     add    sp, 2            ; Clean stack
  234.     mov    ax, oldcurs
  235.     push    ax            ; Pass old cursor column coord
  236.     mov    al, ah
  237.     push    ax            ; Pass old cursor row coord
  238.     call    SetCurPos        ; Restore cursor to orig place
  239.     add    sp, 4            ; Clean stack
  240.  
  241.     .EXIT    0            ; Exit wih return code 0
  242.  
  243.  
  244. ;* disp_menu - Displays main menu.
  245. ;*
  246. ;* Uses:    vconfig - Video configuration structure, declared in the
  247. ;*        DEMO.INC include file. The structure must first be
  248. ;*        initialized by calling the GetVidConfig procedure.
  249. ;*
  250. ;* Return:  None
  251.  
  252. disp_menu PROC NEAR
  253.  
  254.     mov    ax, 0600h        ; Scroll screen service
  255.     mov    bh, fill        ; Menu display attribute
  256.     sub    cx, cx            ; From row 0, col 0
  257.     mov    dh, vconfig.rows    ;   to bottom row,
  258.     mov    dl, 79            ;   rightmost column
  259.     int    10h            ; Clear entire screen
  260.     DispText  4, 15, <OFFSET menu1> ; Display menu
  261.     DispText  8, 28, <OFFSET menu2>
  262.     DispText  9, 28, <OFFSET menu3>
  263.     DispText 10, 28, <OFFSET menu4>
  264.     DispText 11, 28, <OFFSET menu5>
  265.     DispText 12, 28, <OFFSET menu6>
  266.     DispText 13, 28, <OFFSET menu7>
  267.     DispText 17, 15, <OFFSET menu8>
  268.     mov    ax, 56
  269.     push    ax            ; Push column
  270.     mov    al, 17
  271.     push    ax            ; Push row
  272.     call    SetCurPos        ; Park cursor at prompt
  273.     add    sp, 4
  274.     ret
  275.  
  276. disp_menu ENDP
  277.  
  278.  
  279.  
  280. ;* press - Displays a prompt, then waits for a key press.
  281. ;*
  282. ;* Uses:    vconfig - Video configuration structure, declared in the
  283. ;*        DEMO.INC include file. The structure must first be
  284. ;*        initialized by calling the GetVidConfig procedure.
  285. ;*
  286. ;* Return:  None
  287.  
  288. press    PROC NEAR
  289.  
  290.     mov    dl, vconfig.rows
  291.     DispText dx, 50, <OFFSET presmsg>
  292.     mov    ax, 48
  293.     push    ax
  294.     mov    al, vconfig.rows    ; Bottom row of screen
  295.     push    ax
  296.     call    SetCurPos        ; Park cursor at prompt
  297.     add    sp, 4            ; Clean stack
  298.     mov    ax, CLKCL        ; Column for clock
  299.     push    ax
  300.     mov    ax, CLKRW        ; Row for clock
  301.     push    ax
  302.     call    GetKeyClock        ; Wait for keypress
  303.     add    sp, 4            ; Clean stack
  304.     ret
  305.  
  306. press    ENDP
  307.  
  308.  
  309.  
  310. ;* get_vidinfo - Initializes video configuration message for display.
  311. ;*
  312. ;* Uses:    vconfig - Video configuration structure, declared in the
  313. ;*        DEMO.INC include file. The structure must first be
  314. ;*        initialized by calling the GetVidConfig procedure.
  315. ;*
  316. ;* Return:  None
  317.  
  318. get_vidinfo PROC NEAR
  319.  
  320.     push    ds
  321.     pop    es            ; Point ES to data segment
  322.     mov    al, 4            ; Find index to 4-character
  323.     mul    vconfig.adapter     ;   group in string
  324.     add    ax, OFFSET adapstr    ; Point AX to proper group
  325.     mov    si, ax            ; Put pointer in SI
  326.     lea    di, vidmsg1[LEN1]    ; Point to 1st line of message
  327.     mov    cx, 2            ; Copy 4 letters (adapter
  328.     rep    movsw            ;   designation) to message
  329.  
  330.     mov    si, OFFSET monostr    ; Assume display is monochrome
  331.     cmp    vconfig.display, MONO    ; Then check with video struct
  332.     je    @F            ; Yes?    Continue
  333.     mov    si, OFFSET clrstr    ; No?  Point to "color" string
  334. @@:    lea    di, vidmsg2[LEN1]    ; Point to 2nd line of message
  335.     mov    cx, 5            ; Copy 10 chars ("monochrome"
  336.     rep    movsw            ;   or "color     ") to msg
  337.  
  338.     mov    al, vconfig.mode
  339.     cbw                ; AX = video mode
  340.     call    IntToAsc        ; Convert AX to ASCII
  341.     xchg    ah, al            ; Flip bytes for word write
  342.     mov    WORD PTR vidmsg3[LEN1], ax    ; Insert in message string
  343.  
  344.     mov    al, vconfig.rows
  345.     cbw
  346.     inc    ax            ; AX = number of screen rows
  347.     call    IntToAsc        ; Convert to ASCII
  348.     xchg    ah, al            ; Flip bytes for word write
  349.     mov    WORD PTR vidmsg4[LEN1], ax    ; Insert in message string
  350.     ret
  351.  
  352. get_vidinfo ENDP
  353.  
  354.  
  355.  
  356. ;* get_mem - Initializes memory information message.
  357. ;*
  358. ;* Return:  None
  359.  
  360. get_mem PROC NEAR
  361.  
  362.     call    GetMem            ; DX = total memory
  363.     push    ax            ; AX = available memory
  364.     mov    ax, dx
  365.     call    IntToAsc        ; Convert AX to ASCII
  366.     xchg    dh, dl            ; Flip bytes for word write
  367.     xchg    ah, al
  368.     mov    WORD PTR memmsg1[LEN1], dx    ; Insert in message
  369.     mov    WORD PTR memmsg1[LEN1+2], ax    ;   string
  370.     pop    ax                ; Recover avail memory #
  371.     call    IntToAsc            ; Convert to ASCII
  372.     xchg    dh, dl                ; Flip bytes for word write
  373.     xchg    ah, al
  374.     mov    WORD PTR memmsg2[LEN1], dx    ; Insert in message
  375.     mov    WORD PTR memmsg2[LEN1+2], ax    ;   string
  376.     ret
  377.  
  378. get_mem ENDP
  379.  
  380.  
  381.  
  382. ;* check_printer - Initializes printer status message.
  383. ;*
  384. ;* Shows:   Instruction - movsb
  385. ;*
  386. ;* Return:  None
  387.  
  388. check_printer PROC NEAR
  389.  
  390.     push    ds
  391.     pop    es            ; Point ES to data segment
  392.     mov    si, OFFSET yes        ; Assume answer is "yes"
  393.     call    VeriPrint        ; Check if printer ready
  394.     or    al, al            ; Ready?
  395.     jnz    @F            ; Yes?    Continue
  396.     mov    si, OFFSET no        ; No?  Point to "no" answer
  397. @@:    lea    di, prnmsg[LEN1]    ; Point to print message
  398.     mov    cx, 3            ; Copy 3 letters (either "yes"
  399.     rep    movsb            ;   or "no ") to message
  400.     ret
  401.  
  402. check_printer ENDP
  403.  
  404.  
  405.  
  406. ;* check_ansi - Initializes status message for ANSI driver.
  407. ;*
  408. ;* Return:  None
  409.  
  410. check_ansi PROC NEAR
  411.  
  412.     push    ds
  413.     pop    es            ; Point ES to data segment
  414.     mov    si, OFFSET yes        ; Assume answer is "yes"
  415.     call    VeriAnsi        ; Check if driver installed
  416.     or    al, al            ; Installed?
  417.     jnz    @F            ; Yes?    Continue
  418.     mov    si, OFFSET no        ; No?  Point to "no" answer
  419. @@:    lea    di, ansimsg[LEN1]    ; Point to ansi message
  420.     mov    cx, 3            ; Copy 3 letters (either "yes"
  421.     rep    movsb            ;   or "no ") to message
  422.     ret
  423.  
  424. check_ansi ENDP
  425.  
  426.  
  427.  
  428. ;* check_coproc - Initializes coprocessor status message.
  429. ;*
  430. ;* Return:  None
  431.  
  432. check_coproc PROC NEAR
  433.  
  434.     push    ds
  435.     pop    es            ; Point ES to data segment
  436.     mov    si, OFFSET yes        ; Assume answer is "yes"
  437.     call    VeriCop         ; Check for coprocessor
  438.     or    al, al            ; Installed?
  439.     jnz    @F            ; Yes?    Continue
  440.     mov    si, OFFSET no        ; No?  Point to "no" answer
  441. @@:    lea    di, copmsg[LEN1]    ; Point to coprocessor message
  442.     mov    cx, 3            ; Copy 3 letters (either "yes"
  443.     rep    movsb            ;   or "no ") to message
  444.     ret
  445.  
  446. check_coproc ENDP
  447.  
  448.  
  449.  
  450. ;* get_config - Displays system configuration information.
  451.  
  452. get_config PROC NEAR
  453.  
  454.     call    get_vidinfo        ; Initialize video message
  455.     call    get_mem         ; Initialize memory message
  456.     call    check_printer        ; Initialize printer message
  457.     call    check_ansi        ; Initialize ANSI driver msg
  458.     call    check_coproc        ; Initialize coprocessor msg
  459.     Box 4, 13, 20, 67        ; Clear screen with box
  460.     DispText  6, 23, <OFFSET vidmsg1>
  461.     DispText  7, 23, <OFFSET vidmsg2>
  462.     DispText  8, 23, <OFFSET vidmsg3>
  463.     DispText  9, 23, <OFFSET vidmsg4>
  464.     DispText 11, 23, <OFFSET memmsg1>
  465.     DispText 12, 23, <OFFSET memmsg2>
  466.     DispText 14, 23, <OFFSET prnmsg>
  467.     DispText 16, 23, <OFFSET ansimsg>
  468.     DispText 18, 23, <OFFSET copmsg>
  469.     call    press            ; Prompt for keypress
  470.     ret
  471.  
  472. get_config ENDP
  473.  
  474.  
  475.  
  476. ;* speaker - Sounds speaker with ascending frequencies.
  477. ;*
  478. ;* Return:  None
  479.  
  480. speaker PROC NEAR
  481.  
  482.     sub    ax, ax
  483. loop1:    add    ax, 100         ; Sound with frequencies
  484.     cmp    ax, 3000        ;   from 100 to 3000
  485.     ja    exit
  486.     push    ax            ; Save frequency
  487.     mov    bx, 1            ; Use duration = 1 clock
  488.     push    bx            ; Pass duration
  489.     push    ax            ; Pass frequency
  490.     call    Sound            ; Beep speaker
  491.     add    sp, 4            ; Clean stack
  492.     pop    ax
  493.     jmp    SHORT loop1
  494. exit:    ret
  495.  
  496. speaker ENDP
  497.  
  498.  
  499.  
  500. ;* set_lines - Toggles between 25/43-line mode for EGA or 25/43/50-line mode
  501. ;* for VGA.
  502. ;*
  503. ;* Uses:    vconfig - Video configuration structure, declared in the
  504. ;*        DEMO.INC include file. The structure must first be
  505. ;*        initialized by calling the GetVidConfig procedure.
  506. ;*
  507. ;* Return:  None
  508.  
  509. set_lines PROC NEAR
  510.  
  511.     mov    al, 25            ; Assume toggle to 25 line
  512.     cmp    vconfig.rows, 49    ; Current mode 50 lines?
  513.     je    toggle            ; Yes?    Toggle VGA to 25-line
  514.     cmp    vconfig.rows, 42    ; Current mode 43 lines?
  515.     jne    @F            ; No?  Must be 25
  516.     cmp    vconfig.adapter, EGA    ; Yes?    And is adapter EGA?
  517.     je    toggle            ; Yes?    Then toggle to 25 line
  518.     mov    al, 50            ; No?  Toggle VGA to 50 line
  519.     jmp    SHORT toggle
  520. @@:    mov    al, 43            ; If currently 25 lines, make
  521.                     ;   either EGA or VGA 43 lines
  522. toggle: push    ax            ; Pass requested mode param
  523.     call    SetLineMode        ; Change line mode
  524.     add    sp, 2            ; Clean stack
  525.     or    al, al            ; Error?
  526.     jnz    e_exit            ; Yes?    Display message
  527.     call    GetVidConfig        ; No?  Update configuration
  528.     jmp    SHORT exit        ;   structure and return
  529.  
  530. e_exit: Box 16, 13, 20, 67        ; Display error message
  531.     DispText 18, 17, <OFFSET linemsg>
  532.     call    press
  533. exit:    ret
  534.  
  535. set_lines ENDP
  536.  
  537.  
  538.  
  539. ;* pop_windows - Demonstrates windowing with the WinOpen and WinClose
  540. ;* procedures.
  541. ;*
  542. ;* Uses:    vconfig - Video configuration structure, declared in the
  543. ;*        DEMO.INC include file. The structure must first be
  544. ;*        initialized by calling the GetVidConfig procedure.
  545. ;*
  546. ;* Return:  None
  547.  
  548. pop_windows PROC NEAR
  549.  
  550.     LOCAL row1:WORD, col1:WORD, row2:WORD, col2:WORD
  551.     LOCAL index:BYTE, addr[4]:WORD, csize:WORD
  552.  
  553.     call    GetCurSize        ; Get current cursor size
  554.     mov    csize, ax        ; Store it
  555.     or    al, 100000b        ; Set 5th bit for cursor off
  556.     push    ax            ; Bottom line (arbitrary)
  557.     push    ax            ; Top line (arbitrary)
  558.     call    SetCurSize        ; Turn cursor off
  559.     add    sp, 4            ; Clean stack
  560.     mov    winmsg[LEN3], '0'    ; Initialize window message
  561.     mov    row1, 4         ; Initialize window coords
  562.     mov    col1, 10
  563.     mov    row2, 20
  564.     mov    col2, 34
  565.     mov    index, 0
  566.     mov    cx, 4            ; Open 4 windows
  567. open:    push    cx            ; Save loop counter
  568.     mov    al, index
  569.     mov    bx, OFFSET filmono    ; BX points to fill attributes
  570.     cmp    vconfig.display, MONO    ; If monochrome, continue
  571.     je    @F
  572.     mov    bx, OFFSET filcolr    ; Else repoint to color attributes
  573. @@:    xlat                ; Get attributes in succession
  574.     push    ax            ; Push fill attribute
  575.     push    col2            ; Push right column
  576.     push    row2            ; Push bottom row
  577.     push    col1            ; Push left column
  578.     push    row1            ; Push top row
  579.     call    WinOpen         ; Open a window
  580.     add    sp, 10            ; Clean stack
  581.     pop    di            ; Recover counter in DI
  582.     push    di            ;   and save it again
  583.     dec    di
  584.     shl    di, 1            ; Make DI a word index
  585.     mov    addr[di], ax        ; Save address of allocated
  586.                     ;   block returned by WinOpen
  587.     inc    winmsg[LEN3]        ; Increment window number
  588.     mov    bx, row1
  589.     add    bl, 2            ; Message row
  590.     mov    cx, col1
  591.     add    cl, 9            ; Message column
  592.     DispText bx, cx, <OFFSET winmsg>; Display "Window" message
  593.     mov    ax, 18
  594.     push    ax
  595.     call    Pause            ; Pause for approx 1 second
  596.     add    sp, 2            ; Clean stack
  597.     add    row1, 2         ; Adjust coordinates for
  598.     add    col1, 13        ;   next window
  599.     sub    row2, 2
  600.     add    col2, 13
  601.     inc    index
  602.     pop    cx            ; Recover counter
  603.     loop    open
  604.  
  605.     mov    cx, 4            ; Close 4 windows
  606.     sub    di, di            ; DI = index to addresses
  607. close:    push    cx            ; Save loop counter
  608.     push    addr[di]        ; Push allocation address
  609.     call    WinClose        ; Close the window associated
  610.     add    sp, 2            ;   with allocated block
  611.     mov    ax, 18
  612.     push    ax
  613.     call    Pause            ; Pause for 1 second
  614.     add    sp, 2
  615.     add    di, 2            ; Point to next address
  616.     pop    cx            ; Recover counter
  617.     loop    close            ; Close another window
  618.  
  619.     mov    ax, csize        ; Get original cursor size
  620.     push    ax            ; Push bottom line number
  621.     mov    al, ah
  622.     push    ax            ; Push top line number
  623.     call    SetCurSize        ; Restore cursor size
  624.     add    sp, 4            ; Clean stack
  625.  
  626.     ret
  627.  
  628. pop_windows ENDP
  629.  
  630.  
  631.  
  632. ;* set_ attrs - Changes display attributes for the main menu.
  633. ;*
  634. ;* Uses:    vconfig - Video configuration structure, declared in the
  635. ;*        DEMO.INC include file. The structure must first be
  636. ;*        initialized by calling the GetVidConfig procedure.
  637. ;*
  638. ;* Return:  None
  639.  
  640. set_attrs PROC NEAR
  641.  
  642.     Box 3, 12, 23, 68
  643.     cmp    vconfig.adapter, MDA    ; Monochrome?
  644.     jne    @F
  645.     jmp    d_mono
  646. @@:    DispText  4, 18, <OFFSET cmsg1> ; Display "colors" menu for
  647.     DispText  5, 18, <OFFSET cmsg2> ;   color system
  648.     DispText  6, 22, <OFFSET cmsg3>
  649.     DispText  7, 22, <OFFSET cmsg4>
  650.     DispText 10, 18, <OFFSET cmsg5>
  651.     DispText 11, 18, <OFFSET cmsg6>
  652.     DispText 14, 18, <OFFSET cmsg7>
  653.     DispText 15, 18, <OFFSET cmsg8>
  654.     DispText 16, 22, <OFFSET cmsg9>
  655.     DispText 17, 22, <OFFSET cmsg10>
  656.     DispText 18, 22, <OFFSET cmsg11>
  657.     DispText 19, 22, <OFFSET cmsg12>
  658.     mov    al, filcolr        ; Initialize filsub variable
  659.     mov    filsub, al        ;   for color
  660.     jmp    prompt
  661.  
  662. d_mono: DispText  8, 32, <OFFSET cmsg13> ; Display "colors" menu for
  663.     DispText  9, 32, <OFFSET cmsg14> ;   monochrome system
  664.     DispText 10, 36, <OFFSET cmsg15>
  665.     DispText 11, 36, <OFFSET cmsg16>
  666.     DispText 12, 36, <OFFSET cmsg17>
  667.     DispText 13, 36, <OFFSET cmsg18>
  668.     mov    al, filmono        ; Initialize filsub variable
  669.     mov    filsub, al        ;   for monochrome
  670.  
  671. prompt: DispText 22, 15, <OFFSET menu8>
  672.     mov    ax, 56
  673.     push    ax
  674.     mov    al, 22
  675.     push    ax
  676.     call    SetCurPos        ; Park cursor at prompt
  677.     add    sp, 4            ; Clean stack
  678.  
  679. poll:    mov    ax, CLKCL        ; Column for clock
  680.     push    ax
  681.     mov    ax, CLKRW        ; Row for clock
  682.     push    ax
  683.     call    GetKeyClock        ; Wait for keypress
  684.     add    sp, 4            ; Clean stack
  685.     cmp    al, ESCAPE        ; Esc key?
  686.     jne    @F            ; No?  Continue
  687.     jmp    exit            ; Yes?    Exit
  688.  
  689. @@:    cmp    al, 'a'         ; Convert letters to uppercase
  690.     jb    @F            ;   to make comparisons easier
  691.     cmp    al, 'z'
  692.     ja    @F
  693.     and    al, 5Fh
  694.  
  695. @@:    cmp    al, 'B'         ; Request blink toggle?
  696.     je    blink
  697.     cmp    al, 'I'         ; Request intensity toggle?
  698.     je    intens
  699.     mov    bl, filsub        ; Get window display attribute
  700.     cmp    vconfig.adapter, MDA    ; Monochrome?
  701.     jne    colr            ; No?  Jump to color selections
  702.     cmp    al, 'U'         ; Request underline toggle?
  703.     je    under
  704.     cmp    al, 'R'         ; Request reverse toggle?
  705.     jne    poll            ; No?  Then skip invalid key
  706.  
  707. ; What with cross-toggling between reverse, normal, and underline, three
  708. ; bit settings can exist in monochrome:  x111x000 for reverse, x000x111 for
  709. ; normal, and x000x001 for underline. Changing between the three involves
  710. ; more than simply XOR-ing the current attribute; each condition must check
  711. ; for the other two.
  712.  
  713. rever:    test    bl, 1            ; Reverse video on?
  714.     jz    @F            ; Yes?    Go to next step
  715.     or    bl, 00000111b        ; No?  Ensure normal bits are on
  716. @@:    xor    bl, 01110111b        ; Toggle for reverse/normal
  717.     mov    cl, 6            ; Set code for MOV
  718.     jmp    switch
  719. under:    test    bl, 1            ; Reverse video on?
  720.     jnz    @F            ; No?  Go to next step
  721.     and    bl, 10001111b        ; Yes?    Clear bits 4-6 and
  722.     or    bl, 00000111b        ;   set bits 0-2
  723. @@:    xor    bl, 00000110b        ; Toggle bits 1-2 for underline
  724.     mov    cl, 6            ; Set code for MOV
  725.     jmp    switch
  726.  
  727. ; Blink and intensity use the same bits for color and monochrome.
  728.  
  729. blink:    mov    bl, 10000000b        ; Set bit 7 for blink
  730.     mov    cl, 4            ; Set code for XOR
  731.     jmp    switch
  732. intens: mov    bl, 00001000b        ; Set bit 3 for intensity
  733.     mov    cl, 4            ; Set code for XOR
  734.     jmp    switch
  735.  
  736. ; Enter this section only for color displays. First check for arrow keys,
  737. ; which increment or decrement the foreground or background bits of the
  738. ; current attribute stored in the variable filsub. If arrow keys are not
  739. ; pressed, check for the F or A keys, which request specific colors for the
  740. ; foreground or background colors.
  741.  
  742. colr:    mov    ch, bl            ; Copy current attribute to CH
  743.     cmp    ah, 72            ; Up arrow?
  744.     jne    @F            ; No?  Continue check
  745.     mov    cl, 4            ; Yes?    Increment bits 4-6
  746.     shr    ch, cl            ;   to next background color
  747.     inc    ch
  748.     and    ch, 00000111b
  749.     shl    ch, cl
  750.     mov    dl, 10001111b        ; Set background mask
  751.     jmp    SHORT step
  752.  
  753. @@:    cmp    ah, 75            ; Left arrow?
  754.     jne    @F            ; No?  Continue check
  755.     inc    ch            ; Yes?    Increment bits 0-2
  756.     and    ch, 00000111b        ;   to next foreground color
  757.     mov    dl, 11111000b        ; Set foreground mask
  758.     jmp    SHORT step
  759.  
  760. @@:    cmp    ah, 77            ; Right arrow?
  761.     jne    @F            ; No?  Continue check
  762.     dec    ch            ; Yes?    Decrement bits 0-2
  763.     and    ch, 00000111b        ;   to previous foreground color
  764.     mov    dl, 11111000b        ; Set foreground mask
  765.     jmp    SHORT step
  766.  
  767. @@:    cmp    ah, 80            ; Down arrow?
  768.     jne    chk_fa            ; No?  Continue check
  769.     mov    cl, 4            ; Yes?    Decrement bits 4-6
  770.     shr    ch, cl            ;   to previous background color
  771.     dec    ch
  772.     and    ch, 00000111b
  773.     shl    ch, cl
  774.     mov    dl, 10001111b        ; Set background mask
  775.  
  776. step:    and    bl, dl            ; Mask out fore or back bits
  777.     or    bl, ch            ; Copy into original attribute
  778.     mov    filsub, bl        ; Store the new submenu color
  779.     mov    cl, 6            ; Request move operation in
  780.     jmp    SHORT switch        ;   Colors procedure
  781.  
  782. ; This section checks for the F or A keys; if found it checks again for
  783. ; a number key between 0 and 7, then inserts the correct foreground or
  784. ; background bit pattern into the current fill attribute.
  785.  
  786. chk_fa: sub    cx, cx            ; Clear flag for foreground request
  787.     cmp    al, 'F'         ; Request to set foreground color?
  788.     je    @F            ; Yes?    Continue
  789.     cmp    al, 'A'         ; Request to set background color?
  790.     jne    gopoll            ; No?  Then skip invalid key
  791.     inc    cx            ; Set flag for background request
  792. @@:    push    cx            ; Save flag
  793.     mov    ax, CLKCL        ; Column for clock
  794.     push    ax
  795.     mov    ax, CLKRW        ; Row for clock
  796.     push    ax
  797.     call    GetKeyClock        ; Get color number from keyboard
  798.     add    sp, 4            ; Clean stack
  799.     pop    cx            ; Recover flag
  800.     cmp    al, '0'         ; Check for proper number
  801.     jb    gopoll            ;   between 0 and 7
  802.     cmp    al, '7'
  803.     jbe    @F
  804. gopoll: jmp    poll            ; If not valid key, ignore it
  805.  
  806. @@:    xor    al, '0'         ; Convert ASCII numeral into binary
  807.     mov    dl, 11111000b        ; Set foreground mask
  808.     jcxz    @F            ; Skip if foreground request
  809.     mov    cl, 4            ; Otherwise shift bits 0-2
  810.     shl    al, cl            ;   to positions 4-6
  811.     mov    dl, 10001111b        ; Set background mask
  812. @@:    mov    bl, filsub
  813.     and    bl, dl            ; Mask out fore or back bits
  814.     or    bl, al            ; Insert number into fore or back bits
  815.     mov    filsub, bl        ; Store the new submenu color
  816.     mov    cl, 6            ; Request move
  817.  
  818. switch: mov    ax, 68
  819.     push    ax            ; Push window right column
  820.     mov    al, 23
  821.     push    ax            ; Push window bottom row
  822.     mov    al, 12
  823.     push    ax            ; Push window left column
  824.     mov    al, 3
  825.     push    ax            ; Push window top row
  826.     push    bx            ; Push new attribute
  827.     push    cx            ; Push logic code
  828.     call    Colors            ; Reset new attributes in window
  829.     add    sp, 12
  830.     mov    ah, 8            ; Function 8, get char/attribute
  831.     mov    bh, vconfig.dpage
  832.     int    10h            ; Get attribute in AH
  833.     mov    fill, ah        ; New fill variable for main menu
  834.     mov    filsub, ah        ;   and for submenu
  835.     jmp    poll
  836.  
  837. exit:    ret
  838.  
  839. set_attrs ENDP
  840.  
  841.  
  842.  
  843. ;* exec_pgm - Executes a specified program as a child process.
  844. ;*
  845. ;* Uses:    vconfig - Video configuration structure, declared in the
  846. ;*        DEMO.INC include file. The structure must first be
  847. ;*        initialized by calling the GetVidConfig procedure.
  848. ;*        pb - Parameter block structure, declared in the DEMO.INC file
  849. ;*
  850. ;* Return:  None
  851.  
  852. exec_pgm PROC NEAR
  853.  
  854.     Box 16, 13, 20, 67
  855.     DispText 17, 16, <OFFSET execmsg> ; Display prompt for file spec
  856.     mov    ax, 16
  857.     push    ax
  858.     mov    al, 19
  859.     push    ax
  860.     call    SetCurPos        ; Park cursor below prompt
  861.     add    sp, 4            ; Clean stack
  862.     mov    ah, 0Ah         ; Request DOS to read keyboard
  863.     mov    dx, OFFSET fspec    ;   input into fspec string
  864.     int    21h            ; Read Buffered Keyboard Input
  865.  
  866.     Box 16, 13, 20, 67
  867.     DispText 17, 16, <OFFSET tailmsg> ; Display prompt for command tail
  868.     mov    ax, 16
  869.     push    ax
  870.     mov    al, 19
  871.     push    ax
  872.     call    SetCurPos        ; Park cursor below prompt
  873.     add    sp, 4            ; Clean stack
  874.     mov    ah, 0Ah         ; Request DOS to read keyboard
  875.     mov    dx, OFFSET tail     ;   input into tail string
  876.     int    21h            ; Read Buffered Keyboard Input
  877.  
  878.     sub    bh, bh            ; Clear BH
  879.     mov    si, OFFSET fspec    ; DS:SI points to file spec string
  880.     mov    bl, [si+1]        ; BL = number of chars in spec
  881.     mov    BYTE PTR [si+bx+2], 0    ; Terminate string with 0
  882.  
  883.     mov    ax, _env        ; Get segment address of environment
  884.     mov    pb.env, ax        ; Copy it to parameter block
  885.     mov    ax, @data        ; AX points to data segment
  886.     lea    bx, tail[1]        ; BX points to command-line tail
  887.     mov    WORD PTR pb.taddr[0], bx; Copy address of command-line tail
  888.     mov    WORD PTR pb.taddr[2], ax;   to parameter block
  889.     mov    bx, OFFSET fcblk1    ; BX points to first FCB
  890.     mov    WORD PTR pb.fcb1[0], bx ; Copy address of first FCB
  891.     mov    WORD PTR pb.fcb1[2], ax ;   to parameter block
  892.     mov    bx, OFFSET fcblk2    ; BX points to second FCB
  893.     mov    WORD PTR pb.fcb2[0], bx ; Copy address of second FCB
  894.     mov    WORD PTR pb.fcb2[2], ax ;   to parameter block
  895.  
  896. ; At this point, the program file is specified, the command line tail is set,
  897. ; and the parameter block is properly initialized. The Exec procedure will
  898. ; take care of loading the FCBs with command-line arguments and resetting
  899. ; interrupt vectors. Now blank the screen in preparation for executing the
  900. ; process and pass the five pointers to the Exec procedure.
  901.  
  902.     mov    ax, 0600h        ; AH = scroll service, AL = 0
  903.     mov    bh, 7            ; Blank with normal attribute
  904.     sub    cx, cx            ; From row 0, col 0
  905.     mov    dh, vconfig.rows    ;   to bottom row
  906.     mov    dl, 79            ;   and rightmost column
  907.     int    10h            ; Blank screen
  908.     sub    al, al
  909.     push    ax            ; Push column
  910.     push    ax            ; Push row
  911.     call    SetCurPos        ; Set cursor at top of screen
  912.     add    sp, 4            ; Clean stack
  913.  
  914.     IF @CodeSize            ; If medium or large model,
  915.     push    cs            ;   pass code segment
  916.     ENDIF
  917.     mov    ax, OFFSET NewCritErr    ; Pass pointer to new critical
  918.     push    ax            ;   error handler
  919.     IF @CodeSize
  920.     push    cs
  921.     ENDIF
  922.     mov    ax, OFFSET NewCtrlC    ; Pass pointer to new Ctrl-C
  923.     push    ax            ;   error handler
  924.     IF @CodeSize
  925.     push    cs
  926.     ENDIF
  927.     mov    ax, OFFSET NewBreak    ; Pass pointer to new
  928.     push    ax            ;   Ctrl-Break handler
  929.     IF @DataSize
  930.     push    ds
  931.     ENDIF
  932.     mov    ax, OFFSET pb        ; Pass far pointer to
  933.     push    ax            ;   parameter block
  934.     IF @DataSize
  935.     push    ds
  936.     ENDIF
  937.     lea    bx, fspec[2]        ; Pass far pointer to
  938.     push    bx            ;   file specification
  939.  
  940.     call    Exec            ; Exec specified program
  941.     IF @CodeSize
  942.     add    sp, 6            ; Clean stack (far code)
  943.     ENDIF
  944.     IF @DataSize
  945.     add    sp, 4            ; Clean stack (far data)
  946.     ENDIF
  947.     add    sp, 10            ; Clean remainder of stack
  948.  
  949.     cmp    ax, -1            ; Successful?
  950.     je    e_exit            ; No?  Beep speaker and exit
  951.     IF @DataSize            ; Yes? Prepare to display return code
  952.     push    ds
  953.     ENDIF
  954.     mov    bx, OFFSET recode
  955.     push    bx            ; Pass pointer to 6-byte string
  956.     push    ax            ; Pass return code
  957.     call    BinToHex        ; Convert return code to string
  958.     IF @DataSize
  959.     add    sp, 6
  960.     ELSE
  961.     add    sp, 4            ; Clean stack
  962.     ENDIF
  963.     call    GetVidConfig        ; Update video structure
  964.     Box CLKRW, CLKCL-1, CLKRW, CLKCL+17    ; Highlight on-screen clock
  965.     Box vconfig.rows, 0, vconfig.rows, 79    ; Highlight bottom row
  966.     mov    dl, vconfig.rows
  967.     DispText dx, 0, <OFFSET retmsg> ; Display return code at bottom,
  968.     call    press            ;   wait for keypress,
  969.     jmp    SHORT exit        ;   and exit
  970.  
  971. e_exit: mov    ax, 0E07h        ; Write ASCII 7 character
  972.     int    10h            ;   (bell) to console
  973. exit:    ret
  974.  
  975. exec_pgm ENDP
  976.  
  977.  
  978.  
  979. ;* The following three procedures are primitive handlers for Interrupt 1Bh
  980. ;* (Ctrl-Break), Interrupt 23h (Ctrl-C), and Interrupt 24h (Critical Error).
  981. ;* The purpose of an interrupt handler in this context is to prevent termina-
  982. ;* tion of both parent and child processes when the interrupt is invoked.
  983. ;* Such handlers often set flags to signal a process that the interrupt has
  984. ;* been called.
  985.  
  986. ;* NewBreak - Handler for Interrupt 1Bh.
  987.  
  988. NewBreak PROC
  989.  
  990.     sti                ; Reenable interrupts
  991.     push    ax            ; Preserve AX register
  992.     mov    al, 20h         ; Send end-of-interrupt signal
  993.     out    20h, al         ;   to interrupt controller
  994.     pop    ax            ; Recover AX register
  995.     iret                ; Return from handler
  996.                     ;   without taking action
  997. NewBreak ENDP
  998.  
  999.  
  1000. ;* NewCtrlC - Handler for Interrupt 23h.
  1001.  
  1002. NewCtrlC PROC
  1003.  
  1004.     iret                ; Return from handler
  1005.                     ;   without taking action
  1006. NewCtrlC ENDP
  1007.  
  1008.  
  1009. ;* NewCritErr - Handler for Interrupt 24h.
  1010.  
  1011. NewCritErr PROC
  1012.  
  1013.     sub    al, al            ; Tell DOS to ignore error
  1014.     iret                ; Return from handler
  1015.                     ;   without taking action
  1016. NewCritErr ENDP
  1017.  
  1018.     END
  1019.