home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / msdos / asmutl / a86cnvrt.arc / S4.8 < prev    next >
Text File  |  1987-06-16  |  20KB  |  431 lines

  1. ; EPSONSET is a memory-resident program that sends control codes to an
  2. ;    Epson-compatible printer. After EPSONSET is installed, it may be invoked
  3. ;    at any time by pressing the CTRL and the right-SHIFT keys simultaneuosly.
  4. ;    This causes a window to pop up, inviting the user to press a choice
  5. ;    of function keys to send codes to the printer.  The window is deactivated
  6. ;    when the ESC key is pressed.
  7.  
  8. EPSONSET:
  9.   JMP >L1                   ; skip over the copyright message
  10.  
  11.  DB '(C) Copyright 1986, Ziff-Davis Publishing Company ',01A
  12.  
  13.  
  14. ; The first part of our program exists only at installation time.  The buffer
  15. ;    OLD_IMAGE is declared at location 0 in our code segment; so our PSP and
  16. ;    all of our installation code will be destroyed the first time our window
  17. ;    is popped up.
  18.  
  19. OLD_IMAGE EQU 0
  20.  
  21. W_LINES EQU 19               ; height of the pop-up window
  22. W_COLS  EQU 28               ; width of the pop-up window
  23. W_SIZE EQU W_LINES * W_COLS  ; number of chars in the window
  24. IMAGE_SIZE EQU W_SIZE * 2    ; number of bytes in a video window image
  25.  
  26. W_ROW         EQU 2               ; row number (0-24) of the top of the window
  27. W_COLUMN      EQU 26              ; column number (0-79) of start of the window
  28. VIDEO_OFFSET  EQU W_ROW*160 + W_COLUMN*2    ; offset of the pop-up window
  29. VIDEO_GAP     EQU 160-W_COLS*2    ; gap between successive window lines
  30.  
  31. L1:
  32.   CALL MAKE_WINDOW_IMAGE    ; construct the video image of our pop-up window
  33.   CALL ADJUST_PCJR          ; if we are on a PCJr then adjust the cursor
  34.   CALL NEW_KB_VECTOR        ; replace the keyboard-interrupt handler
  35.   MOV DX,END_OF_PROGRAM     ; point DX to the end of our resident section
  36.   INT 027                   ; terminate but stay resident
  37.  
  38.  
  39. ; MAKE_WINDOW_IMAGE determines the appropriate attribute bytes for our pop-up
  40. ;    window, combines those bytes with the text from WINDOW_SOURCE, and
  41. ;    places the conglomeration into WINDOW_IMAGE.
  42.  
  43. KEYBOARD_INT  DD  0:9*4
  44.  
  45. MAKE_WINDOW_IMAGE:
  46.   CLD                   ; string scanning is forward
  47.   MOV AH,15             ; BIOS function number for GET_VIDEO_MODE
  48.   INT 010               ; set AL to the video mode
  49.   CMP AL,7              ; is it a monochrome mode?
  50.   MOV AX,0704F          ; load color attributes in case it isn't
  51.   IF E MOV AX,0770      ; if monochrome then load the monochrome attributes
  52.   MOV SI,WINDOW_SOURCE  ; point SI to table of text
  53.   MOV DI,WINDOW_IMAGE   ; point DI to the storage area
  54.   CALL COPY_4_LINES     ; create the first four lines
  55.   MOV BX,11             ; load the count of the second-attribute lines
  56. L1:                     ; loop here for each of the middle 11 lines of window
  57.   MOVSB                 ; copy the left-border byte to the buffer
  58.   STOSB                 ; output the first attribute byte, to complete the word
  59.   MOV CX,W_COLS-2       ; load the number of bytes in the middle of the line
  60.   XCHG AL,AH            ; swap the second attribute byte into AL
  61.   CALL COPY_ATTRIBUTE   ; output the middle of the line
  62.   XCHG AL,AH            ; swap the first attribute byte back to AL
  63.   MOVSB                 ; copy the right-border byte to the buffer
  64.   STOSB                 ; output the first attribute byte, to complete the word
  65.   DEC BX                ; count down the middle lines
  66.   JNZ L1                ; loop if more; else drop to make the last 4 lines
  67. COPY_4_LINES:           ; copy 4 lines, attribute AL, to video image
  68.   MOV CX,4 * W_COLS     ; load the number of characters in 4 lines
  69. COPY_ATTRIBUTE:         ; copy CX bytes from SI to words at DI with attr. AL
  70.   MOVSB                 ; copy the text byte
  71.   STOSB                 ; output the attribute byte to complete the video word
  72.   LOOP COPY_ATTRIBUTE   ; loop for the next text byte
  73.   RET
  74.  
  75.  
  76. ; ADJUST_PCJR checks to see if we are a PCJr, and if we are, resets the
  77. ;    cursor and corrects the CURSOR_MODE word at 0040:0060.
  78.  
  79. MACHINE_ID    DD  0F000:0FFFE   ; pointer to ROM identification byte
  80. CURSOR_MODE   DD  040:060       ; pointer to cursor mode word
  81.  
  82. ADJUST_PCJR:
  83.   LES DI,MACHINE_ID     ; point to the identification byte for this machine
  84.   MOV AL,0FD            ; load the ID to the PCJr
  85.   SCASB                 ; is this a PCJr?
  86.   JNE RET               ; no, then skip this routine
  87.   LES DI,CURSOR_MODE    ; point to the BIOS's cursor mode indicator
  88.   MOV AX,0607           ; load our new value for the indicator
  89.   STOSW                 ; store the new value in the BIOS area
  90.   XCHG CX,AX            ; swap the value into CX, for a BIOS call
  91.   MOV AH,1              ; BIOS function number for SET_CURSOR_SIZE
  92.   INT 010               ; set cursor to scan-lines 6 and 7 in character block
  93.   RET
  94.  
  95.  
  96. ; NEW_KB_VECTOR saves the old keyboard interrupt vector, and replaces it with
  97. ;    the new one.
  98.  
  99. NEW_KB_VECTOR:
  100.   LDS SI,KEYBOARD_INT       ; point DS:SI to INT 9 in the vector table
  101.   MOV DI,OFFSET OLD_KB_INT  ; point ES:DI to our storage for old INT 9 vector
  102.   MOV ES,CS
  103.   CLI                       ; disable all interrupts but NMI
  104.   MOV AX,OUR_HANDLER        ; point to our new handler
  105.   XCHG AX,[SI]              ; store new handler offset and fetch the old one
  106.   STOSW                     ; store the old handler offset
  107.   MOV AX,CS                 ; point to this code segment
  108.   XCHG AX,[SI+2]            ; store new segment and fetch the old one
  109.   STOSW                     ; store the old handler segment
  110.   STI                       ; re-enable interrupts
  111.   RET
  112.  
  113.  
  114. ; WINDOW_SOURCE contains the text to be used to construct the pop-up window.
  115. ;   Our program will combine this text with attribute bytes, to make a video
  116. ;   image.
  117.  
  118. WINDOW_SOURCE:
  119.   DB 201,        W_COLS-2 DUP 205    ,187
  120.   DB 186,'    PRINTER SETUP MENU    ',186
  121.   DB 186,'   EPSON RX/FX PRINTERS   ',186
  122.   DB 199,        W_COLS-2 DUP 196    ,182
  123.   DB 186,' F1    Compressed Mode    ',186
  124.   DB 186,' F2    Expanded Mode      ',186
  125.   DB 186,' F3    Emphasized Mode    ',186
  126.   DB 186,' F4    Double-Strike Mode ',186
  127.   DB 186,' F5    Elite Mode         ',186
  128.   DB 186,' F6    Miniature Mode     ',186
  129.   DB 186,' F7    Skip Perforation   ',186
  130.   DB 186,' F8    Indent Left Margin ',186
  131.   DB 186,' F9    Reset Top-of-Form  ',186
  132.   DB 186,' F10   Reset Print Modes  ',186
  133.   DB 186,' ESC   Exit               ',186
  134.   DB 199,        W_COLS-2 DUP 196    ,182
  135.   DB 186,' Unshifted:   Toggle ON   ',186
  136.   DB 186,' Shifted:     Toggle OFF  ',186
  137.   DB 200,        W_COLS-2 DUP 205    ,188
  138. W_SIZE EQU ($-WINDOW_SOURCE)
  139.  
  140.  
  141.  
  142. ;-----------------------------------------------------------------------------
  143. ;  Above this point is the part of the program that exists only when we
  144. ;       being installed.  Everything above this point is wiped out by
  145. ;       the filling of OLD_IMAGE when our window is popped up.
  146.  
  147.  
  148.  
  149. TRUE EQU (0 LT 1)           ; define TRUE so following line is an assertion
  150. TRUE EQU ($ LT IMAGE_SIZE)  ; insure we haven't used up too much room
  151. ORG IMAGE_SIZE              ; now there's enough room for OLD_IMAGE
  152.  
  153.  
  154. OLD_KB_INT     DD ?     ; storage for old keyboard interrupt vector
  155. CURSOR_TYPE    DW ?     ; cursor scan line definition saved from user screen
  156. WINDOW_ACTIVE? DB 0     ; NZ if our pop-up window is already active
  157. ENABLE_VALUE   DB ?     ; video-chip programming value for the user's screen
  158. VIDEO_SEG      DW ?     ; segment address of the current memory-mapped video
  159.  
  160.  
  161. ; CODE_TABLE gives the codes to be output to the printer for each successive
  162. ;   function key that can be pressed when the window is popped up.  The
  163. ;   255 terminator bytes are also used to locate the code for a given key.
  164.  
  165. CODE_TABLE:
  166.   DB 15,255                  ; F1: compressed mode on
  167.   DB 27,87,1,255             ; F2: expanded mode on
  168.   DB 27,69,255               ; F3: emphasized mode on
  169.   DB 27,71,255               ; F4: double-strike mode on
  170.   DB 27,77,255               ; F5: elite mode on
  171.   DB 15,27,83,0,27,65,6,255  ; F6: miniature mode on
  172.   DB 27,78,12,255            ; F7: perfskip on
  173.   DB 27,108,10,255           ; F8: indent left margin
  174.   DB 27,67,66,255            ; F9: reset top-of-form
  175.   DB 18,27,87,0,27,70,27,72  ; F10: reset print modes
  176.   DB   27,80,27,84,27,50,255 ;        (continued)
  177.   DB 18,255                  ; Shift-F1: compress off
  178.   DB 27,87,0,255             ; Shift-F2: expand off
  179.   DB 27,70,255               ; Shift-F3: emphasize off
  180.   DB 27,72,255               ; Shift-F4: double-strike off
  181.   DB 27,80,255               ; Shift-F5: elite off
  182.   DB 18,27,84,27,50,255      ; Shift-F6: miniature off
  183.   DB 27,79,255               ; Shift-F7: perfskip off
  184.   DB 27,108,0,255            ; Shift-F8: indent off
  185.  
  186.  
  187.  
  188. ; OUR_HANDLER is our replacement for the INT 9 keyboard handler.  We save
  189. ;    registers, then call the old keyboard handler.  If CTRL+RIGHT_SHIFT is
  190. ;    pressed, we activate our code.  Otherwise, we exit as if we were the
  191. ;    old handler.
  192.  
  193. OUR_HANDLER:
  194.   STI                    ; enable software interrupts
  195.   PUSH AX                ; hot-key check clobbers AX only so save it
  196.   IN AL,0A0              ; re-enable NMI on PCjr
  197.   PUSHF                  ; simulate interrupt call to old keyboard routine
  198.   CS CALL OLD_KB_INT     ; call old routine
  199.   MOV AH,2               ; BIOS function number for GET_SHIFT_STATUS
  200.   INT 016                ; set AL to the shift-status bitmap
  201.   AND AL,5               ; mask the map down to the CTRL and RIGHT_SHIFT keys
  202.   CMP AL,5               ; are CTRL and RIGHT_SHIFT depressed?
  203.   JNE AX_EXIT            ; exit if they are-- we're already activated
  204.   PUSH BX,CX,DX,SI,DI    ; save the other general registers
  205.   PUSH DS,ES             ; also save segment registers
  206.   MOV DS,ES,CS           ; set ES and DS to the code segment
  207.   TEST WINDOW_ACTIVE?    ; is the window already open?
  208.   JNZ EXIT               ; if yes then ignore request
  209.   MOV AH,15              ; BIOS function number for GET_VIDEO_STATUS
  210.   INT 010                ; set AL = video mode, BH = video page number
  211.   MOV AH,0               ; ENABLE_BYTE is zero for video mode 7
  212.   MOV CX,0B000           ; VIDEO_SEG is 0B000 for video mode 7
  213.   CMP AL,7               ; is the video mode 7 (monochrome)?
  214.   JE >L0                 ; jump if yes, that's an acceptible mode
  215.   MOV CH,0B8             ; VIDEO_SEG is 0B800 for page 0, color modes
  216.   ADD CH,BH              ; advance VIDEO_SEG to the proper value for this page
  217.   MOV AH,02D             ; ENABLE_BYTE is 02D for video mode 2
  218.   CMP AL,2               ; is the video mode 2?
  219.   JE >L0                 ; jump if yes, that's also an acceptible mode
  220.   MOV AH,029             ; ENABLE_BYTE is 029 for video mode 3
  221.   CMP AL,3               ; not 7 or 2; it had better be 3
  222.   JNE EXIT               ; error if not
  223. L0:
  224.   CALL POPUP_WINDOW      ; everything's OK so pop up our window
  225.   JMP SHORT NEXT_KEY     ; jump into the interactive loop
  226.  
  227.  
  228. ; ESC_SEEN is jumped to when the ESC key is pressed. The window is refilled
  229. ;     with its original contents, the cursor is restored, and control is handed
  230. ;     back to the application program.
  231.  
  232. ESC_SEEN:
  233.   CALL VIDEO_DISABLE       ; if not then turn off the display
  234.   MOV SI,OLD_IMAGE         ; point SI to the buffer area
  235.   CALL MEM_TO_VIDEO        ; write the buffer contents to the display
  236.   CALL VIDEO_ENABLE        ; if not then turn display back on
  237.   MOV CX,CURSOR_TYPE       ; fetch the user's cursor type
  238.   MOV AH,1                 ; BIOS function number for SET_CURSOR_SIZE
  239.   INT 010                  ; restore the user's cursor
  240.   MOV WINDOW_ACTIVE?,0     ; the window is no longer active
  241. EXIT:                      ; common exit point
  242.   POP ES,DS                ; restore interrupted segment registers
  243.   POP DI,SI,DX,CX,BX       ; restore interrupted general registers
  244. AX_EXIT:                   ; exit here if we saved AX only
  245.   POP AX                   ; restore interrupted AX
  246.   IRET                     ; return from interrupt
  247.  
  248.  
  249. ; NEXT_KEY is the main loop for the interactive portion of our handler.  We
  250. ;    intercept all keystrokes while our window is open, and act on them.
  251. ;    This interactive mode is terminated when the ESC key is seen.
  252.  
  253. FUNC    EQU 58      ; defining code for non-shifted function keys
  254. SHIFT_F EQU 83      ; defining code for shifted function keys
  255.  
  256. BEEP_KEY:           ; jump here if an illegal key is seen
  257.   CALL BEEP         ; beep and wait for another keypress
  258. NEXT_KEY:
  259.   MOV AH,0          ; BIOS function code for GET_KEY
  260.   INT 016           ; fetch a keystroke from the BIOS
  261.   CMP AL,27         ; is it the ESC key?
  262.   JE ESC_SEEN       ; jump if it is, to exit our interactive mode
  263.   CMP AL,0          ; is it an extended code?
  264.   JNE BEEP_KEY      ; error if not
  265.   MOV AL,AH         ; move the extended code into AL, for examination
  266.   CMP AL,FUNC 1     ; less than F1?
  267.   JB BEEP_KEY       ; yes, then don't accept it
  268.   CMP AL,SHIFT_F 8  ; greater than Shift-F8?
  269.   JA BEEP_KEY       ; yes, then don't accept it
  270.   CMP AL,FUNC 10    ; between F1 and F10?
  271.   JBE >L1           ; jump if yes -- unshifted function key
  272.   CMP AL,SHIFT_F 1  ; between Shift-F1 and Shift-F9?
  273.   JB BEEP_KEY       ; error if not
  274.   SUB AL,15         ; adjust so Shift-F1 has an index of 10
  275. L1:
  276.   SUB AL,FUNC 1     ; adjust so F1 has an index of 0
  277.   CBW               ; extend the index AL to AX
  278.   XCHG CX,AX        ; swap the index into CX
  279.   MOV SI,CODE_TABLE ; point to the first of our code sequences
  280.   JCXZ >L3          ; skip if our index is zero
  281. L2:                 ; loop here for each code byte to be skipped
  282.   LODSB             ; fetch a code byte
  283.   CMP AL,255        ; is it a terminator?
  284.   JNE L2            ; if yes then loop without counting down the index
  285.   LOOP L2           ; terminator: count down index and loop for next line
  286. L3:
  287.   CALL LPT1_ERROR?  ; check for printer ready
  288.   JNZ BEEP_KEY      ; beep if printer not ready
  289.   MOV BL,255        ; specify delimiter for call to LPRINTZ
  290.   CALL LPRINTZ      ; send control code string to printer
  291.   JMP NEXT_KEY      ; return for another keypress
  292.  
  293.  
  294. ; POPUP_WINDOW saves the current video state, then overlays our window
  295. ;   on the screen.
  296.  
  297. POPUP_WINDOW:
  298.   MOV VIDEO_SEG,CX         ; store our video segment
  299.   MOV ENABLE_VALUE,AH      ; store hardware value for re-enabling the screen
  300.   CLD                      ; all string scanning is forward
  301.   INC WINDOW_ACTIVE?       ; store the fact that the window is now active
  302.   MOV AH,3                 ; BIOS function number for READ_CURSOR
  303.   INT 010                  ; set CX to the cursor type (scan-line boundaries)
  304.   MOV CURSOR_TYPE,CX       ; save the cursor type
  305.   MOV CH,32                ; load impossible scan-line number
  306.   MOV AH,1                 ; BIOS function number for SET_CURSOR_SIZE
  307.   INT 010                  ; the cursor is now invisible
  308.   CALL VIDEO_DISABLE       ; turn display off for snow-free writing
  309.   MOV DS,VIDEO_SEG         ; fetch the video segment in effect
  310.   MOV DI,OLD_IMAGE         ; set DI to buffer area to save screen contents
  311.   CALL VIDEO_TO_MEM        ; then transfer screen contents to buffer
  312.   MOV ES,DS                ; set ES to video memory
  313.   MOV DS,CS                ; reset DS to code segment
  314.   LEA SI,WINDOW_IMAGE      ; point SI to window image
  315.   CALL MEM_TO_VIDEO        ; and write the window to the display
  316. VIDEO_ENABLE:
  317.   MOV AL,ENABLE_VALUE      ; fetch the re-enable hardware value
  318.   TEST AL                  ; are we in monochrome mode?
  319.   JZ RET                   ; return if yes, we never disabled the screen
  320.   MOV DX,03D8              ; address the CGA Mode Control Register
  321.   OUT DX,AL                ; output the ENABLE_VALUE to the control register
  322.   RET
  323.  
  324.  
  325.  
  326. ; VIDEO_ENABLE and VIDEO_DISABLE manipulate bit 3 of port 3D8H, the CGA Mode
  327. ;    Control Register, to temporarily turn the display on or off. Since these
  328. ;    routines write directly to hardware, they have no effect on other video
  329. ;    adapters.
  330.  
  331. VIDEO_DISABLE:
  332.   TEST ENABLE_VALUE        ; are we in monochrome mode?
  333.   JZ RET                   ; return if yes-- snow is not a problem
  334.   MOV DX,03DA              ; address CGA status port
  335. L1:                        ; loop here until we see vertical retrace
  336.   IN AL,DX                 ; fetch the status directly from hardware
  337.   TEST AL,8                ; mask the vertical-retrace bit
  338.   JE L1                    ; loop if we do not yet see vertical retrace
  339.   MOV DL,0D8               ; retrace is seen: address the Control Register
  340.   MOV AL,025               ; this value will disable the display
  341.   OUT DX,AL                ; the display is disabled
  342.   RET
  343.  
  344.  
  345.  
  346. ; VIDEO_TO_MEM copies a window from the video segment DS, to a memory buffer at
  347. ;     ES:DI.
  348.  
  349. VIDEO_TO_MEM:
  350.   MOV BL,W_LINES           ; load the number of lines in a window
  351.   MOV SI,VIDEO_OFFSET      ; point to our window within the video segment
  352. L1:                        ; loop here to copy each line
  353.   MOV CX,W_COLS            ; load the number of columns in the line
  354.   REP MOVSW                ; transfer one line
  355.   ADD SI,VIDEO_GAP         ; advance SI to next line address
  356.   DEC BL                   ; count down lines
  357.   JNZ L1                   ; loop until all lines are done
  358.   RET
  359.  
  360.  
  361.  
  362. ; MEM_TO_VIDEO writes a window from memory at DS:SI to the video segment ES.
  363.  
  364. MEM_TO_VIDEO:
  365.   MOV BL,W_LINES           ; load the number of lines in a window
  366.   MOV DI,VIDEO_OFFSET      ; point to our window within the video segment
  367. L1:                        ; loop here to copy each line
  368.   MOV CX,W_COLS            ; load the number of columns in the line
  369.   REP MOVSW                ; transfer one line
  370.   ADD DI,VIDEO_GAP         ; advance DI to next line address
  371.   DEC BL                   ; count down lines
  372.   JNZ L1                   ; loop until all lines are done
  373.   RET
  374.  
  375.  
  376.  
  377. ; LPRINTZ routine sends a string of bytes, delimited by BL, from DS:SI to
  378. ;    LPT1: thru INT 17h.
  379.  
  380. L1:                 ; loop here to send AL to the printer
  381.   MOV DX,0          ; printer no. 0 (LPT1:)
  382.   MOV AH,0          ; BIOS function number for SEND_BYTE_TO_PRINTER
  383.   INT 017           ; send the byte
  384. LPRINTZ:
  385.   LODSB             ; get one byte
  386.   CMP AL,BL         ; is it the delimiter?
  387.   JNE L1            ; loop if not, to output the byte
  388.   RET
  389.  
  390.  
  391. ; LPT1_ERROR? checks the current status of printer LPT1:. If it's either
  392. ; powered off or off-line, then we return NZ to signal an error condition.
  393. ; If LPT1 is ready, we return Z.
  394.  
  395. LPT1_ERROR?:
  396.   SUB DX,DX         ; printer number 0
  397.   MOV AH,2          ; use ROM BIOS 'get status' function
  398.   INT 017           ; status is returned in AH
  399.   TEST AH,8         ; test bit 3, I/O error indicator
  400.   RET               ; Z means ready, NZ means error
  401.  
  402.  
  403. ; BEEP uses the 8253 timer chip to emit a short beep thru the PC's speaker.
  404.  
  405. BEEP:
  406.   MOV AL,182        ; notify 8253 that frequency data is coming
  407.   OUT 67,AL         ; 8253 now programmed to take a frequency
  408.   MOV AL,0          ; load the low byte of the frequency (776.8 Hz)
  409.   OUT 66,AL         ; output the low byte
  410.   MOV AL,6          ; load the high byte of the frequency
  411.   OUT 66,AL         ; output the high byte
  412.   IN AL,97          ; fetch program value from hardware
  413.   OR AL,3           ; turn on the bottom two bits, to activate the speaker
  414.   OUT 97,AL         ; speaker is activated
  415.   MOV CX,06000      ; time delay for sound duration
  416. L1:                 ; loop here while speaker sounds
  417.   LOOP L1
  418.   IN AL,97          ; fetch program value from hardware
  419.   AND AL,NOT 3      ; turn off the bottom two bits, to deactivate the speaker
  420.   OUT 97,AL         ; speaker is shut off
  421.   RET
  422.  
  423.  
  424. ; WINDOW_IMAGE is the place where the video image of our pop-up window is
  425. ;   constructed when we install ourselves.
  426.  
  427. WINDOW_IMAGE:
  428.  
  429. END_OF_PROGRAM  EQU  $ + IMAGE_SIZE
  430.  
  431.