[comp.unix.xenix] EGA Bitmaps on Xenix

jfh@rpp386.cactus.org (John F. Haugh II) (03/13/90)

I wrote a TPLOT -> Hercules converter some time ago, and now that I have
entered the 1980's and purchased a used EGA board and display [ Yes, I am
somewhat behind the times ... ], I am interested in writing a TPLOT ->
EGA converter.

What I would like very much is a collection of algorithms for converting
a random (x, y) coordinate in (r, g, b) color into an actual point on the
screen.  The goal is to use this code as the lowest level routine ala
point() from the tplot library.  I am graphics adapter illiterate, but a
good explanation of the mapping and general scheme of the EGA adapter in
some reasonable mode should suffice.  The results of this project will be
posted to some newsgroup.  Possibly along with the latest incarnation of
the Hercules TPLOT filter, which works nicely with GNUPLOT when I use
both monitors ;-)

In the meantime, if anyone can point me at a GIF viewer for SCO 2.2.3,
I'd be happy.  I've discovered the joy of 30 hour ray tracings and I'd
like to see what they look like, in color rather than the lousey mono
hack job I've been playing with [ Yuck! ].
-- 
John F. Haugh II                             UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 832-8832                           Domain: jfh@rpp386.cactus.org

chip@chinacat.Lonestar.ORG (Chip Rosenthal) (03/14/90)

jfh@rpp386.cactus.org (John F. Haugh II) writes:
>I wrote a TPLOT -> Hercules converter some time ago, and now that I have
>entered the 1980's and purchased a used EGA board and display [ Yes, I am
>somewhat behind the times ... ], I am interested in writing a TPLOT ->
>EGA converter.

This gets nasty when you get above CGA resolution.  CGA and below it's
real easy - you just do an ioctl to get a shared memory segment located
at the video memory, and twiddle bits from there.  A little magic goes
into encoding the memory bit positions into color plane and pixel location,
but no real big deal.

I severly hacked on the glplot program posted to comp.sources.misc a while
back.  I ported the CGA stuff to XENIX and added EGA capabilities.  The
code which did the CGA pixel write looks something like:

    /*
     * Lookup tables to convert pixel number to byte position.  Uses
     * 2 bits/pixel, first pixel is most significant 2 bits.
     */
    static int pix2byte[] =  { 0xC0, 0x30, 0x0C, 0x03 };

    /*
     * Lookup tables to convert color number to bit pattern - 2 bits/pixel.
     */
    static int color2byte[] = { 0x00, 0x55, 0xAA, 0xFF, };

    row = ( y >> 1 );
    col = ( x >> 2 );
    mask = ( color2byte[GL_color&03] & pix2byte[x&03] );
    if ( y & 01 )
	video_memory_page2[row][col] |= mask;
    else
	video_memory_page1[row][col] |= mask;
    break;

However, at EGA and higher resolutions it gets ugly.  The memory segment
is no longer a direct map of the video screen.  Instead you need to take
three steps.  First, you write to the video controller to set the color
planes you want to write.  Second, you write to the video controller to
say which pixel(s) within a group of eight to write.  Finally, you do a
dummy write to the shared memory region to place the octet of pixels you
are writing.

Here is the ugliness I used to write EGA memory:

    #include <sys/machdep.h>
    #define GDR_SEL		0x3CE	/* graphics data registers - select   */
    #define GDR_DATA		0x3CF	/* graphics data register - data      */
    #define GDR_BIT_MASK	8	/*  bit mask			      */
    static struct port_io_struct io_mask_ctrl[4] = {
	{ OUT_ON_PORT,	GDR_SEL,	GDR_BIT_MASK	},
	{ OUT_ON_PORT,	GDR_DATA,	0x00 		},
	{ IN_ON_PORT,	0,		0		},
	{ IN_ON_PORT,	0,		0		},
    };

    /*
     * Lookup tables to convert pixel number to byte position.  Uses
     * 1 bit/pixel, first pixel is most significant bit.
     */
    static int pix1byte[] =  { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };

    row = ( y );
    col = ( x >> 3 );
    mask = pix1byte[ x & 07 ];
    io_mask_ctrl[1].data = mask;
    (void) ioctl(0,CONSIO,io_mask_ctrl);
    video_memory[row][col] |= 0xFF;

