home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / msdos / asmutl / a86cnvrt.arc / S2.8 < prev    next >
Text File  |  1987-05-24  |  19KB  |  523 lines

  1.   jmp initialize               ; goto initialization routine
  2.  
  3. interrupts    EQU 0h           ; interrupt table segment
  4. keyboard_int  EQU (9*4) W      ; interrupt 9 vector
  5.  
  6. rom_bios_data EQU 40h          ; ROM BIOS data area segment
  7. cursor_mode   EQU W[60H]       ; starting and ending cursor scan lines
  8.  
  9. rom           EQU 0F000h       ; ROM segment
  10. machine_id    EQU B[0FFFEh]    ; ID byte identifies machine as PCjr or other
  11.  
  12.  db '(C) Copyright 1986, Ziff-Davis Publishing Company ', 1Ah
  13.  
  14. column_count  dw ?             ; width of window in columns
  15. cursor_type   dw ?             ; cursor scan line definition
  16. setup_status  db 0             ; indicates if printer window is already active
  17. display_mode  dw ?             ; current crt display mode
  18. page_no       dw ?             ; current displayed page
  19. attribute1    db 4Fh           ; window attribute bytes
  20. attribute2    db 70h
  21.  
  22. display_table db 2Dh,29h       ; display re-enable values for modes 2 and 3
  23. video         dw 0B800h,0B900h,0BA00h,0BB00h     ; starting addresses of video
  24.                                                  ; memory for CGA pages 0 - 3
  25.  
  26. mono_video    dw 0B000h        ; video segment address for
  27.                                ; monochrome adapter
  28.  
  29. old_kb_int    DD
  30. old_keyboard_int        dw 2 dup (?)             ; storage for old keyboard
  31.                                                  ; 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_TEXT 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_buffer   DW
  40. buffer_text:
  41.   db 201,26 dup (205),187
  42.   db 186,'    PRINTER SETUP MENU    ',186
  43.   db 186,'   EPSON RX/FX PRINTERS   ',186
  44.   db 199,26 dup (196),182
  45.   db 186,' F1    Compressed Mode    ',186
  46.   db 186,' F2    Expanded Mode      ',186
  47.   db 186,' F3    Emphasized Mode    ',186
  48.   db 186,' F4    Double-Strike Mode ',186
  49.   db 186,' F5    Elite Mode         ',186
  50.   db 186,' F6    Miniature Mode     ',186
  51.   db 186,' F7    Skip Perforation   ',186
  52.   db 186,' F8    Indent Left Margin ',186
  53.   db 186,' F9    Reset Top-of-Form  ',186
  54.   db 186,' F10   Reset Print Modes  ',186
  55.   db 186,' ESC   Exit               ',186
  56.   db 199,26 dup (196),182
  57.   db 186,' Unshifted:   Toggle ON   ',186
  58.   db 186,' Shifted:     Toggle OFF  ',186
  59.   db 200,26 dup (205),188
  60.   db 532 dup (?)
  61.  
  62. ; Storage area for the combination of text and attribute bytes that
  63. ; form the window image.
  64.  
  65. window_bytes  label byte
  66. window_text   dw 532 dup (?)
  67.  
  68. ; Control code strings for all of the printer setup options.
  69.  
  70. code_table:
  71.   db 15,255,14 dup (0)                 ; compressed mode on
  72.   db 27,87,1,255,12 dup (0)            ; expanded mode on
  73.   db 27,69,255,13 dup (0)              ; emphasized mode on
  74.   db 27,71,255,13 dup (0)              ; double-strike mode on
  75.   db 27,77,255,13 dup (0)              ; elite mode on
  76.   db 15,27,83,0,27,65,6,255,8 dup (0)  ; miniature mode on
  77.   db 27,78,12,255,12 dup (0)           ; perfskip on
  78.   db 27,108,10,255,12 dup (0)          ; indent left margin
  79.   db 27,67,66,255,12 dup (0)                         ; reset top-of-form
  80.   db 18,27,87,0,27,70,27,72,27,80,27,84,27,50,255,0  ; reset print modes
  81.   db 18,255,14 dup (0)                               ; compress off
  82.   db 27,87,0,255,12 dup (0)            ; expand off
  83.   db 27,70,255,13 dup (0)              ; emphasize off
  84.   db 27,72,255,13 dup (0)              ; double-strike off
  85.   db 27,80,255,13 dup (0)              ; elite off
  86.   db 18,27,84,27,50,255,10 dup (0)     ; miniature off
  87.   db 27,79,255,13 dup (0)              ; perfskip off
  88.   db 27,108,0,255,12 dup (0)           ; indent off
  89.  
  90.  
  91.  
  92. ; Execution comes here, to the main body of the program, when an interrupt 9
  93. ; is generated from the keyboard. Registers are saved, then the keypress is
  94. ; checked and compared to the key combination that activates the menu window.
  95.  
  96. main:
  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
  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.   cmp setup_status,0     ; is the window already open?
  121.   jne 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.   mov setup_status,1      ; set status flag to indicate that window is active
  140.   mov ah,0                ; save mode number
  141.   mov display_mode,ax
  142.   push bx
  143.   mov bl,bh               ; save page number for color displays
  144.   mov bh,0
  145.   mov page_no,bx
  146.   pop bx
  147.   mov ah,3                ; get cursor type
  148.   int 10h
  149.   mov cursor_type,cx      ; save it
  150.   mov ah,1                ; hide the cursor until later
  151.   mov ch,20h
  152.   int 10h
  153.  
  154. ; Preparatory routines are completed. Now open the window by first saving the
  155. ; contents of video memory beneath the window and then writing the window text
  156. ; directly to memory.
  157.  
  158.   mov bx,page_no           ; use bx as index into video segment address table
  159.   cmp display_mode,7       ; manually adjust index for monochrome adapter
  160.   IF E mov bx,4
  161.   shl bx,1                 ; multiply bx by two since table is made up of words
  162.   mov ax,video[bx]         ; read segment from table
  163.   mov ds,ax                ; ds set to video memory
  164.   CS cmp display_mode,7    ; skip disable if in mode 7
  165.   IF NE call video_disable ; turn display off for snow-free writing
  166.   lea di,window_buffer     ; set di to buffer area to save screen contents
  167.   mov ch,28                ; define window dimensions and location
  168.   mov cl,19
  169.   mov dh,2
  170.   mov dl,26
  171.   call video2mem           ; then transfer screen contents to buffer
  172.   MOV ES,DS                ; set es to video memory
  173.   MOV DS,CS                ; reset ds to code segment
  174.   lea si,window_text       ; point si to window image
  175.   mov ch,28                ; define window region
  176.   mov cl,19
  177.   mov dh,2
  178.   mov dl,26
  179.   call mem2video           ; and write the window to the display
  180.   cmp display_mode,7       ; skip enable if in mode 7
  181.   IF NE call video_enable  ; re-enable the video display
  182.  
  183. ; Window is now present on the screen, so wait for a keypress.
  184.  
  185. getkey:
  186.   mov ah,0                 ; get a keypress
  187.   int 16h
  188.   cmp al,0                 ; is it an extended code?
  189.   je extended_code         ; yes, go interpret it
  190.   cmp al,27                ; is it the ESC key?
  191.   jne getkey1              ; no, then signal illegal keypress
  192.  
  193.  
  194.  
  195. ; Execution comes here when the ESC key is pressed. The window is refilled
  196. ; with its original contents, the cursor is restored, and control is handed
  197. ; back to the application program.
  198.  
  199.   cmp display_mode,7       ; skip disable if in mode 7
  200.   IF NE call video_disable ; turn off the display
  201.   lea si,window_buffer     ; point si to the buffer area
  202.   mov ch,28                ; define the window
  203.   mov cl,19
  204.   mov dh,2
  205.   mov dl,26
  206.   call mem2video           ; and write the buffer contents to the display
  207.   cmp display_mode,7       ; skip enable if in mode 7
  208.   IF NE call video_enable  ; turn display back on
  209.   mov ah,1                 ; restore cursor
  210.   mov cx,cursor_type
  211.   int 10h
  212.   mov setup_status,0       ; reset window status
  213.   jmp exit                 ; and exit
  214.  
  215. ; Getkey1 routine handles an illegal keypress by beeping and returning
  216. ; for another.
  217.  
  218. getkey1:
  219.   call beep                ; beep and return for another keypress
  220.   jmp getkey
  221.  
  222. ; An extended code has been entered...check its validity and goto the
  223. ; appropriate routine.
  224.  
  225. extended_code:
  226.   cmp ah,59                ; less than F1?
  227.   jb getkey1               ; yes, then don't accept it
  228.   cmp ah,91                ; greater than Shft-F8?
  229.   ja getkey1               ; yes, then don't accept it
  230.   cmp ah,68                ; between F1 and F10?
  231.   jbe unshifted            ; yes
  232.   cmp ah,84                ; between Shft-F1 and Shft-F9?
  233.   jae shifted              ; yes
  234.   jmp getkey1              ; if all tests failed, then keypress was illegal
  235.  
  236.  
  237.  
  238. ; If a legal function key was pressed, its scan code is translated here to the
  239. ; starting address of the string of bytes to be sent to the printer. The
  240. ; string is then sent to LPT1: provided it's powered on and on-line.
  241.  
  242. shifted:
  243.   sub ah,15                ; adjustment for shifted function keys
  244. unshifted:
  245.   sub ah,59                ; adjustment for unshifted function keys
  246.   mov al,ah                ; convert index to word in ax
  247.   xor ah,ah
  248.   mov cl,4                 ; multiply ax by 16
  249.   shl ax,cl
  250.   add ax,code_table        ; convert ax to full offset address
  251.   mov si,ax                ; and transfer it to si
  252.   call lpt1stat            ; check for printer ready
  253.   jc getkey1               ; beep if printer not ready
  254.   mov bl,255               ; specify delimiter for call to LPRINTZ
  255.   call lprintz             ; send control code string to printer
  256.   jmp getkey               ; return for another keypress
  257.  
  258.  
  259.  
  260. ; VIDEO_ENABLE and VIDEO_DISABLE routines manipulate bit 3 of port 3D8h,
  261. ; the CGA Mode Control Register, to temporarily turn the display on or off.
  262. ; Since these routines write directly to hardware, they have no effect on
  263. ; other video adapters.
  264.  
  265. video_disable:
  266.   mov dx,3DAh              ; read CGA status port
  267. L1:
  268.   in al,dx                 ; wait for vertical retrace to occur
  269.   test al,8                ; is bit 3 set?
  270.   je L1                    ; no, wait until it is
  271.   mov dx,3D8h              ; now disable the display
  272.   mov al,25h               ; by clearing bit 3 of the Mode Control Register
  273.   out dx,al
  274.   ret
  275.  
  276. video_enable:
  277.   mov dx,3D8h              ; CGA Mode Control Register
  278.   mov bx,display_mode      ; get value to re-enable display
  279.   sub bx,2
  280.   mov al,display_table[bx]
  281.   out dx,al                ; and send it to the port
  282.   ret
  283.  
  284.  
  285.  
  286. ; VIDEO2MEM routine transfers the contents of a portion of video memory
  287. ; to a memory buffer for storage.
  288. ; Entry:      DS    - video segment
  289. ;             ES:DI - memory buffer
  290. ;             DH,DL - row and column of upper left corner of window
  291. ;             CH    - width of window in columns
  292. ;             CL    - number of lines in window
  293.  
  294. video2mem:
  295.   mov al,ch                ; store number of columns
  296.   mov ah,0
  297.   mov column_count,ax
  298.   mov ch,0                 ; cx = number of lines
  299.   push di                  ; save di
  300.   call video_offset        ; get cell address of first character
  301.   mov si,di                ; put it in si
  302.   pop di                   ; restore di
  303. L1:
  304.   push si,cx               ; save next line pointer and line count
  305.   mov cx,column_count      ; set cx for call to WRITELN
  306.   call writeln             ; transfer one line
  307.   pop cx,si                ; restore saved registers
  308.   add si,160               ; set si for next line address
  309.   loop L1                  ; loop until all lines are done
  310.   ret
  311.  
  312.  
  313.  
  314. ; MEM2VIDEO writes a selected area of memory to the video display.
  315. ; Entry:      DS:SI - memory buffer
  316. ;             ES    - video segment
  317. ;             DH,DL - row and column of upper left corner of window
  318. ;             CH    - width of window in columns
  319. ;             CL    - number of lines in window
  320.  
  321. mem2video:
  322.   mov al,ch                ; save number of columns
  323.   mov ah,0
  324.   mov column_count,ax
  325.   mov ch,0                 ; cx = number of lines
  326.   call video_offset        ; get offset into video memory
  327. L1:
  328.   push di,cx               ; save video starting address and line count
  329.   mov cx,column_count      ; set cx for call to WRITELN
  330.   call writeln             ; transfer one line
  331.   pop cx,di                ; restore registers
  332.   add di,160               ; set di for next display line
  333.   loop L1                  ; loop until done
  334.   ret
  335.  
  336.  
  337.  
  338. ; VIDEO_OFFSET calculates the offset into video memory of a character cell.
  339. ; Entry:      DH,DL - row and column of cell (0-24,0-79)
  340. ; Exit:       DI    - offset address
  341.  
  342. video_offset:
  343.   mov al,160
  344.   mul dh                   ; row * 160
  345.   shl dl,1                 ; column * 2
  346.   mov dh,0                 ; byte to word
  347.   add ax,dx                ; (row *160)+(column*2)
  348.   mov di,ax                ; set offset in di
  349.   ret
  350.  
  351.  
  352.  
  353. ; WRITELN subroutine copies a string of words from one memory location to
  354. ; another. The CGA status port is not checked for vertical retrace status
  355. ; before transfer.
  356. ; Entry:      DS:SI - source
  357. ;             ES:DI - destination
  358. ;             CX    - number of words
  359.  
  360. writeln:
  361.   cld                      ; clear for string instructions
  362. L1:
  363.   movsw                    ; move one word
  364.   loop L1                  ; loop until done
  365.   ret
  366.  
  367.  
  368.  
  369. ; LPRINTZ routine sends a string of bytes delimited by a user-specified byte to
  370. ; LPT1: thru INT 17h.
  371. ; Entry:       DS:SI - string address
  372. ;              BL    - delimiter (0-255)
  373.  
  374. lprintz:
  375.   cld                      ; for 8088 string instructions
  376. L1:
  377.   lodsb                    ; get one byte
  378.   cmp al,bl                ; is it the delimiter?
  379.   je RET                   ; yes, then exit
  380.   mov dx,0                 ; printer no. 0 (LPT1:)
  381.   mov ah,0
  382.   int 17h                  ; send byte to printer
  383.   jmp L1                   ; return for next byte
  384.  
  385.   ret
  386.  
  387.  
  388.  
  389. ; LPT1STAT checks the current status of printer LPT1:.  If it's either
  390. ; powered off or off-line, then an error condition is signalled upon return
  391. ; thru the carry flag.
  392. ; Exit:        Carry clear - no error
  393. ;              Carry set   - error
  394.  
  395. lpt1stat:
  396.   mov dx,0                 ; printer no. 0
  397.   mov ah,2                 ; use ROM BIOS 'get status' function
  398.   int 17h
  399.   test ah,8                ; test bit 3, I/O error indicator
  400.   je >L1                   ; if clear, then no error
  401.   stc                      ; raise error flag
  402.   ret
  403.  
  404. L1:
  405.   clc                      ; clear error flag
  406.   ret
  407.  
  408.  
  409.  
  410. ; BEEP uses the 8253 timer chip to emit a short beep thru the PC's speaker.
  411.  
  412. beep:
  413.   mov al,182               ; notify 8253 that frequency data is coming
  414.   out 67,al
  415.   mov al,0                 ; send frequency (776.8 Hz)
  416.   out 66,al
  417.   mov al,6
  418.   out 66,al
  419.   in al,97                 ; activate speaker
  420.   or al,3
  421.   out 97,al
  422.   mov cx,6000h             ; time delay for sound duration
  423. L1:
  424.   loop L1
  425.   in al,97                 ; deactivate speaker
  426.   and al,252
  427.   out 97,al
  428.   ret
  429.  
  430.  
  431.  
  432. ; MEM2MEM subroutine transfers a non-overlapping block of memory one byte
  433. ; at a time.
  434. ; Entry:       DS:SI - source
  435. ;              ES:DI - destination
  436. ;              CX    - number of bytes
  437.  
  438. mem2mem:
  439.   cld
  440. L1:
  441.   movsb                    ; transfer one byte
  442.   loop L1                  ; and loop until done
  443.   ret
  444.  
  445.  
  446.  
  447. ; Initialization routine sets up the window image in the WINDOW_TEXT area,
  448. ; resets the CURSOR_MODE word if this is a PCjr, and saves and replaces the
  449. ; old keyboard interrupt vector.
  450.  
  451. initialize:
  452.  
  453. ; Initialize the window text area by combining the text data with the attribute
  454. ; bytes and placing the conglomeration in the WINDOW_TEXT area.
  455.  
  456.   mov ah,15            ; check the current video mode
  457.   int 10h
  458.   cmp al,7             ; if it's mode 7, then replace the attribute
  459.   jne >L0              ; bytes with ones appropriate for mono adapter
  460.   mov attribute1,70h
  461.   mov attribute2,07h
  462. L0:
  463.   cld                  ; now combine the text and attribute bytes
  464.   lea si,buffer_text   ; point si to table of text
  465.   lea di,window_bytes  ; and di to storage area
  466.   mov cx,112           ; create first four lines by combining
  467.   mov al,attribute1    ; text with attribute1 (112 words)
  468. L1:
  469.   movsb                ; text byte
  470.   stosb                ; attribute byte
  471.   loop L1              ; loop until all 112 words are done
  472.   mov cx,11            ; now do the next 11 lines
  473. L2:
  474.   push cx              ; first attribute in each line is attribute1
  475.   movsb
  476.   stosb
  477.   mov cx,26            ; next 26 attributes are attribute2
  478.   mov al,attribute2
  479. L3:
  480.   movsb
  481.   stosb
  482.   loop L3
  483.   movsb
  484.   mov al,attribute1    ; and the last in each line is attribute1
  485.   stosb
  486.   pop cx
  487.   loop L2              ; loop until all 11 lines are done
  488.   mov cx,112           ; create the last four lines just like
  489. L4:
  490.   movsb                ; the first four
  491.   stosb
  492.   loop L4
  493.  
  494. ; Check the machine ID byte in ROM and if this is a PCjr, then reset the
  495. ; cursor and correct the CURSOR_MODE word at 0040:0060.
  496.  
  497.   mov ax,rom            ; set ds to rom
  498.   mov ds,ax
  499.   cmp machine_id,0FDh   ; is this a PCjr?
  500.   jne >L5               ; no, then skip this routine
  501.   mov ax,rom_bios_data  ; set ds to ROM BIOS data area
  502.   mov ds,ax
  503.   mov cursor_mode,0607h ; reset the cursor mode indicator
  504.   mov ah,1              ; then physically reset the cursor
  505.   mov cx,0607h
  506.   int 10h
  507.  
  508. ; Now save the old keyboard interrupt vector and replace it with the new one.
  509.  
  510. L5:
  511.   mov ax,interrupts             ; set ds to the interrupt vector area
  512.   mov ds,ax
  513.   mov ax,keyboard_int           ; save old vector
  514.   CS mov old_keyboard_int,ax
  515.   mov ax,keyboard_int[2]
  516.   CS mov old_keyboard_int[2],ax
  517.   cli                           ; disable all interrupts but NMI
  518.   mov keyboard_int,main         ; and install new vector
  519.   mov keyboard_int[2],cs
  520.   sti                           ; re-enable interrupts
  521.   mov dx,initialize             ; point dx to end of resident section
  522.   int 27h                       ; terminate-but-stay-resident
  523.