Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!rutgers!sri-spam!ames!ucbcad!ucbvax!decvax!decwrl!labrea!rocky!rokicki From: rokicki@rocky.STANFORD.EDU (Tomas Rokicki) Newsgroups: comp.sys.amiga Subject: Safe sex: Play with your blitter! Message-ID: <245@rocky.STANFORD.EDU> Date: Fri, 17-Apr-87 15:16:24 EST Article-I.D.: rocky.245 Posted: Fri Apr 17 15:16:24 1987 Date-Received: Tue, 21-Apr-87 02:11:00 EST Organization: Stanford University Computer Science Department Lines: 785 Part 2 of 2. #! /bin/sh : This is a shar archive. Extract with sh, not csh. echo x - render.c cat > render.c << '7544!Funky!Stuff!' /* * This file handles the graphics primitives for BlitLab. */ #include "structures.h" /* * External variables we use. */ extern struct RastPort *myrp ; /* * color sets the current foreground color to the appropriate value. */ color(c) int c ; { SetAPen(myrp, (long)c) ; SetDrMd(myrp, (long)JAM1) ; } /* * This routine draws a horizontal or vertical line. */ line(x1, y1, x2, y2) int x1, y1, x2, y2 ; { int t ; if (x1 > x2) { t = x1 ; x1 = x2 ; x2 = t ; } if (y1 > y2) { t = y1 ; y1 = y2 ; y2 = t ; } if (x1 != x2 && y1 != y2) error("! can only draw h/v lines currently") ; RectFill(myrp, (long)x1, (long)y1, (long)x2, (long)y2) ; } /* * This routine draws a box. */ box(x1, y1, xsize, ysize) int x1, y1, xsize, ysize ; { xsize = x1 + xsize - 1 ; ysize = y1 + ysize - 1 ; line(x1, y1, xsize, y1) ; line(xsize, y1, xsize, ysize) ; line(xsize, ysize, x1, ysize) ; line(x1, ysize, x1, y1) ; } /* * This routine draws a filled box. */ fbox(x1, y1, xsize, ysize) int x1, y1, xsize, ysize ; { RectFill(myrp, (long)x1, (long)y1, (long)(x1 + xsize - 1), (long)(y1 + ysize - 1)) ; } /* * This routine draws a text string at a particular location. It is * somewhat crude; we build an IntuiText structure, and tell it to * draw it. */ static struct IntuiText dmy = { WHITE, BLUE, JAM2, 0, 0, NULL, NULL, NULL } ; drawtext(x, y, s) int x, y ; char *s ; { dmy.IText = (UBYTE *)s ; PrintIText(myrp, &dmy, (long)(x), (long)(y)) ; } 7544!Funky!Stuff! echo x - gadgets.c cat > gadgets.c << '7544!Funky!Stuff!' /* * Gadgets for BlitLab. We have something like 40 gadgets here. */ #include "structures.h" /* * To make things nice, we build the gadgets up, one by one. First, * the externals we use. */ extern struct Window *mywindow ; extern char *bufarr[] ; extern char strings[] ; extern void *allocmem() ; extern struct Gadget *gadgets[] ; /* * This routine allocates a border description. */ static struct Border *givebox(xsize, ysize) int xsize, ysize ; { register struct Border *bp ; register short *r ; bp = allocmem((long)sizeof(struct Border), MEMF_CLEAR) ; r = allocmem(20L, MEMF_CLEAR) ; r[2] = xsize ; r[4] = xsize ; r[5] = ysize ; r[7] = ysize ; bp->FrontPen = WHITE ; bp->DrawMode = JAM2 ; bp->Count = 5 ; bp->XY = r ; return(bp) ; } /* * This routine allocates an intuitext structure, with a string * centered in it. */ static struct IntuiText *centertext(size, s) int size ; char *s ; { register struct IntuiText *itp ; itp = allocmem((long)sizeof(struct IntuiText), MEMF_CLEAR) ; itp->FrontPen = WHITE ; itp->DrawMode = JAM2 ; itp->TopEdge = 2 ; itp->LeftEdge = (size - strlen(s) * 8) / 2 ; itp->IText = (UBYTE *)s ; return(itp) ; } /* * This routine builds a simple hit gadget, given an id, x and * y locations, xsize and ysize, and a string label. */ static buildhit(id, x, y, xsize, ysize, s) int id ; int x, y, xsize, ysize ; char *s ; { register struct Gadget *gp ; gp = allocmem((long)sizeof(struct Gadget), MEMF_CLEAR) ; gp->LeftEdge = x ; gp->TopEdge = y ; gp->Width = xsize ; gp->Height = ysize ; gp->Flags = GADGHCOMP ; gp->Activation = RELVERIFY ; gp->GadgetType = BOOLGADGET ; gp->GadgetRender = (APTR)givebox(xsize, ysize) ; gp->GadgetText = centertext(xsize, s) ; gp->GadgetID = id ; gadgets[id] = gp ; AddGadget(mywindow, gp, 0) ; } /* * This routine builds a gadget with two possible strings. It is up * to the user to flip the strings when it is selected; this means * taking it off the list and putting it back on. */ static buildtoggle(id, x, y, xsize, ysize, s1, s2) int id ; int x, y, xsize, ysize ; char *s1, *s2 ; { register struct Gadget *gp ; gp = allocmem((long)sizeof(struct Gadget), MEMF_CLEAR) ; gp->LeftEdge = x ; gp->TopEdge = y ; gp->Width = xsize ; gp->Height = ysize ; gp->Flags = GADGHNONE ; gp->Activation = GADGIMMEDIATE ; gp->GadgetType = BOOLGADGET ; gp->GadgetRender = (APTR)givebox(xsize, ysize) ; gp->GadgetText = centertext(xsize, s1) ; gp->GadgetID = id ; gp->UserData = (APTR)centertext(xsize, s2) ; gadgets[id] = gp ; AddGadget(mywindow, gp, 0) ; } /* * This routine builds a simple string gadget. We allocate pieces * of the `strings' array as we do the gadgets. `p' holds a pointer * to the next available chunk; we have to be careful to initialize. * We also allow a label parameter which lives to the left of the * string gadget. */ static char undobuf[100] ; static char *p ; static buildstring(id, x, y, width, init, rmax, lab) int id ; int x, y ; int width ; char *init ; int rmax ; char *lab ; { register struct Gadget *gp ; register struct StringInfo *sip ; register struct Border *bp ; int ysize ; int xsize ; int chars ; if (lab != NULL) { drawtext(x + 4, y + 2, lab) ; x += 8 + strlen(lab) * 8 ; width -= 8 + strlen(lab) * 8 ; } chars = ( width - 4 ) / 8 ; ysize = VSTRSIZE ; xsize = HSTRSIZE(chars) ; bufarr[id] = p ; strcpy(p, init) ; gp = allocmem((long)sizeof(struct Gadget), MEMF_CLEAR) ; sip = allocmem((long)sizeof(struct StringInfo), MEMF_CLEAR) ; sip->Buffer = (UBYTE *)p ; p += rmax ; sip->UndoBuffer = (UBYTE *)undobuf ; sip->MaxChars = rmax ; gp->LeftEdge = x + 2 ; gp->TopEdge = y + 2 ; gp->Width = xsize ; gp->Height = ysize - 3 ; gp->Flags = GADGHCOMP ; gp->Activation = RELVERIFY ; gp->GadgetType = STRGADGET ; bp = givebox(xsize - 2, ysize - 2) ; bp->XY[0] = -2 ; bp->XY[1] = -2 ; bp->XY[3] = -2 ; bp->XY[6] = -2 ; bp->XY[8] = -2 ; bp->XY[9] = -2 ; gp->GadgetRender = (APTR)bp ; gp->GadgetText = NULL ; gp->SpecialInfo = (APTR)sip ; gp->GadgetID = id ; gadgets[id] = gp ; AddGadget(mywindow, gp, 0) ; } /* * This routine actually creates all of the gadgets. Wish * us luck placing all of these correctly! */ buildgadgets() { int i ; p = strings ; buildhit(GDGGO, HGOSTART, VGOSTART, HGOSIZE, VGOSIZE, "GO") ; buildhit(GDGSETUP, HMG3START, VMG2START, HMGSIZE, VMGSIZE, "Setup") ; buildhit(GDGCALC, HLMGSTART, VLMG5, HLMGSIZE, VLMGSIZE, "Calc") ; buildtoggle(GDGPNTREG, HLMGSTART, VLMG1, HLMGSIZE, VLMGSIZE, "Point", " Box ") ; buildtoggle(GDGCLRSET, HLMGSTART, VLMG2, HLMGSIZE, VLMGSIZE, "Clear", " Set ") ; buildtoggle(GDGLINE, HMG3START, VMG1START, HMGSIZE, VMGSIZE, "(line)", " LINE ") ; buildtoggle(GDGDESC, HMG6START, VMG1START, HMGSIZE, VMGSIZE, "(desc)", " DESC ") ; buildtoggle(GDGFCI, HMG7START, VMG1START, HMGSIZE, VMGSIZE, "(fci)", " FCI ") ; buildtoggle(GDGIFE, HMG8START, VMG1START, HMGSIZE, VMGSIZE, "(ife)", " IFE ") ; buildtoggle(GDGEFE, HMG9START, VMG1START, HMGSIZE, VMGSIZE, "(efe)", " EFE ") ; for (i=0; i<4; i++) buildtoggle(GDGUSEA+i, HRVC8, VRG1 + 11 * i, 24, VSTRSIZE, "N", "Y") ; buildstring(GDGSX, HMG1START, VMG1START, HMGSIZE, "0", 20, "SX") ; buildstring(GDGSY, HMG2START, VMG1START, HMGSIZE, "0", 20, "SY") ; buildstring(GDGEX, HMG1START, VMG2START, HMGSIZE, "0", 20, "EX") ; buildstring(GDGEY, HMG2START, VMG2START, HMGSIZE, "0", 20, "EY") ; buildstring(GDGH, HMG4START, VMG1START, HMGSIZE, "0", 20, "W") ; buildstring(GDGV, HMG5START, VMG1START, HMGSIZE, "0", 20, "H") ; buildstring(GDGFUNC, HMG4START, VMG2START, 6 * HMGSIZE, "0", 100, "Function") ; for (i=0; i<4; i++) buildstring(GDGAPT+i, HRVC9, VRG1 + 11 * i, HSTRSIZE(8), "0", 20, NULL) ; for (i=0; i<4; i++) buildstring(GDGAMOD+i, HRVC10, VRG1 + 11 * i, HSTRSIZE(6), "0", 20, NULL) ; for (i=0; i<3; i++) buildstring(GDGADAT+i, HRVC11, VRG1 + 11 * i, HSTRSIZE(18), "0", 20, NULL) ; for (i=0; i<2; i++) buildstring(GDGASH+i, HRVC12, VRG1 + 11 * i, HSTRSIZE(4), "0", 20, NULL) ; buildstring(GDGAFWM, HRVC11, VRG1 + 33, 180, "%1111111111111111", 20, "FWM") ; buildstring(GDGALWM, HRVC11, VRG1 + 44, 180, "%1111111111111111", 20, "LWM") ; RefreshGadgets(mywindow->FirstGadget, mywindow, NULL) ; } 7544!Funky!Stuff! echo x - mem.c cat > mem.c << '7544!Funky!Stuff!' /* * Memory allocation and deallocation for BlitLab. */ #include "structures.h" struct memnode { struct memnode * next ; long size ; } ; static struct memnode *head ; /* * Replacement for AllocMem. If not enough memory, we exit. */ void *allocmem(size, type) long size ; long type ; { struct memnode *p ; extern void *AllocMem() ; p = (struct memnode *)AllocMem(size + sizeof(struct memnode), type) ; if (p==NULL) error("! out of memory") ; p->size = size + sizeof(struct memnode) ; p->next = head ; head = p ; return(p + 1) ; } /* * Frees all allocated memory. */ freemem() { struct memnode *p ; while (head != NULL) { p = head->next ; FreeMem(head, head->size) ; head = p ; } } 7544!Funky!Stuff! echo x - parse.c cat > parse.c << '7544!Funky!Stuff!' /* * Parse.c of BlitLab software package. This routine handles * parsing the strings into integers, in any of the possible * formats. */ #include "structures.h" /* * Externals we use. */ extern short *realbits ; extern char *bufarr[] ; extern long gvals[] ; extern struct blitregs blitregs ; extern char errorbuf[] ; /* * This is the main parse routine. First, a static to indicate if * we saw a parse error or not. */ static int parseerr ; /* * We allow the following formats: * * (M+)?-?[$%]?[0-9a-f]+ * (~?[ABC])(+(~?[ABC]))* */ long parse(s) register char *s ; { int negative = 1 ; int c ; int radix = 10 ; long toadd = 0 ; long val ; static varr[] = { 0xf0, 0xcc, 0xaa } ; parseerr = 0 ; while (*s == ' ') s++ ; if (*s=='~' || *s=='A' || *s=='B' || *s=='C' || *s=='a' || *s=='b' || *s=='c') { val = 0 ; while (1) { toadd = 255 ; while (1) { if (*s == '~') { negative = 255 ; s++ ; } else negative = 0 ; c = *s++ ; if (c == 0 || c == '+') { if (toadd == 255) parseerr = 1 ; break ; } if (c >= 'a' && c <= 'z') c -= 'a' - 'A' ; if (c < 'A' || c > 'C') { parseerr = 1 ; break ; } toadd &= negative ^ varr[c-'A'] ; } val |= toadd ; if (c != '+') { if (c != 0) parseerr = 1 ; break ; } } return(val) ; } else { if (*s == 'm' || *s == 'M') { if (s[1]=='+') { s += 2 ; toadd = (long)realbits ; } else if (s[1]==0) return((long)realbits) ; else { parseerr = 1 ; return(0) ; } } if (*s == '-') { negative = -1 ; s++ ; } if (*s == '$') { radix = 16 ; s++ ; } else if (*s == '%') { radix = 2 ; s++ ; } val = 0 ; if (*s == 0) { parseerr = 1 ; return(val) ; } while (1) { c = *s ++ ; if (c == 0) break ; if (c >= 'a' && c <= 'z') c -= 'a' - 'A' ; if (c >= 'A' && c <= 'F') c -= 'A' - 10 ; else c -= '0' ; if (c < 0 || c >= radix) { parseerr = 1 ; break ; } val = val * radix + c ; } return(toadd + negative * val) ; } } /* * This routine parses all of the string gadgets. If it is successful, * it returns 1, otherwise it returns 0. */ int parseall() { int i ; for (i=0; i>= 4 ; tmp[2] = hex[val & 15] ; val >>= 4 ; tmp[1] = hex[val & 15] ; val >>= 4 ; tmp[0] = hex[val & 15] ; drawtext(x, y, tmp) ; } /* * This routine calculates and writes out *all* of the blitter * register values. */ updateregs() { int i ; blitregs.con0 = ((gvals[GDGASH] & 15) << 12) + (gvals[GDGUSEA] << 11) + (gvals[GDGUSEB] << 10) + (gvals[GDGUSEC] << 9) + (gvals[GDGUSED] << 8) + (gvals[GDGFUNC] & 255) ; blitregs.con1 = ((gvals[GDGBSH] & 15) << 12) + (gvals[GDGEFE] << 4) + (gvals[GDGIFE] << 3) + (gvals[GDGFCI] << 2) + (gvals[GDGDESC] << 1) + gvals[GDGLINE] ; blitregs.size = ((gvals[GDGV] & 1023) << 6) + (gvals[GDGH] & 63) ; blitregs.afwm = (gvals[GDGAFWM] & 65535) ; blitregs.alwm = (gvals[GDGALWM] & 65535) ; for (i=0; i<4; i++) { blitregs.pth[i] = ((gvals[GDGAPT+i] >> 16) & 65535) ; blitregs.ptl[i] = (gvals[GDGAPT+i] & 65535) ; blitregs.mod[i] = (gvals[GDGAMOD+i] & 65535) ; } for (i=0; i<3; i++) blitregs.dat[i] = (gvals[GDGADAT+i] & 65535) ; /* * Now we write out the values. */ writefour(HRVC2, VRVL1, blitregs.con0) ; writefour(HRVC2, VRVL2, blitregs.con1) ; writefour(HRVC2, VRVL3, blitregs.size) ; writefour(HRVC2, VRVL4, blitregs.afwm) ; writefour(HRVC2, VRVL5, blitregs.alwm) ; for (i=0; i<4; i++) { writefour(HRVC4, VRVL2 + 9 * i, blitregs.pth[i]) ; writefour(HRVC5, VRVL2 + 9 * i, blitregs.ptl[i]) ; writefour(HRVC6, VRVL2 + 9 * i, blitregs.mod[i]) ; } for (i=0; i<3; i++) writefour(HRVC6B, VRVL2 + 9 * i, blitregs.dat[i]) ; } 7544!Funky!Stuff! echo x - math.c cat > math.c << '7544!Funky!Stuff!' /* * This is the math routines of BlitLab. It checks a possible blit to * insure that it is safe. It also handles the line calculations. */ #include "structures.h" /* * The externals we use. */ extern long gvals[] ; extern struct Gadget *gadgets[] ; extern short *realbits ; extern struct Window *mywindow ; extern char errorbuf[] ; /* * This routine insures that a blit is safe. It returns 1 if it is * okay, and 0 if it is not. */ int blitsafe() { long x1, x2, x3, x4 ; long lower, upper ; if (gvals[GDGUSED]==0) return(1) ; lower = (long)realbits ; upper = 382 + (long)realbits ; if (gvals[GDGH] < 1 || gvals[GDGV] < 1 || gvals[GDGH] > 64 || gvals[GDGV] > 1024) return(0) ; if (gvals[GDGLINE]) { } else { x1 = gvals[GDGDPT] ; if (gvals[GDGDESC]) { x2 = x1 - gvals[GDGH] * 2 + 2 ; x3 = x1 - (gvals[GDGV] - 1) * ((gvals[GDGH] * 2) + (gvals[GDGDMOD] & ~1)) ; x4 = x3 - gvals[GDGH] * 2 + 2 ; if (x1 < lower || x2 < lower || x3 < lower || x4 < lower || x1 > upper || x2 > upper || x3 > upper || x4 > upper) return(0) ; else return(1) ; } else { x2 = x1 + gvals[GDGH] * 2 - 2 ; x3 = x1 + (gvals[GDGV] - 1) * ((gvals[GDGH] * 2) + (gvals[GDGDMOD] & ~1)) ; x4 = x3 + gvals[GDGH] * 2 - 2 ; if (x1 < lower || x2 < lower || x3 < lower || x4 < lower || x1 > upper || x2 > upper || x3 > upper || x4 > upper) return(0) ; else return(1) ; } } } /* * This routine stuffs a value in a gadget. Could be dangerous, but * that's life. */ stuff(id, s) int id ; char *s ; { gvals[id] = parse(s) ; RemoveGadget(mywindow, gadgets[id]) ; strcpy(((struct StringInfo *)(gadgets[id]->SpecialInfo))->Buffer, s) ; AddGadget(mywindow, gadgets[id], -1) ; RefreshGadgets(gadgets[id], mywindow, NULL) ; } /* * This routine flips the state of a toggle gadget. */ flipgadg(id) int id ; { struct IntuiText *temp ; struct Gadget *gp = gadgets[id] ; RemoveGadget(mywindow, gp) ; temp = gp->GadgetText ; gp->GadgetText = (struct IntuiText *)gp->UserData ; gp->UserData = (APTR)temp ; gp->NextGadget = NULL ; AddGadget(mywindow, gp, -1) ; RefreshGadgets(gp, mywindow, NULL) ; gvals[id] = 1 - gvals[id] ; } /* * This routine sets up a line. */ setupline() { int x, y ; int i ; int X, Y ; int q = 0 ; parseall() ; stuff(GDGADAT, "$8000") ; stuff(GDGBDAT, "$ffff") ; x = gvals[GDGSX] ; y = gvals[GDGSY] ; sprintf(errorbuf, "%d", x & 15) ; stuff(GDGASH, errorbuf) ; i = ((x >> 3) & ~1) + y * 12 ; sprintf(errorbuf, "M+%d", i) ; stuff(GDGCPT, errorbuf) ; stuff(GDGDPT, errorbuf) ; stuff(GDGCMOD, "12") ; stuff(GDGDMOD, "12") ; stuff(GDGH, "2") ; x = (gvals[GDGEX] - gvals[GDGSX]) ; y = (gvals[GDGEY] - gvals[GDGSY]) ; if (x < 0) X = - x ; else X = x ; if (y < 0) Y = - y ; else Y = y ; if (x > 0) { if (y > 0) { q = (X > Y ? 1 : 0) ; } else { q = (X > Y ? 3 : 4) ; } } else { if (y > 0) { q = (X > Y ? 5 : 2) ; } else { q = (X > Y ? 7 : 6) ; } } if (Y > X) { i = X ; X = Y ; Y = i ; } sprintf(errorbuf, "%d", X+1) ; stuff(GDGV, errorbuf) ; sprintf(errorbuf, "%d", 2 * Y - X) ; stuff(GDGAPT, errorbuf) ; sprintf(errorbuf, "%d", 4 * (Y - X)) ; stuff(GDGAMOD, errorbuf) ; sprintf(errorbuf, "%d", 4 * Y) ; stuff(GDGBMOD, errorbuf) ; stuff(GDGAFWM, "%1111111111111111") ; stuff(GDGALWM, "%1111111111111111") ; if (! gvals[GDGLINE]) flipgadg(GDGLINE) ; if ((q & 1) != gvals[GDGEFE]) flipgadg(GDGEFE) ; if (((q >> 1) & 1) != gvals[GDGIFE]) flipgadg(GDGIFE) ; if (((q >> 2) & 1) != gvals[GDGFCI]) flipgadg(GDGFCI) ; if (! gvals[GDGUSEA]) flipgadg(GDGUSEA) ; if (gvals[GDGUSEB]) flipgadg(GDGUSEB) ; if (! gvals[GDGUSEC]) flipgadg(GDGUSEC) ; if (! gvals[GDGUSED]) flipgadg(GDGUSED) ; } 7544!Funky!Stuff! echo x - doblit.c cat > doblit.c << '7544!Funky!Stuff!' /* * This is the routine which actually does the hard blits. We just get * the blitter, stuff the values, wait for it to finish, disown the * blitter, and get out of there. */ #include "structures.h" /* * External values we use. */ extern struct blitregs blitregs ; /* * This include file includes the defines for all the blitter functions. * It only allows use of the `blit' operations; for area fills or line * drawing, it will need to be extended. * * Information gleaned from the Hardware Reference Manual. */ #define BLTADD (0xdff040L) /* * This structure contains everything we need to know. * Do not do a structure copy into this! Instead, assign * each field. The last field assigned must be bltsize; that * starts up the blitter. Also note that all of these are * write only, and you can't read them. */ struct bltstruct { short con0 ; short con1 ; short afwm ; short alwm ; short cpth, cptl, bpth, bptl, apth, aptl, dpth, dptl ; short bltsize ; short dmy1, dmy2, dmy3 ; short cmod, bmod, amod, dmod ; short dmy4, dmy5, dmy6, dmy7 ; short cdat, bdat, adat ; } *blitter = BLTADD ; /* * The actual routine. After we own the blitter, we need to wait for * it to finish. */ doblit() { OwnBlitter() ; WaitBlit() ; blitter->con0 = blitregs.con0 ; blitter->con1 = blitregs.con1 ; blitter->afwm = blitregs.afwm ; blitter->alwm = blitregs.alwm ; blitter->apth = blitregs.pth[0] ; blitter->bpth = blitregs.pth[1] ; blitter->cpth = blitregs.pth[2] ; blitter->dpth = blitregs.pth[3] ; blitter->aptl = blitregs.ptl[0] ; blitter->bptl = blitregs.ptl[1] ; blitter->cptl = blitregs.ptl[2] ; blitter->dptl = blitregs.ptl[3] ; blitter->amod = blitregs.mod[0] ; blitter->bmod = blitregs.mod[1] ; blitter->cmod = blitregs.mod[2] ; blitter->dmod = blitregs.mod[3] ; blitter->adat = blitregs.dat[0] ; blitter->bdat = blitregs.dat[1] ; blitter->cdat = blitregs.dat[2] ; /* * Wham! It is the following assignment that starts the blitter. */ blitter->bltsize = blitregs.size ; WaitBlit() ; DisownBlitter() ; } 7544!Funky!Stuff!