KnowledgeBase Archive

An Archive of Early Microsoft KnowledgeBase Articles

View on GitHub

Q51886: How to Print Hercules Graphics SCREEN 3 to an Epson Printer

Article: Q51886
Product(s): See article
Version(s): 4.00 4.00b 4.50
Operating System(s): MS-DOS
Keyword(s): ENDUSER | appnote BQ0085 B_BasicCom | mspl13_basic
Last Modified: 18-OCT-1990

Below is an example of printing Hercules graphics SCREEN 3 to an Epson
or Epson-compatible printer.

This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
and 4.50 for MS-DOS; to Microsoft BASIC Compiler versions 6.00 and
6.00b for MS-DOS; and to Microsoft BASIC PDS (Professional Development
System) versions 7.00 and 7.10 for MS-DOS. (SCREEN 3 is supported in
MS-DOS and MS OS/2 real mode, but not in MS OS/2 protected mode.)

If you have a printer other than Epson, you must change the printer
control codes used in the program for setting line spacing and
graphics mode. You must find these control codes in your printer
manual and make the appropriate modifications to the code below.

This article is one part of the application note titled "How to Print
BASIC Video Screens to Epson Printers." A printed copy of this
application note can be obtained by calling Microsoft Product Support
Services at (206) 637-7096. This application note can also be obtained
as separate parts in this Knowledge Base by searching for the
following words:

   Epson and print and screen and QuickBASIC

If you want further information about Hercules graphics memory, please
refer to the following book, which is available from bookstores or by
calling Microsoft Press at (800) 888-3303 or (206) 882-8661:

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

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-paragraph B000 (decimal 45056), and
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).

   DECLARE SUB HerculesPrintScreen ()
   ' Before using Hercules SCREEN 3, you must run QBHERC.COM (included
   ' with QuickBASIC 4.00 or 4.00b, and BASIC compiler 6.00 or 6.00b)
   ' or MSHERC.COM (included with QuickBASIC 4.50).
   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

THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Copyright Microsoft Corporation 1986-2002.