[net.micro.amiga] Fun with 6 Bit Planes

bobp@amiga.UUCP (Robert S. Pariseau) (11/09/85)

TITLE:  Fun With 6 Bit Planes (SOURCE)

There are lots of fun things you can do in 6 bit planes on the Amiga,
including Hold and Modify color displays and dual-playfield mode
with two separately scroll-able, completely independent, 8 color
playfields with overlay and transparency.

But tonight I'm going to discuss something you don't already know about
your Amiga -- even if you've read all the tech manuals cover to cover.

The specs for the Amiga say that in a completely static, low-resolution
display, with nothing fancy going on (like Hold and Modify), you can
display up to 32 colors simultaneously out of a pallette of 4096.

Well not quite.

You can actually display up to 64 distinct colors out of that pallette
of 4096!  Yes, an unlimited choice of any of 64 colors at each pixel
in the screen!

Have I got your attention?

Welcome to Extra-Half-Brite mode.

The Amiga display hardware automatically enters Extra-Half-Brite mode
whenever you select a 6 plane display (which must be low res due to
the hardware) and have NOT selected either Hold and Modify or Dual
Playfield mode.

The graphics kernel software further enforces the rule that you must
set the EXTRA_HALFBRITE flag in the ViewModes for the ViewPort (Screen
in Intution lingo) or it will automatically trim your screen down to
5 planes.  This is done both for backward compatability and to insure
support in future Amiga architectures.

Consider the playfield data bits for a given pixel.  The bits from the
first five planes form a color register selector for that pixel,
allowing you to choose among the 32 color registers in the Amiga.  The
bit from the sixth plane is interpreted as follows:
  0 -- Use the color in the selected color register just as specified.

  1 -- Take the color in the selected color register, shift each of
       its R, G, and B components right one bit, and use the new
       color value thus formed.

The net result is as if you had 64 color registers where the colors
in the top 32 were "half-intensity" counterparts of the colors in the
bottom 32!

Of course, that means there is a dependency between the choice of
colors in the 32 real registers and the resulting colors in the
32 psuedo-registers.  Nevertheless, I assert we have as much right
to claim 64 colors on screen as IBM has to claim 16 colors from a
monitor that is physically capable of producing only 8 colors at
2 intensities!  At least we can select our 32 colors out of a
pallatte of 4096!

Note also that, since fractional color components have no meaning
in the hardware, there are several distinct real colors that produce
the same extra color.  For instance (in hex):
  888 --> 444,    988 --> 444,   898 --> 444,   999 --> 444,  etc.

Despite all this quibbling, with a little thought it's easy to see
how you can choose a set of 32 real colors to make sure all 64 real
plus extra colors are distinct.  And they are every-pixel-addressable!

Why have we kept this little jewel a secret?  No, it's not that we
were planning to lull the competition into complacency and then
spring an instant double of the Amiga's color capacity on them.

Actually, the rev of the custom chips in which this worked was the
last rev before we went into production.  Thus the info was too
late to make it into the current version of the Amiga Hardware
Manual.

Some caveats.  Although ALL the consumer machines have the necessary
chip rev, there are some older developer's machines out there which
can't do this trick.  BEWARE!  Some of the store demo units come out
of that older developer's stock and won't contain the Extra-Half-Brite
hardware.  Note that you can't hurt anything by running such a program
on an older machine -- the values in the 6th bit plane will simply
be ignored.

Also the V1.0 printer device will not correctly handle this trick
for color printing -- it works fine in V1.1.

The sample program below shows Extra-Half-Brite mode in operation.

-------------------------Program Notes

The Extra program will compile and link cleanly using the native
Amiga Lattice C tools on the standard V1.0 C disk.  The Make
script in the examples directory will do all the work for you.

I suggest you copy your source file into ram disk, cd over to your
C development disk, and type
  1> execute Make ram:Extra    [assumes you are where Make is]

Afterwards, copy the resulting Extra program back out of ram: to
someplace safe from power failures.

The program itself is pretty straightforward.  It opens a 6 plane
low res custom screen and then opens a window in that screen.
64 color patches are then drawn into that window with color register
usage increasing left to right then top to bottom from 0 to 63.  For
simplicity, this program uses the default color pallette supplied
with the new screen.

Due to the EXTRA_HALFBRITE special ViewMode in the screen definition,
the bottom 4 rows of color should be the half intensity counterparts
of the corresponding patches in the top 4 rows.

The program waits for a CLOSEWINDOW message from Intution, then
cleans up and goes away.

-------------------------Program Source Follows:

