home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / mskermit / mspeps.asm < prev    next >
Assembly Source File  |  2020-01-01  |  18KB  |  525 lines

  1.          page  60,132
  2.          title Graphics Module for Print Screen with EGA and Epson Printer
  3.  
  4. ; Revised 17 Nov 1989 by Joe Doupnik
  5. ;  Add initial jump label start: and identify it for the DOS loader.
  6. ;  Relabel "Out" to be "Out1" to avoid assembler keyword.
  7. ;
  8. ; Revised 6 Dec 1989 by Frank da Cruz
  9. ;  Change Epson initialization and restore strings:
  10. ;  Disable perforation skip and paper-out detect during graphics print.
  11. ;  Restore string is now ESC @ (initialize) rather than ESC 0 (1/8"/line)
  12.  
  13. Epson    segment para public 'code'
  14.          assume cs:Epson,ds:Epson,es:Epson
  15.  
  16. comment #
  17.  
  18. This routine is for public domain for those of you who bought an
  19. EGA and enhanced monitor and determined that you could no longer
  20. do a Shf_Prt_Scn in mode 10h (16).  If you have an IBM compatible
  21. and an Epson FX series printer then this routine will replace the
  22. GRAPHICS.COM routine. I also have routines for Radio Shack DMP 
  23. printers with 8 pins (but only 7 usable for graphics) and for HP
  24. LaserJet printers when used with an EGA. Enjoy...
  25.  
  26. Dr. R. Brooks Van Horn, Jr.
  27. 701 Fall Place
  28. Herndon, VA. 22070
  29.  
  30. #
  31.          org 100h 
  32. start:   jmp   Setup
  33.  
  34. Mlen     db    'EGA Graphics Ver 1.0'
  35. Cmp_Str  dw    $-mlen
  36.  
  37. ;        normal int 5 entry point
  38.  
  39. Begin:   pushf               ; enable further interrupts
  40.          push  ax
  41.          push  bx
  42.          push  bp
  43.          push  di
  44.          push  si
  45.          mov   ah,15         ; setup a function call to dos to
  46.          int   10h           ; get the video mode
  47.          and   ax,007fh      ; mask off unwanted data
  48.          mov   cs:[Mode],ax  ; and save it for future use
  49.          cmp   al,7          ; is this a mono card?
  50.          jz    Out1          ; yes, exit - when in text mode
  51.          cmp   al,3          ; see if we are in the graphics mode?
  52.          jg    cont          ; yes, go around using dos
  53. Out1:    pop   si            ; restore the registers saved
  54.          pop   di
  55.          pop   bp
  56.          pop   bx
  57.          pop   ax
  58.          popf
  59. ;-----   jump far to Dos
  60.          db    0EAh          ; jump far segment to Print
  61. dos      dw    0             ; offset of jump
  62. dos2     dw    0             ; segment of jump
  63.  
  64. Cont:    push  cx            ; and save all the registers
  65.          push  dx
  66.          push  ds
  67.          push  es
  68.          push  cs            ; now put code seg register into
  69.          pop   es            ; the extra segment register
  70.          xor   ax,ax
  71.          mov   ds,ax
  72.          inc   al            ; see if we are already being done
  73.          mov   al,Byte Ptr ds:[500h] ; get the current mode and also set it
  74.          or    al,al
  75.          jnz   Getout        ; if 550h was not zero then exit
  76.          push  cs
  77.          pop   ds
  78.          xchg  al,Byte Ptr cs:switch
  79.          or    al,al
  80.          jnz   GetOut
  81.          sti
  82.          mov   cs:[sp_save],sp
  83.          jmp   Process
  84.  
  85. Return:  mov   si,Offset Restore
  86.          mov   cl,cs:[si]    ; get number of bytes to print
  87.          xor   ch,ch
  88.          inc   si
  89.          call  Tabptr        ; restore printer to original state
  90. Exit:    mov   sp,cs:[sp_save]
  91.          xor   ax,ax
  92.          mov   Byte Ptr cs:switch,al ; set value to zero
  93. Getout:  pop   es            ; restore registers and exit
  94.          pop   ds
  95.          pop   dx
  96.          pop   cx
  97.          pop   si
  98.          pop   di
  99.          pop   bp
  100.          pop   bx
  101.          pop   ax
  102.          popf
  103.          sti
  104.          iret                ; bye...............
  105.  
  106. ;--------------------------------------------------------------------
  107. ;              Epson FX Printer with IBM-PC
  108. ;--------------------------------------------------------------------
  109. Line_Sp  db    7,27,51,24,27,79,27,56 ; Control Codes for 24/216" line spacing
  110.                              ; Also disable perforation skip (ESC O) and
  111.                              ; disable paper-out detect (ESC 8) (fdc)
  112. Set_Graf db    4,27,76       ; Cntrl Code for each graphics line printed
  113. Col_2_Do dw    0             ; last column number  to be printed
  114. Restore  db    2,27,64,12    ; change count to 3 if you want a form feed
  115.                              ; changed from ESC 0 to ESC @ (fdc)   
  116.  
  117. Line_Buf db    960 dup (?)   ; line buffer
  118. Eight    dw    8
  119. Four     dw    4
  120. Switch   db    0
  121. Sp_Save  dw    0
  122. Mode     dw    0             ; Current Video Mode
  123. Rows     dw    0             ; Number of rows for this mode
  124. Cols     dw    0             ; Number of columns for this mode
  125.  
  126. ;      Modes =   4   5   6   7   8   9   A   B   C   D   E   F  10
  127. Col_Mode dw    320,320,640,  0,  0,320,640,  0,720,320,640,640,640
  128. Row_Mode dw    200,200,200,  0,  0,200,200,  0,348,200,200,350,350
  129.  
  130. ;--------------------------------------------------------------------
  131.  
  132. ;        Print a Table of Control Values
  133. ;        ===============================
  134. ;
  135. Tabptr:  mov   al,cs:[si]
  136.          call  Printer
  137.          inc   si
  138.          loop  Tabptr
  139.          nop
  140.          ret
  141. ;
  142. ;        Send an alarm bell sound
  143. ;        ========================
  144. ;
  145. Bell:    mov   al,7
  146.          mov   ah,14
  147.          int   10h
  148.          ret
  149.  
  150. ;        Send the character in AL to the printer
  151. ;        =======================================
  152. ;
  153. Printer: push  dx
  154.          sub   dx,dx
  155.          xor   ah,ah
  156.          int   17h
  157.          pop   dx
  158.          test  ah,25h
  159.          jnz   Error
  160.          ret      
  161. ;
  162. ;        Error returns on printer commands
  163. ;        =================================
  164. Error:   call  Bell
  165.          call  Bell
  166.          jmp   Exit         
  167. ;
  168. ;        Send a form feed to the Printer
  169. ;        ===============================
  170. ;
  171. Cr_Lf:   push  dx
  172.          sub   dx,dx
  173.          mov   ax,0dh
  174.          int   17h
  175.          mov   ax,0ah
  176.          int   17h
  177.          pop   dx
  178.          test  ah,25h
  179.          jnz   Error
  180.          ret
  181.  
  182. ;---------------------------------------------------------------------
  183. ;                                                                    l
  184. ;                  Graphics Processing Section                       l
  185. ;                                                                    l
  186. ;---------------------------------------------------------------------
  187.  
  188. Process: mov   bp,cs:[Mode]
  189.          sub   bp,4
  190.          sal   bp,1
  191.  
  192.          mov   ax,cs:Row_Mode[bp]   ; save rows-1 and cols-1
  193.          dec   ax
  194.          mov   cs:Rows,ax
  195.          mov   ax,cs:Col_Mode[bp]
  196.          dec   ax
  197.          mov   cs:Cols,ax
  198.  
  199.          mov   ah,1             ; initialize the printer
  200.          xor   dx,dx
  201.          int   17h
  202.  
  203.          mov   si,Offset cs:Line_Sp ; setup for correct interline spacing
  204.          mov   cl,cs:[si]       ; get length
  205.          xor   ch,ch
  206.          inc   si
  207.          call  TabPtr
  208.          
  209.          mov   ax,cs:[Cols]     ; decide to do graphics by row or column mode
  210.          cmp   ax,320
  211.          jg    By_Rows
  212.          jmp   By_Cols
  213.  
  214. ;--------------------------------------------------------------------
  215. ;         for By_Rows calls we have usually 640 x 200 type, so do 200
  216. ;         across and 640 down the page.  This means that we can only 
  217. ;         single dot to get lines to connect on the printer paper.
  218. ;--------------------------------------------------------------------
  219.  
  220. By_Rows: mov   cx,0          ; start the column index at zero
  221.  
  222. Br_Strt: push  cx            ; save the current column index
  223.          mov   dx,cs:[Rows]  ; initialize the row count to max
  224.          mov   bh,Byte Ptr cs:[Eight]
  225.          xor   si,si         ; max characters to print
  226.          mov   cs:[Col_2_Do],si
  227.          mov   di,Offset cs:Line_Buf
  228.          xor   bl,bl
  229.  
  230. ;        do for a count of 'Eight'
  231.  
  232. Br_Cont: call  Read          ; read the next dot at (row,col)
  233.          and   al,07fh       ; check if any thing is there
  234.          jz    Br_Fill       ; and skip if nothing there
  235.          mov   al,1          ; else fill the byte 
  236. Br_Fill: shl   bl,1          ; move reg left one bit 
  237.          or    bl,al         ; and or in the next value
  238.          inc   cx            ; increment the column count
  239.          dec   bh            ; and the loop index
  240.          jnz   Br_Cont       ; continue loop for 8 times
  241.  
  242. ;        undo
  243.  
  244.          add   si,2          ; add two to the column counter
  245.          mov   Byte Ptr cs:[di],bl ; save filled byte
  246.          mov   Byte Ptr cs:[di+1],bl ; twice for filling
  247.          cmp   cs:[Rows],199 ; check for less than 200 rows
  248.          jg    Br_Two
  249.          mov   Byte Ptr cs:[di+2],bl ; and 3 times for low resolution
  250.          inc   di
  251.          inc   si
  252. Br_Two:  add   di,2          ; up the buffer ptr
  253.          or    bl,bl         ; do we have anything to print?
  254.          jz    Br_Skp        ; no, skip
  255.  
  256.          mov   cs:[Col_2_Do],si ; save index
  257.  
  258. Br_Skp:  mov   bh,Byte Ptr cs:[Eight] ; set loop for 8 more cols per row
  259.          dec   dx            ; delete one from the row index
  260.          pop   cx            ; restore the column count
  261.          push  cx            ; and save it again for this row
  262.          cmp   dx,0          ; and test to see if we are finished
  263.          jge   Br_Cont       ; loop
  264.  
  265.          mov   cx,cs:[Col_2_Do] ; get the number of bytes to print
  266.          or    cx,cx
  267.          jz    Br_NoP        ; skip if didn't get anything
  268.  
  269.          push  cx            ; save number to do
  270.          mov   si,Offset cs:Set_Graf ; setup for graphics
  271.          mov   cl,cs:[si]    ; get length
  272.          xor   ch,ch
  273.          inc   si            ; point past length field
  274.          call  TabPtr        ; perform the setup
  275.          pop   cx            ; now get the real characters to do
  276.          mov   si,Offset cs:Line_Buf ; get print line pointer
  277.          call  TabPtr        ; and print the line
  278.  
  279. Br_NoP:  call  Cr_Lf         ; do carriage return and line feed at end
  280.  
  281.          pop   cx
  282.          add   cx,cs:[Eight] ; add 8 to column count
  283.          cmp   cx,cs:[Cols]  ; compare to max to do
  284.  
  285.          jg    Br_Ret
  286.          jmp   Br_Strt       ; continue until fini
  287.  
  288. Br_Ret:  jmp   Return        ; restore printer and exit
  289.  
  290. ;--------------------------------------------------------------------
  291. ;         for By_Cols calls we have usually 320 x 200 type, so do 320
  292. ;         across and 200 down the page.  This means that we must double
  293. ;         dot to get lines to connect on the printer paper.
  294. ;--------------------------------------------------------------------
  295.  
  296. By_Cols: mov   dx,0          ; start the row index at zero
  297.  
  298. ;        for each row do all the columns
  299. Bc_Strt: push  dx            ; save the current row index
  300.          mov   cx,0          ; initialize the col count to start
  301.          mov   bh,Byte Ptr cs:[Four]
  302.          xor   si,si         ; max characters to print
  303.          mov   cs:[Col_2_Do],si
  304.          mov   di,Offset cs:Line_Buf
  305.  
  306. ;        for each column in the row, do
  307. Bc_Cont: call  Read          ; read the next dot at (row,col)
  308.          and   al,07fh       ; check if any thing is there
  309.          jz    Bc_Fill       ; and skip if nothing there
  310.          mov   al,3          ; else fill the byte from the bottom
  311. Bc_Fill: shl   bl,1          ; move reg left one bit 
  312.          shl   bl,1          ; and repeat
  313.          or    bl,al         ; and 'or' in the next value
  314.          inc   dx            ; increment the row count
  315.          dec   bh            ; and the loop index
  316.          jnz   Bc_Cont       ; continue loop for 4 times
  317.  
  318.          add   si,3          ; add three to the column counter
  319.          mov   Byte Ptr cs:[di],bl ; save filled byte
  320.          mov   Byte Ptr cs:[di+1],bl ; twice for filling
  321.          mov   Byte Ptr cs:[di+2],bl ; and three times for a lady
  322.          add   di,3          ; up the buffer ptr
  323.          or    bl,bl         ; see if anything is there
  324.          jz    Bc_Skp        ; skip if we have nothing to plot
  325.  
  326.          mov   cs:[Col_2_Do],si ; save index
  327.  
  328. Bc_Skp:  mov   bh,Byte Ptr cs:[Four] ; set loop for 8 more cols per row
  329.          inc   cx            ; add one to the col index
  330.          pop   dx            ; restore the row count
  331.          push  dx            ; and save it again for this row
  332.          cmp   cx,cs:[Cols]  ; and test to see if we are finished
  333.          jle   Bc_Cont       ; loop
  334.  
  335.          mov   cx,cs:[Col_2_Do] ; get the number of bytes to print
  336.          or    cx,cx
  337.          jz    Bc_NoP        ; skip if didn't get anything
  338.  
  339.          push  cx            ; save number to do
  340.          mov   si,Offset cs:Set_Graf ; setup for graphics
  341.          mov   cl,cs:[si]    ; get length
  342.          xor   ch,ch
  343.          inc   si            ; point past length field
  344.          call  TabPtr        ; perform the setup
  345.  
  346.          pop   cx            ; now get the real characters to do
  347.          mov   si,Offset cs:Line_Buf ; get print line pointer
  348.          call  TabPtr        ; print the line
  349.  
  350. Bc_NoP:  call  Cr_Lf
  351.  
  352.          pop   dx
  353.          add   dx,cs:[Four]  ; add to column count
  354.          cmp   dx,cs:[Rows]  ; compare to max to do
  355.  
  356.          jg    Bc_Ret        ; if fini then exit
  357.          jmp   Bc_Strt       ; else go do next row
  358.  
  359. Bc_Ret:  jmp   Return        ; restore printer and exit
  360.  
  361. ;--------------------------------------------------------------------
  362. ;
  363. ;        Read Dot Routine Using DOS/BIOS or VDI interface for int 10h
  364. ;
  365. ;-------------------------------------------------------------------
  366. Read:     xor  al,al
  367.           cmp   dx,0          ; see if all is ok
  368.           jl    Read_Ret
  369.           cmp   cx,cs:[Cols]  ; also check on overdoing it
  370.           jg    Read_Ret
  371.           cmp   cs:[Mode],10h
  372.           je    Read_Dot      ; if mode = 10 then do special I/O
  373.           mov   ah,13
  374.           push  bx
  375.           push  cx
  376.           push  dx
  377.           int   10h
  378.           pop   dx
  379.           pop   cx
  380.           pop   bx
  381.           xor   ah,ah         ; clear the high byte for testing
  382. Read_Ret: ret
  383.  
  384. ;---------------------------------------------------------------
  385. ;
  386. ;        Read a Pixel (Dot) from the EGA using Read Mode 0
  387. ;
  388. ;----------------------------------------------------------------
  389.  
  390. Read_Dot: push bx
  391.          push  cx
  392.          push  dx
  393.          mov   ax,dx         ; save column value
  394.          mov   bx,cx         ; and row value
  395.          mov   dx,0a000h     ; Video ram address
  396.          mov   ds,dx         ; into segment register
  397.          mov   dx,80
  398.          mul   dx            ; column * 80
  399.          shr   bx,1
  400.          shr   bx,1
  401.          shr   bx,1          ; row / 8
  402.          add   bx,ax         ; actual data byte address
  403.          and   cl,7          ; row mod 8
  404.          xor   cl,7          ; bit mask 7 - (row mod 8)
  405.          mov   ch,1
  406.          shl   ch,cl         ; 2^mask
  407.          mov   ah,3          ; initialize bit plane number
  408. Plane_Loop:
  409.          mov   dx,03CEh      ; EGA Controller
  410.          mov   al,4          ; map select register
  411.          out   dx,al
  412.          mov   dx,03CFh      ; data register
  413.          mov   al,ah         ; select bit planes 3,2,1,0
  414.          out   dx,al
  415.          mov   al,ds:[bx]    ; read bit plane
  416.          shl   cl,1
  417.          and   al,ch
  418.          jz    Not_On
  419.          or    cl,1
  420. Not_On:  dec   ah
  421.          jge   Plane_Loop
  422.          and   cl,0fh
  423.          mov   al,cl
  424.          pop   dx
  425.          pop   cx
  426.          pop   bx
  427.          ret
  428.          dw    -1            ; fense
  429.          
  430. ;--------------------------------------------------------------------
  431. ;
  432. ;        Initialization Routine for EPSON.COM
  433. ;
  434. ;--------------------------------------------------------------------
  435. Setup:   xor   ax,ax
  436.          mov   es,ax              ; setup to address segment zero
  437.          mov   cx,es:[0016h]      ; get current segment
  438.          mov   bx,es:[0014h]      ; and offset
  439.          mov   ds,cx              ; make that the data segment
  440.          mov   cx,cs:[Cmp_Str]    ; setup to check bytes for same
  441.          mov   si,Offset cs:mlen  ; data field "Graphic..."
  442.          mov   bx,si  
  443.  
  444. Check:   mov   ax,cs:[si]         ; get a byte in accum
  445.          cmp   ax,ds:[bx]         ; is it the same
  446.          jne   Ok                 ; no, then we are ok
  447.          inc   si                 ; otherwise, increment pointers
  448.          inc   bx                 ; to both fields
  449.          loop  Check              ; and loop for 7 checks
  450.  
  451.          mov   ax,cs
  452.          mov   ds,ax
  453.          mov   ah,09h
  454.          mov   dx,Offset Message1
  455.          int   21h
  456.          int   20h                ; if same then dont overlay but exit
  457.  
  458. Ok:      mov   bx,es:[0014h]      ; get the current offset in int vector
  459.          mov   ax,cs              ; now setup to display a message
  460.          mov   ds,ax
  461.          mov   Word Ptr dos,bx    ; and save it locally
  462.          mov   bx,es:[0016h]      ; get the segment location of item too
  463.          mov   Word Ptr dos2,bx   ; and save it also
  464.          mov   ax,cs              ; save our entry at int vector
  465.          mov   es:[0016h],ax      ; segment
  466.          mov   bx,Offset cs:Begin ; define entry point to routine
  467.          mov   es:[0014h],bx      ; offset
  468.          mov   di,Offset Field1
  469.          call  Convert            ; convert starting address
  470.          mov   di,Offset Field2
  471.          mov   bx,Offset Setup
  472.          add   bx,15              ; convert to next paragraph addr
  473.          mov   cl,4
  474.          shr   bx,cl
  475.          add   ax,bx
  476.          call  Convert            ; and the new ending address
  477.          mov   ah,09h             ; now do our message
  478.          mov   dx,Offset Message2
  479.          int   21h
  480.          mov   dx,Offset cs:Setup
  481.          int   27h                ; terminate but stay resident
  482.  
  483. Convert  proc  near
  484. ;
  485. ;        ax = number to be converted 
  486. ;        di = address of field in which to put the hex characters 
  487. ;
  488.          push  ax
  489.          push  bx
  490.          push  cx
  491.          push  dx
  492.          lea   bx,Ascii
  493.          mov   cl,4
  494.          mov   dx,ax
  495.          mov   al,ah
  496.          shr   al,cl
  497.          xlat  Ascii
  498.          mov   Byte Ptr cs:[di],al
  499.          mov   al,dh
  500.          and   al,0fh
  501.          xlat  Ascii
  502.          mov   Byte Ptr cs:[di+1],al
  503.          mov   al,dl
  504.          shr   al,cl
  505.          xlat  Ascii
  506.          mov   Byte Ptr cs:[di+2],al
  507.          mov   al,dl
  508.          and   al,0fh
  509.          xlat  Ascii
  510.          mov   Byte Ptr cs:[di+3],al
  511.          pop   dx
  512.          pop   cx
  513.          pop   bx
  514.          pop   ax
  515.          ret
  516. Convert  endp
  517. Message1 db    'EGA Graphics routine is already resident',13,10,'$'
  518. Message2 db    'EGA Graphics routine is now resident ('
  519. Field1   db    '0000-'
  520. Field2   db    '0000)',13,10,'$'
  521. Ascii    db    '0123456789abcdef'
  522. Epson    ends
  523.          end    start
  524.