Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!cs.utexas.edu!tut.cis.ohio-state.edu!snorkelwacker!mit-eddie!uw-beaver!Teknowledge.COM!unix!hplabs!hpfcso!hpldola!hpctdlb!hpctdls!wei From: wei@hpctdls.HP.COM (Bill Ives) Newsgroups: comp.sys.ibm.pc Subject: Re: VGA - direct memory access question Message-ID: <2010022@hpctdls.HP.COM> Date: 9 Feb 90 15:42:44 GMT References: <90039.091705IAP@PSUVM.BITNET> Organization: Hewlett-Packard CTD, Colo. Spgs. Lines: 99 >/ 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