/***********************************************************************
 *  Extra -- Program to demonstrate Extra-Half-Brite graphics display
 *           mode on the Amiga.
 *
 *  Dale Luck    -- October, 1985
 *  Bob Pariseau -- November 8, 1985  (Editorial changes)
 *
 **********************************************************************/

#include <exec/types.h>
#include <exec/tasks.h>
#include <exec/libraries.h>
#include <exec/devices.h>
#include <devices/keymap.h>
#include <graphics/copper.h>
#include <graphics/display.h>
#include <graphics/gfxbase.h>
#include <graphics/text.h>
#include <graphics/view.h>
#include <graphics/gels.h>
#include <graphics/regions.h>
#include <hardware/blit.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>


struct   GfxBase        *GfxBase;         /* Export library base pointers */
struct   IntuitionBase  *IntuitionBase;

struct   Screen   *colscreen;             /* Pointers to new screen and   */
struct   Window   *wndo;                  /* window.                      */

struct   NewScreen newscreen;             /* OpenX() arguments for new    */
struct   NewWindow newwindow;             /* screen and window.           */

struct   TextAttr Font =
{
   "topaz.font",            /* Use standard system font */
   8,
   FS_NORMAL,
   FPF_ROMFONT,
};

struct IntuiMessage *message;



main()
{
   if ((IntuitionBase = (struct  IntuitionBase *)OpenLibrary("intuition.library", 0)) == 0)
   {
      printf("WOT !  No Intuition ???\n");
      exit();
   }

   if ((GfxBase = (struct   GfxBase *)OpenLibrary("graphics.library", 0)) == 0)
   {
      printf("Oh ! No Graphics??\n");
      CloseLibrary(IntuitionBase);
      exit();
   }

/* values for new screen */
   newscreen.LeftEdge       = 0;
   newscreen.TopEdge        = 0;
   newscreen.Width          = 320;
   newscreen.Height         = 200;
   newscreen.Depth          = 6;
   newscreen.DetailPen      = 0;
   newscreen.BlockPen       = 1;
   newscreen.ViewModes      = EXTRA_HALFBRITE;
   newscreen.Type           = CUSTOMSCREEN;
   newscreen.Font           = &Font;
   newscreen.DefaultTitle   = "Six Planes Low Res";
   newscreen.Gadgets        = NULL;
   
   colscreen = (struct Screen *)OpenScreen(&newscreen);
   if (colscreen == 0)
   {
      printf("Screen Failed !!!!!\n");
      CloseLibrary(GfxBase);
      CloseLibrary(IntuitionBase);
      exit();
   }

/* values for new window */
   newwindow.LeftEdge      = 0;
   newwindow.TopEdge       = 15;
   newwindow.Width         = 320;
   newwindow.Height        = 185;
   newwindow.DetailPen     = 0;
   newwindow.BlockPen      = 1;
   newwindow.Flags         = ACTIVATE | SIMPLE_REFRESH | WINDOWCLOSE;
   newwindow.IDCMPFlags    = CLOSEWINDOW;
   newwindow.FirstGadget   = NULL;
   newwindow.CheckMark     = NULL;
   newwindow.Title         = "Extra-Half-Brite Colors!";
   newwindow.Screen        = colscreen;
   newwindow.BitMap        = NULL;
   newwindow.MinWidth      = 20;
   newwindow.MinHeight     = 20;
   newwindow.MaxWidth      = 320;
   newwindow.MaxHeight     = 200;
   newwindow.Type          = CUSTOMSCREEN;

   wndo = (struct Window *)OpenWindow(&newwindow);
   if (wndo == 0)
   {
       printf("Window failed!!!\n"); 
       CloseScreen(colscreen);
       CloseLibrary(GfxBase);
       CloseLibrary(IntuitionBase);
       exit();
   }

   setup(wndo->RPort);

   FOREVER
   {
      WaitPort(wndo->UserPort);
      message = (struct IntuiMessage *)GetMsg(wndo->UserPort);
      if(message->Class == CLOSEWINDOW)
      {
         ReplyMsg(message);       /* Can't reply till done using */
         CloseWindow(wndo);
         CloseScreen(colscreen);
         CloseLibrary(GfxBase);
         CloseLibrary(IntuitionBase);
         exit();
      }
      ReplyMsg(message);
   }
 
}

setup(rastp)
struct RastPort *rastp;
{
   USHORT   countx;
   USHORT   county;
   USHORT   color;

   for (countx = 0; countx < 8; countx++)
      for (county = 0; county < 8; county++)
      {
         color = (county<<3) + countx;
         SetAPen(rastp,color);
         RectFill(rastp,countx*35+10,county*20+15,countx*35+45,county*20+35);
      }
}

------------------------That's all for now!