[comp.sys.amiga] Xspecs 3D sample code

rsb584@leah.Albany.Edu (Raymond S Brand) (05/13/89)

This is some [ugly!] code that I wipped up to play with the XSpecs 3D glasses.
It works by toggling the FIRE line (pin 6) of mouseport 2 like the software
that comes with the glasses. The pieces of the code of real interest are
the two .asm files and the last part of testview.c. This code is not supported
in any way but I may answer questions about it or the glasses if you can track
me down.

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	testview.c
#	testview.lnk
#	wire.c
#	wiretest.c
#	wiretest.lnk
#	xspecint.asm
#	xspeclens.asm
# This archive created: Fri May 12 10:09:49 1989
# By:	Raymond S Brand (his computer)
export PATH; PATH=/bin:$PATH
if test -f 'testview.c'
then
	echo shar: will not over-write existing file "'testview.c'"
else
sed 's/^X//' << \HI_MOM > 'testview.c'
X
X
X#include <exec/types.h>
X#include <graphics/gfx.h>
X#include <hardware/dmabits.h>
X#include <hardware/custom.h>
X#include <hardware/intbits.h>
X#include <graphics/gfxmacros.h>
X#include <graphics/rastport.h>
X#include <graphics/view.h>
X#include <exec/execbase.h>
X#include <exec/exec.h>
X#include <exec/interrupts.h>
X
Xextern struct Custom custom;
X
X#define DEPTH 1
X#define WIDTH 640
X#define HEIGHT 200 
X#define NOT_ENOUGH_MEMORY -1000
X#define FOREVER for(;;) 
X        /* construct a simple display */ 
X 
Xstruct View v[4];
Xstruct ViewPort vp[4];
Xstruct ColorMap *cm[4];  /* pointer to colormap structure, dynamic alloc */
Xstruct RasInfo ri[4];
Xstruct BitMap b[4];
Xstruct RastPort rp[4];
X 
Xshort i,j,k,n,Z;
Xstruct ColorMap *GetColorMap();
Xstruct GfxBase *GfxBase;
X
XUSHORT colortable[] = { 0x000, 0xfff, 0x0f0, 0x00f,
X                        0xf0f, 0x0ff, 0xff0, 0xfff };
X                        /* black, red, green, blue */
X
XUWORD *colorpalette;
X
Xextern void LensInt();
Xextern void OpenLensPort();
Xextern void CloseLensPort();
Xextern void RemindLensPort();
X
Xstruct Interrupt IntNode;
X
Xstruct
X  {
X   APTR  ExecLibPT;
X   APTR  GraphicsLibPT;
X   APTR  Task;
X   LONG  SignalMask;
X   APTR  CLV;
X   APTR  CRV;
X   APTR  LV[2];
X   APTR  RV[2];
X   UWORD Frame;
X   UBYTE Lens;
X   UBYTE Flip;
X  } LID;
X
XLONG ExecBase;
X
Xmain()
X{
X   GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0);
X   if (GfxBase == NULL) exit(1);
X   ExecBase = OpenLibrary("exec.library",0);
X   if (ExecBase == NULL) exit(1);
X
X   for(Z=0; Z<4; Z++)
X    {
X
X                                /* initialize view */
X        InitView(&(v[Z]));
X                                /* link view into viewport */
X        v[Z].ViewPort = &(vp[Z]);
X        v[Z].Modes = HIRES;
X                                /* init view port */
X        InitVPort(&(vp[Z]));
X                                /* now specify critical characteristics */
X        vp[Z].DWidth = WIDTH;
X        vp[Z].DHeight = HEIGHT;
X        vp[Z].RasInfo = &(ri[Z]);
X        vp[Z].Modes = HIRES;
X                                /* init bit map (for rasinfo and rastport) */
X        InitBitMap(&(b[Z]),DEPTH,WIDTH,HEIGHT);
X
X        InitRastPort(&(rp[Z]));
X        rp[Z].BitMap = &(b[Z]);
X
X                                /* (init RasInfo) */
X        ri[Z].BitMap = &(b[Z]);
X        ri[Z].RxOffset = 0;        /* align upper left corners of display
X                                 * with upper left corner of drawing area */
X        ri[Z].RyOffset = 0;
X        ri[Z].Next = NULL;
X                                /* (init color table) */
X        cm[Z] = GetColorMap(1<<DEPTH);
X        colorpalette = cm[Z]->ColorTable;
X        for(i=0; i< (1<<DEPTH); i++)
X                *colorpalette++ = colortable[i];
X                                /* copy my colors into this data structure */
X        vp[Z].ColorMap = cm[Z];       /* link it with the viewport */
X
X                                 /* allocate space for bitmap */
X        for(i=0; i<DEPTH; i++)
X           {
X           b[Z].Planes[i] = (PLANEPTR)AllocRaster(WIDTH,HEIGHT);
X           if(b[Z].Planes[i] == NULL) exit(NOT_ENOUGH_MEMORY);
X           }
X
X        MakeVPort( &v[Z], &vp[Z] );   /* construct copper instr (prelim) list */
X        MrgCop( &v[Z] );           /* merge prelim lists together into a real 
X                                 * copper list in the view structure. */
X
X
X        SetRast(&rp[Z],0);
X
X
X   }
X
X
X   LID.GraphicsLibPT = GfxBase;
X   LID.ExecLibPT = ExecBase;
X   LID.Task = FindTask(0);
X   LID.SignalMask = 1 << AllocSignal(-1);
X   LID.CLV = &v[3];
X   LID.CRV = &v[2];
X   LID.LV[0] = &v[0];
X   LID.LV[1] = &v[3];
X   LID.RV[0] = &v[1];
X   LID.RV[1] = &v[2];
X   LID.Frame = 0;          /* index to non-displayed views */
X   LID.Lens = 0;
X   LID.Flip = 0;
X
X
X
X   IntNode.is_Node.ln_Type = NT_INTERRUPT;
X   IntNode.is_Node.ln_Pri = 20;
X   IntNode.is_Node.ln_Name = "X-Specs Int Handler";
X   IntNode.is_Data = &LID;
X   IntNode.is_Code = LensInt;
X
X
X
X   SetAPen(&rp[0],1);
X   SetAPen(&rp[1],1);
X   SetAPen(&rp[2],1);
X   SetAPen(&rp[3],1);
X   SetDrMd(&rp[0],JAM1);
X   SetDrMd(&rp[1],JAM1);
X   SetDrMd(&rp[2],JAM1);
X   SetDrMd(&rp[3],JAM1);
X
X   OFF_SPRITE;
X
X   OpenLensPort();
X
X
X   AddIntServer(INTB_VERTB, &IntNode);
X
X   Init3D();
X
X    FOREVER
X    {
X     /*
X      *  frame 0
X      */
X     SetRast(&rp[0],0);
X     SetRast(&rp[1],0);
X     Update3D(&rp[0],&rp[1]);
X     LID.Flip = 1;
X     Wait(LID.SignalMask);
X
X
X     /*
X      *  frame 1
X      */
X     SetRast(&rp[3],0);
X     SetRast(&rp[2],0);
X     Update3D(&rp[3],&rp[2]);
X     LID.Flip = 1;
X     Wait(LID.SignalMask);
X
X    }
X
X
X}       /* end of main() */
X
X
HI_MOM
fi # end of overwriting check
if test -f 'testview.lnk'
then
	echo shar: will not over-write existing file "'testview.lnk'"
