How to Print Basic Video Screens to Epson Printers (57354)



The information in this article applies to:

  • Microsoft Visual Basic for MS-DOS
  • Microsoft QuickBASIC 4.0
  • Microsoft QuickBASIC 4.0b
  • Microsoft QuickBASIC 4.5
  • Microsoft BASIC Compiler for MS-DOS and OS/2 6.0
  • Microsoft BASIC Compiler for MS-DOS and OS/2 6.0b
  • Microsoft Basic Professional Development System for MS-DOS 7.0
  • Microsoft Basic Professional Development System for MS-DOS 7.1

This article was previously published under Q57354

SUMMARY

The following article explains how Microsoft Basic programs can print video screen images to Epson-compatible printers. If you have a printer other than an Epson, you must change the printer control codes used in the following programs for setting line spacing and graphics mode. Control codes can be found in your printer's manual.

The information in this article is also included in the Help file provided with the Standard and Professional Editions of Microsoft Visual Basic for MS-DOS, version 1.0.

MORE INFORMATION

Introduction

This document explains how Microsoft Basic programs can print video screen images to Epson-compatible printers. If you have a printer other than an Epson, you must change the printer control codes used in the following programs for setting line spacing and graphics mode. Control codes can be found in your printer's manual.

The routines presented below are divided up based on SCREEN modes. SCREEN modes 0 through 2 use one method of printing, SCREEN 3 uses another method, SCREEN modes 7 through 12 are all combined into one routine, and SCREEN 13 uses another separate routine.

The routines for printing EGA and VGA SCREEN modes 7 through 13 are required only if you are not running under MS-DOS version 4.0 or later. In MS-DOS version 4.0 and later, the GRAPHICS.COM program supports all standard EGA and VGA SCREEN modes. Thus, the routine listed below for printing CGA SCREEN modes can be used to print EGA and VGA SCREENs in MS-DOS 4.0 version and later.

Each of these groups of SCREEN modes uses different methods of storing graphics information in video memory. A brief explanation of this is listed before each program.

Printing CGA Screen Modes 0 Through 2

The following are two methods of performing a CGA screen dump to a graphics printer:

Note: These methods will also support all standard EGA and VGA SCREEN modes (SCREENs 7 through 13) if you are using GRAPHICS.COM provided in MS-DOS version 4.0 or later.

  1. You can manually execute a screen dump to a graphics printer of a CGA SCREEN 0, 1, or 2 in Basic by doing the following:

    1. Run GRAPHICS.COM, which is a Terminate-and-Stay-Resident (TSR) program located on the MS-DOS disk (run GRAPHICS.COM only once per boot session).
    2. Press SHIFT+PRINT SCREEN (that is, press the PRINT SCREEN key while holding down the SHIFT key).

      The above SHIFT+PRINT SCREEN screen dump also can print the screen in GW-Basic, in IBM BasicA, or in most programs that use CGA text or graphics.

      NOTE: If you press SHIFT+PRINT SCREEN while running an application in the VBDOS.EXE environment, you may experience problems with editing and entering keystrokes after you finish the program and return to the VBDOS.EXE environment. It is suggested that you not use this method while in the VBDOS.EXE environment.
  2. A hardware Interrupt 5 also can be invoked to perform a CGA screen dump to a graphics printer from a Microsoft Basic program run on an IBM PC. To perform the screen dump, do the following:

    1. Run the GRAPHICS.COM program provided with the MS-DOS disk (run GRAPHICS.COM only once per boot session).
    2. Once GRAPHICS.COM is resident in memory, if you press SHIFT+PRINT SCREEN or use hardware Interrupt 5, the screens displayed by the IBM CGA card will be printed. In versions of MS-DOS earlier than 4.0, the IBM GRAPHICS.COM program does not support the printing of EGA or VGA screens, and only Basic SCREENs 0, 1, and 2 can be printed.
