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