else
sed 's/^X//' << \HI_MOM > 'testview.lnk'
XFROM LIB:c.o+testview.o+xspecint.o+xspeclens.o+wire.o
XTO testview
XLIB +LIB:lcmffp.lib+LIB:lc.lib+LIB:amiga.lib
HI_MOM
fi # end of overwriting check
if test -f 'wire.c'
then
	echo shar: will not over-write existing file "'wire.c'"
else
sed 's/^X//' << \HI_MOM > 'wire.c'
X/*
X * COPYRIGHT 1988 by Raymond S. Brand, All rights reserved.
X *
X * 19880904
X */
X
X#include <math.h>
X#include <exec/types.h>
X#include <graphics/rastport.h>
X
X#define XROTI 4
X#define YROTI 5
X#define ZROTI 6
X
X
X#define SCREEN_DIAGONAL 13       /* inches */
X#define SCREEN_WIDTH 640         /* pixels */
X#define SCREEN_HEIGHT 200        /* pixels */
X#define VIEW_DISTANCE 5          /* display units */
X#define EYE_OFFSET 1             /* inches */
X
X#define FLOAT float
X
X
XFLOAT object[][4] =
X  {  {  0.5,  0.5,  0.5,  1.0},
X     { -0.5,  0.5,  0.5,  1.0},
X     { -0.5,  0.5, -0.5,  1.0},
X     {  0.5,  0.5, -0.5,  1.0},
X     {  0.5, -0.5,  0.5,  1.0},
X     { -0.5, -0.5,  0.5,  1.0},
X     { -0.5, -0.5, -0.5,  1.0},
X     {  0.5, -0.5, -0.5,  1.0}
X  };
X
Xunsigned int numpoints = sizeof(object)/(sizeof(FLOAT)*4);
X
Xstruct Line
X  {
X   unsigned int end1,end2;
X  };
X
Xstruct Line lines[] =
X  {  {  0,  1},
X     {  1,  2},
X     {  2,  3},
X     {  3,  0},
X     {  4,  5},
X     {  5,  6},
X     {  6,  7},
X     {  7,  4},
X     {  0,  4},
X     {  1,  5},
X     {  2,  6},
X     {  3,  7}
X  };
X
Xunsigned int numlines = sizeof(lines)/sizeof(struct Line);
X
XFLOAT display[ sizeof(object)/(sizeof(FLOAT)*4) ][4];
X
XFLOAT objectMatrix[4][4];
XFLOAT LeyeMatrix[4][4];
XFLOAT ReyeMatrix[4][4];
XFLOAT WorkMatrix1[4][4];
XFLOAT WorkMatrix2[4][4];
XFLOAT WorkMatrix3[4][4];
X
XFLOAT XRot,YRot,ZRot;
X
X
X
Xvoid CopyMatrix(src, dst, rows)
X   FLOAT (*src)[ ][4];
X   FLOAT (*dst)[ ][4];
X   unsigned int rows;
X  {
X   unsigned int i,j;
X
X   for (i=0; i<rows; i++)
X     {
X      for (j=0; j<4; j++)
X        {
X         (*dst)[i][j] = (*src)[i][j];
X        }
X     }
X  }
X
X
X
Xvoid ZeroMatrix(dst, rows)
X   FLOAT (*dst)[ ][4];
X   unsigned int rows;
X  {
X   unsigned int i,j;
X
X   for (i=0; i<rows; i++)
X     {
X      for (j=0; j<4; j++)
X        {
X         (*dst)[i][j] = 0;
X        }
X     }
X  }
X
X
X
Xvoid MultMatrix(src1, src2, rslt, rows)
X   FLOAT (*src1)[ ][4];
X   FLOAT (*src2)[4][4];
X   FLOAT (*rslt)[ ][4];
X   unsigned int rows;
X  {
X   unsigned int i,j,k;
X
X   ZeroMatrix(rslt, rows);
X
X   for (i=0; i<rows; i++)
X     {
X      for (j=0; j<4; j++)
X        {
X         for (k=0; k<4; k++)
X           {
X            (*rslt)[i][j] += (*src1)[i][k] * (*src2)[k][j];
X           }
X        }
X     }
X  }
X
X
X
Xvoid MultMatrixN(src1, src2, rslt, rows)
X   FLOAT (*src1)[ ][4];
X   FLOAT (*src2)[4][4];
X   FLOAT (*rslt)[ ][4];
X   unsigned int rows;
X  {
X   unsigned int i,j,k;
X
X   ZeroMatrix(rslt, rows);
X
X   for (i=0; i<rows; i++)
X     {
X      for (j=0; j<4; j++)
X        {
X         for (k=0; k<4; k++)
X           {
X            (*rslt)[i][j] += (*src1)[i][k] * (*src2)[k][j];
X           }
X        }
X      for (j=0; j<4; j++)
X        {
X         (*rslt)[i][j] /= (*rslt)[i][3];
X        }
X     }
X  }
X
X
X
Xvoid Init3D()
X  {
X   FLOAT eyeoffset;
X   FLOAT eyedistance;
X   FLOAT cosalpha;
X   FLOAT sinalpha;
X
X   XRot = 0;
X   YRot = 0;
X   ZRot = 0;
X
X   eyeoffset = EYE_OFFSET * 2.5 / SCREEN_DIAGONAL;
X   eyedistance = sqrt(VIEW_DISTANCE*VIEW_DISTANCE + eyeoffset*eyeoffset);
X
X   cosalpha = VIEW_DISTANCE / eyedistance;
X   sinalpha = sqrt(1.0 - cosalpha*cosalpha);
X
X   ZeroMatrix(&WorkMatrix1, 4);
X   ZeroMatrix(&WorkMatrix2, 4);
X
X   WorkMatrix1[0][0] =  cosalpha;
X   WorkMatrix1[0][2] = -sinalpha;
X   WorkMatrix1[1][1] =  1.0;
X   WorkMatrix1[2][0] =  sinalpha;
X   WorkMatrix1[2][2] =  cosalpha;
X   WorkMatrix1[3][3] =  1.0;
X
X   WorkMatrix2[0][0] =  1.0;
X   WorkMatrix2[1][1] =  1.0;
X   WorkMatrix2[2][2] =  1.0;
X   WorkMatrix2[2][3] =  1/eyedistance;
X   WorkMatrix2[3][3] =  1.0;
X
X   MultMatrix(&WorkMatrix1, &WorkMatrix2, &ReyeMatrix, 4);
X
X   WorkMatrix1[0][0] =  cosalpha;
X   WorkMatrix1[0][2] =  sinalpha;
X   WorkMatrix1[1][1] =  1.0;
X   WorkMatrix1[2][0] = -sinalpha;
X   WorkMatrix1[2][2] =  cosalpha;
X   WorkMatrix1[3][3] =  1.0;
X
X   MultMatrix(&WorkMatrix1, &WorkMatrix2, &LeyeMatrix, 4);
X
X   ZeroMatrix(&WorkMatrix1, 4);
X
X   WorkMatrix1[0][0] =  SCREEN_WIDTH * 3/8;
X   WorkMatrix1[1][1] =  SCREEN_HEIGHT/2;
X   WorkMatrix1[2][2] =  1.0;
X   WorkMatrix1[3][0] =  SCREEN_WIDTH/2;
X   WorkMatrix1[3][1] =  SCREEN_HEIGHT/2;
X   WorkMatrix1[3][3] =  1.0;
X
X   MultMatrix(&LeyeMatrix, &WorkMatrix1, &WorkMatrix2, 4);
X   CopyMatrix(&WorkMatrix2, &LeyeMatrix, 4);
X
X   MultMatrix(&ReyeMatrix, &WorkMatrix1, &WorkMatrix2, 4);
X   CopyMatrix(&WorkMatrix2, &ReyeMatrix, 4);
X  }
X
X
X
Xvoid MakeRotMatrix()
X  {
X   FLOAT rad,cosalpha,sinalpha;
X
X   ZeroMatrix(&WorkMatrix1, 4);
X   ZeroMatrix(&WorkMatrix2, 4);
X
X   rad = XRot*PI/180;
X   cosalpha = cos(rad);
X   sinalpha = sin(rad);
X
X   WorkMatrix1[0][0] =  1;
X   WorkMatrix1[1][1] =  cosalpha;
X   WorkMatrix1[1][2] =  sinalpha;
X   WorkMatrix1[2][1] = -sinalpha;
X   WorkMatrix1[2][2] =  cosalpha;
X   WorkMatrix1[3][3] =  1;
X
X   rad = YRot*PI/180;
X   cosalpha = cos(rad);
X   sinalpha = sin(rad);
X
X   WorkMatrix2[0][0] =  cosalpha;
X   WorkMatrix2[0][2] = -sinalpha;
X   WorkMatrix2[1][1] =  1;
X   WorkMatrix2[2][0] =  sinalpha;
X   WorkMatrix2[2][2] =  cosalpha;
X   WorkMatrix2[3][3] =  1;
X
X   MultMatrix(&WorkMatrix1, &WorkMatrix2, &WorkMatrix3, 4);
X
X   ZeroMatrix(&WorkMatrix1, 4);
X
X   rad = ZRot*PI/180;
X   cosalpha = cos(rad);
X   sinalpha = sin(rad);
X
X   WorkMatrix1[0][0] =  cosalpha;
X   WorkMatrix1[0][1] =  sinalpha;
X   WorkMatrix1[1][0] = -sinalpha;
X   WorkMatrix1[1][1] =  cosalpha;
X   WorkMatrix1[2][2] =  1;
X   WorkMatrix1[3][3] =  1;
X
X   MultMatrix(&WorkMatrix3, &WorkMatrix1, &objectMatrix, 4);
X  }
X
X
X
Xvoid Update3D(Lrp, Rrp)
X   struct RastPort *Lrp;
X   struct RastPort *Rrp;
X  {
X
X
X   XRot += XROTI;
X   YRot += YROTI;
X   ZRot += ZROTI;
X
X   while (XRot < -180)
X     {
X      XRot += 360;
X     }
X
X   while (YRot < -180)
X     {
X      YRot += 360;
X     }
X
X   while (ZRot < -180)
X     {
X      ZRot += 360;
X     }
X
X   while (XRot > 180)
X     {
X      XRot -= 360;
X     }
X
X   while (YRot > 180)
X     {
X      YRot -= 360;
X     }
X
X   while (ZRot > 180)
X     {
X      ZRot -= 360;
X     }
X
X   MakeRotMatrix();
X
X/*
X * LEFT
X */
X
X   MultMatrix(&objectMatrix, &LeyeMatrix, &WorkMatrix1, 4);
X
X   MultMatrixN(&object, &WorkMatrix1, &display, numpoints);
X
X   DisplayObject(Lrp);
X
X/*
X * RIGHT
X */
X
X   MultMatrix(&objectMatrix, &ReyeMatrix, &WorkMatrix1, 4);
X
X   MultMatrixN(&object, &WorkMatrix1, &display, numpoints);
X
X   DisplayObject(Rrp);
X
X  }
X
X
X
Xunsigned int checkbounds(x, lo, hi)
X   FLOAT x,lo,hi;
X  {
X   unsigned int status;
X
X   status = 0;
X
X   if (x < lo)
X     {
X      status |= 1;
X     }
X
X   if (x > hi)
X     {
X      status |= 2;
X     }
X
X   return status;
X  }
X
X
X
Xint clip(x1,y1,z1,x2,y2,z2,LM,RM,TM,BM,HM,YM)
X   FLOAT *x1,*y1,*z1,*x2,*y2,*z2;
X   FLOAT LM,RM,TM,BM,HM,YM;
X  {
X   unsigned int end1,end2;
X
X   for (;;)
X     {
X      end1 = 0;
X      end2 = 0;
X
X      end1 |= checkbounds(*x1, LM, RM);
X      end1 |= checkbounds(*y1, TM, BM) << 2;
X      end1 |= checkbounds(*z1, HM, YM) << 4;
X
X      end2 |= checkbounds(*x2, LM, RM);
X      end2 |= checkbounds(*y2, TM, BM) << 2;
X      end2 |= checkbounds(*z2, HM, YM) << 4;
X
X      if ((end1 & end2) != 0)
X        {
X         return 0;
X        }
X
X      if ((end1 | end2) == 0)
X        {
X         return 1;
X        }
X
X
X
X
X
X      return 0;
X
X
X
X
X     }
X  }
X
X
X
Xint DisplayObject(rp)
X   struct RastPort *rp;
X  {
X   unsigned int i;
X   FLOAT x1,y1,z1;
X   FLOAT x2,y2,z2;
X
X   for (i=0; i<numlines; i++)
X     {
X      x1 = display[lines[i].end1][0];
X      y1 = display[lines[i].end1][1];
X      z1 = display[lines[i].end1][2];
X      x2 = display[lines[i].end2][0];
X      y2 = display[lines[i].end2][1];
X      z2 = display[lines[i].end2][2];
X
X      if (clip(&x1, &y1, &z1, &x2, &y2, &z2,
X            (FLOAT)(0), (FLOAT)(SCREEN_WIDTH-1),
X            (FLOAT)(0), (FLOAT)(SCREEN_HEIGHT-1),
X            (FLOAT)(-3),(FLOAT)(100)))
X        {
X         Move(rp,(int)x1,(int)y1);
X         Draw(rp,(int)x2,(int)y2);
X        }
X     }
X  }
X
HI_MOM
fi # end of overwriting check
if test -f 'wiretest.c'
then
	echo shar: will not over-write existing file "'wiretest.c'"