The following program, DUMP.BAS, shows the preferred method to CALL hardware Interrupt 5 to perform a screen dump. This program can be compiled in Visual Basic for MS-DOS, version 1.0; in QuickBasic for MS-DOS, versions 4.0, 4.0b, or 4.5; in Basic Compiler for MS-DOS, versions 6.0 or 6.0b; or in Basic PDS for MS-DOS, versions 7.0 or 7.1):
   ' To try this example in VBDOS.EXE:
   '
   ' 1. From the File menu, choose New Project.
   ' 2. Copy the code example to the Code window.
   ' 3. Press F5 to run the program.
   '
   ' To run this example in the programming environment, you must
   ' invoke the environment with the /L switch to load the default
   ' Quick library. For example, with Microsoft Visual Basic for
   ' MS-DOS, version 1.0 use:
   '
   ' VBDOS.EXE /L
   '
   ' DUMP.BAS
   '
   ' Use the following include file for Visual Basic for MS-DOS,
   ' version 1.0:
   '
   REM $INCLUDE: 'VBDOS.BI'
   '
   ' With QuickBasic for MS-DOS, version 4.x, use the include
   ' file 'QB.BI'
   '
   ' With Basic PDS for MS-DOS, version 7.x, use the include
   ' file 'QBX.BI'

   TYPE Regtype

     AX AS INTEGER
     BX AS INTEGER
     CX AS INTEGER
     DX AS INTEGER
     BP AS INTEGER
     SI AS INTEGER
     DI AS INTEGER
     FLAGS AS INTEGER
     DS AS INTEGER
     ES AS INTEGER

   END TYPE
   DIM inary AS RegType
   DIM outary AS RegType
   CLS
   SCREEN 1
   PRINT "This goes to the printer"
   LINE (1,1)-(100,100)
   CALL interrupt (&H5, inary, outary)      ' Performs screen dump.
				
The program below, DUMP2.BAS, can be used with QuickBasic for MS-DOS, versions 2.0, 2.01, and 3.0 if you change CALL INT86OLD to CALL INT86. Otherwise, if you do not change CALL INT86OLD to CALL INT86, this program can be compiled as is in QuickBasic for MS-DOS, versions 4.0, 4.0b, or 4.5; in Basic Compiler for MS-DOS, versions 6.0 or 6.0b; or in Basic PDS for MS-DOS, versions 7.0 or 7.1:
   ' DUMP2.BAS
   DIM inary%(7), outary%(7)
   SCREEN 1
   PRINT "This goes to the printer"
   LINE (1,1)-(100,100)
   CALL INT86OLD ( &H5, VARPTR(inary%(0)), VARPTR(outary%(0)) )

   ' The following syntax, which leaves out the VARPTR function,
   ' is also supported in QuickBasic for MS-DOS, version 4.x; in
   ' Basic Compiler for MS-DOS, version 6.x; and in Basic PDS for
   ' MS-DOS, version 7.x:
   '
   '         CALL INT86OLD ( &H5, inary%(), outary%() )
   '
   ' This INT86OLD syntax is listed on Pages 86-88 of the "QuickBasic
   ' 4.0: Language Reference" for version 4.x; and on Pages 86-88 of
   ' "Basic Compiler 6.0: Language Reference" for version 6.x.
   '
   ' NOTE: The following syntax is ILLEGAL for CALL INT86 in
   ' QuickBasic for MS-DOS, versions 2.0, 2.01, or 3.0:
   '
   '           CALL INT86 ( &H5, inary%(), outary%() )
				
To run the above DUMP.BAS or DUMP2.BAS program within the QB.EXE version 4.x editor (or within QB.EXE from Basic Compiler for MS-DOS, version 6.x), you must invoke the editor with the QB.QLB Quick library, as follows:
   QB DUMP.BAS /L QB.QLB
				
To make an EXE program from one of the above programs, you must LINK with QB.LIB as follows:
   BC DUMP.BAS;
   LINK DUMP.OBJ,DUMP.EXE,,QB.LIB;
				
