IAP@psuvm.psu.edu (Kirk Hanawalt) (02/08/90)
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!iap@psuvm.bitnet |
zmact61@tsun4.doc.ic.ac.uk.doc.ic.ac.uk (D Spinellis) (02/09/90)
In article <90039.091705IAP@PSUVM.BITNET> IAP@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: dds@cc.ic.ac.uk Department of Computing BITNET: dds@cc.ic.ac.uk Imperial College UUCP: ...!cernvax!cc.imperial.ac.uk!dds London SW7 2BZ JANET: dds@uk.ac.ic.cc
wei@hpctdls.HP.COM (Bill Ives) (02/09/90)
>/ hpctdls:comp.sys.ibm.pc / IAP@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!iap@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>
scjones@sdrc.UUCP (Larry Jones) (02/10/90)
In article <90039.091705IAP@PSUVM.BITNET>, IAP@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 scjones@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
lorena@infmx.UUCP (Lon Anderson) (02/13/90)
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@bluemtn.uucp (Greg Richter (2XS)) (02/14/90)
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
news@nems.dt.navy.mil (USENET News System) (02/26/90)
From: flitter@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.