home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / asmutil / a86cnvrt.zip / S1.8 < prev    next >
Text File  |  1987-05-24  |  28KB  |  561 lines

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