The above LINK creates DUMP.EXE, which is a program that can be executed from MS-DOS by typing DUMP.

For Basic PDS for MS-DOS, version 7.x, you must use QBX.EXE, QBX.QLB, and QBX.LIB (instead of QB.EXE, QB.QLB, and QB.LIB) in the above steps.

DUMP.BAS cannot be run in QuickBasic for MS-DOS, versions 2.0, 2.01, or 3.0; instead, you must use DUMP2.BAS. To run DUMP2.BAS in QB.EXE version 2.0, 2.01, or 3.0, do the following:

  1. Make a USERLIB.EXE that contains INT86, as follows:

    1. In version 2.0 or 2.01, type the following at the MS-DOS command line:
               BUILDLIB USERLIB.OBJ,userlib.EXE;
    2. In version 3.0, type the following at the MS-DOS command line:
               BUILDLIB INT86.OBJ,userlib.EXE;
  2. Run GRAPHICS.COM (only once per boot session) if you will be printing graphics.
  3. Invoke QB.EXE as follows:
          QB DUMP2.BAS /L userlib.EXE
  4. Change INT86OLD to INT86 in DUMP2.BAS (since there is no INT86OLD in version 2.0, 2.01, or 3.0).
  5. Press CTRL+R to run the program in QB.EXE.
To make DUMP2.BAS into DUMP2.EXE using QuickBasic for MS-DOS, version 2.0, 2.01, or 3.0, do the following:

  1. Do ONE of the following:

    1. Create DUMP2.OBJ using the Compile command from the Run menu in the QB.EXE editor.
    2. You can also create DUMP2.OBJ using the separate compilation method, where you must end the QB command line with a semicolon (;), as follows:
               QB DUMP2;
  2. Do one of the following, depending on which version of QuickBasic for MS-DOS you are using:

    1. In version 2.0 or 2.01, type the following at the MS-DOS command line:
               LINK DUMP2+USERLIB.OBJ;
    2. In version 3.0, type the following at the MS-DOS command line:
               LINK DUMP2+INT86.OBJ;

Printing Hercules Screen Mode 3

Understanding how to print graphics screens generated by Hercules and Hercules-compatible graphics adapters requires familiarity with how Hercules graphics memory is set up.

Hercules memory starts at hex-paragraph B000 (decimal 45056). Graphics memory starts with Page 0 at hex-parapraph B000 (decimal 45056), and at Page 1 at hex-paragraph B800 (decimal 47104). (Paragraphs mark segment boundaries, and there are 16 bytes per paragraph.)

However, graphics memory is interleaved, and is not contiguous. Each line of pixels in SCREEN mode 3 consists of 90 bytes. Thus, the top line of pixels (line 0) on Page 0 will start at hex-paragraph B000 at offset 0 and go for 90 bytes.

To draw a line of pixels at the top of the screen (in line 0 of Page 0), POKE 255 into positions 0 through 89 (where 255 means all 8 bits per byte being "on"), as follows:
   SCREEN 3
   DEF SEG = &HB000
   FOR x = 0 TO 89    ' B000:0000 hex to B000:0059 hex (in
      POKE x, 255     ' segment:offset notation).
   NEXT x
				
To perform this procedure on Page 1, change the value of the DEF SEG statement to hex-paragraph &HB800.

Because graphics memory is interleaved and not contiguous, if you continue to POKE at an offset 90 bytes after hex-paragraph B000, the next line will appear on the screen at the fourth line down. To draw a line just one line down (on line 1), add 2000 Hex (8192 decimal) to the offset of the first byte on line 0, then POKE as follows:
   DEF SEG = &HB000
   FOR x = 8192 TO 8281     ' Or B000:2000 hex to B000:2059 hex (in
      POKE x, 255           ' segment:offset notation).
   NEXT x
				