else
sed 's/^X//' << \HI_MOM > 'wiretest.c'
X#include <stdio.h>
X
Xchar c;
X
Xmain()
X  {
X   Init3D();
X
X   for (;;)
X     {
X      printf("\n********************************************\n\n");
X
X      Update3D(&c, &c);
X     }
X  }
X
XMove(r, x, y)
X   char *r;
X   int x,y;
X  {
X   printf("  %d  %d\n",x,y);
X  }
X
XDraw(r, x, y)
X   char *r;
X   int x,y;
X  {
X   printf("                   %d  %d\n",x,y);
X  }
X
HI_MOM
fi # end of overwriting check
if test -f 'wiretest.lnk'
then
	echo shar: will not over-write existing file "'wiretest.lnk'"
else
sed 's/^X//' << \HI_MOM > 'wiretest.lnk'
XFROM LIB:c.o+wiretest.o+wire.o
XTO wiretest
XLIB +LIB:lcm.lib+LIB:lc.lib+LIB:amiga.lib
HI_MOM
fi # end of overwriting check
if test -f 'xspecint.asm'
then
	echo shar: will not over-write existing file "'xspecint.asm'"
else
sed 's/^X//' << \HI_MOM > 'xspecint.asm'
X; X-Specs interrupt code for double-buffered 3-D animated drawings
X;
X; Copyright 1988 by Raymond S. Brand, All rights reserved.
X;  19880830
X;
X;  This code is designed to be part of the Copper interrupt, Vertical Blank
X;  interrupt or Software interrupt server chains. If this code is made part
X;  of the Software interrupt chain, some other interrupt will need to
X;  Cause() this code to be executed.
X;
X;  See SetLens routine for assumptions about interface to X-Specs.
X;
X; Theory of Operation:
X;  Each time this code is invoked, it changes which lens is transparent and
X;  which is opaque. If this change opens the left lens, a check is made to
X;  see if the "hidden" display buffers should now be displayed and the
X;  "visible" display buffers made hidden. If so, the change is made. At this
X;  point, the appropriate visible buffer for the open lens is displayed
X;  using LoadView().
X;
X; Warnings:
X;  This is a brute force method of achiving 3-D double-buffered animated
X;  drawings in that it requires 4 complete Views to work.
X;
X;  This is NOT friendly with intuition since it simply takes over the
X;  display with a LoadView().
X;
X;  The multiple Views method of double buffering is probably NOT compatible
X;  with the Amiga animation routines.
X;
X;  LoadView() is not listed as being safe to use durring interrupts.
X
X
X        SECTION text
X
X        NOLIST                ; no need to output this stuff
X
X        INCLUDE "exec/types.i"
X        INCLUDE "exec/libraries.i"
X
XCALLSYS MACRO
X        CALLLIB _LVO\1
X        ENDM
X
XXLIB    MACRO
X        XREF    _LVO\1
X        ENDM
X
X        LIST
X
X        XDEF    _LensInt      ; this is the start of it all....
X
X        XREF    SetLens
X        XREF    _custom
X
X        XLIB    Signal        ; in Exec
X        XLIB    LoadView      ; in Graphics
X
X        PAGE
XLEFT    equ     $00
XRIGHT   equ     $80
X
X STRUCTURE      LensIntData,0 ; WARNING!!! This structure and the "C"
X                              ;            version MUST match!!!!
X        APTR    ExecLib       ; ExecBase
X        APTR    GraphicsLib   ; GfxBase
X        APTR    Task          ; task to signal
X        LONG    SignalMask    ; signal(s) to send to task
X        APTR    CurrentLeftView  ; View to LoadView() for open left lens
X        APTR    CurrentRightView ; View to LoadView() for open right lens
X        APTR    LeftView0     ; left lens View 0
X        APTR    LeftView1     ; left lens View 1
X        APTR    RightView0    ; right lens View 0
X        APTR    RightView1    ; right lens View 1
X        UWORD   Frame         ; which left & right Views do I want
X        UBYTE   Lens          ; which lens is open
X        UBYTE   Flip          ; flag to change Views
X
X        PAGE
X_LensInt:
X        move.l  A1,A5         ; need A1, make A5 point to LensIntData
X        cmpi.b  #LEFT,Lens(A5)   ; check current lens state
X        bne.b   OpenLeftLens
X
XOpenRightLens:
X        move.b  #RIGHT,D0     ; go open the right lens
X        move.b  D0,Lens(A5)   ; save as new lens state
X        jsr     SetLens
X
X        move.l  CurrentRightView(A5),A1   ; get the right View
X        bra.b   CommonCode    ; go put it up
X
XOpenLeftLens:
X        move.b  #LEFT,D0      ; go open the left lens
X        move.b  D0,Lens(A5)   ; save as new lens state
X        jsr     SetLens
X
X        tst.b   Flip(A5)      ; hidden buffers ready?
X        beq.b   NoChange      ; nope
X        clr.b   Flip(A5)      ; yes, clear flip request
X
X        tst.w   Frame(A5)     ; determine which frame to display
X        bne.b   Frame2
X
XFrame1:
X        move.l  LeftView0(A5),CurrentLeftView(A5)     ; make frame 0 display
X        move.l  RightView0(A5),CurrentRightView(A5)
X        move.w  #1,Frame(A5)  ; set hidden frame to 1
X        bra.b   Signal        ; hop
X
XFrame2:
X        move.l  LeftView1(A5),CurrentLeftView(A5)     ; make frame 1 display
X        move.l  RightView1(A5),CurrentRightView(A5)
X        clr.w   Frame(A5)     ; set hidden frame to 0
X
XSignal:
X        move.l  SignalMask(A5),D0   ; signal task it can start drawing into
X        move.l  Task(A5),A1         ; hidden Views
X        move.l  ExecLib(A5),A6
X        CALLSYS Signal
X
XNoChange:
X        move.l  CurrentLeftView(A5),A1 ; get the left View
X
X        PAGE
XCommonCode:
X        move.l  GraphicsLib(A5),A6  ; LoadView the View
X        CALLSYS LoadView
X
X        moveq   #0,D0         ; let other handlers in the chain run
X        lea     _custom,A0    ; I shouldn't have to do this
X        rts
X
X
X        END
X
HI_MOM
fi # end of overwriting check
if test -f 'xspeclens.asm'
then
	echo shar: will not over-write existing file "'xspeclens.asm'"
