home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / ega / egaepsn1.arc / EPSON.ASM next >
Assembly Source File  |  1989-10-28  |  15KB  |  579 lines

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