This procedure must also be performed for line 2 and line 3. (Note that line numbering starts at 0.) As a result, the first byte of line 2 will be B000:4000 hex, and the first byte of line 3 will be B000:6000 hex. The interleaving cycles every four lines, thus the first byte of line 4 will be B000:005A hex (45056:0090 decimal), and subsequent lines will follow the previous pattern, at offset intervals of 2000 hex (8192 decimal).

The following diagram shows how the scan lines relate to the interleaved video buffer:
               Video Buffer                    Display
      B000:0000 +---------+                       +-------------
                |         |<----------Scan Line 0 | ............
           005A |---------|       +---Scan Line 1 | ............
                |         |<---+  |  *Scan Line 2 | ............
           00B4 |---------|    |  |  *Scan Line 3 | ............
                .         .    +------Scan Line 4 | ............
                .         .       |               |
      B000:2000 |---------|       |
                |         |<------+
           205A |---------|          * NOTE:
                |         |            Scan line 2 is at B000:4000 hex
                                       Scan line 3 is at B000:6000 hex
				
This same interleaving is used in video Page 1, which begins at hex- paragraph B800. Please see the figure on Page 89 of the "Programmer's Guide to PC and PS/2 Video Systems" for a more complete diagram of the display memory for Hercules graphics mode.

The following subprogram prints SCREEN Page 0 of a Hercules graphics screen to an Epson or Epson-compatible printer. To print SCREEN Page 1, use a DEF SEG = &HB800 statement (instead of &HB000 for Page 0).
   ' To try this example in VBDOS.EXE:
   ' 1. From the File menu, choose New Project.
   ' 2. Copy the code example to the Code window.
   ' 3. Press F5 to run the program.
   '
   DECLARE SUB HerculesPrintScreen ()
   ' Before using Hercules SCREEN 3, you must MSHERC.COM (included
   ' with Visual Basic for MS-DOS, version 1.0; and QuickBasic for
   ' MS-DOS, version 4.5); or run QBHERC.COM (included with
   ' QuickBasic for MS-DOS, version 4.0 or 4.0b, and Basic Compiler
   ' for MS-DOS, version 6.x).
   SCREEN 3
   ' Put your screen graphics commands here - and take out commands
   ' between these markers:
   ' --------------------------------------------------------------
     FOR i% = 1 TO 719 STEP 10
       LINE (1, 1)-(i%, 348)
       LINE (1, 348)-(i%, 1)
     NEXT i%
   ' --------------------------------------------------------------
   CALL HerculesPrintScreen

   SUB HerculesPrintScreen STATIC
      DEF SEG = &HB000  ' Set segment to SCREEN 3, video Page 0.
      OPEN "LPT1" FOR BINARY AS #1 ' Open printer port in binary mode.
      WIDTH #1, 255               ' Set print width to 256 bytes wide.
      adv872$ = CHR$(27) + "A" + CHR$(8)
      dots408$ = CHR$(27) + "K" + CHR$(92) + CHR$(1)
      linefeed$ = CHR$(10)

      PUT #1, , adv872$        ' Set printer linefeed to 8/72".
      FOR x = 0 TO 89
         PUT #1, , dots408$  ' Set printer for bit image graphic mode.
         FOR y = 7740 + x TO x STEP -90
            FOR z = 24576 + y TO y STEP -8192
               image$ = CHR$(PEEK(z))
               PUT #1, , image$ ' Send bit-image graphics to printer.
            NEXT z
         NEXT y
         PUT #1, , linefeed$   ' Send a linefeed to the printer.
      NEXT x

      ResetPrn$ = CHR$(27) + "@"
      PUT #1, , ResetPrn$    ' Reset the printer to default settings.
      CLOSE #1

   END SUB
				

Printing EGA or VGA Screen Modes 7 Through 12

Because EGA and VGA memory are stored in contiguous blocks per "plane," printing the screen to a printer can be a fairly simple operation. The method used in the program below prints the image sideways, which avoids the need to do any bit-shifting and uses a simple two-dots-per-pixel shading pattern to represent different colors.

