From: jmunkki@vipunen.hut.fi (Juri Munkki)
Subject: Re: Direct screen writing; getting to (x,y)
Reply-To: jmunkki@vipunen.hut.fi (Juri Munkki)
Organization: Helsinki University of Technology
Date: Tue, 12 Jan 1993 02:13:20 GMT

In article <1993Jan11.235448.22675@afterlife.ncsc.mil> mssmith@afterlife.ncsc.mil (M. Scott Smith) writes:
>void PlotPoint(long x, long y, long color)
>{
>  if (SCR_X == 640)
>    *(char *)(base_addr + x + ((y << 7) + (y << 9))) = color;
>  else if (SCR_X == 512)
>    *(char *)(base_addr + x + (y << 9)) = color;
>  else if (SCR_X == 1024)
>    *(char *)(base_addr + x + (y << 10)) = color;
>  else
>    *(char *)(base_addr + x + (row_bytes * y)) = color;
>}
>
>   Actually, x- and y- should be integers, or can be, or whatever.  base_addr
>is the base address of the video memory.  (Corresponds to (0,0) in all cases,
>I hope!)  row_bytes is the number of bytes in each row on the monitor.
>Color is just some hexadecimal value.

>   And SCR_X is the width of the monitor, in pixels.

It looks like you are hard-coding for 8 bit deep displays. That's of
course up to you, if you want to limit yourself to a certain bit depth.

If SCR_X is indeed the width of the display, you will run into trouble
with most Macintosh video cards. If it's the same as row_bytes, then
things should be almost ok.

If a screen is 640 pixels wide, it doesn't mean that the next row starts
640 bytes after the first one. Most video cards leave some unused bytes
to the right of the screen and use a rowBytes field of 1024.

>   For speed's sake, I'm doing some tricks with the left shifts.  If the
>width of the monitor is a nice multiple of 2 (say 640, 512, or 1024), then
>I perform left shifts to take care of the (y * row_bytes) part.  If all
>else fails, I multiply the long way.

A multiply isn't all that slow, unless you are running on the 68000 (which
isn't the case, since you are assuming 8 bits per pixel). I think you are
wasting a lot of time with those ifs.

>   Anyway, this code seems to work.  I'd like a few suggestions on better ways
>of doing this.  Do I have the right idea, or did I miss the boat completely?

Of course, it doesn't really work. It only works on some hardware, but
it will cause big problems with a lot of machines.

As I said earlier, the keys to compatibly do direct video writes are:

	SwapMMUMode
and	ShieldCursor

The first one will make you compatible with any video cards that are only
visible with 32-bit addressing on (the new PowerBooks are an example of this
and any video card with more than 1MB of VRAM is another example).

The second one makes you compatible with all sorts of kludges. I seem
to remember that something called "Soft Pivot" requires this and most
SCSI-video interfaces probably also work by watching calls to ShieldCursor
and ShowCursor.

>   One thing I plan on trying is to create an array of rowbyte values for
>every y- position on the monitor, at the initialization part of the program.

This works as long as no one changes the screen resolution suddenly. It
usually doesn't happen, but I think it's possible under some circumstances.

>But, on second thought, C is really doing
>multiplication anytime you access a subscript of an array, right?

Not really, if the element size is a multiple of 2. The 68020 has addressing
modes that internally do the multiplication and in any case you can do it
with a shift.

-- 
  Juri Munkki					       Windsurf: fast sailing
 jmunkki@hut.fi					      Macintosh: fast software
Newsgroups: comp.sys.mac.programmer