Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

VGA - direct memory access question

129 views
Skip to first unread message

Kirk Hanawalt

unread,
Feb 8, 1990, 9:17:05 AM2/8/90
to

I'm trying to write a program (TurboC 2.0, IBM PS/2 Model 50
with VGA adapter, HP LaserJet II) to dump a bitmap image of the
high resolution VGA screen to a LaserJet printer. Using the
TurboC getpixel function, the 640x480 graphics screen can be
dumped in about 35 seconds. I would like to access memory
directly, and dispense with getpixel() altogether.
Unfortunately, I can't figure out how the pixels are mapped in
memory.

Starting at address A000:0000, each byte in memory seems to
indicate the on/off state of 8 pixels on the screen. For
example, the statement:

*((unsigned char far *) 0xa0000000L) = 0x80;

turns the first pixel in the first row of the graphics screen
on. I can use this method to get monochrome graphics.
Obviously, 16 color graphics requires 4 bits to specify pixel
color.

The problem is this: when using this method to read pixels
from the screen, I only get the odd color pixels (for the
default EGA/VGA palette 1=blue, 3=cyan,...,15=white). The even
color pixels do not have a bit set. The following pseudo-code
works only for odd colors, the even colors aren't printed.

ptr=(unsigned char huge *) 0xa0000000L;
for (j=0; j<=MaxY; j++)
for (i=0; i < (MaxX+1)/8; i++)
Send_To_Printer(*ptr++); /* send byte = 8 pixels */

This method dumps the screen to the LaserJet in about 15
seconds, so I would like to use it. However, getting only
half of the displayed colors printed is a drawback :-).

My question is this: where in the heck are the pixel values
stored in memory for the VGA adapter in 640x480 16 color mode?
Every book I've seen covers only monochrome graphics and uses
the method above to write/read pixels.
-------
Kirk Hanawalt | |
Chem. Eng. Dept. | BITNET: IAP @ PSUVM |
Penn. St. Univ. | OTHER: ...!psuvax1!i...@psuvm.bitnet |

D Spinellis

unread,
Feb 9, 1990, 7:03:57 AM2/9/90
to
In article <90039.0...@PSUVM.BITNET> I...@psuvm.psu.edu (Kirk Hanawalt) writes:
>
> I'm trying to write a program (TurboC 2.0, IBM PS/2 Model 50
>with VGA adapter, HP LaserJet II) to dump a bitmap image of the
>high resolution VGA screen to a LaserJet printer.
[...]

>Unfortunately, I can't figure out how the pixels are mapped in
>memory.
[...]
The EGA and VGA cards have all the color planes mapped into the same
memory address. You specify from which color plane you want to read
or write by outputing appropriate values to the various card controller
registers. Different read and write modes give you the ability to access
the planes together; naturally with some restrictions. For example you can
write a color value to a specified pixel, or you can set all color planes
to the same value. The Technical Reference Manual for the PS/2 systems
covers these things.

> The problem is this: when using this method to read pixels
>from the screen, I only get the odd color pixels

>The following pseudo-code
>works only for odd colors, the even colors aren't printed.
>
> ptr=(unsigned char huge *) 0xa0000000L;
> for (j=0; j<=MaxY; j++)
> for (i=0; i < (MaxX+1)/8; i++)
> Send_To_Printer(*ptr++); /* send byte = 8 pixels */
>

[...]
You need to modify your code to access the four color planes. Register 4
in address 0x3cf can be set to specify which plane you want to read. You
must set the index register in address 0x3ce to 4 to point to the correct
register. The following code should work:

outp(0x3c4, 4); /* Set index register */


ptr=(unsigned char huge *) 0xa0000000L;
for (j=0; j<=MaxY; j++)

for (i=0; i < (MaxX+1)/8; i++, ptr++)
for (k = 0; k < 4; k++) {
outp(0x3cf, k); /* Specify color plane */
Send_To_Printer(*ptr, k); /* send byte = 8 pixels */
}

Diomidis
--
Diomidis Spinellis Internet: d...@cc.ic.ac.uk
Department of Computing BITNET: d...@cc.ic.ac.uk
Imperial College UUCP: ...!cernvax!cc.imperial.ac.uk!dds
London SW7 2BZ JANET: d...@uk.ac.ic.cc

Bill Ives

unread,
Feb 9, 1990, 10:42:44 AM2/9/90
to
>/ hpctdls:comp.sys.ibm.pc / I...@psuvm.psu.edu (Kirk Hanawalt) / 7:17 am Feb 8, 1990 /

> I'm trying to write a program (TurboC 2.0, IBM PS/2 Model 50
>with VGA adapter, HP LaserJet II) to dump a bitmap image of the
>high resolution VGA screen to a LaserJet printer. Using the
>TurboC getpixel function, the 640x480 graphics screen can be
>dumped in about 35 seconds. I would like to access memory
>directly, and dispense with getpixel() altogether.
>Unfortunately, I can't figure out how the pixels are mapped in
>memory.

> Starting at address A000:0000, each byte in memory seems to
>indicate the on/off state of 8 pixels on the screen. For
>example, the statement:

> *((unsigned char far *) 0xa0000000L) = 0x80;

>turns the first pixel in the first row of the graphics screen
>on. I can use this method to get monochrome graphics.
>Obviously, 16 color graphics requires 4 bits to specify pixel
>color.

>Kirk Hanawalt | |


>Chem. Eng. Dept. | BITNET: IAP @ PSUVM |

>jPenn. St. Univ. | OTHER: ...!psuvax1!i...@psuvm.bitnet |


