From piziali!andy@sulaco.cox.smu.edu  Sun Dec 19 17:12:15 1993
Return-Path: <piziali!andy@sulaco.cox.smu.edu>
Received: from tidmmpl.csc.ti.com by sun_97d1 (4.1/SMI-4.1)
	id AA06330; Sun, 19 Dec 93 17:12:15 CST
Received: by tidmmpl.csc.ti.com ( 5.52 (84)/5.17)
	id AA13958; Sun, 19 Dec 93 17:08:34 CST
Received: from lobby.ti.com (ti.com) by tilde.csc.ti.com id AA05779; Sun, 19 Dec 1993 17:10:11 -0600
Received: from sulaco.dia.com (sulaco.cox.smu.edu) by lobby.ti.com with SMTP 
	(5.65c/LAI-3.2) id AA08513; Sun, 19 Dec 1993 17:10:31 -0600
Received: from piziali by sulaco.dia.com with uucp
	(Smail3.1.28.1 #1) id m0pBXFk-000151C; Sun, 19 Dec 93 17:09 CST
Received: by piziali.lonestar.org (Smail3.1.28.1 #6)
	id m0pBVQP-0005NcC; Sun, 19 Dec 93 15:12 CST
Message-Id: <m0pBVQP-0005NcC@piziali.lonestar.org>
From: andy@piziali.lonestar.org (Andrew J. Piziali)
Subject: /dos/transfer/p9000ch6.txt
To: andy@tidmmpl.csc.ti.com (Andrew J. Piziali)
Date: Sun, 19 Dec 1993 15:12:24 -0600 (CST)
X-Mailer: ELM [version 2.4 PL21]
Mime-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Content-Length: 20913     
Status: RO

POWER 9000
USER INTERFACE
CONTROLLER

October 1992

Chapter 6. Pseudo-Code for Definition of the Power 9000

6.1. Introduction

This chapter presents information for those who need to
know specifically how the Power 9000 performs various
functions. Blocks of pseudo-code illustrate the chip's han-
dling of:

  coordinate register load/store
  meta-coordinate register load
  blit operations
  quad draw operations and drawing modes
  pixel8 operations
  pixel1 operations
  next._pixels operation

The pseudo-code presented in this appendix illustrates
Power 9000 functions only; it does not represent callable
programs or subroutines.

Also, although the pseudo-code is C-based, it contains
some constructs that are not legal C code, but do reflect the
operation of the chip.

123


6.2. Coordinate Register Load/Store

Figure 123 presents pseudo-code that defines the functions
used by the Power 9000 to load and store the x and y coor-
dinates. The absolute form is used to perform the reads and
writes without any modifications on the data. The relative

form allows coordinates to be loaded relative to the cur-
rent window offset, and is only meaningful for write oper-
ations.

void 1oad_x(rel,reg,data)
unsigned rel:l;
unsigned reg:2;
int data;
{
set_x(reg,data,rel ? w_off.x:
}

  relative to window offset ? */
/* register number from address field */
/* data from data bus */

0);   /* set the register */

void 1oad_y(rel,reg,data)
unsigned rel:l;
unsigned reg:2;
int data;
{
set_y(reg,data,rel ? w_off.y
}

/* relative to window offset ? */
/* register number from address field */
/* data from data bus */

: 0);    /* set the register */

void 1oad_xy (rel, reg, data)

unsigned rel:l;
unsigned reg:2;
struct XY {
    short x.y;
} data;
{
 1oad_x(rel,reg
 1oad_y(rel,reg
}

,data.x);
,data.y);

/* load X and Y as two 16-bit numbers */

/* X in high half, Y in low half */

/* load low 16-bits sign extended */
/* load high 16-bits sign extended */

store_x(regnum)
unsigned regnum:2;
{
return (x[regnum]);
}

/* read X register */

store__v (regnum)
unsigned regnum: 2;

 return (y [regnum] );
}

/* read Y register */

store_xy (regnum)
unsigned regnum: 2;
{
return ((x[regnum]<<16)
}

/* read X and Y registers together (packed)  */
  (y[regnum] & Oxffff));

Figure 123. Coordinate register load/store commands

124


6.3. Meta-Coordinate Register Load

The commands in figure 124 are used to load the coordi-
nates for the vertices of points, lines, triangles, quadrilater-
als and rectangles using a short hand notation that uses the

POWER 9000
USER INTERFACE
CONTROLLER

October 1992

minimum number of data transfers. Two options are pro-
vided, one relative to the window offset and one relative to
the previously specified vertex.

void vertex_x(rel,vtype,data)
unsigned rel:l;
enum VTYPE vtype:3;
int data;
{
int tmp;

/* X vertex */
/* relative to previous coordinate ? */
/* vertex/object type */
/* X coordinate data "/

#define reg_x(offset)  (rel ? x[(cindex+offset) % 4]  : w_off.x)
#define reg_pot_x(offset)  (rel ?  (tmp=x[(cindex+offset) % 4])  : w_off.x)
#define reg_pot_2x(offset)  (rel ? tmp: w_off.x)

switch(vtype)  {
case POINT:
     set_x(O,data,reg_pot_x(O));
     set_x(l,data,reg_pot_2x(O));
     set_x(2,data,reg_pot_2x(O));
     set_x(3,data,reg_pot_2x(O));
        break;
case LINE:
     set_x(cindex,data,reg_x(2)  ;
     set_x((cindex+l)%4,data,reg_x(2));
        break;
case TRI:
     set_x(cindex.data,reg_x(3));
     set_x((cindex+l)%4,data,reg_x(3));

        break;
case QUAD:
     set_x(cindex,data,reg_x(3));

        break;
case RECT:
     set_x(cindex,data,reg_x(2));
     set_x((cindex-l)%4,data,reg_x(2));
     break;
}

Figure 124. Meta-coordinate register load commands

125


6.3. Meta-Coordinate Register Load, continued

void vertex_y(rel,vtype,data)         /* Y vertex */
unsigned rel:1;                       /* relative to previous coordinate */
enum VTYPE vtype:3;                   /* vertex/object type */
int data;                             /* Y coordinate data */
int ~mp;
#define re~_y(offset)  (rel ? y[(cindex+offset) % 4]  : w_off.y)
#define reg_pot_y(offset)  (rel ? (tmp=y[(cindex+offset) % 4])  : w_off.y)
#define reg_pot_2y(offset)  (rel ? tmp: w_off.y)

switch(vtype)  {
case POINT:
     set_y(O,data,reg_pot_.y(O))
     set_.v(l,data,reg_pot_2y(O)  ;
     set_y(2,data,reg_pot_2y(O)  ;
     set_y(3,data,reg_pot_2y(O)  ;
     cindex=O;
        break;
case LINE:
     set_y (cindex, data, reg__v (2)  ;
     set_y((cindex+l)%4,data,reg_.v(2));
     cindex+=2;
        break;
case TRI:
     se~j(cindex,data,reg_y(3));
     set_y((cindex+l)%4,data,reg_y(3));;
     cindex+=l;
        break;
case QUAD:
     set_y(cindex,data,reg_y(3));
     cindex+=l;
        break;
case RECT:
     set_y(cindex, data,reg_y(2));
     set_y((cindex+l)%4,da~a,reg_y(2));
     cindex+=2;
     break;

void vertex_xy(rel,vtype,data)
unsigned rel:l;
enum VTYPE vtype:3;

struct  PXY  {
 short x,y;

   ;

 vertex_x ( rel, vtype, data. x);
 vertex_y ( rel, vtype, data. y );

/* X and Y vertex */
/* relative to previous coordinate */

/* vertex/object type */

/* X and Y coordinate data */

/* set X vertex */
/* set Y vertex */

Figure 124, continued. Meta-coordinate register load commands
                                  126


POWER 9000
USER INTERFACE
CONTROLLER

October 1992

6.4. Load/Store Register Support Routines

This section presents subroutines used by the coordinate
register load/store and meta-coordinate register load com-
mands.

set_x(i,data,off)
unsigned i:2;
int data;
int off;
{
#define PLIMIT 8191
#define NLIMIT -8192
#define PLIMIT16 32767
#define NLIMIT16 -32768

/* set an X register */
/* register number to set */
/* full 32 bit data */
/* offset */

int midata;
     x [i ] =data+of f;

/* set the register

oor.x_oor[i]=                      /* compute out-of-range */
(((data < NLIMIT) 11 (data > PLIMIT)) 1~
(((data + off)  < NLIMIT)  ~1  ((data + off)  > PLIMIT))  1~
((x[i] < -8192)  1~  (x[i]  > 8191)));

/* 14 bit sign extend */
   midata=x[i];
 x[i]  = midata&Ox2000 ? midataIOxffffcOOO: midata&OxOOOO3fff;

clip.x_it_min[i]  = x[i]  <  (short)w_min.x;       /* check against window */
      clip.x_gt_max[i] = x[i] > (short)w_max.x;

clip.x_bnd_It[i]  = x[i]
clip.x_bnd_gt[i] = x[i]
clip.x_bnd_It[(i-l) & 3]
clip.x_bnd_gt[(i-l) & 3]

< x[(i+l) & 3];       /* check against boundaries */
> x[(i+l) & 3];
= x[(i-l)  & 3]  < x[i];
= x[(i-l)  & 3]  > x[i];

if( (i==l)  11  (i==3)  )  {
  clip.x_bnd_it[4] = x[l] < x[3];
    clip.x_bnd_gt[4]  = x[l]  > x[3];
} else {
  clip.x_bnd_it[5]  = x[O]  < x[2];
  clip.x_bnd_gt[5] = x[O] > x[2];

}

update_status ( );

/* update the sta/us register */

Figure 125. Set_x subroutine

127


6.4. Load/Store Register Support Routines, continued

set_y(i,data,off)
unsigned i:2;
int data;
int off;

#define PLIMIT 8191
#define NLIMIT -8192
#define PLIMIT16 32767
#define NLIMIT16 -32768
int midata;

/* set a Y register */
/* register number to set */
/* full 32-bit data */
/* offset */

y[ii=data+off;                     /* set the register */

oor.y_oor[i]=                      /* compute out-of-range */
(((data < NLIMIT) ~ (data > PLIMIT)) I~
(((data + off) < NLIMIT)  ~  ((data + off) > PLIMIT))
((y[i] < -8192)  ~  (y[i] > 8191)));

/* 14 bit sign extend */
   midata=y[i];
 y[i] = midata&Ox2000 ? midata~OxffffcOOO: midata&OxOOOO3fff;

clip.y_It_min[i]  = y[i]  <  (short)w_min.y;
clip.y_gt_max[i]  = y[i] > (short)w_max.y;

/* check against window */

clip.y_bnd_it[i]  = y[i]
clip.y_bnd_gt[i] = y[i]
clip.y_bnd_It[(i-l) & 3]
clip.y_bnd_gt[(i-l) & 3]

< y[(i+l) & 3];       /* check boundaries */
> y[ (i+l)  & 3];
= y[ (i-l) & 3] < y[i];
= y[ (i-l) & 3] > y[i];

 if(  (is=l)  ~  (i==3))  {
  clip.y_bnd_it[4] = y[l] < y[3];
    clip.y_bnd_gt[4]  = y[l]  > y[3];
} else {
  clip.y_bnd_It[5] = y[O] < y[2];
  clip.y_bnd_gt[5] = y[O] > y[2];
}

update_status();                     /* update the status register */

       }

Figure 126. Set_y subroutine

128


POWER 9000
USER INTERFACE
CONTROLLER

October 1992

6.4. Load/Store Register Support Routines, continued

update_status()                        /* update the status register */
{
#define visible(ix)  (!clip.x_it_min[ix] &a .'clip.x_gt_max[ix] &a\
                      !clip.y_it_min[ix] && !clip.y_gt_max[ix])
#define hidn(name)  (clip.name[O] && clip.name[l] && \
                     clip.name[2] && clip.name[3])
#define Oor(ix)   (0or.x_oor[ix]  11 oor.y_oor[ix])

status.pixel_software =
  Oor(1)  I~ oor.x_oor[O]  ~ 0or(2)  ~ oor.y_oor[3]
  clip.x_bnd_gt[O]     :(clip.x_bnd_it[l])  ;

status.blit_software =
     Oor(O)  11 Oor(1)
     clip.x_bnd_gt [0]
     clip.y_bnd_gt[O]

0or(2)  II 0or(3)
clip.x_bnd_gt[2]
clip.y_bnd_gt[2]  ;

status.quad_visible = visible(O) && visible(l) && visible(2) && visible(3);

status.quad_hidden = hidn(x_it_min)  ~I
                      hidn(x_gt_max)  I1
                      hidn(y It .min)  II
                      hidn(y_gt_max);

status.quad_intersects = !status.quad_visible && !status.quad_hidden;

status.quad_concave = concave_check();      /* can't do quad ? */

status.quad_software = Oor(O)  II Oor(1)  II 0or(2)  II 0or(3)  il
                        status. quad_concave;

Figure 127. Update_status subroutine

129


6.5. Subroutine Operations

This section presents pseudo-code that defines subroutine
operations used by the major Power 9000 operations. For
example, the function defined by the put_pixol subroutine
is called by the blit, quad draw, pixell, and pixel8 opera-
tions.

6.5.1. PUT_PIXEL SUBROUTINE

Actual Format: put_pixel(src. x, y)

The put_pixel subroutine is called when an individual pixel
is to be written to the display by the Power 9000 drawing
engine.

It incorporates: clipping, picking, plane masking, and ras-
ter operations.

6.5.2. COMPUTE_LINEAR SUBROUTINE

Actual Format: compute_linear(x, y)

This subroutine is used to convert x,y addresses into linear
addresses in memory. The y value is multiplied by the

width of the scan line and then the x value is added. The
width of the scan line is required to be expressed as the sum
of three powers of 2 so the multiply operation is expressed
as three shift and add operations.

6.5.3. CALCULATE_ROP SUBROUTINE

Actual Format: pixel calculate_rop(src, dest)

This subroutine defines the raster operation. The boolean
raster operations on each of the eight planes is computed
independently. The result is a boolean function with four
inputs: foreground, background, source, and destination.
All possible combinations are defined in a 216 entry ras-
ter. minterms array. Each bit in the array corresponds to
one of the 16 possible possible minterms for the boolean
input variables.

130


POWER 9000
USER INTERFACE
CONTROLLER

October 1992

6.5. Subroutine Operations, continued

void put_pixel(src,x,y)
Pixel src;
int x,y;
{

int dest;
Pixel temp;

/* source pixel */
/* x,y coordinates */

/* destination pixel if needed */

int linear = compute_linear(x,y);              /* linear address of pixel */
int inside = ((x>=w_min.x) && (x<=w_max.x) &&             /* inside window ? */
                   (y>=w_min.y)  &&  (y<=w_max.y));
if (draw_mode.pick)  {
 interrupt.picked I= inside;     /* indicate picked */
 status.picked ~= inside;            /* indicate picked */
 } else {
           if(:inside) return;       /* supress if outside window */
           if (dest_pix_required())  /* do we need to read the destination pixel ? */
          dest=pixmap[draw_mode.dest_buffer][linear];     /* fetch destination pixel */

    temp=calculate_rop(src,dest);     /* apply raster operation */
/* plane masking, use vram write-per-bit */

pixrnap[draw_mode.dest_buffer][linear]=(dest&~pmask)~(temp&pmask);

 }
)

Figure 128. Put_pixel subroutine

131


6.5. Subroutine Operations, continued

int compute_linear(x,y)
int x,y;
{
#define shift(s)  (s? (y<<(4+s))

  /* compute linear address from x,y coordinates */

:  O)

int linear=x;
int maddr;

linear+=shift (sysconfig. shift2)
linear+=shift (sysconfig. shiftl)
linear+=shift (sysconfig. shiftO)

/* adjust linear address depending upon memory configuration */

switch(mem_config.memory_configuration)  {
   case O:
   case 1:
   case 3:
 maddr = Oxfffff;/* 1 meg */
 break;
 case 2:
 case 4:
   maddr = Oxlfffff;/* 2 meg */
 break;
 default: break;
}

 return(linear&maddr);
}

Figure 129. Compute_linear subroutine

132


POWER 9000
USER INTERFACE
CONTROLLER

October 1992

6.5. Subroutine Operations, continued

Pixel calculate_rop(src,dest)
Pixel src,dest;
{
 int Ibound,hbound;
 int index;
 short plane;
 Pixel result=O;

/* calculate raster op */

for (plane=l; plane<OxlOO ;plane=plane<<l)
 index= ( fground & plane ? Ox8     : 0 )  I
 (bground & plane ? Ox4             :  O)  I
 (src      & plane
 (dest     & plane ? Oxl  :  0);

{   /* all eight planes */

#define MINTERM_SEL ( (raster.minterms &  (l<<index))  >> index)

      resultI=MINTERM_SEL ? plane: O;
}
return(result);

Figure 130. Calculate_rop subroutine

6.6. The Blit Operation

The blit operation copies a rectangular area of the display
from one location to another. Its primary use is the imple-
menration of smooth scrolling for text displays. It can also
be used for simple animation or to create mouse-event han-

diers such as moving tiles or display areas around the
screen window.

Figure 131 presents pseudo-code that defines the actions of
the Power 9000 during a bfit operation.

133


6.6. The Blit Operation, continued

struct STATUS blit() {
short sx, sy;
short dx.dy;
int xincr,yincr,xcount
xcount = x[l] - x[O];
ycount = y[l] - y[O];

           /* Always returns status register */
           /* Source X and Y */
                   /* Dest X and Y */
, ycount, csx, cdx, cxcount;

if (y[2] > y[O]  11 x[2] < x[O])  {        /* Direction of blit */
      sx = x[O];
      sy = y[O];
      dx = x[2];
      dy = y[2];
      xincr = 1;
      yincr = 1;

} else {
   sx = x[l];
   sy = y[l];
   dx = x[3];
   dy = y[3];
   xincr = -l;
   yincr = -l;
}
return status;

if (status.busy
status.blit_software)
return;

status.busy = TRUE;
 while (ycount-- >= O)  {

   cxcount   =   xcount;
    CSX  =  SX;
    cdx = dx;
    while (cxcount-- >= O)

/* Go in - direction */

* Not legal C; pseudo-code statement defining
 function:  Put status register on bus to return
 status to host.*/
 * Drawing Engine Busy? */
 *  Nothing  to do?       */
* Quit if the drawing engine is busy or if
there is nothing to do */

* Mark drawing engine Busy */

put_pixel (cdx, dy,memory [draw_mode. src_buffer] [compute_linear (csx, sy) ] );

     cdx += xincr;
     csx += xincr;

   sy += yincr;
   dy += yincr;
}
status.busy = FALSE;

/* Set internal status register to mark drawing
 engine available */

Figure 131. Blit operation pseudo-code

134


POWER 9000
USER INTERFACE
CONTROLLER

6.7. The Quad Draw Operation

The quad drawing operation fills a quadrilateral specified
by the contents of the coordinate registers. In fact, there are
multiple cases of the quad drawing operation which draw
triangles, points, lines, poly-lines, and quads. The quad
drawing operation can fail for two reasons: one or more of

October 1992

the coordinates is out of range of the drawing engine or the
quad is concave.

Figure 132 presents pseudo-code thatdefines the actions of
the Power 9000 during a quad draw operation.

struct STATUS quad ( )  {

return status;

if (status.quad_softwareli
status. busy )
{
      return;
}
status.busy = TRUE;
y = [Lowest Y Value]
   py = y - pat_originy;
while (y< [Largest Y Value] &&
      [Still within the clip window])
{
          do_left_bresenham (y, &Ix);
          do_right_bresenham (y, &rx);
          x = min(Ix,rx);
          px = x - pat_originx;
          while (x< max(Ix,rx))

/* Copy the sorted vertices to local variables */
/* Not legal C; pseudo-code statement defining
function: Put status register on bus to return
status to host and continue.  */
/* Need help */

/* Drawing engine busy */

* Done.  * /

/* Mark drawing engine busy */

/* Not legal C; pseudo-code statements defining */;
/* chip function */
/'* Not legal C; pseudo-code statements defining
/* chip function */

/* Advance to the scan line */
/* Advance to the scan line */

/* Fill the scan line *

put_pixel (x,y, !raster.use_pattern I~ pattern[px % 16] [py % 16])?Oxff:O);

      }
   y++;
   py+ +;

    }
status. busy
}

x++;
px++;

= FALSE;

Figure 132. Quad draw operation pseudo-code

/* Mark drawing engine available */

6.8. The Pixe18 Operation

The pixel8 operation transfers pixels from a linear host
memory array to a rectangular display memory array. The
linear array in host memory must be padded out to a multi-
ple of four pixels for each scan line. The pixel8 operation
writes exactly one word (32 bits)into the VRAM each time
it is executed. If the destination array is not word-aligned,
the operation uses the internal pixelg_reg register to save

the extra pixels that must be transmitted from one pixol8
operation to the next. At the end of each scan line, this reg-
ister is forced into memory.

Figure 133 presents pseudo-code that defines the actionsOf
the Power 9000 during a pixel8 operation.

135


6.8. The Pixe18 Operation, continued

void pixelg(data)
Pixel data[4];

/* data from host, data[O] = HD[31..24] */

in~ i,j;
int ctr=O;
int b=x[l] & 3;
int wxl=x[l] &
struct PIXEL p[4];

while (status.busy);   /* wait for drawing engine */

if (status.pixel_software)  {
  return;
}

/* can't do it in software ? */
/* throw away the operation */

status.busy=TRUE;          /* mark drawing engine busy */

if  (b=sO)  {                    /* word aligned address */
  for (i=O;i<4;i++)  {
              p[ii=data[i];
} else {                         /* misaligned address */
for    i=O,j=4-b;j<=3;i++,j++)  {
              p[i]=pixelg_reg[j];      /* load saved left-over pixels from pixel8_reg */
}

for

i=b,j=O;i<=3;i++,j++)  {
   p[ii=data[j];

for

i=O;i<=3;i++)  {
pixelg_reg[i]=data[i];

for

;ctr<4;ctr++,++wxl)  {
if ((wxl<x[2] && (x[O])!=(x[l]))  11   /* is this pixel ok ? */
(wxl<x[2] && wxl>=x[l] && (x[O])==(x[l])))  {
   put_pixel(p[ctr],wxl,y[l]);

Figure 133. Pixe18 operation pseudo-code

136


POWER 9000
USER INTERFACE
CONTROLLER

October 1992

             i
6.8. The Pixe18 Operation, continued

set_x(l,x[1], 4);

if (x[l] >= x[2])  {     /* time for a reErace ? */
     if (b 1= O)  {          /* dump extra pixels */
      for (ctr = 4-b; ctr < 4; ++ctr)  {
           if  (wxl < x[2] && wxl >= x[O])  (
            put_pixel (pixelg_reg [ctr], wxl++, y [ 1 ] );
           }
      }
      )
set_x(l,x[O], 0);     /* reset pointer to left hand edge */
set_.y(l,y[l],y[3]);   /* go to next scanline */
}  status.busy=FALSE;   /* mark drawing engine available */

Figure 133, continued. Pixel8 operation pseudo-code

137


6.9. The Pixell Operation

The pixell drawing operation places from 1 to 32 pixels
onto a rectangular area of the screen. The data is trans-
mitted from the host data bus with each bit representing
one pixel. In fact, there are 32 operations performed, one
for each pixel to be transmitted.

Figure 134 presents pseudo-code that defines the actions of
the Power 9000 during a pixol1 operation.

pixell(count,data)
unsigned count:5;
unsigned daea[32]:l;

(
 int ctr=O;
 int dv=Oxff;

/* not legal C, pseudo-code statement
   indicating an array of bits which is
   actually a word.
 Data from host, data[O]=HD[31]  */

while status.busy;      /* wait for the drawing engine */

status.busy=TRUE;              /* mark drawing engine busy */

if (status.pixel_software)  {
  return;

/* can it be done ? */
/* just ignore it */

while (ctr<count)  {
   if  (x[l]<x[2])  {

/* for each input pixel */
/* inside scanline ? */

put_pixel(data[ctr++] ? dv: O,xEl],y[l]);
set_x(l, x[l], 1);

} else {                    /* outside scanline */

set_x(1, x[O], 0);
set_y(l,y[l] ,y[3]);

/* reset to left edge */
/* go to next scanline */

if (x[l]>=x[2])  {   /* outside scanline */
  set_x(l,x[O],O);
  set_y(l,y[l],y[3]);
}

    status.busy=FALSE;     /* mark drawing engine available */
   }

Figure 134. Pixell operation pseudo-code

138


POWER 9000
USER INTERFACE
CONTROLLER

October 1992

6.10. The Next_pixels Operation

The next_pixels operation is used to advance the pixel1
and pixel8 drawing parameters to the next point in the se-
quence of operations. The host data bus contains the width
of the new transfer.

Figure 135 presents pseudo-code that defines the actions of
the Power 9000 during a noxt._pixols operation.

next_pixels (width)
    wideh;
(
set_x(O,x[2], O);
set_x(l,x[2], O);
set_x(2,x[2] ,width);
set_y(1,y[2], 0);
}

/* data bus specifies width */

/* current pointer  */
/* new left hand edge       */

/* new right hand edge        */

/* re-initialize top edge */

Figure 135. Next_pixels operation pseudo-code

139



