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

  1. ; SETUP is a memory-resident program that sends control codes to an
  2. ;    Epson-compatible printer. After SETUP 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.   JMP INITIALIZE               ; goto initialization routine
  9.  
  10.  DB '(C) Copyright 1986, Ziff-Davis Publishing Company ',01A
  11.  
  12. KEYBOARD_INT  DD  0:(09 * 4)
  13. MACHINE_ID    DD  0F000:0FFFE
  14. CURSOR_MODE   DD  040:060
  15.  
  16. COLUMN_COUNT   DW ?            ; width of window in columns
  17. CURSOR_TYPE    DW ?            ; cursor scan line definition
  18. WINDOW_ACTIVE? DB 0            ; indicates if printer window is already active
  19. DISPLAY_MODE   DW ?            ; current crt display mode
  20. PAGE_NUMBER    DW ?            ; current displayed page
  21. ATTRIBUTE1     DB 4FH          ; window attribute bytes
  22. ATTRIBUTE2     DB 70H
  23.  
  24. DISPLAY_TABLE  DB 2DH,29H      ; display re-enable values for modes 2 and 3
  25. VIDEO          DW 0B800,0B900  ; starting addresses of video memory for CGA
  26.                DW 0BA00,0BB00
  27.  
  28. MONO_VIDEO     DW 0B000H       ; video segment address for
  29.                                ; monochrome adapter
  30.  
  31. OLD_KB_INT    DD ?             ; storage for old keyboard interrupt vector
  32.  
  33.  
  34. ; Text of the Printer Setup Menu window.
  35. ; After initialization, text and attribute bytes are combined and stored
  36. ; in the WINDOW_IMAGE area, and this area is used to store the contents of
  37. ; the screen that underlie the window when the window is called up.
  38.  
  39. WINDOW_SOURCE:
  40.   DB 201,        26 DUP 205          ,187
  41.   DB 186,'    PRINTER SETUP MENU    ',186
  42.   DB 186,'   EPSON RX/FX PRINTERS   ',186
  43.   DB 199,        26 DUP 196          ,182
  44.   DB 186,' F1    Compressed Mode    ',186
  45.   DB 186,' F2    Expanded Mode      ',186
  46.   DB 186,' F3    Emphasized Mode    ',186
  47.   DB 186,' F4    Double-Strike Mode ',186
  48.   DB 186,' F5    Elite Mode         ',186
  49.   DB 186,' F6    Miniature Mode     ',186
  50.   DB 186,' F7    Skip Perforation   ',186
  51.   DB 186,' F8    Indent Left Margin ',186
  52.   DB 186,' F9    Reset Top-of-Form  ',186
  53.   DB 186,' F10   Reset Print Modes  ',186
  54.   DB 186,' ESC   Exit               ',186
  55.   DB 199,        26 DUP 196          ,182
  56.   DB 186,' Unshifted:   Toggle ON   ',186
  57.   DB 186,' Shifted:     Toggle OFF  ',186
  58.   DB 200,        26 DUP 205          ,188
  59.   DB 532 DUP (?)
  60.  
  61. ; Storage area for the combination of text and attribute bytes that
  62. ; form the window image.
  63.  
  64. WINDOW_IMAGE:
  65.   DW 532 DUP ?
  66.  
  67. ; Control code strings for all of the printer setup options.
  68.  
  69. CODE_TABLE:
  70.   DB 15,255,14 DUP 0                   ; compressed mode on
  71.   DB 27,87,1,255,12 DUP 0              ; expanded mode on
  72.   DB 27,69,255,13 DUP 0                ; emphasized mode on
  73.   DB 27,71,255,13 DUP 0                ; double-strike mode on
  74.   DB 27,77,255,13 DUP 0                ; elite mode on
  75.   DB 15,27,83,0,27,65,6,255,8 DUP 0    ; miniature mode on
  76.   DB 27,78,12,255,12 DUP 0             ; perfskip on
  77.   DB 27,108,10,255,12 DUP 0            ; indent left margin
  78.   DB 27,67,66,255,12 DUP 0                           ; reset top-of-form
  79.   DB 18,27,87,0,27,70,27,72,27,80,27,84,27,50,255,0  ; reset print modes
  80.   DB 18,255,14 DUP 0                                 ; compress off
  81.   DB 27,87,0,255,12 DUP 0              ; expand off
  82.   DB 27,70,255,13 DUP 0                ; emphasize off
  83.   DB 27,72,255,13 DUP 0                ; double-strike off
  84.   DB 27,80,255,13 DUP 0                ; elite off
  85.   DB 18,27,84,27,50,255,10 DUP 0       ; miniature off
  86.   DB 27,79,255,13 DUP 0                ; perfskip off
  87.   DB 27,108,0,255,12 DUP 0             ; indent off
  88.  
  89.  
  90.  
  91. ; OUR_HANDLER is our replacement for the INT 9 keyboard handler.  We save
  92. ;    registers, then call the old keyboard handler.  If CTRL+RIGHT_SHIFT is
  93. ;    pressed, we activate our code.  Otherwise, we exit as if we were the
  94. ;    old handler.
  95.  
  96. OUR_HANDLER:
  97.   STI                       ; enable software interrupts
  98.   PUSH AX,BX,CX,DX,SI,DI    ; save all registers
  99.   PUSH DS,ES
  100.   PUSH AX                   ; save ax for call to old routine
  101.   IN AL,0A0H                ; re-enable NMI on PCjr
  102.   POP AX                    ; restore ax
  103.   PUSHF                     ; simulate interrupt call to old keyboard routine
  104.   CS CALL OLD_KB_INT        ; call old routine
  105.   MOV AH,2                  ; check status of the shift keys
  106.   INT 16H
  107.   AND AL,5                  ; Ctrl and Rt-Shift depressed?
  108.   CMP AL,5
  109.   JE >L1                    ; yes, then skip exit routine
  110. EXIT:                       ;  common exit point
  111.   POP ES,DS
  112.   POP DI,SI,DX,CX,BX,AX
  113.   IRET                      ; return from interrupt
  114.  
  115. ; Execution comes here when the proper key combination, Ctrl/Rt-Shift, is
  116. ; pressed. First task is to check whether or not the window is already open.
  117.  
  118. L1:
  119.   MOV DS,ES,CS           ;  set es and ds to the code segment
  120.   TEST WINDOW_ACTIVE?    ; is the window already open?
  121.   JNZ EXIT               ; yes, then ignore request
  122.  
  123. ; Check current video mode. If it's mode 2, 3, or 7, then set the window
  124. ; status flag, store the mode number and page number, save the cursor type,
  125. ; and hide the cursor. If any other display mode is active instead, ignore
  126. ; the request and exit.
  127.  
  128.   MOV AH,15            ; get page and mode numbers
  129.   INT 10H              ; al=mode, bh=page
  130.   CMP AL,2             ; is crt now in an acceptable mode?
  131.   JE >L0               ; yes, then continue
  132.   CMP AL,3
  133.   JE >L0
  134.   CMP AL,7
  135.   JE >L0
  136.   JMP EXIT
  137.  
  138. L0:
  139.   CLD                     ; all string scanning is forward
  140.   INC WINDOW_ACTIVE?      ; store the fact that the window is now active
  141.   MOV AH,0                ; extend the mode number AL to AX
  142.   MOV DISPLAY_MODE,AX     ; save the mode number
  143.   PUSH BX
  144.   MOV BL,BH               ; save page number for color displays
  145.   MOV BH,0
  146.   MOV PAGE_NUMBER,BX
  147.   POP BX
  148.   MOV AH,3                ; get cursor type
  149.   INT 10H
  150.   MOV CURSOR_TYPE,CX      ; save it
  151.   MOV AH,1                ; hide the cursor until later
  152.   MOV CH,20H
  153.   INT 10H                 ;
  154.  
  155. ; Preparatory routines are completed. Now open the window by first saving the
  156. ; contents of video memory beneath the window and then writing the window text
  157. ; directly to memory.
  158.  
  159.   MOV BX,PAGE_NUMBER       ; use BX as index into video segment address table
  160.   CMP DISPLAY_MODE,7       ; manually adjust index for monochrome adapter
  161.   IF E MOV BX,4
  162.   SHL BX,1                 ; multiply BX by two since table is made up of words
  163.   MOV AX,VIDEO[BX]         ; read segment from table
  164.   CMP DISPLAY_MODE,7       ; skip disable if in mode 7
  165.   MOV DS,AX                ; DS set to video memory
  166.   IF NE CALL VIDEO_DISABLE ; turn display off for snow-free writing
  167.   MOV DI,WINDOW_SOURCE     ; set DI to buffer area to save screen contents
  168.   MOV CX,28 BY 19          ; define window dimensions and location
  169.   MOV DX,2 BY 26
  170.   CALL VIDEO_TO_MEM        ; then transfer screen contents to buffer
  171.   MOV ES,DS                ; set ES to video memory
  172.   MOV DS,CS                ; reset DS to code segment
  173.   LEA SI,WINDOW_IMAGE      ; point SI to window image
  174.   MOV CX,28 BY 19          ; define window region
  175.   MOV DX,2 BY 26
  176.   CALL MEM_TO_VIDEO        ; and write the window to the display
  177.   CMP DISPLAY_MODE,7       ; skip enable if in mode 7
  178.   IF NE CALL VIDEO_ENABLE  ; re-enable the video display
  179.   JMP SHORT NEXT_KEY
  180.  
  181.  
  182. ; ESC_SEEN is jumped to when the ESC key is pressed. The window is refilled
  183. ;     with its original contents, the cursor is restored, and control is handed
  184. ;     back to the application program.
  185.  
  186. ESC_SEEN:
  187.   CMP DISPLAY_MODE,7       ; are we in monochrome mode?
  188.   IF NE CALL VIDEO_DISABLE ; if not then turn off the display
  189.   MOV SI,WINDOW_SOURCE     ; point SI to the buffer area
  190.   MOV CX,28 BY 19          ; define the window
  191.   MOV DX,2 BY 26
  192.   CALL MEM_TO_VIDEO        ; write the buffer contents to the display
  193.   CMP DISPLAY_MODE,7       ; are we in monochrome mode?
  194.   IF NE CALL VIDEO_ENABLE  ; if not then turn display back on
  195.   MOV AH,1                 ; restore cursor
  196.   MOV CX,CURSOR_TYPE
  197.   INT 10H
  198.   MOV WINDOW_ACTIVE?,0     ; the window is no longer active
  199.   JMP EXIT                 ; exit back to the interrupted user program
  200.  
  201.  
  202.  
  203. ; NEXT_KEY is the main loop for the interactive portion of our handler.  We
  204. ;    intercept all keystrokes while our window is open, and act on them.
  205. ;    This interactive mode is terminated when the ESC key is seen.
  206.  
  207. BEEP_KEY:           ; jump here if an illegal key is seen
  208.   CALL BEEP         ; beep and wait for another keypress
  209. NEXT_KEY:
  210.   MOV AH,0          ; BIOS function code for GET_KEY
  211.   INT 16H           ; fetch a keystroke from the BIOS
  212.   CMP AL,27         ; is it the ESC key?
  213.   JE ESC_SEEN       ; jump if it is, to exit our interactive mode
  214.   CMP AL,0          ; is it an extended code?
  215.   JNE BEEP_KEY      ; error if not
  216.   MOV AL,AH         ; move the extended code into AL, for examination
  217.   CMP AL,59         ; less than F1?
  218.   JB BEEP_KEY       ; yes, then don't accept it
  219.   CMP AL,91         ; greater than Shft-F8?
  220.   JA BEEP_KEY       ; yes, then don't accept it
  221.   CMP AL,68         ; between F1 and F10?
  222.   JBE UNSHIFTED     ; yes
  223.   CMP AL,84         ; between Shft-F1 and Shft-F9?
  224.   JAE SHIFTED       ; yes
  225.   JMP BEEP_KEY      ; if all tests failed, then keypress was illegal
  226.  
  227. ; If a legal function key was pressed, its scan code is translated here to the
  228. ; starting address of the string of bytes to be sent to the printer. The
  229. ; string is then sent to LPT1: provided it's powered on and on-line.
  230.  
  231. SHIFTED:
  232.   SUB AL,15                ; adjustment for shifted function keys
  233. UNSHIFTED:
  234.   SUB AL,59                ; adjustment for unshifted function keys
  235.   MOV AH,0
  236.   MOV CL,4                 ; multiply ax by 16
  237.   SHL AX,CL
  238.   ADD AX,CODE_TABLE        ; convert ax to full offset address
  239.   MOV SI,AX                ; and transfer it to si
  240.   CALL LPT1_ERROR?         ; check for printer ready
  241.   JNZ BEEP_KEY             ; beep if printer not ready
  242.   MOV BL,255               ; specify delimiter for call to LPRINTZ
  243.   CALL LPRINTZ             ; send control code string to printer
  244.   JMP NEXT_KEY             ; return for another keypress
  245.  
  246.  
  247.  
  248. ; VIDEO_ENABLE and VIDEO_DISABLE manipulate bit 3 of port 3D8h, the CGA Mode
  249. ;    Control Register, to temporarily turn the display on or off. Since these
  250. ;    routines write directly to hardware, they have no effect on other video
  251. ;    adapters.
  252.  
  253. VIDEO_DISABLE:
  254.   MOV DX,03DA              ; read CGA status port
  255. L1:
  256.   IN AL,DX                 ; wait for vertical retrace to occur
  257.   TEST AL,8                ; is bit 3 set?
  258.   JE L1                    ; no, wait until it is
  259.   MOV DX,03D8              ; now disable the display
  260.   MOV AL,025               ; by clearing bit 3 of the Mode Control Register
  261.   OUT DX,AL
  262.   RET
  263.  
  264. VIDEO_ENABLE:
  265.   MOV DX,03D8              ; CGA Mode Control Register
  266.   MOV BX,DISPLAY_MODE      ; get value to re-enable display
  267.   MOV AL,DISPLAY_TABLE[BX-2]
  268.   OUT DX,AL                ; and send it to the port
  269.   RET
  270.  
  271.  
  272.  
  273. ; VIDEO_TO_MEM copies a window (size CH columns by CL lines) from row DH,
  274. ;    column DL of the video segment DS, to a memory buffer at ES:DI.
  275.  
  276. VIDEO_TO_MEM:
  277.   MOV AL,CH                ; store number of columns
  278.   MOV AH,0
  279.   MOV COLUMN_COUNT,AX
  280.   MOV CH,0                 ; CX = number of lines
  281.   PUSH DI                  ; save DI
  282.   CALL VIDEO_OFFSET        ; get cell address of first character
  283.   MOV SI,DI                ; put it in SI
  284.   POP DI                   ; restore DI
  285. L1:
  286.   PUSH SI,CX               ; save next line pointer and line count
  287.   MOV CX,COLUMN_COUNT      ; load the number of columns in the line
  288.   REP MOVSW                ; transfer one line
  289.   POP CX,SI                ; restore saved registers
  290.   ADD SI,160               ; set si for next line address
  291.   LOOP L1                  ; loop until all lines are done
  292.   RET
  293.  
  294.  
  295.  
  296. ; MEM_TO_VIDEO writes a window (size CH columns by CL lines), from memory at
  297. ;   DS:SI to the video segment ES, row DH, column DL.
  298.  
  299. MEM_TO_VIDEO:
  300.   MOV AL,CH                ; save number of columns
  301.   MOV AH,0
  302.   MOV COLUMN_COUNT,AX
  303.   MOV CH,0                 ; cx = number of lines
  304.   CALL VIDEO_OFFSET        ; get offset into video memory
  305. L1:
  306.   PUSH DI,CX               ; save video starting address and line count
  307.   MOV CX,COLUMN_COUNT      ; load the number of columns in the line
  308.   REP MOVSW                ; transfer one line
  309.   POP CX,DI                ; restore registers
  310.   ADD DI,160               ; set di for next display line
  311.   LOOP L1                  ; loop until done
  312.   RET
  313.  
  314.  
  315.  
  316. ; VIDEO_OFFSET sets DI to the offset within the video memory segment of row
  317. ;    DH (0-24), column DL (0-79).
  318.  
  319. VIDEO_OFFSET:
  320.   MOV AL,160
  321.   MUL DH                   ; row * 160
  322.   SHL DL,1                 ; column * 2
  323.   MOV DH,0                 ; byte to word
  324.   ADD AX,DX                ; (row *160)+(column*2)
  325.   MOV DI,AX                ; set offset in di
  326.   RET
  327.  
  328.  
  329. ; LPRINTZ routine sends a string of bytes, delimited by BL, from DS:SI to
  330. ;    LPT1: thru INT 17h.
  331.  
  332. L1:
  333.   MOV DX,0          ; printer no. 0 (LPT1:)
  334.   MOV AH,0
  335.   INT 17H           ; send byte to printer
  336. LPRINTZ:
  337.   LODSB             ; get one byte
  338.   CMP AL,BL         ; is it the delimiter?
  339.   JNE L1            ; loop if not, to output the byte
  340.   RET
  341.  
  342.  
  343. ; LPT1_ERROR? checks the current status of printer LPT1:. If it's either
  344. ; powered off or off-line, then we return NZ to signal an error condition.
  345. ; If LPT1 is ready, we return Z.
  346.  
  347. LPT1_ERROR?:
  348.   MOV DX,0          ; printer no. 0
  349.   MOV AH,2          ; use ROM BIOS 'get status' function
  350.   INT 17H           ; status is returned in AH
  351.   TEST AH,8         ; test bit 3, I/O error indicator
  352.   RET               ; Z means ready, NZ means error
  353.  
  354.  
  355. ; BEEP uses the 8253 timer chip to emit a short beep thru the PC's speaker.
  356.  
  357. BEEP:
  358.   MOV AL,182        ; notify 8253 that frequency data is coming
  359.   OUT 67,AL
  360.   MOV AL,0          ; send frequency (776.8 Hz)
  361.   OUT 66,AL
  362.   MOV AL,6
  363.   OUT 66,AL
  364.   IN AL,97          ; activate speaker
  365.   OR AL,3
  366.   OUT 97,AL
  367.   MOV CX,6000H      ; time delay for sound duration
  368. L1:
  369.   LOOP L1
  370.   IN AL,97          ; deactivate speaker
  371.   AND AL,NOT 3
  372.   OUT 97,AL
  373.   RET
  374.  
  375.  
  376.  
  377. ; Initialization routine sets up the window image in the WINDOW_IMAGE area,
  378. ; resets the CURSOR_MODE word if this is a PCjr, and saves and replaces the
  379. ; old keyboard interrupt vector.
  380.  
  381. INITIALIZE:
  382.  
  383. ; Initialize the window text area by combining the text data with the attribute
  384. ; bytes and placing the conglomeration in the WINDOW_IMAGE area.
  385.  
  386.   CLD                  ; string scanning is forward
  387.   MOV AH,15            ; check the current video mode
  388.   INT 10H
  389.   CMP AL,7             ; if it's mode 7, then replace the attribute
  390.   JNE >L0              ; bytes with ones appropriate for mono adapter
  391.   MOV ATTRIBUTE1,70H
  392.   MOV ATTRIBUTE2,07H
  393. L0:                    ; now combine the text and attribute bytes
  394.   LEA SI,WINDOW_SOURCE ; point SI to table of text
  395.   LEA DI,WINDOW_IMAGE  ; point DI to the storage area
  396.   MOV CX,112           ; create first four lines by combining text with
  397.   MOV AL,ATTRIBUTE1    ;     ATTRIBUTE1 (112 words)
  398. L1:
  399.   MOVSB                ; text byte
  400.   STOSB                ; attribute byte
  401.   LOOP L1              ; loop until all 112 words are done
  402.   MOV CX,11            ; now do the next 11 lines
  403. L2:
  404.   PUSH CX              ; first attribute in each line is ATTRIBUTE1
  405.   MOVSB
  406.   STOSB
  407.   MOV CX,26            ; next 26 attributes are ATTRIBUTE2
  408.   MOV AL,ATTRIBUTE2
  409. L3:
  410.   MOVSB
  411.   STOSB
  412.   LOOP L3
  413.   MOVSB
  414.   MOV AL,ATTRIBUTE1    ; and the last in each line is ATTRIBUTE1
  415.   STOSB
  416.   POP CX
  417.   LOOP L2              ; loop until all 11 lines are done
  418.   MOV CX,112           ; create the last four lines just like the first four
  419. L4:
  420.   MOVSB
  421.   STOSB
  422.   LOOP L4
  423.  
  424. ; Check the machine ID byte in ROM and if this is a PCjr, then reset the
  425. ; cursor and correct the CURSOR_MODE word at 0040:0060.
  426.  
  427.   LES DI,MACHINE_ID     ; point to the identification byte for this machine
  428.   MOV AL,0FD            ; load the ID to the PCJr
  429.   SCASB                 ; is this a PCJr?
  430.   JNE >L5               ; no, then skip this routine
  431.   LES DI,CURSOR_MODE    ; point to the BIOS's cursor mode indicator
  432.   MOV AX,0607           ; load our new value for the indicator
  433.   STOSW                 ; store the new value
  434.   XCHG CX,AX            ; swap the value into CX, for a BIOS call
  435.   MOV AH,1              ; then physically reset the cursor
  436.   INT 10H
  437.  
  438. ; Now save the old keyboard interrupt vector and replace it with the new one.
  439.  
  440. L5:
  441.   LDS SI,KEYBOARD_INT       ; point DS:SI to INT 9 in the vector table
  442.   MOV DI,OFFSET OLD_KB_INT  ; point ES:DI to our storage for old INT 9 vector
  443.   MOV ES,CS
  444.   CLI                       ; disable all interrupts but NMI
  445.   MOV AX,OUR_HANDLER        ; point to our new handler
  446.   XCHG AX,[SI]              ; store new handler offset and fetch the old one
  447.   STOSW                     ; store the old handler offset
  448.   MOV AX,CS                 ; point to this code segment
  449.   XCHG AX,[SI+2]            ; store new segment and fetch the old one
  450.   STOSW                     ; store the old handler segment
  451.   STI                       ; re-enable interrupts
  452.   MOV DX,INITIALIZE         ; point dx to end of resident section
  453.   INT 27H                   ; terminate-but-stay-resident
  454. 
  455.