From: pochanay@cae.wisc.edu (Adisak Pochanayon)
Subject: Re: Bug in ViewPorts under 2.0
Organization: College of Engineering, Univ. of Wisconsin--Madison
Date: 16 Nov 92 07:28:03 CST


     This program illustrates the bug I mentioned about RxOffset under
     2.0 using hi-resolution screens.

     pochanay@cae.wisc.edu

----------------------------  cut here   -----------------------------

/* 
   boxomatic.c    by Gregg Williams
                     BYTE Magazine
                     PO Box 372
                     Hancock NH  03449
                     Phone: 603-924-9281
                     BIX: greggw


modified by Adisak Pochanayon to show hires scrolling problem under 2.0.
Ignore all the dual playfield comments.  The second playfield has been
removed.  pochanay@cae.wisc.edu
*/

#include <exec/types.h>
#include <stdio.h>
#include <graphics/gfx.h>
#include <hardware/dmabits.h>
#include <hardware/custom.h>
#include <hardware/blit.h>
#include <graphics/gfxmacros.h>
#include <graphics/copper.h>
#include <graphics/view.h>
#include <graphics/rastport.h>
#include <graphics/gels.h>
#include <graphics/regions.h>
#include <graphics/clip.h>
#include <exec/exec.h>
#include <graphics/text.h>
#include <graphics/gfxbase.h>
#include <proto/graphics.h>
#include <proto/exec.h>

#define DEPTH 3L      /* depth of playfield 1, (scrolling, on bottom) */
#define WIDTH 640L    /* dimensions of playfield 1 */
#define HEIGHT 400L
#define VPWIDTH 322L   /* dimensions of the viewport */
#define VPHEIGHT 200L
#define NOT_ENOUGH_MEMORY -1000
#define PF1_BACKGD 7L

/* construct a simple display */

struct View view;
struct ViewPort viewport;
struct ColorMap *cm;
struct RasInfo rasinfo;
struct BitMap bitmap;
struct RastPort rastport;
struct GfxBase *GfxBase;
struct View *oldview;

USHORT colortable[]={
  0x000, 0xfb0, 0xccc, 0xf15,  0xa50, 0x0c5, 0x777, 0x77f,
  0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0
};

UWORD *colorpalette;

void draw_playfields(void);
void draw_box(LONG, LONG, LONG, LONG);
void FreeMemory(void);

void _main()

{
  LONG i, n;
  SHORT nmax;
  SHORT pf1_xmove, pf1_ymove;

  /* 'nmax' determines how long the display runs; see below */

    nmax = 10;

  GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0L);
  if (GfxBase == NULL) _exit(100);
  oldview = GfxBase->ActiView;

  InitView(&view);
  InitVPort(&viewport);
  view.ViewPort = &viewport;
/**************************************************************************

    Works fine if Modes = 0;  Does the wierd 2 pixel thing under 2.0
  if Modes = HIRES;  How do you get around this.  It works fine under
  1.3 either way.

**************************************************************************/
  view.Modes = viewport.Modes = HIRES;   

  InitBitMap(&bitmap, DEPTH, WIDTH, HEIGHT);
  InitRastPort(&rastport);
  rastport.BitMap = &bitmap;
  rasinfo.BitMap = &bitmap;
  rasinfo.RxOffset = 0;
  rasinfo.RyOffset = 0;
  rasinfo.Next = NULL;

  viewport.DWidth = VPWIDTH;
  viewport.DHeight = VPHEIGHT;
  viewport.RasInfo = &rasinfo;

  cm = GetColorMap(32);
  if (cm == NULL) {
    FreeMemory();
    _exit(100);
  }
  colorpalette = (UWORD *)cm->ColorTable;
  for(i=0; i<32; i++) {
    *colorpalette++ = colortable[i];
  }
  viewport.ColorMap = cm;

  for(i=0; i<DEPTH; i++) {
    bitmap.Planes[i] = (PLANEPTR) AllocRaster(WIDTH, HEIGHT);
        if(bitmap.Planes[i] == NULL) {
		FreeMemory();
		_exit(NOT_ENOUGH_MEMORY);
      }
    BltClear(bitmap.Planes[i], RASSIZE(WIDTH, HEIGHT), 1);
  }

  draw_playfields();

  /* These three instructions assemble and "load" the view we've defined.*/
  MakeVPort(&view, &viewport);
  MrgCop(&view);
  LoadView(&view);
  pf1_xmove = 1; pf1_ymove = 1;
  for( n=1; n<=nmax;  )   {
/**************************************************************************

      All right, here is where the RxOffset is modified.
      Note that under 2.0 in hires, RxOffset is multiplied by 2
      somehow during the display.  This is a bug I wish to get
      around.  Please send help to pochanay@cae.wisc.edu.

**************************************************************************/
          rasinfo.RxOffset = rasinfo.RxOffset + pf1_xmove;
          rasinfo.RyOffset = rasinfo.RyOffset + pf1_ymove;

      if (rasinfo.RxOffset <= 0  ||  rasinfo.RxOffset >= 319)  {
            pf1_xmove = -pf1_xmove;
                n = n + 1;
      }
      if (rasinfo.RyOffset <= 0  ||  rasinfo.RyOffset >= 199)  {
            pf1_ymove = -pf1_ymove;
                n = n + 1;
      }

     /* Reexecute this trio of instructions to make the changes visible. */
          MakeVPort(&view, &viewport);
          MrgCop(&view);
          LoadView(&view);

          WaitTOF();
  }

  /* Restore the system to its original state. */
  LoadView(oldview);
  FreeMemory();
  CloseLibrary((struct Library *)GfxBase);
}

void draw_playfields()
{
  LONG x, y, temp, color1, color2;
  SetRast( &rastport, PF1_BACKGD );
  temp = 1L;
  for( x=25L; x<=590L; x=x+50L )   {
    for ( y=0L; y<=350L; y=y+50L)   {
          color1 = temp;
          temp = temp + 1L;
          if (temp > 7L) temp = 1L;
          color2 = temp;
          temp = temp + 1L;
          if (temp > 7L) temp = 1L;
          draw_box( x, y, color1, color2 );
        }
  }
}

void draw_box( x, y, bigsq_color, smallsq_color )
LONG x, y, bigsq_color, smallsq_color;
{
   SetAPen( &rastport, 0 );   /* draw black shadow */
   RectFill( &rastport, x+4L, y+4L, x+40L, y+40L );
   SetAPen( &rastport, 0 );   /* draw large black box */
   RectFill( &rastport, x, y, x+36L, y+36L );
   SetAPen( &rastport, bigsq_color );   /* draw large colored box */
   RectFill( &rastport, x+2L, y+2L, x+34L, y+34L );
   SetAPen( &rastport, smallsq_color );   /* draw small colored box */
   RectFill( &rastport, x+12L, y+12L, x+24L, y+24L );
}

void FreeMemory()
{
  LONG i;
  for (i=0; i<DEPTH; i++) {
        if (bitmap.Planes[i] != NULL) {
      FreeRaster(bitmap.Planes[i], WIDTH, HEIGHT);
        }
  }
  if (cm != NULL)  FreeColorMap(cm);
  FreeVPortCopLists(&viewport);
  FreeCprList(view.LOFCprList);
}