[comp.sys.ibm.pc] HELP: with EGA/VGA page-to-page memory copy

tcamp@dukeac.UUCP (Ted A. Campbell) (07/27/89)

For the next version of the "Space Flight Simulator" (posted recently 
to comp.binaries.ibm.pc) I need a faster EGA/VGA memory copy routine.  
The program utilizes a form of animation in which I write to one page, 
switch it into visual memory, write to the other page, switch it in, 
and so forth.  At each switch, however, I have to update the new "active" 
page by copying the entire contents of the previous active page to it.  
Currently, I'm accomplishing this by writing the entire page out to 
a buffer in user-accessible RAM (about 128k), then writing the whole 
buffer back to the other page.  Obviously, this wastes a great deal 
of time for each screen update.  

It should be possible to copy one page to the other.  The problem is 
that in the mode I'm using (640x350 16 color on both EGA and VGA) 
the memory is divided into four planes, each of which would have to 
be copied.  Based on the best information I have had to date, I thought
that the following loop would accomplish this task:

	for ( i = 1; i < 10; i *= 2 )
		{
		outp( 0x3CE, 0x04 );		/* set read map    */
		outp( 0x3CF, i );		/* to plane 'i'    */
		outp( 0x3C4, 0x02 );		/* set write map   */
		outp( 0x3C5, i );		/* to plane 'i'    */
		memcpy( (char *) 0xa0000000,	/* copy to here    */
			(char *) 0xa8000000,	/* from here       */
			(size_t) 0x8000 );      /* this many bytes */
		}

But this doesn't work and I'm not even sure why:  some copying is being 
done, but apparently colors are getting mixed up, and eventually the 
bit patterns are lost.  

If any experienced EGA/VGA programmers out there can suggest a fast 
way to accomplish this task, I'd be very appreciative.  

Ted A. Campbell
tcamp@dukeac.ac.duke.edu

cb@sequoia.UUCP (Christopher D. Brown) (07/28/89)

In article <1495@dukeac.UUCP> tcamp@dukeac.UUCP (Ted A. Campbell) writes:
...
>	for ( i = 1; i < 10; i *= 2 )
>		{
>		outp( 0x3CE, 0x04 );		/* set read map    */
>		outp( 0x3CF, i );		/* to plane 'i'    */
>		outp( 0x3C4, 0x02 );		/* set write map   */
>		outp( 0x3C5, i );		/* to plane 'i'    */
>		memcpy( (char *) 0xa0000000,	/* copy to here    */
>			(char *) 0xa8000000,	/* from here       */
>			(size_t) 0x8000 );      /* this many bytes */
>		}
>
>But this doesn't work and I'm not even sure why:  some copying is being 
...

Close.  Try the following ...
   for ( z = 0; z < 4; ++z )
   {
      outp( 0x3CE, 0x04 );              /* set read map    */
      outp( 0x3CF, z );                 /* to plane 'i'    */
      outp( 0x3C4, 0x02 );              /* set write map   */
      outp( 0x3C5, 1 << z );            /* to plane 'i'    */
      memcpy( (char *) 0xa0000000,      /* copy to here    */
         (char *) 0xa8000000,           /* from here       */
         (size_t) 0x8000 );             /* this many bytes */
   }

chris brown
Net: cb!execu@cs.texas.edu
Voice: (512) 346-4980

everett@hpcvlx.HP.COM (Everett Kaser) (07/28/89)

When writing to EGA/VGA memory, you have to do a read first, even though you
don't use the data, then do the write.  The read latches the current video RAM
data into internal latches in the video controller, then when you do the write,
the video controller can combine the two according to the current replacement
rule.  If you don't do the read first, your write data is getting combined with
whatever garbage is in the internal latches.  Hence, I don't think you can use
memcpy.  I could be all wet, but this is what I've found in the little bit
of EGA programming I've done.

Everett Kaser                   "Your thoughts create your reality."
!hplabs!hp-pcd!everett
everett%hpcvlx@hplabs.hp.com