You are correct -- you cannot directly access the entire screen
the way you are currently. The EGA and VGA ( in color graphics
modes ) screen is made up of bit planes. Thus in 640 by 480 16 color
graphics -- there are 4 bit planes. Your technique reads only the
currently active bit plane -- probably plane 0 .

Now, there are two techniques to actually read the screen memory.

1) use BIOS read pixel function -- this will work but is probably
not the most optimal.
2) talk directly to the video hardware -- this is faster but
requires more work. Thus you should really get a good
EGA/VGA h/w reference book for all the details. For now, I
will try to give an outline for what you have to do to
read the entire screen ( since I have also written a graphics
dump program for the Laserjet/PaintJet/ThinkJet series as you
are now trying to do)
First some terminology - since there are 4 bit planes
there has to be a way of selecting which bit plane is
currently active. The graphics controller register
Read Map Select Register (Index 4) does this function.

Thus the graphics controller index register is at port 3ceh
and the Read Map Select Register is selected to be at port
3cfh by writing 4 to the graphics controller index reg:

mov dx, 3ceh ; set DX to GC index register
mov al,4 ;
out dx,al ; select register index 4 -- the Read Map Select Register

mov al,3 ; let's select bit plane 3
inc dx
out dx,al

Selecting the bit plane is not all that has to be done to
read the pixels from a particular bit plane. You must also
use the Bit Mask Register. This tells the adaptor which bits
in a particular byte you are interested in. For reading the
entire screen, you want to read all the bits for each byte.

mov dx,3ceh ; set DX to GC index register
mov al,8 ; Bit Mask Register is at index 8
out dx,al ; select bit mask register
mov al,0ffh ; set bit mask to all 1's .
inc dx
out dx,al

Now, you also have to make sure you are in read mode 0 for this
to work. SInce this is the default for BIOS don't worry about
it until you get to more advanced functions. Now to read
an entire bit plane from bit plane 3 to ES:DI you would loop
640 * 480 /8 bytes or 38400 times.

cld
mov ax,0a000 ; set ds:si to bit plane start
mov ds,ax
mov si,0
mov dx,3ceh
mov ax,08ffh ; set bit mask reg to all 1's
out dx,ax
mov ax,0403h ; select bit plane 3
out dx,ax
mov cx,38400 ; set loop count.
rep movsb

I hope this helps. I did the algorithm above from memory so
there may be minor mistakes - hey no one's perfect. But the
algorithm is essentially correct in how to read screen memory.

Bill Ives
HP CTD
#include <standard disclaimer here>

Larry Jones

unread,
Feb 9, 1990, 5:14:13 PM2/9/90
to
In article <90039.0...@PSUVM.BITNET>, I...@psuvm.psu.edu (Kirk Hanawalt) writes:
> I'm trying to write a program (TurboC 2.0, IBM PS/2 Model 50
> with VGA adapter, HP LaserJet II) to dump a bitmap image of the
> high resolution VGA screen to a LaserJet printer. Using the
> TurboC getpixel function, the 640x480 graphics screen can be
> dumped in about 35 seconds. I would like to access memory
> directly, and dispense with getpixel() altogether.
> Unfortunately, I can't figure out how the pixels are mapped in
> memory.

Both the EGA and VGA need more memory than there is room for in
the reserved address space. To get around the problem, they have
a number of different mapping schemes which allow access to some
of the bits at a time. Precisely which bits and where in memory
they are depends on the particular mapping scheme which has been
invoked. I suggest you get a good book such as Programmer's
Guide to PC and PS/2 Video Systems (Microsoft Press, if I
remember correctly) and study it. The mapping schemes are
incredibly complex.
----
Larry Jones UUCP: uunet!sdrc!scjones
SDRC scj...@SDRC.UU.NET
2000 Eastman Dr. BIX: ltl
Milford, OH 45150-2789 AT&T: (513) 576-2070
"You know how Einstein got bad grades as a kid? Well MINE are even WORSE!"
-Calvin

Lon Anderson

unread,
Feb 12, 1990, 12:06:55 PM2/12/90
to

The VGA adapter uses a concept knows as memory planes. These memory
planes map th the same location in memory and hold the "other" bits
associated with a pixel in the color modes. You need to toggle the
planes on and off to read the individual bits that make up the 4 bits
of the pixel. This is done by manipulating the VGA registers.

The code to do this is available in a number of books on VGA
programming. Two I would recomend are Programmers guide to the EGA
and VGA and Programming the VGA adapter by Brady. These are available
at most good computer book stores.

Greg Richter (2XS)

unread,
Feb 13, 1990, 1:41:54 PM2/13/90
to
I recommend you take a look at "Programmer's Guide to the EGA/VGA" it
explains these matters clearly, and in sufficient detail to be useful.

At most bookstores, about 15 bucks.

-GR

USENET News System

unread,
Feb 26, 1990, 7:36:25 AM2/26/90
to
From: fli...@dtrc.dt.navy.mil (Flitter)
Path: dtrc!flitter

> My question is this: where in the heck are the pixel values
>stored in memory for the VGA adapter in 640x480 16 color mode?
>Every book I've seen covers only monochrome graphics and uses
>the method above to write/read pixels.

In 16 color mode there are four bit planes each of which are mapped into the
same address space: A0000 - AFFFF. In order to get the value of a pixel you
have to use the segment registers so you get all four bit planes. You will
want to AND them together to find whether the monochrome pixel is on or off.
I don't remember the proper settings off the top of my head. If you still
need them write me a message and I'll look it up.

0 new messages