home *** CD-ROM | disk | FTP | other *** search
/ Frostbyte's 1980s DOS Shareware Collection / floppyshareware.zip / floppyshareware / APOG / ASM5.ZIP / PRSET.ASM < prev    next >
Assembly Source File  |  1990-06-15  |  25KB  |  494 lines

  1. ;===========================================================
  2. ; PrSet -- Memory-resident printer setup utility
  3. ;===========================================================
  4. ; Compile with MASM 5.1 or TASM 1.0 or 2.0
  5. ;
  6. ; Save as PRSET.ASM
  7. ; Compile:  MASM prset;
  8. ;           LINK prset;
  9. ;
  10. ; Use these 2 lines for Borland's TASM:
  11. ;               QUIRKS
  12. ;               MASM51
  13. ;===========================================================
  14. MAX_CHOICES     =       20              ;Maximum printer choices
  15. POP_SHIFT       =       0Ah             ;Left-shift / Alt
  16. POP_KEY         =       19h             ; P
  17. P_ATTRIB        =       70h             ;Vid. attr. used during popup
  18. PRNT_NUM        =       0               ;Use for LPT1
  19. MSG_LEN         =       41              ;Length of option message + 1
  20. CODE_LEN        =       11              ;Max. # of printer codes per line +1
  21. V_ROWS          =       25              ;Number of display rows we'll use
  22. V_COLS          =       80              ;Number of display columns we'll use
  23. ;===========================================================
  24. ;  Define segments and order of segments
  25. ;===========================================================
  26.                 .SEQ                    ;Keep segments in this order
  27. bios_mem        segment at 0000h
  28. bios_mem        ends
  29. tsr_group       group   tsr_seg, tsr_stack, prt_data
  30. tsr_seg         segment word
  31. tsr_seg         ends
  32. tsr_stack       segment stack word
  33.                 dw      1feh dup (?)
  34.    tsr_sp       dw      ?
  35. tsr_stack       ends
  36. prt_data        segment para
  37. prt_data        ends
  38. init_code       segment para            ;Must be aligned on a paragraph
  39. init_code       ends
  40. init_data       segment word
  41. init_data       ends
  42. ;===========================================================
  43. ; Define absolute segment to give us access to low-memory BIOS data
  44. ;===========================================================
  45. bios_mem        segment at 0000h
  46.                 org     417h
  47. b_shift         db      ?               ;Keyboard control #1
  48.                 org     449h
  49. b_mode          db      ?               ;Current video mode
  50. b_cols          dw      ?               ;Columns on screen
  51. b_buflen        dw      ?               ;Length of video buffer
  52. b_bufaddr       dw      ?               ;Offset of current page buffer
  53. b_cursor        dw      8 dup (?)       ;Cursor loc. on each page
  54. b_cursize       dw      ?               ;Cursor size info.
  55. b_apage         db      ?               ;Active page
  56. bios_mem        ends
  57. ;===========================================================
  58. ;  Data for display screen & printer setup
  59. ;===========================================================
  60. prt_data        segment
  61.         entry   struc
  62.           desc  db      MSG_LEN  dup (?)        ;Room for option's display,
  63.           prt   db      CODE_LEN dup (?)        ;  code count, & codes
  64.         entry   ends
  65. OPT_LENGTH      =       MSG_LEN + CODE_LEN 
  66. ; DO NOT ALTER THE FOLLOW db DECLARATIONS! -- PRINST uses them to know
  67. ; where to include the uer's printer codes into the .EXE file
  68.         db      'PRINTER OPTIONS:'
  69.         db      MAX_CHOICES
  70.         db      MSG_LEN
  71.         db      CODE_LEN
  72. option_1        equ     $
  73.         entry   MAX_CHOICES dup (<>)
  74. m1              db      "        <ESC> to end",0
  75. m2              db      "           Your choice ==> ",0
  76. tsr_title       db      '       PC Resource Printer Setup Utility',0
  77. prt_data        ends
  78. ;===========================================================
  79. ; Data for TSR-portion of program
  80. ;===========================================================
  81. tsr_seg         segment
  82.                 assume nothing
  83.                 even
  84.         irp     x,<08,09,10,13,14,16,17>;;Create storage for 7 captured
  85. old_&x          equ     this dword      ;;  interrupt vectors
  86. old_&x&_off     dw      ?
  87. old_&x&_seg     dw      ?
  88.         endm
  89. popup_gate      dw      0               ;Gate to stop recursion and
  90.                                         ;calls during vital interrupts
  91. popup_req       dw      0               ;Set when popup requested
  92. save_sp         dw      ?               ;Save caller's stack pointer
  93. save_ss         dw      ?               ;  and stack segment
  94. vid_off         dw      ?               ;Offset of physical vid. buffer
  95. vid_seg         dw      ?               ;Segment of vid. buffer
  96. cursor_loc      dw      ?               ;Cursor column
  97. active_pg       db      ?               ;Active video page
  98. save_buf        dw      V_ROWS * V_COLS dup (?) ;Buffer to save video image
  99. ;===========================================================
  100. ; New Interrupt Services:
  101. ;  Int 10h: Video services
  102. ;  Int 13h: Disk I/O
  103. ;  Int 14h: Serial Port I/O
  104. ;  Int 16h: Keyboard Request
  105. ;  Int 17h: Parallel Port I/O
  106. ;===========================================================
  107.         irp     x,<10,13,14,16,17>      ;Don't pop up during these!
  108.                 assume cs:tsr_seg
  109. new_&x          proc    far
  110.         assume  cs:tsr_seg
  111.         pushf                           ;;Simulate an Int call 
  112.         inc     cs:[popup_gate]         ;;Set our flag
  113.         call    cs:[old_&x&]            ;;Call original service
  114.         sti                             ;;Be sure interrupts are on
  115.         pushf                           ;;Save returned flags
  116.         dec     cs:[popup_gate]         ;;Reset our flag
  117.         popf                            ;;Recover interrupt's flags
  118.         retf    2                       ;;Fake IRET that keeps flags
  119. new_&x          endp
  120.                 endm
  121. ;===========================================================
  122. ; New Interrupt Service:
  123. ;  Int 08h: Timer interrupt
  124. ;===========================================================
  125. new_08          proc    far             ;popup, when ready, on timer tick
  126.         assume  cs:tsr_seg
  127.         pushf                           ;Simulate interrupt call
  128.         call    cs:[old_08]             ;Call previous service
  129.         sti                             ;Allow interrupts
  130.         test    cs:[popup_req],-1       ;Popup requested?
  131.         jz      end_08                  ;No -- continue
  132.         test    cs:[popup_gate],-1      ;Popup ok?
  133.         jnz     end_08                  ;No -- forget it
  134.         inc     cs:[popup_gate]         ;Else set the gate to stop recursion
  135.         call    popup                   ;  and then pop up
  136.         mov     cs:[popup_req],0        ;Clear request gate
  137.         dec     cs:[popup_gate]         ;  and popup gate
  138. end_08: iret                            ;Back to caller
  139. new_08          endp
  140. ;===========================================================
  141. ; New Interrupt Service:
  142. ;  Int 09h: Keyboard
  143. ;===========================================================
  144. new_09          proc    far             ;Test for popup keys
  145.         push    ax                      ;Save AX register
  146.         in      al,60h                  ;Get keystroke
  147.         cmp     al,POP_KEY              ;Our key?
  148.         je      test_shift              ;Yes -- test shift keys
  149. end_09: pop     ax                      ;else recover AX
  150.         jmp     dword ptr cs:[old_09]   ;Let previous owner handle it
  151. test_shift:
  152.         push    ds                      ;Save DS
  153.         sub     ax,ax                   ;AX = 0
  154.         mov     ds,ax                   ;Set DS==> bios memory
  155.         assume  ds:bios_mem
  156.         mov     al,[b_shift]            ;Get shift byte
  157.         pop     ds                      ;We're done with DS
  158.         assume  ds:nothing
  159.         and     al,POP_SHIFT            ;Mask off extra bits
  160.         cmp     al,POP_SHIFT            ;Right value?
  161.         jne     end_09                  ;No -- continue
  162.         in      al,61h                  ;Else get keyboard ctrl lines
  163.         mov     ah,al                   ;  and save them
  164.         or      al,80h                  ;Set 'enable kbd' bit
  165.         out     61h,al                  ;Send it out
  166.         mov     al,ah                   ;Get original control values
  167.         out     61h,al                  ;Send them out
  168.         mov     al,20h                  ;End-of-interrupt signal
  169.         out     20h,al                  ;Show end of hardware interrupt
  170.         inc     cs:[popup_req]          ;Show we want to popup
  171.         pop     ax                      ;Recover AX
  172.         iret                            ;Return from interrupt
  173. new_09          endp
  174. ;===========================================================
  175. ; Popup here on user's request when it is safe to do so.
  176. ; It is NOT safe to use any DOS services during this popup!
  177. ;===========================================================
  178. popup           proc    near
  179.         assume  ds:nothing, es:nothing
  180.         push    ax                      ;Save AX on app.'s stack
  181.         cli                             ;No interrupts now
  182.         mov     cs:[save_ss],ss         ;Save app.'s stack
  183.         mov     cs:[save_sp],sp
  184.         mov     ax,tsr_stack
  185.         mov     ss,ax
  186.         mov     sp,offset tsr_sp
  187.         sti
  188.         pushf                           ;Save flags
  189.         irp     x,<bx,cx,dx,di,si,bp,ds,es>
  190.         push    &x                      ;;Save registers
  191.         endm
  192.         cld                             ;Don't forget the direction flag!
  193.         sub     ax,ax
  194.         mov     ds,ax                   ;DS ==> bios_mem
  195.         assume  ds:bios_mem
  196.         mov     bp,[b_cols]             ;Get columns on screen
  197.                                         ;BP will never change during popup!
  198.         mov     si,[b_bufaddr]          ;SI = offset to screen
  199.         mov     cs:[vid_off],si         ;  and save it
  200.         mov     al,[b_apage]            ;Get video page
  201.         mov     cs:[active_pg],al       ;  and save it
  202.         add     ax,ax                   ;AX = vid page * 2
  203.         mov     di,offset b_cursor      ;DS:DI ==> cursor location info
  204.         add     di,ax                   ;DS:DI ==> info for this page
  205.         mov     ax,[di]                 ;Get cursor position
  206.         mov     cs:[cursor_loc],ax      ;  and save it
  207.         mov     al,[b_mode]             ;Get video mode
  208.         assume  ds:nothing
  209.         cmp     al,1                    ;40-cols?
  210.         jbe     pop_done                ;Yes -- forget everything
  211.         cmp     al,3                    ;80-cols or more in color?
  212.         jbe     @F                      ;Yes -- looks okay
  213.         cmp     al,7                    ;80-col mono?
  214.         jne     pop_done                ;No -- skip if graphics
  215.   @@:   call    save_scrn               ;Save user's screen
  216.         call    set_printer             ;Now reset printer
  217.         call    restore_scrn            ;Restore the screen
  218. pop_done:
  219.         assume  ds:nothing, es:nothing
  220.         irp     x,<es,ds,bp,si,di,dx,cx,bx>
  221.         pop     &x                      ;;Recover registers
  222.         endm
  223.         popf                            ; Restore everything
  224.         cli                             ;No interrupts for now
  225.         mov     ss,cs:[save_ss]         ;Restore orig. stack
  226.         mov     sp,cs:[save_sp]
  227.         sti                             ;Interrupts back on
  228.         pop     ax                      ;Recover AX
  229.         ret
  230. popup           endp
  231. ;===========================================================
  232. ; Save the foreground screen and move cursor off screen
  233. ;===========================================================
  234. save_scrn       proc    near            ;Entry: AL = video mode
  235.                                         ;BP = screen columns
  236.                                         ;SI = b_bufaddr
  237.         assume  ds:nothing, es:tsr_seg
  238.         push    si                      ;Save screen pointer
  239.         mov     di,0b800h               ;Assume color text mode
  240.         cmp     al,7                    ;Mono text?
  241.         jne     @F                      ;No -- go
  242.         mov     di,0b000h               ;Yes -- load mono segment 
  243.   @@:   mov     ds,di                   ;DS ==> screen
  244.         mov     cs:[vid_seg],di         ;  and save for later
  245.         mov     bx,tsr_seg              ;Get our segment
  246.         mov     es,bx                   ;  into ES
  247.         mov     di,offset save_buf      ;ES:DI ==> buffer to save screen
  248.         mov     dx,V_ROWS               ;Rows to save
  249.   @@:   push    si                      ;Save screen pointer
  250.         mov     cx,V_COLS               ;Columns to save
  251.         rep     movsw                   ;Move one row to buffer
  252.         pop     si                      ;Recover orig. screen pointer
  253.         add     si,bp                   ;SI ==> next screen row
  254.         add     si,bp
  255.         dec     dx                      ;Count this row
  256.         jnz     @B                      ;Repeat for all rows
  257.         pop     si                      ;Recover pointer
  258.         mov     bh,es:[active_pg]       ;Get video page
  259.         mov     dx,V_ROWS shl 8 + 0     ;First invisible row, column 0
  260.         mov     ah,2                    ;BIOS func.: set cursor posn
  261.         int     10h                     ;Call video BIOS
  262.         ret
  263.         assume  ds:nothing, es:nothing
  264. save_scrn       endp
  265. ;===========================================================
  266. ; Restore the foreground screen and cursor
  267. ;===========================================================
  268. restore_scrn    proc    near            ;Entry: BP = cols on screen
  269.         assume  ds:tsr_seg, es:nothing
  270.         mov     ax,tsr_seg
  271.         mov     ds,ax                   ;DS ==> our data area
  272.         mov     es,[vid_seg]
  273.         mov     di,[vid_off]            ;ES:DI ==> video buffer
  274.         mov     si,offset save_buf      ;DS:SI ==> save buffer
  275.         mov     dx,V_ROWS               ;Rows to restore
  276.   @@:   push    di                      ;Save screen pointer
  277.         mov     cx,V_COLS               ;Columns to restore
  278.         rep     movsw                   ;Restore 1 row
  279.         pop     di
  280.         add     di,bp                   ;DI ==> next row on screen
  281.         add     di,bp
  282.         dec     dx                      ;Count this row
  283.         jnz     @B                      ;Repeat until done
  284.         mov     bh,[active_pg]          ;Get page number
  285.         mov     dx,[cursor_loc]         ;Get original cursor location
  286.         mov     ah,2                    ;BIOS func.: set cursor posn.
  287.         int     10h
  288.         ret
  289.         assume  ds:nothing
  290. restore_scrn    endp
  291. ;===========================================================
  292. ; Clear the screen with our display attribute
  293. ;===========================================================
  294. set_screen      proc    near            ;Set screen to our attributes
  295.         assume  ds:tsr_seg, es:nothing
  296.         mov     ax,tsr_seg
  297.         mov     ds,ax                   ;DS ==> our data
  298.         mov     es,[vid_seg]
  299.         mov     di,[vid_off]            ;ES:DI ==> video buffer
  300.         mov     dx,V_ROWS               ;Rows to set
  301.         mov     ah,P_ATTRIB             ;AH = new attribute
  302.         mov     al,' '                  ;Clear screen to all spaces
  303.   @@:   push    di                      ;Save screen pointer
  304.         mov     cx,V_COLS               ;Columns to set
  305.         rep     stosw                   ;Set one row
  306.         pop     di
  307.         add     di,bp                   ;DI ==> next row on screen
  308.         add     di,bp
  309.         dec     dx                      ;Count this row
  310.         jnz     @B                      ;Repeat until done
  311.         ret
  312.         assume  ds:nothing
  313. set_screen      endp
  314. ;===========================================================
  315. ; Get user's choice & send command to the printer
  316. ;===========================================================
  317. set_printer     proc    near
  318.         assume  ds:tsr_seg, es:nothing
  319.         mov     ax,tsr_seg
  320.         mov     ds,ax                   ;DS ==> our data
  321.         call    set_screen              ;Clear display screen
  322.         call    disp_opts               ;Display options
  323.         call    get_choice              ;Get choice
  324.         jc      @F                      ;Go if no choice
  325.         call    to_printer              ;Send code to printer
  326.   @@:   ret                             ;Then end
  327. set_printer     endp
  328. ;===========================================================
  329. ; Display list of options
  330. ;===========================================================
  331. disp_opts       proc    near            ;Display user's options
  332.         mov     ax,prt_data     
  333.         mov     es,ax                   ;ES ==> data for screen & printer
  334.         assume  es:prt_data
  335.         mov     si,offset tsr_title     ;ES:SI ==> string to print
  336.         mov     dx,0                    ;DH, DL = row & column
  337.         call    print_string            ;Print it
  338.         mov     dx,2 SHL 8 + 8          ;Row 2, Col 8
  339.         mov     cx,MAX_CHOICES          ;Number of choices
  340.         mov     si,offset option_1      ;ES:SI ==> option table
  341.   @@:   call    print_string            ;Print the string
  342.         inc     dh                      ;Move to next row
  343.         add     si,OPT_LENGTH           ;Move to next option
  344.         loop    @B                      ;Display all options
  345.         mov     si,offset m1
  346.         call    print_string
  347.         inc     dh
  348.         mov     si,offset m2
  349.         call    print_string
  350.         assume  es:nothing
  351.         ret
  352. disp_opts       endp
  353. ;===========================================================
  354. ; Print an ASCIIZ string directly to video memory
  355. ;===========================================================
  356. print_string    proc    near            ;On Entry: ES:SI ==> ASCIIZ string
  357.                                         ;DH = row, DL = col to print
  358.         irp     x,<dx,di,si,ds,es>      ;Save registers we'll change
  359.         push    &x
  360.         endm
  361.         sub     ax,ax
  362.         mov     al,dh                   ;AX = row number
  363.         mul     bp                      ;AX = bytes to begin. of row
  364.         shl     ax,1                    ;AX = beg. of row
  365.         sub     dh,dh                   ;DX = col #
  366.         add     ax,dx
  367.         add     ax,dx                   ;AX = offset on screen
  368.         add     ax,[vid_off]            ;AX = absolute screen offset
  369.         mov     di,ax
  370.         mov     ah,P_ATTRIB             ;AH = attribute for screen
  371.         mov     bx,[vid_seg]
  372.         push    es
  373.         pop     ds                      ;DS:SI ==> string
  374.         mov     es,bx                   ;ES:DI ==> screen
  375.   @@:   lodsb                           ;Get char. from string
  376.         and     al,al                   ;Is it 0?
  377.         jz      @F                      ;Yes -- go
  378.         stosw                           ;Else store char. & attrib.
  379.         jmp     @B                      ;  and repeat
  380.   @@:   irp     x,<es,ds,si,di,dx>      ;Restore registers
  381.         pop     &x
  382.         endm
  383.         ret
  384. print_string    endp
  385. ;===========================================================
  386. ; Get the user's option from the keyboard
  387. ;===========================================================
  388. get_choice      proc    near
  389.   @@:   mov     ah,1                    ;Keystroke waiting?
  390.         int     16h                     ;Ask BIOS
  391.         jz      @F                      ;No -- go
  392.         mov     ah,0                    ;Else get key
  393.         int     16h                     ; from BIOS
  394.         jmp     @B                      ;Until no type-ahead
  395.   @@:   mov     ah,0                    ;Now wait for keystroke
  396.         int     16h
  397.         cmp     al,'a'                  ;If lower-case, convert
  398.         jb      @F                      ;Go if not
  399.         cmp     al,'z'                  ;Test upper limit
  400.         ja      @F                      ;Go if not 'a' - 'z'
  401.         sub     al,32                   ;Convert to upper-case
  402.   @@:   cmp     al,27                   ;ESCape?
  403.         jne     @F                      ;No -- go
  404.         stc                             ;On ESC, set carry flag
  405.         ret                             ;  and leave
  406.   @@:   sub     al,'A'                  ;A = 0, B = 1, etc.
  407.         cmp     al,MAX_CHOICES          ;Valid choice?
  408.         jae     get_choice              ;No -- get another
  409.         clc                             ;Clear carry flag
  410.         ret                             ;Else return with AL = choice
  411. get_choice      endp                    ;  and CF clear
  412. ;===========================================================
  413. ; Send command codes to the printer
  414. ;===========================================================
  415. to_printer      proc    near            ;On entry, AL = user's choice
  416.         mov     bx,prt_data
  417.         mov     es,bx                   ;ES ==> data for screen & printer
  418.         assume  es:prt_data
  419.         mov     si,offset option_1.prt  ;SI ==> 1st option choice
  420.         mov     cl,al
  421.         sub     ch,ch                   ;CX = user's choice
  422.         jcxz    send_out                ;Go if choice 0
  423.   @@:   add     si,OPT_LENGTH           ;Else move SI to next choice
  424.         loop    @B                      ;Until SI ==> user's choice
  425. send_out:
  426.         sub     cx,cx                   ;CX = 0
  427.         mov     cl,ES:[si]              ;CX = bytes to send
  428.         jcxz    prt_end                 ;Go if none
  429.         mov     dx,PRNT_NUM             ;DX = printer number
  430.   @@:   inc     si                      ;ES:SI ==> Next data byte
  431.         mov     al,es:[si]              ;Get byte to send
  432.         sub     ah,ah                   ;AH = 0: Send byte to printer
  433.         int     17h                     ;Send it out
  434.         test    ah,1                    ;Time out?
  435.         jnz     prt_end                 ;Yes -- leave
  436.         loop    @B                      ;Else loop for all bytes
  437. prt_end:
  438.         assume  es:nothing
  439.         ret
  440. to_printer      endp
  441. tsr_seg         ends                    ;End of resident code & data
  442. ;===========================================================
  443. ; Initialization Routines -- removed from memory after startup
  444. ;===========================================================
  445. init_code       segment
  446.         assume cs:init_code, ds:nothing, es:nothing, ss:tsr_stack
  447. install proc    near
  448.         push    es                      ;Save PSP segment
  449.         mov     ax,tsr_seg              ;Get TSR segment
  450.         mov     ds,ax
  451.         assume  ds:tsr_seg
  452.         mov     ah,35h                  ;DOS Func: get interrupt vector
  453.    irp  x,<08,09,10,13,14,16,17>        ;;Get and save interrupt vectors
  454.         mov     al,&x&h                 ;;Inter. number in AL
  455.         int     21h                     ;;Call DOS
  456.         mov     [old_&x&_off],bx        ;;Save offset
  457.         mov     [old_&x&_seg],es        ;;  and segment
  458.    endm
  459.         mov     ah,25h                  ;DOS Func: set interrupt vector
  460.    irp  x,<08,09,10,13,14,16,17>        ;;Set new interrupt vectors
  461.         mov     al,&x&h                 ;;Interrupt number in AL
  462.         mov     dx,offset new_&x        ;;DS:DX has vector address
  463.         int     21h
  464.    endm
  465.         mov     ax,init_data            ;Get segment for initial data
  466.         mov     ds,ax                   ;Into DS
  467.         assume  ds:init_data
  468.         mov     dx,offset hello         ;Print sign-on message
  469.         mov     ah,9                    ;Print a string 
  470.         int     21h                     ;  via DOS
  471.         pop     ax                      ;Get segment of PSP
  472.         mov     dx,init_code            ;Beginning of throw-away area
  473.         sub     dx,ax                   ;AX = paras - 1 to keep
  474.         inc     dx                      ;DX = paragraphs to keep
  475.         mov     ax,3100h                ;Term. but stay resident
  476.         int     21h                     ;Back to DOS
  477. install         endp
  478. init_code       ends
  479. ;===========================================================
  480. ; Installation Data
  481. ;===========================================================
  482. init_data       segment
  483. CR      =       13
  484. LF      =       10
  485. hello   db      "PC Resource's Printer Setup Utility",CR,LF
  486.         db      "  has been installed in memory.",CR,LF,CR,LF
  487.         db      "Press <Left-Shift><Alt><P> to set up your printer.",CR,LF
  488.         db      CR,LF
  489.         db      "You can modify this program to work with your printer",CR,LF
  490.         db      "by running PRINST.",CR,LF,CR,LF,'$'
  491. init_data       ends
  492.         end     install
  493.  
  494.