To produce different patterns for different colors, each color plane must be analyzed. In SCREEN modes with four video planes (7, 8, 9, and 12), each of the four different base EGA/VGA colors -- blue, green, red, and intensity -- is represented in a separate memory bank or plane of EGA/VGA memory. Each bit in a color plane represents a pixel on the screen; thus, each pixel on the screen has a color attribute depicted by four bits, one in each color plane.

Each plane is addressed for reading/writing by selecting the bank of memory to access with an OUT instruction. This program logically OR's the blue and red planes together and does the same with the green and intensity planes. This effectively reduces the number of pattern (color) combinations from 16 to 4. Therefore, some colors that appear to be different on the screen have the same appearance on paper.

SCREEN modes 10 and 11 are almost identical, except that there are only two color planes; thus, each pixel on the screen has a color attribute depicted by two bits, one in each of the two color planes. Because there are only two bits per pixel and two pins are being fired, no OR'ing of the color planes needs to be done.

The Epson printer can fire up to eight pins per graphics byte sent. Thus, moving from left to right, a loop that reads screen data from the bottom of the screen upward can access eight vertical columns at a time. This behavior coincides with the printer firing eight pins at a time and creates eight horizontal columns on the page, turning the printout sideways.

Example

   ' To try this example in VBDOS.EXE:
   ' 1. From the File menu, choose New Project.
   ' 2. Copy the code example to the Code window.
   ' 3. Press F5 to run the program.

   DECLARE SUB ScreenParams (scrn%, ScreenWidth%, ScreenLength%, NP%)
   DECLARE SUB DRAWPIC (scrn%)
   DECLARE SUB VGAtoEpson (scrn%, f$, flip%, border%)
   ' Demonstrates the use of VGAtoEpson, a subprogram that dumps
   ' a SCREEN 7, 8, 9, 10, 11 or 12 image to an Epson printer.

   CLS : scrn% = 0
   WHILE (scrn% < 7) OR (scrn% > 12)

      INPUT "Enter Screen Mode: (7, 8, 9, 10, 11 or 12)"; scrn%

   WEND

   SCREEN scrn% : CALL DRAWPIC(scrn%)      ' Draw the picture.
   CALL VGAtoEpson(scrn%, "LPT1", 0, 255)  ' Do the VGA screen print.
   END

   SUB DRAWPIC (scrn%)     ' Draw the picture on the screen.
     CALL ScreenParams(scrn%, ScreenWidth%, ScreenLength%, NumPlanes%)
     IF NumPlanes% = 2 THEN ci% = 0 ELSE ci% = 1  ' Color increment.
     xmax% = ScreenWidth% : ymax% = ScreenLength%
     halfx% = xmax% / 2 : halfy% = ymax% / 2
     x% = halfx% : c% = 1
      FOR y% = ymax% TO halfy% STEP -5
         deltax% = xmax% - x% : deltay% = ymax% - y%
         LINE (halfx%, y%)-(x%, halfy%), c%
         LINE (x%, ymax%)-(xmax%, y%), c% + ci%
         LINE (halfx%, deltay%)-(x%, halfy%), c% + 2 * ci%
         LINE (x%, 0)-(xmax%, deltay%), c% + 3 * ci%
         LINE (halfx% + 1, y%)-(deltax%, halfy%), c% + 4 * ci%
         LINE (deltax%, ymax%)-(0, y%), c% + 5 * ci%
         LINE (halfx%, deltay%)-(deltax%, halfy% + 1), c% + 6 * ci%
         LINE (deltax%, 0)-(0, deltay%), c% + 7 * ci%
         x% = x% + (((xmax% + 1) / (ymax% + 1)) * 5)
      NEXT y%
   END SUB

   SUB ScreenParams (scrn%, ScreenWidth%, ScreenLength%, NumPlanes%)
     ' Return the screen dimensions in pixels
     ' and the number of planes.
     NumPlanes% = 4          ' Set default values for SCREEN 12.
     ScreenWidth% = 640 : ScreenLength% = 480
     SELECT CASE scrn%       ' Change values for other SCREEN modes.
        CASE 7
           ScreenWidth% = 320 : ScreenLength% = 200
        CASE 8
           ScreenLength% = 200
        CASE 9
           ScreenLength% = 350
        CASE 10
           NumPlanes% = 2 : ScreenLength% = 350
        CASE 11
           NumPlanes% = 2
     END SELECT
   END SUB

   SUB VGAtoEpson (scrn%, fileN$, flip%, border%) STATIC
   ' Sends the image on SCREEN 7, 8, 9, 10, 11 or 12
   ' to an Epson printer.
   ' Parameters:
   '    scrn%   - SCREEN video mode of screen to print (7 through 12).
   '    fileN$  - Name of file or device to send image to.
   '    flip%   - Invert flag (0 = normal, not 0 = invert).
   '    border% - Character to use for border drawing on screens 9
   '              and 10 (0 = none, 255 = solid, etc.)
     OPEN fileN$ FOR BINARY AS 1            ' Open the output file.
     WIDTH #1, 255
     esc$ = CHR$(27) : crlf$ = CHR$(13) + CHR$(10)
     line$ = esc$ + "A" + CHR$(8) ' Set printer to 8/72 lines per inch.
     PUT #1, , line$
     CALL ScreenParams(scrn%, ScreenWidth%, ScreenLength%, NumPlanes%)

     IF ScreenLength% < 480 THEN           ' Figure how many bytes to
        numbyte% = ScreenLength% * 2 + 16  ' send to the printer for
        maxy% = ScreenLength% - 1          ' one line of graphics.
     ELSE
        numbyte% = 960 : maxy% = 479
     END IF

     DEF SEG = &HA000             ' Start of EGA/VGA screen memory.
     BorderOffset% = (960 - numbyte%) / (2 * 8)
     IF ScreenLength% < 480 THEN
        ' Print top line for border on screens where border will fit.
        line$ = SPACE$(BorderOffset%)         ' (For margin).
        PUT #1, , line$
        line$ = esc$ + "L" + MKI$(numbyte%)
        line$ = line$ + STRING$(numbyte%, border%) + crlf$
        PUT #1, , line$
     END IF

     ' This loop is the horizontal byte location.
     colend% = (ScreenWidth% / 8) - 1
     FOR col% = 0 TO colend%
       ' Set the printer up to receive 716 or 960 bytes
       ' of graphics data.
       IF ScreenLength% < 480 THEN
          line$ = SPACE$(BorderOffset%)
          PUT #1, , line$  ' (For border).
       END IF

       line$ = esc$ + "L" + MKI$(numbyte%)  ' (For init).
       PUT #1, , line$
       IF ScreenLength% < 480 THEN
          line$ = STRING$(8, border%)
          PUT #1, , line$    ' (For border).
       END IF

       '--- This loop is the vertical byte position.
       FOR row% = maxy% TO 0 STEP -1
         ' For 4 plane screens (7, 8, 9 and 12) logically OR the blue
         ' plane with the red plane, send that byte, then OR the green
         ' plane with the intensity plane and send that byte.

         ' For screens 10 and 11, the video planes are sent directly
         ' to the printer.
         FOR plane% = 0 TO 1                ' Plane (* 2) set.
           OUT &H3CE, 4 : OUT &H3CF, plane%
           place& = row%                   ' Figure out screen memory
           place& = place& * (colend% + 1) ' location to read - use
           place& = place& + col%          ' a long to avoid overflow.
           mem% = PEEK(place&)

           IF NumPlanes% = 4 THEN ' OR color planes together.
              OUT &H3CE, 4 : OUT &H3CF, plane% + 2
              mem% = mem% OR PEEK(place&)
           END IF

           '--- Flip the byte if need be (inverses printed picture).
           IF flip% <> 0 THEN mem% = 255 - mem%
           line$ = CHR$(mem%) : PUT #1, , line$
         NEXT plane%
       NEXT row%

       line$ = crlf$    ' Default for no border.
       IF ScreenLength% < 480 THEN
          line$ = STRING$(8, border%) + crlf$   ' Righthand border.
       END IF
       PUT #1, , line$
     NEXT col%

     IF ScreenLength% < 480 THEN   '--- Print bottom line for border.
        line$ = SPACE$(BorderOffset%)     ' (For margin).
        PUT #1, , line$
        line$ = esc$ + "L" + MKI$(numbyte%)
        line$ = line$ + STRING$(numbyte%, border%) + crlf$
        PUT #1, , line$
     END IF
     ResetPrn$ = esc$ + "@"
     PUT #1, , ResetPrn$                 ' Reset printer.
     line$ = CHR$(12) : PUT #1, , line$  ' Send formfeed (page eject).
     CLOSE 1                             ' All done.

   END SUB
				