Note that this is assuming that your color is already set, so it is only
doing the last two steps:  writing the video controller to select the
pixel within the group of eight, and then a dummy memory write to place
the octet.

Here lies the problem:  you are doing a system trap *per pixel*!  I got
gnuplot running with this stuff, but it was a real pig.  To improve things
a bit, I played some games caching up the pixels within an octet, and
doing a write only when you moved to a different octet.  This helped, and
it made drawing sine curves very dramatic.  With high dy/dx (e.g.  around
y = 0) it drew very slow, but at low dy/dx (at the tops & bottoms) it
would move at a nice clip because you'd hit lots of groups of adjacent
pixels.  Never the less, the performance was still suboptimal.

>What I would like very much is a collection of algorithms for converting
>a random (x, y) coordinate in (r, g, b) color into an actual point on the
>screen.  The goal is to use this code as the lowest level routine ala
>point() from the tplot library.  I am graphics adapter illiterate, but a
>good explanation of the mapping and general scheme of the EGA adapter in
>some reasonable mode should suffice.

I guess I'm trying to keep anybody from running down the blind alley I
did.  Direct screen control works fine at low resolutions, but the overhead
of an ioctl() per pixel makes it unusable at higher resolutions.  Were I
to do it over again (and I probably will), I would look into using the
CGI routines.  If that fails, then I think you are stuck having to write
a device driver to do console graphics output.

There was a lot of hacking and trial and error and aggravation in figuring
out the above.  The screen(HW) man page documents the necessary ioctl's
and the (struct port_io_struct), but it gives no information on the video
display architecture, most notably the video controller register set.  I
ultimately figured it out by looking through a peecee graphics book to
get the information on the video system, and figuring out the ioctl()
implementation which would replace their BIOS calls.  Unfortunately, I
do not recall the title or author of this book.

-- 
Chip Rosenthal                            |  Yes, you're a happy man and you're
chip@chinacat.Lonestar.ORG                |  a lucky man, but are you a smart
Unicom Systems Development, 512-482-8260  |  man?  -David Bromberg

ron@mlfarm.uucp (Ronald Florence) (03/14/90)

In article <18134@rpp386.cactus.org> jfh@rpp386.cactus.org (John F. Haugh II) writes:

   In the meantime, if anyone can point me at a GIF viewer for SCO 2.2.3,
   I'd be happy.  I've discovered the joy of 30 hour ray tracings and I'd
   like to see what they look like, in color rather than the lousey mono
   hack job I've been playing with [ Yuck! ].

I can't help with a GIF viewer, but I do have a hack to GNUPLOT that
drives the SCO CGI devices.  Works fine with an EGA, VGA, Laserjet,
HP7470a, or Deskjet.  If there's interest, I'll post it, although I'm
not sure I can create proper diff files at this point.  And with
GNUPLOT 2.0 coming Real Soon Now, maybe we should all wait.
--

Ronald Florence			ron@mlfarm.uu.net
				{yale,uunet}!hsi!mlfarm!ron

ron@mlfarm.uucp (Ronald Florence) (03/15/90)

This is going to make a semi-Indian-giver out of me...

I've received a number of requests for my hack of GNUPLOT to the SCO
CGI drivers.  If someone will be so kind as to send me the following
files from the original GNUPLOT distribution

	Makefile, command.c, misc.c, plot.c, plot.h, term.c

I will prepare and post a proper patch.  Thanks.
--

Ronald Florence			ron@mlfarm.uu.net
				{yale,uunet}!hsi!mlfarm!ron