else
sed 's/^X//' << \HI_MOM > 'xspeclens.asm'
X; X-Specs lens control routines
X;
X; Copyright 1988 by Raymond S. Brand, All rights reserved.
X;  19880831
X;
X
X
X        SECTION text
X
X        XDEF    SetLens
X        XDEF    _OpenLensPort
X        XDEF    _CloseLensPort
X        XDEF    _RemindLensPort
X
X        PAGE
X        SECTION data
X
XDATAPORT        equ     $00bfe001
XDIRECTIONPORT   equ     $00bfe201
XLENSBIT         equ     7
XLENSMASK        equ     $80
XNOTLENSMASK     equ     $7f
X
XLensDirSave     DS.B    1
X                CNOP    0,4
X        PAGE
X        SECTION text
X
X; SetLens makes the given lens transparent and the other opaque
X;  Lens to open is in D0. May trash D0-D1,A0-A1
X;
X; Theory of Operation:
X;  Sets or clears the "Fire Button" line of the second mouse port as
X;  appropriate for the lens to open. Setting the bit opens the left lens
X;  and clearing the bit opens the right lens.
X;
X; Warnings:
X;  There seems to be no "nice" way to do this sort of thing.
X;
X;  The data direction is assumed to have already been set to output on the
X;  "fire button" line.
X
XSetLens:
X        move.b  DATAPORT,D1      ; get (possibly) other ouputs state
X        andi.b  #NOTLENSMASK,D1  ; clear our bit
X        andi.b  #LENSMASK,D0     ; shouldn't need to do this but.....
X        or.b    D0,D1            ; set out bit as appropriate
X        move.b  D1,DATAPORT      ; make the "fire" line reflect my wishes
X        rts
X
X
X; _OpenLensPort save the current direction bit of the "fire button" line
X;  of the second mouse port and then sets the direction to output.
X;  May trash D0-D1,A0-A1
X;
X; Warnings:
X;  There seems to be no "nice" way to do this sort of thing.
X
X_OpenLensPort:
X        move.b  DIRECTIONPORT,D1 ; get current direction bits
X        move.b  D1,LensDirSave   ; save them
X        ori.b   #LENSMASK,D1     ; set "fire" to output
X        move.b  D1,DIRECTIONPORT
X        rts
X
X
X        PAGE
X; _CloseLensPort restores the direction bit of the "fire button" line
X;  of the second mouse port saved in _OpenLensPort.
X;  May trash D0-D1,A0-A1
X;
X; Warnings:
X;  There seems to be no "nice" way to do this sort of thing.
X
X_CloseLensPort:
X        move.b  DIRECTIONPORT,D1 ; dir bits may have changed since open
X        move.b  LensDirSave,D0   ; get saved "fire" direction
X        andi.b  #NOTLENSMASK,D1  ; clear "fire" direction bit
X        andi.b  #LENSMASK,D0     ; remove other bits
X        or.b    D0,D1            ; set it to saved state
X        move.b  D1,DIRECTIONPORT ; restore direction
X        rts
X
X
X; _RemindLensPort sets the direction bit of the "fire button" line
X;  of the second mouse port to output. This is used in cases where some
X;  other program reprogrammed the direction port.
X;  May trash D0-D1,A0-A1
X;
X; Warnings:
X;  There seems to be no "nice" way to do this sort of thing.
X
X_RemindLensPort:
X        move.b  DIRECTIONPORT,D1 ; get current directions
X        ori.b   #LENSMASK,D1     ; set "fire" for output
X        move.b  D1,DIRECTIONPORT
X        rts
X
X
X
X        END
HI_MOM
fi # end of overwriting check
#	End of shell archive
exit 0