Printing VGA Screen Mode 13

Printing SCREEN mode 13 can also be fairly simple. The method used in the program below prints the image sideways, which avoids the need to do any bit-shifting and uses a simple eight-dots-per-pixel shading pattern to represent different colors.

To produce different patterns for different colors, each byte of pixel information must be analyzed. In SCREEN 13, each pixel is represented by 1 contiguous byte of information, thus allowing 256 colors per pixel. Since 8 printer pins are fired for each pixel, a direct mapping of the pixel byte to the printer pins to be fired is done.

As stated before, 8 pins are fired for each pixel; the pins are fired in a 2 by 4 pattern. Since this is not square, some slight image distortion does occur.

The Epson printer can fire up to eight pins per graphics byte sent. Thus, moving from left to right, a loop that reads screen data from the bottom of the screen upward can access eight vertical columns at a time. This behavior coincides with the printer firing eight pins at a time and creates eight horizontal columns on the page, turning the printout sideways.

Example

   ' To try this example in VBDOS.EXE:
   '
   ' 1. From the File menu, choose New Project.
   ' 2. Copy the code example to the Code window.
   ' 3. Press F5 to run the program.
   '
   ' To run this example in the programming environment, you must
   ' invoke the environment with the /L switch to load the default
   ' Quick library. For example, with Microsoft Visual Basic for
   ' MS-DOS, version 1.0 use:
   '
   ' VBDOS.EXE /L
   '
   DECLARE SUB VGAtoEpson (f$, flip%)

   '--- VGAEPSON.BAS
   '--- Demonstrates the use of VGAtoEpson, a subprogram that
   '--- dumps a SCREEN 13 image to an Epson printer.
   '--- Copyright (c) 1988 Microsoft Corp.

   ' Use the following include file for Visual Basic for MS-DOS,
   ' version 1.0:
   '
   REM $INCLUDE: 'VBDOS.BI'
   '
   ' With QuickBasic for MS-DOS, version 4.x, use the include
   ' file 'QB.BI'
   '
   ' With Basic PDS for MS-DOS, version 7.x, use the include
   ' file 'QBX.BI'

   DIM SHARED inregs AS regtype
   DIM SHARED outregs AS regtype

   SCREEN 13
   '--- Draw the picture on the screen.
   xmax% = 319
   ymax% = 199
   halfx% = xmax% / 2
   halfy% = ymax% / 2
   x% = halfx%
   c% = 1
   FOR y% = ymax% TO halfy% STEP -2

     LINE (halfx%, y%)-(x%, halfy%), c%
     LINE (x%, ymax%)-(xmax%, y%), c% + 20
     LINE (halfx%, (ymax% - y%))-(x%, halfy%), c% + 40
     LINE (x%, 0)-(xmax%, (ymax% - y%)), c% + 60
     LINE (halfx% + 1, y%)-((xmax% - x%), halfy%), c% + 80
     LINE ((xmax% - x%), ymax%)-(0, y%), c% + 100
     LINE (halfx%, (ymax% - y%))-((xmax% - x%), halfy% + 1), c% + 120
     LINE ((xmax% - x%), 0)-(0, (ymax% - y%)), c% + 140
     x% = x% + (((xmax% + 1) / (ymax% + 1)) * 5)
     c% = c% + 1
   NEXT y%
   CALL VGAtoEpson("LPT1", 1)
   SCREEN 0
   END

   SUB VGAtoEpson (f$, flip%) STATIC
   '--- Sends the image on SCREEN 13 to an Epson graphics printer.
   '--- Parameters:
   '         f$    -   Name of file or device to send image to.
   '         flip% -   Invert flag (0 = normal, not 0 = invert).

     OPEN f$ FOR BINARY AS 1         ' Open the output file.
     WIDTH #1, 255
     esc$ = CHR$(27)
     line$ = esc$ + "A" + CHR$(8)
     PUT #1, , line$     ' Set printer to 8/72 lines per inch.
     DEF SEG = &HA000    ' Start of VGA screen memory.
     '--- This loop is the horizontal byte location.
     FOR Col% = 0 TO 79
        '--- Set the printer to receive 800 bytes of graphics data.
        line$ = esc$ + "L" + MKI$(800)
        PUT #1, , line$  ' (For init).

        '--- This loop is the vertical byte position.
        FOR row% = 199 TO 0 STEP -1

           place& = row% * 320&;
           place& = place& + Col% * 4
           ' 4 bytes of pixel information are read in. Each
           ' of these bytes is broken up across 4 variables
           ' that are used to fire the printer pins. 2 bits
           ' from each pixel byte are stored to each of the
           ' variables.
           mem1% = 0           ' Initialize storage bytes for
           mem2% = 0           ' color information.
           mem3% = 0
           mem4% = 0
           FOR byte% = 0 TO 3
              newplace& = place& + byte%
              shift% = 2 ^ ((7 - 2 * byte%) - 1)
              mem% = PEEK(newplace&)
              mem% = mem% AND 3
              mem% = mem% * shift%
              mem1% = mem1% OR mem%

              mem% = PEEK(newplace&)
              mem% = (mem% AND 12) / 4
              mem% = mem% * shift%
              mem2% = mem2% OR mem%

              mem% = PEEK(newplace&)
              mem% = (mem% AND 48) / 16
              mem% = mem% * shift%
              mem3% = mem3% OR mem%

              mem% = PEEK(newplace&)
              mem% = (mem% AND 192) / 64
              mem% = mem% * shift%
              mem4% = mem4% OR mem%
           NEXT

           '--- Flip the byte, if called from.
           IF flip% <> 0 THEN
              mem1% = 255 - mem1%
              mem2% = 255 - mem2%
              mem3% = 255 - mem3%
              mem4% = 255 - mem4%
           END IF

           '--- Send bytes to device.
           line$ = CHR$(mem1%) + CHR$(mem2%)

           line$ = line$ + CHR$(mem3%) + CHR$(mem4%)
           PUT #1, , line$
        NEXT
        line$ = CHR$(13) + CHR$(10)
        PUT #1, , line$
     NEXT
     ResetPrn$ = esc$ + "@"
     PUT #1, , ResetPrn$  ' Reset printer.
     line$ = CHR$(12)
     PUT #1, , line$      ' Send formfeed (page eject).
     CLOSE 1              ' All done.

   END SUB
				

REFERENCES

This article is part of a collection of articles explaining how to print Basic video screens to Epson printers. Find the entire collection by querying in the Microsoft Knowledge Base using the following words:

Epson and print and screen and QuickBasic

If you want further information, please refer to the following book, which is available in bookstores or by calling Microsoft Press at (800) 888-3303 or (425) 882-8661:

"Programmer's Guide to PC and PS/2 Video Systems," by Richard Wilton (published by Microsoft Press, 1987)


Modification Type:MinorLast Reviewed:8/16/2005
Keywords:KB57354 kbAudDeveloper