Mercurial > hg > Members > kono > nitros9-code
changeset 1188:aaae5eac20e1
Provded by James Jones
author | boisy |
---|---|
date | Fri, 30 May 2003 21:13:48 +0000 |
parents | df263e490f85 |
children | 93f0119d2c27 |
files | 3rdparty/utils/viewgif/ReadMe 3rdparty/utils/viewgif/gifwin.c 3rdparty/utils/viewgif/setmap.c 3rdparty/utils/viewgif/viewgif.c 3rdparty/utils/viewgif/viewgif.h 3rdparty/utils/viewgif/viewvef.c |
diffstat | 6 files changed, 2383 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/3rdparty/utils/viewgif/ReadMe Fri May 30 21:13:48 2003 +0000 @@ -0,0 +1,151 @@ +The following is some discussion of just what's going on in viewgif, so that +future code maintainers and modifiers can have an easier time of it. + +Viewgif's main purpose is to decode GIF files and turn them into images that +can be displayed on the CoCo. The obstacles to such display are: + +1. GIF images can contain up to 256 colors, which are specified in RGB-888 + form (i.e. eight bits of resolution along each axis of RGB space, a 3-D + space for colors whose basis consists of {red, green, blue}). The CoCo + can display at most 16 colors out of the 64 colors that live in RGB-222. + +2. GIF images are compressed, using Lempel-Ziv compression (up to 12-bit + code length). + +The second part is no big deal; in fact, the method used in viewgif is that +used in the early LZ compress program ported to OS-9/6809 a few years ago. +The first part is the one of major interest here. + +Viewgif uses two methods to overcome the GIME's limitations: + +1. Representing each color c[i] in the GIF image with a sum of two colors + c1[i] and c2[i], where c1[i] + c2[i] is approximately equal to c[i]. + The c1[i] are displayed on one window and the c2[i] on another, and + viewgif alternates rapidly between the two windows. This gives us + additional resolution in RGB space. + +2. Dithering, adding random noise to the displayed image. It may seem odd + that adding noise to an image should improve it, but in fact it does, + because it spreads out quantization error, and quantization error, + the error induced by going from a continuous quantity to a discrete + representation or, in our case, cutting down the resolution available, + is the big problem here. The easiest way to see it is to use a non- + dithering CoCo GIF viewer on an image with lots of shading--portraits + are best, because you know what color people are. (Starships could be + any color. :-) It will look like someone painted the person brick red + or yellow, or like whoever does the *USA Today* weather maps body painted + the person. Or maybe both! + +The real guts of viewgif is that portion which determines what "dithering +factor" is the best for a given image. (You get to specify whether you +want one or two windows.) This is done in the function newwind(), in the +file viewgif.c, and the functions it calls (setmap() and approx1() and +approx2() in setmap.c). newwind() uses a binary search to find the largest +dithering factor less than or equal to the one given on the command line +(or the default, if you don't specify one) for which all the colors can +successfully be mapped to those available on the one or two windows available. +The dithering factor is "extended" in the negative direction by interpreting +a negative dithering factor as increased sloppiness about what is considered +"successful" mapping, so that this search always "succeeds." Viewgif will +show a positive "color tolerance" in this case. + +(If you look at the function approx2(), the function that approximates the +the colors in the GIF CLUT (Color Look-Up Table) for the two-screen case, +you'll note that not all pairs of colors are considered as possible sums; +instead, only those pairs that are "near" one another are tried. I can only +guess at the reason behind this, but I think that it is done to prevent the +change between windows from being excessively noticeable. If you know +of a reference that describes the algorithms used here, it would be nice +to add that in the program comments.) + +Scattered throughout the original code were some numbers like 85, 42, and +21. These have to do with the conversion from RGB888 to RGB222. The +maximum value for a color component in RGB888 is 255, and in RGB222 is 3, +so...to convert, one scales by a factor of 255 / 3 = 85. (For two screens, +this program uses 85 / 2, or 42.) toler() and toler2(), the functions that +determine how "close" two colors are, do their comparison in RGB888 space, +but consider all colors that would map to the goal color in the CoCo display +space equally close. (The upper bound on the dithering factor is the +"radius" of that neighborhood in RGB888 space.) + +For those who saw the original viewgif, here are the changes I've made: + + 1. A header file, viewgif.h, has been added, with #defines that I hope will + give some idea where the magic values come from. We've also anticipated + attempts to port to OS-9/68000, though of course the low-level routines + are quite CoCo-specific. + + 2. The data have been restructured. Most notably, the rgbcolor and + cocoscreen types are attempts to collect related data in an intelligible + fashion, to allow iteration over screens or color components, to let + the common outer loop in setmap() be actual common code, and to avoid + needless replication of code in the loop that tries to extend just + one CLUT in approx2(). We hope we are anticipating generalization to + three or more windows, though that way lies madness, more memory usage, + and a combinatorial explosion in the approx3() function that one would + have to add. + + 3. Scalar global variables have been explicitly put on the direct page + for speed. (This has been made conditional for possible porting.) + The assembly-language functions have been changed to reflect this + placement as well, since Vaughn Cato tried to pick time-critical + functions for conversion to assembly language. Speaking of which, + we added comments showing addpixel() in C--not that it's tough to + figure out, but every little bit helps. + + 4. Some judiciously-placed register declarations have been added, again + for speed. + + 5. Subscripting has been turned into pointer arithmetic in various places. + + 6. Some functions have been moved into what seems to me to be more + appropriate files, considering who calls them and the general purpose + of the functions in the file. (Some more of this should be done; in + particular, functions not related to window manipulation should be + moved out of gifwin.c.) + + 7. A bug in what was setmap2() but is now approx2() was corrected. The + original was not toggling the "mode" variable, so that it would never + look at possible sums extending the larger CLUT. + + 8. approx2() (formerly setmap2()) has added an array in which we recall + the results of the nearcolor() function, rather than calling it lots + of times. (I think this is the big win for speeding up the analysis + phase.) + + 9. We added a -? option. + +10. We added a -z option, that overwrites the global color map after + replacing unused colors with some color that is used. CAUTION: + this overwrites the whole global color map, and said color map is + manipulated in other ways via the -g, -g2, and -b options. You + can lose information if you combine -z with those options, and + perhaps we should prevent them from being used together. + +There is still more that can be done to speed things up. + + 1. It should be possible to speed up the decompression. Alas, the obvious + way, i.e. going with a hash table rather than a tree, may eat more memory + than we can afford; nevertheless, it is worth investigating. + + 2. It may be worth trying putting two scan lines at a time instead of one, + to cut system call overhead. One would have to allocate get/put buffers + for each window to do this. It's not clear whether it would be a win + for interleaved images. + + 3. This version of viewgif shares the problems of the program it is based + on. (Indeed, it would be surprising if it didn't!) Aside from smarter + mapping of colors, which I fear would require two passes over the GIF + file, the main one concerns smarter handling of aspect ratios. Most + likely, since the current GIF specification doesn't say beans about + aspect ratio, one will have to let the user tweak the aspect ratio + on the command line. + + 4. The VEF files generated may not be quite correct; vefprt seems to emit + a few lines of junk before putting out the rest of the image properly. + This behavior seems to be the same for the old and the new versions of + the program. + + 5. The code that waits for the user to type a character could be changed + to use the SS_SSIG setstat along with an intercept() routine, to cut + system overhead.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/3rdparty/utils/viewgif/gifwin.c Fri May 30 21:13:48 2003 +0000 @@ -0,0 +1,308 @@ +/* + * gifwin.c - window functions for ViewGIF 2.0 + * by Vaughn Cato + */ + +#include "viewgif.h" + +char *mapgpb(); +extern int errno; + +checksig() +{ + char buf[6]; + + fread(buf, sizeof(*buf), 6, infile); + if (strncmp(buf, "GIF", 3) != 0) + fatal("file is not a GIF file"); + if (strncmp(&buf[3], "87a", 3) != 0) + fatal("Unknown GIF version number"); +} + +perror(str) +char *str; +{ + fprintf(stderr, "%s: error\n", str); +} + +error(str, errnum) +char *str; +int errnum; +{ + fprintf(stderr, "viewgif: %s\n", str); + exit(errnum); +} + +sleep(ticks) +int ticks; +{ +#asm + ldx 4,s + os9 F$Sleep +#endasm +} + +static char *ustext[] = { + "OS9 ViewGIF 2.0 by Vaughn Cato\n", + "usage: viewgif <filename> [-<option> ...]\n", + " displays a gif picture\n", + "\n", + " options:\n", + " -d[[=]dfactor] Set dithering factor, default is 0\n", + " -a Align to pixels\n", + " -u[=]<filename> Create/use a color usage file\n", + " -m[=]<magfact> Set magnification factor (1-64)\n", + " -x[=]<start x> Set start x (0-64)\n", + " -y[=]<start y> Set start y (0-64)\n", + " -v[[=]<filename>] Generate vef format picture\n", + " -g grey scale picture (average color brite)\n", + " -g2 grey scale picture (max color brite)\n", + " -g3 grey scale picture (NTSC color brite)\n", + " -r Use random generator instead of table\n", + " -s Silent. No info printed\n", + " -i Extended information\n", + " -n No display\n", + " -p[[=]seconds] Pause time (default 0)\n", + " -c Use current screen\n", + " -f Disable flicker\n", + " -b[=]<britefact> Set brightness (1-16)\n", + " -z Zap unused global color map entries\n", + NULL +}; + +usage() +{ + register char **uscan; + + for (uscan = ustext; *uscan != NULL; uscan++) + fputs(*uscan, stderr); + exit(1); +} + +initwin(firstscreen, oldpath) +bool firstscreen; +int oldpath; +{ + register bool newwin; + + newwin = (oldpath == -1); + + if (newwin) { + if (!newscrn && firstscreen) { + /* just use stdout */ + actwin = oldpath = 1; + dwend(); + } else if ((actwin = oldpath = open("/w", 3)) == -1) + exit(errno); + } else { + actwin = oldpath; + dwend(); + } + + dwset(gmode ? 7 : 8, 0, 0, gmode ? 80 : 40, 24, 0, 0, 0); + curoff(); + select(); + flushwin(); + + if (newwin && firstscreen) { + groupnum = getpid(); + bufnum = 1; + getblk(groupnum, bufnum, 0, 0, 640, 1); + flushwin(); + if ((gpbufptr = mapgpb(actwin, groupnum, bufnum, 1)) == NULL) + exit(errno); + } + + return actwin; +} + +dwset(sty, cpx, cpy, szx, szy, prn1, prn2, prn3) +int sty, cpx, cpy, szx, szy, prn1, prn2, prn3; +{ + static char outstr[] = { + 0x1b, 0x20, 0, 0, 0, 0, 0, 0, 0, 0 + }; + int size; + + outstr[2] = sty; + outstr[3] = cpx; + outstr[4] = cpy; + outstr[5] = szx; + outstr[6] = szy; + if (sty > 0 && sty <= 8) { + outstr[7] = prn1; + outstr[8] = prn2; + outstr[9] = prn3; + size = sizeof(outstr); + } else + size = sizeof(outstr) - 3; + writemem(outstr, size); +} + +dwend() +{ + static char outstr[] = {0x1b, 0x24}; + + writemem(outstr, sizeof(outstr)); +} + +select() +{ + static char outstr[] = {0x1b, 0x21}; + + writemem(outstr, sizeof(outstr)); +} + +bell() +{ + char c = 7; + writemem(&c, 1); +} + +palette(prn, ctn) +{ + static char outstr[] = {0x1b, 0x31, 0, 0}; + + outstr[2] = prn; + outstr[3] = ctn; + writemem(outstr, sizeof(outstr)); +} + +point(x, y) +int x, y; +{ + static char outstr[] = {0x1b, 0x42, 0, 0, 0, 0}; + + *(int *) &outstr[2] = x; + *(int *) &outstr[4] = y; + writemem(outstr, sizeof(outstr)); +} + +lineto(x, y) +int x, y; +{ + static char outstr[] = {0x1b, 0x46, 0, 0, 0, 0}; + + *(int *) &outstr[2] = x; + *(int *) &outstr[4] = y; + writemem(outstr, sizeof(outstr)); +} + +fcolor(c) +int c; +{ + static char outstr[] = {0x1b, 0x32, 0}; + + outstr[2] = c; + writemem(outstr, sizeof(outstr)); +} + +border(c) +int c; +{ + static char outstr[] = {0x1b, 0x34, 0}; + + outstr[2] = c; + writemem(outstr, sizeof(outstr)); +} + +SetDPtr(x, y) +int x, y; +{ + static char outstr[] = {0x1b, 0x40, 0, 0, 0, 0}; + + *(int *) &outstr[2] = x; + *(int *) &outstr[4] = y; + writemem(outstr, sizeof(outstr)); +} + +curoff() +{ + static char outstr[] = {0x05, 0x20}; + + writemem(outstr, sizeof(outstr)); +} + +getblk(grp, bfn, cpx, cpy, szx, szy) +int grp, bfn, cpx, cpy, szx, szy; +{ + static char outstr[] = {0x1b, 0x2c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + outstr[2] = grp; + outstr[3] = bfn; + *(int *) (&outstr[4]) = cpx; + *(int *) (&outstr[6]) = cpy; + *(int *) (&outstr[8]) = szx; + *(int *) (&outstr[10]) = szy; + writemem(outstr, sizeof(outstr)); +} + +putblk(grp, bfn, cpx, cpy) +int grp, bfn, cpx, cpy; +{ + static char outstr[] = {0x1b, 0x2d, 0, 0, 0, 0, 0, 0}; + + outstr[2] = grp; + outstr[3] = bfn; + *(int *) (&outstr[4]) = cpx; + *(int *) (&outstr[6]) = cpy; + writemem(outstr, sizeof(outstr)); +} + +killbuf(grp, bfn) +int grp, bfn; +{ + static char outstr[] = {0x1b, 0x2a, 0, 0}; + + outstr[2] = grp; + outstr[3] = bfn; + writemem(outstr, sizeof(outstr)); +} + +char * +mapgpb(path, grp, bfn, action) +int path, grp, bfn, action; +{ +#asm + lda 7,s group + ldb 9,s buffer + tfr d,x ->X + lda 5,s path + ldb #$SS.MpGPB setstat code + pshs y + ldy 10+2,s action (1 => map, 0 => unmap) + os9 I$SetStt + puls y + bcc _mapgpb1 + clra error-- + std errno,y save error code, + ldx #0 return NULL pointer +_mapgpb1: tfr x,d move pointer into position for return +#endasm +} + +static char outbuf[256]; +static DIRECT char *outptr = outbuf; +static DIRECT int bufleft = sizeof(outbuf); + +writemem(str, size) +register char *str; +register int size; +{ + while (size > bufleft) { + size -= bufleft; + while (--bufleft >= 0) + *outptr++ = *str++; + flushwin(); + } + bufleft -= size; + while (--size >= 0) + *outptr++ = *str++; +} + +flushwin() +{ + write(actwin, outbuf, outptr - outbuf); + outptr = outbuf; + bufleft = sizeof(outbuf); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/3rdparty/utils/viewgif/setmap.c Fri May 30 21:13:48 2003 +0000 @@ -0,0 +1,363 @@ +/* + * SetMap - Palette creator for ViewGIF 2.0 + * These routines are the heart of the color analysis. They take the + * global bitmap and, based on the dithering factor, produce a CoCo color + * palette. + */ + +#include "viewgif.h" + +int toler2(), exact(); +bool nearcolor(); + +/* + * setmap() -- determine whether, given the specified dithering factor, + * there are CLUTs for the screens we've been told to use that will let + * us come reasonably close to representing the colors in the GIF image. + * We change the semantics from the original version, returning FALSE + * if not all the CLUT etnries can be fit in, or TRUE if they all work. + * + * Method: look for approximations to each color in use in terms of colors + * already in the CLUTs. If none is close enough, then add the color + * (or some decomposition thereof, in the multiple screen case) to the + * CLUTs. If there's no room left to add the color, we return FALSE. + * + * Note: we're trying to trade space for speed in the innermost loop of + * doline() by always leaving an end marker, avoiding double testing in + * said loop. We'll see how it works out. + */ +bool +setmap() +{ + rgbcolor next; + register int add; + register rgbcolor *gcscan; + register xlate *trscan; + int numtrans, tolrnce, x, uplim, lowlim; + + /* should be a loop if we really do change NSCREENS */ + screen[0].clutsize = screen[1].clutsize = 0; + + lowlim = low0; + uplim = up0; + + if (dfactor > 0) { + tolrnce = 0; + lowlim -= dfactor; + } else + tolrnce = -dfactor; + + if (dfactor > (int) flicker) + uplim += dfactor; + + for (gcscan = globclut, x = 0; x < globcolors; gcscan++, x++) { + if (coloruse[x]) { + numtrans = 0; + trscan = &transtab[x][0]; + for (add = lowlim; add < uplim; add = minadd(gcscan, add)) { + trscan->addval = add; + addoff(&next, gcscan, add); + if (!(*approx)(&next, trscan, tolrnce)) + return FALSE; + if (++numtrans > 4) + fatal("BUG: numtrans>4"); + trscan++; + } + /* mark end of transtab entries for this color */ + trscan->addval = BOGUSDITH; + } + } + return TRUE; +} + +addoff(color, color0, offset) +register BYTE *color, *color0; +int offset; +{ + register int accum, x; + + for (x = 3; --x >= 0; ) { + if ((accum = arith(*color0++) + offset) > 0xff) + accum = 0xff; + *color++ = accum; + } +} + +/* + * approx1() -- the approximation seeker if there's only one screen + */ +bool +approx1(goal, trans, toler) +rgbcolor *goal; +xlate *trans; +int toler; +{ + register rgbcolor *cscan, *nearest; + int x, mintoler, tv; + + mintoler = toler + 1; + nearest = NULL; + for (cscan = screen[0].clut, x = screen[0].clutsize; --x >= 0; cscan++) { + if ((tv = tolerval(cscan, goal)) < mintoler) { + nearest = cscan; + if ((mintoler = tv) == 0) + break; + } + } + + if (nearest == NULL) { + if (++screen[0].clutsize > MCCLUT) + return FALSE; + cscan->red = arith(goal->red) / SCALE1; + cscan->green = arith(goal->green) / SCALE1; + cscan->blue = arith(goal->blue) / SCALE1; + nearest = cscan; + } + trans->clutval[0] = nearest - screen[0].clut; + return TRUE; +} + +/* + * approx2() -- a two-screen approximator + * + * The general idea here takes multiple passes: + * 1. Iterate over sums of pairs of colors taken one from each screen. + * 2. If that fails, then for each screen, try adding something that + * should come close with each of the colors in the CLUT for the + * other screen. (Try it with the smallest CLUT first, to save space.) + * 3. If *that* fails, extend both CLUTs with the new color (at half + * intensity). + * + * Since in step 1, which one would think eats the most time, viewgif was + * making repeated calls to nearcolor(), we've switched over to keeping + * a table remembering which colors in the palettes are near as determined + * by nearcolor(). (Donald Michie would be proud of us.) + */ + +static bool neartab[MCCLUT][MCCLUT]; + +#define ROW 1 +#define COLUMN 2 + +bool +approx2(goal, trans, toler) +rgbcolor *goal; +xlate *trans; +int toler; +{ + register int c1, c0; + rgbcolor *scan0, *scan1, *near0, *near1; + cocoscreen *extend, *exam, *temp; + int (*tolfun)(); + char *near_row; + rgbcolor scalergb; + int mintoler, tv; + int x; + bool found; + + scalergb.red = arith(goal->red) / SCALE2; + scalergb.green = arith(goal->green) / SCALE2; + scalergb.blue = arith(goal->blue) / SCALE2; + + if (toler > 0) + tolfun = toler2; + else { + goal = &scalergb; + tolfun = exact; + } + + found = FALSE; + mintoler = toler + 1; + + for (scan0 = &screen[0].clut[c0 = screen[0].clutsize]; + scan0--, --c0 >= 0; ) + { + near_row = neartab[c0]; + for (c1 = screen[1].clutsize; --c1 >= 0; ) { + if (near_row[c1]) { + scan1 = &screen[1].clut[c1]; + if ((tv = (*tolfun)(scan0, scan1, goal)) < mintoler) { + near0 = scan0; + near1 = scan1; + found = TRUE; + if ((mintoler = tv) == 0) + goto out; + } + } + } + } + +out: + if (!found) { + if (screen[1].clutsize < screen[0].clutsize) { + extend = &screen[1]; + exam = &screen[0]; + } else { + extend = &screen[0]; + exam = &screen[1]; + } + for (x = 2; --x >= 0; ) { + if (extend->clutsize < MCCLUT) { + near0 = &extend->clut[extend->clutsize]; + for (scan1 = &exam->clut[c1 = exam->clutsize]; + scan1--, --c1 >= 0; ) + { + forcenear(near0, scan1, &scalergb); + if ((tv = (*tolfun)(near0, scan1, goal)) < mintoler) { + near1 = scan1; + found = TRUE; + if ((mintoler = tv) == 0) + break; + } + } + if (found) + break; + } + temp = extend; + extend = exam; + exam = temp; + } + + if (found) { + if (mintoler > 0) + forcenear(near0, near1, &scalergb); + extend->clutsize++; + if (extend == &screen[0]) + nearfill(ROW); + else { + temp = (cocoscreen *) near0; + near0 = near1; + near1 = (rgbcolor *) temp; + nearfill(COLUMN); + } + } else { + if (screen[0].clutsize >= MCCLUT || + screen[1].clutsize >= MCCLUT) + return FALSE; + near0 = &screen[0].clut[screen[0].clutsize++]; + near0->red = arith(scalergb.red) / 2; + near0->green = arith(scalergb.green) / 2; + near0->blue = arith(scalergb.blue) / 2; + near1 = &screen[1].clut[screen[1].clutsize++]; + near1->red = (arith(scalergb.red) + 1) / 2; + near1->green = (arith(scalergb.green) + 1) / 2; + near1->blue = (arith(scalergb.blue) + 1) / 2; + nearfill(ROW | COLUMN); + } + } + trans->clutval[0] = near0 - screen[0].clut; + trans->clutval[1] = near1 - screen[1].clut; + return TRUE; +} + +nearfill(section) +int section; +{ + register int i, j; + rgbcolor *newrgb; + + if (section & ROW) { + newrgb = &screen[0].clut[j = screen[0].clutsize - 1]; + for (i = screen[1].clutsize; --i >= 0; ) + neartab[j][i] = nearcolor(newrgb, &screen[1].clut[i]); + } + if (section & COLUMN) { + newrgb = &screen[1].clut[j = screen[1].clutsize - 1]; + for (i = screen[0].clutsize; --i >= 0; ) + neartab[i][j] = nearcolor(&screen[0].clut[i], newrgb); + } +} + +/* + * nearcolor() -- tell approx2() whether two colors are close enough + * to be considered for approximate summation to a color in the GIF CLUT. + */ +bool +nearcolor(c1, c2) +register rgbcolor *c1, *c2; +{ + return abs(arith(c2->red) - arith(c1->red)) < 2 && + abs(arith(c2->green) - arith(c1->green)) < 2 && + abs(arith(c2->blue) - arith(c1->blue)) < 2; +} + +/* + * forcenear() -- stuff a color into a CLUT that is guaranteed to + * pass the nearcolor test with the other fixed color (so we don't + * have to call nearcolor() explicitly), and should come close to + * adding to the fixed color (already in the other screen's CLUT) + * to give a specified goal color from the GIF CLUT. + */ +forcenear(vary, fixed, goal) +register BYTE vary[], fixed[], goal[]; +{ + register int d, x; + + for (x = 3; --x >= 0; ) { + if ((d = arith(*vary = *goal++ - *fixed) - arith(*fixed)) < 0) + d = -1; + else if (d > 0) + d = 1; + *vary++ = *fixed++ + d; + } +} + +int +minadd(color, add) +register BYTE *color; +int add; +{ + int maxval, tryadd, x; + + maxval = 0; + for (x = 3; --x >= 0; ) { + if ((tryadd = (arith(*color++) + add) % minmod) > maxval) + maxval = tryadd; + } + return minmod - maxval + add; +} + +int +tolerval(ccolor, gcolor) +register BYTE *ccolor, *gcolor; +{ + int x, v, mv; + + mv = 0; + for (x = 3; --x >= 0; ) { + v = abs(SCALE1 * *ccolor++ + SCALE1 / 2 - arith(*gcolor++)) - + SCALE1 / 2; + if (v > mv) + mv = v; + } + return mv; +} + +int +toler2(ccolor1, ccolor2, gcolor) +register BYTE *ccolor1, *ccolor2, *gcolor; +{ + int x, v, mv; + + mv = 0; + for (x = 3; --x >= 0; ) { + v = abs(SCALE2 * (*ccolor1++ + *ccolor2++) + SCALE2 / 2 - + arith(*gcolor++)) - SCALE2 / 2; + if (v > mv) + mv = v; + } + return mv; +} + +int +exact(ccolor1, ccolor2, gcolor) +register BYTE *ccolor1, *ccolor2, *gcolor; +{ + if (arith(ccolor1[0]) + arith(ccolor2[0]) != arith(gcolor[0])) + return 2; + if (arith(ccolor1[1]) + arith(ccolor2[1]) != arith(gcolor[1])) + return 2; + if (arith(ccolor1[2]) + arith(ccolor2[2]) != arith(gcolor[2])) + return 2; + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/3rdparty/utils/viewgif/viewgif.c Fri May 30 21:13:48 2003 +0000 @@ -0,0 +1,1024 @@ +/* OS-9 ViewGIF 2.0 Copyright (C) 1989 by Vaughn Cato */ + +/* + * This program was specifically written for OS-9 on the Tandy Color + * Computer 3 as its graphics routines will only work on that system. + * The GIF decoding routines were originally taken from the Apollo + * workstation version of viewgif by Ben Samit. As noted in the source + * code provided by Ben, most of his code was taken from a GIF to + * PostScript converter by Scott Hemphill. Because of their consideration + * in providing the source code with their respective programs I am doing + * the same. + * + * I encourage you to send any enhancements in the Color Computer version + * you wish to be publicly distributed to me so that I may update the + * program and re-release it. In this way, a standard version of the + * program can be maintained. + * + * My address is: + * Vaughn Cato + * 1244 E. Piedmont Rd. NE + * Marietta, Ga. 30062 + */ + +/* + * Any portion of this program may be freely used in any software provided + * the source for that program is made freely available to the public and + * credit is given to me, Ben Samit, and Scott Hemphill. + */ + +#define EXTERN /* force a defining instance of global variables */ + +#include <string.h> +#include "viewgif.h" + +void showdata(); +char *mapgpb(); +extern int errno; + +DIRECT int pauselen = -1; +DIRECT bool global; + +main(argc, argv) +int argc; +char *argv[]; +{ + register char *p; + register bool *cscan; + char opt; + bool quit; + int x, argnum; + + dfactor = D_DITHER; + magfact = D_MAG; + britefac = D_BRITE; + infomode = D_INFO; + graytype = D_GRAY; + myheight = D_HEIGHT; + + zapmap = aligned = realrand = vefon = FALSE; + flicker = newscrn = dispon = TRUE; + + for (cscan = &coloruse[MGCLUT]; cscan > coloruse; ) + *--cscan = TRUE; + + screen[0].winpath = screen[1].winpath = -1; + + for (argnum = 1; argnum < argc; ++argnum) { + if (argv[argnum][0] == '-') { + p = &argv[argnum][1]; + while (opt = *p++) { + if (*p == '=') + ++p; + switch (opt) { + case 'd': + if (*p == '\0') + dfactor = 0; + else { + dfactor = atoi(p); + if (dfactor < -MAXTOL1 || dfactor > MAXDITH1) + error("Invalid dithering factor", 1); + } + break; + case 'u': + usefname = p; + break; + case 'm': + magfact = atoi(p); + if (magfact < MINMAG || magfact > MAXMAG) + error("Invalid magnification", 1); + break; + case 'x': + startx = atoi(p); + if (startx < MINCOORD || startx > MAXCOORD) + error("Invalid start x coordinate", 1); + break; + case 'y': + starty = atoi(p); + if (starty < MINCOORD || starty > MAXCOORD) + error("Invalid start y coordinate", 1); + break; + case 'g': + switch (*p) { + case '2': + graytype = MAX_GRAY; + break; + case '3': + graytype = NTSC_GRAY; + break; + default: + graytype = AVG_GRAY; + } + break; + case 'a': + aligned = TRUE; + continue; + case 'z': + dispon = zapmap = TRUE; + continue; + case 'v': + dispon = vefon = TRUE; + if (*p != '\0') + vefname = p; + break; + case 'r': + realrand = TRUE; + continue; + case 's': + infomode = NO_INFO; + continue; + case 'i': + if (newscrn) + infomode = MUCH_INFO; + continue; + case 'n': + if (vefname == NULL) + dispon = FALSE; + continue; + case 'p': + pauselen = atoi(p); + break; + case 'c': + newscrn = FALSE; + infomode = NO_INFO; + continue; + case 'f': + flicker = FALSE; + continue; + case 'b': + britefac = atoi(p); + if (britefac < MINBRITE || britefac > MAXBRITE) + error("Invalid brightness factor", 1); + break; + case '?': + usage(); + default: + fatal("Unknown option"); + } + break; + } + for (x = argnum + 1; x < argc; ++x) + argv[x - 1] = argv[x]; + --argc; + --argnum; + } + } + + if (argc < 2) + usage(); + + if ((infile = fopen(argv[1], "r")) == NULL) + error("Cannot open input file", errno); + + if (flicker) { + maxdith = MAXDITH2; + minmod = SCALE2; + approx = approx2; + } else { + maxdith = MAXDITH1; + minmod = SCALE1; + approx = approx1; + } + if (dfactor > maxdith) + dfactor = maxdith; + low0 = minmod / 2; + up0 = low0 + 1; + + checksig(); + readscrn(); + if (!realrand) + makerand(); + + + quit = FALSE; + framenum = 0; + do { + switch (getc(infile)) { + case '\0': + break; + case ',': + ++framenum; + readimag(); + waituser(); + break; + case ';': + quit = TRUE; + break; + case '!': + readext(); + break; + default: + quit = TRUE; + break; + } + if (!dispon && vefname == NULL && (usefname == NULL || !newuse)) + break; + } while (!quit); + + if (dispon) { + if (zapmap) { + if ((infile = freopen(argv[1], "r+", infile)) == NULL) + error("Cannot rewrite global map", errno); + else + zapglobmap(); + } + killwind(); + } + + actwin = 1; + select(); + flushwin(); +} + +makerand() +{ + register char *rscan1, *rscan2; + int x, f2; + char temp; + bool oddrow, oddrc; + + f2 = maxdith / 2; + + /* initialize */ + x = 256; + for (rscan2 = &randtab[16][0]; (rscan2 -= 16) >= &randtab[0][0]; ) + for (rscan1 = rscan2 + 16; rscan1 > rscan2; ) + *--rscan1 = (--x * f2) >> 8; + + /* + * permute randomly (I don't think the original made all + * permutations equally likely, alas) + */ + rscan1 = &randtab[0][0]; + for (x = 256; x > 0; x--) { + rscan2 = rscan1 + (rand() % x); + temp = *rscan1; + *rscan1++ = *rscan2; + *rscan2 = temp; + } + + oddrow = FALSE; + for (rscan2 = &randtab[16][0]; (rscan2 -= 16) >= &randtab[0][0]; ) { + oddrc = oddrow = !oddrow; + for (rscan1 = rscan2 + 16; --rscan1 >= rscan2; ) { + if (oddrc = !oddrc) + *rscan1 += maxdith; + if (oddrow) + *rscan1 += f2; + } + } +} + +readuse() +{ + char newname[64]; + register char *ep; + int usefile; + + getusename(newname); + if ((usefile = open(newname, 1)) == -1) { + for (ep = &coloruse[MGCLUT]; --ep >= coloruse; ) + *ep = TRUE; + newuse = TRUE; + } else { + read(usefile, coloruse, MGCLUT * sizeof(bool)); + close(usefile); + if (infomode != NO_INFO) + printf("Using usage file\n"); + newuse = FALSE; + } +} + +getusename(buffer) +{ + if (framenum > 1) + sprintf(buffer, "%s%d", usefname, framenum); + else + strcpy(buffer, usefname); +} + +writeuse() +{ + register char *cp, *gp; + int usecount, usefile; + char newname[64]; + + usecount = 0; + for (gp = &globuse[globcolors], cp = &coloruse[globcolors]; + --gp, --cp >= coloruse; ) + { + if (*cp) { + *gp = TRUE; + ++usecount; + } + } + if (infomode != NO_INFO) + printf("%d out of %d colors used.\n", usecount, globcolors); + if (usefname != NULL) { + getusename(newname); + if (newuse) { + if ((usefile = creat(newname, 3)) == -1) + error("Cannot create usage file", errno); + else + write(usefile, coloruse, globcolors); + } + close(usefile); + } +} + +zapglobmap() +{ + register rgbcolor *gp, *used; + register int i; + + for (i = 0; i < globcolors; i++) { + if (globuse[i]) { + used = &globclut[i]; + for (gp = &globclut[i = globcolors]; --i, --gp >= globclut; ) + { + if (!globuse[i]) { + gp->red = used->red; + gp->green = used->green; + gp->blue = used->blue; + } + } + fseek(infile, clutpos, 0); + fwrite(globclut, sizeof(rgbcolor), globcolors, infile); + return; + } + } +} + +saveimag() +{ + register cocoscreen *sscan; + char newname[64]; + int file, x, scrnum, scrntype = 0; + + for (scrnum = 0; scrnum <= flicker; ++scrnum) { + sscan = &screen[scrnum]; + strcpy(newname, vefname); + if (framenum > 1) + sprintf(newname + strlen(newname), "%d", framenum); + if (scrnum == 1) + strcat(newname, ".2"); + actwin = sscan->winpath; + select(); + flushwin(); + if ((file = creat(newname, 3)) == -1) + error("Cannot create vef file", errno); + else { + write(file, &scrntype, sizeof(scrntype)); + write(file, sscan->pal, MCCLUT * sizeof(colorcode)); + for (x = 0; x < 8; ++x) + write(file, gpbufptr, 160); + for (x = 0; x < MROWS; ++x) { + getblk(groupnum, bufnum, 0, x, MCOLS - 1, 1); + flushwin(); + write(file, gpbufptr, 160); + } + close(file); + } + } +} + +readext() +{ + char buf[255]; + int count; + + (void) getc(infile); + while (count = getc(infile)) + fread(buf, 1, count, infile); +} + +DIRECT int real_x, real_y; +DIRECT int x_coord, y_coord; + +typedef struct { + int ilv_r0; /* starting row */ + int ilv_dr; /* step size */ +} ilvspec; + +static ilvspec ilvdat[] = { + {1, 2}, /* .|.|.|.|.|.|.|.|. */ + {2, 4}, /* ..|...|...|...|.. */ + {4, 8}, /* ....|.......|.... */ + {0, 8}, /* |.......|.......| */ +}; + +readimag() +{ + BYTE buf[9]; + unsigned left, top, width, height; + bool local, intrlevd; + int lclbits; + int row, rowoffset; + register int n; + int lineread, hold, xpos, x; + register ilvspec *ilvscan; + + readuse(); + newwind(); + + /* read header info */ + fread(buf, sizeof(BYTE), sizeof(buf) / sizeof(BYTE), infile); + left = arith(buf[0]) | (buf[1] << 8); + top = arith(buf[2]) | (buf[3] << 8); + imagwid = width = arith(buf[4]) | (buf[5] << 8); + imaghigh = height = arith(buf[6]) | (buf[7] << 8); + + if (infomode != NO_INFO) + printf("gif dimensions: %d x %d pixels\n", imagwid, imaghigh); + + local = buf[8] & 0x80; + intrlevd = buf[8] & 0x40; + + if (local) { + char tempbuf[3]; + + lclbits = (buf[8] & 0x7) + 1; + for (x = 1 << lclbits; --x >= 0; ) + fread(tempbuf, 3, 1, infile); + } else if (!global) + fatal("no CLUT present for image"); + + ilevtab[MROWS] = ILEVEND; + for (x = MROWS; --x >= 0; ) + ilevtab[x] = ILEVMISS; + + if (!aligned) + n = myheight; + else { + for (n = imaghigh; n > 200; n /= 2) + ; + } + n *= magfact; + + rowoffset = 3 * starty * magfact; + lineread = 0; + if (intrlevd) { + for (ilvscan = &ilvdat[elements(ilvdat)]; --ilvscan >= ilvdat; ) { + for (x = ilvscan->ilv_r0; x < imaghigh; x += ilvscan->ilv_dr) { + row = (long) x * n / imaghigh - rowoffset; + if (row >= 0 && row < MROWS) + ilevtab[row] = lineread; + ++lineread; + } + } + } else { + for (x = 0; x < imaghigh; ++x) { + row = (long) x * n / imaghigh - rowoffset; + if (row >= 0 && row < MROWS) + ilevtab[row] = lineread; + ++lineread; + } + } + + x = startx * (imagwid / 64); + hold = xpos = 0; + while (xpos < mywidth) { + for (hold += mywidth * magfact; hold >= imagwid; hold -= imagwid) + xtab[xpos++] = x; + x++; + } + + real_x = real_y = 0; + x_coord = y_coord = 0; + + if (dispon || (usefname != NULL && newuse)) { + readrast(width, height); + writeuse(); + if (vefname != NULL) + saveimag(); + } +} + +DIRECT int datum; +DIRECT int bits; +char buf[255]; + +readrast(width, height) +unsigned width, height; +{ + register char *ch; + register codetype *cscan; + int count, code; + + datasize = getc(infile); + codesize = datasize + 1; + codemask = (1 << codesize) - 1; + clear = 1 << datasize; + eoi = clear + 1; + bits = 16; + + /* initialize code table */ + for (cscan = &codetab[code = clear]; --cscan, --code >= 0; ) { + cscan->prefix = (codetype *) NULL; + cscan->first = cscan->suffix = code; + } + + while ((count = getc(infile)) > 0) { + fread(buf, sizeof(*buf), count, infile); + for (ch = buf; --count >= 0; ) + addbyte(*ch++); + } + + datum >>= bits; + for (bits = 16 - bits; x_coord != 0 && bits >= codesize; bits -= codesize) { + process(datum & codemask); + datum >>= codesize; + } +} + +addbyte(c) +char c; +{ + /* + * datum += (long)(*ch & 0xff) << bits; + * bits += 8; + * while (bits >= codesize) { + * code = datum & codemask; + * datum >>= codesize; + * bits -= codesize; + * if (code == eoi) + * goto exitloop; + * process(code); + * } + */ +#asm + ldb 5,s + lda <bits+1 + suba #7 + bls _addb3 + sta <bits+1 + lda <datum + sta <datum+1 + stb <datum + lda #1 + bra _addb4 +_addb3 + lda #8 +_addb1 + lsrb + ror <datum + ror <datum+1 +_addb4 + dec <bits+1 + bne _addb2 +* pshs d + tfr d,u + ldd <codesize + std <bits + ldd <datum + anda <codemask + andb <codemask+1 + pshs d + lbsr process + leas 2,s +* puls d + tfr u,d +_addb2 + deca + bne _addb1 +#endasm +} + +process(code) +int code; +{ + register codetype *p, *cp; + static DIRECT int avail; + static DIRECT codetype *oldcp; + + if (code == clear) { + /* clear table */ + codesize = datasize + 1; + codemask = (1 << codesize) - 1; + avail = clear + 2; + oldcp = NULL; + } else if (code < avail) { + outcode(cp = &codetab[code]); /* output the code */ + if (oldcp != NULL) { + /* add new entry */ + p = &codetab[avail++]; + /* prefix is previous code, first is prefix's first */ + p->first = (p->prefix = oldcp)->first; + p->suffix = cp->first; /* suffix is first of current */ + if ((avail & codemask) == 0 && avail < MCODE) { + /* increase code size */ + codesize++; + codemask += avail; + } + } + oldcp = cp; + } else if (code == avail && oldcp != NULL) { + /* repeat of last code */ + p = &codetab[avail++]; + /* prefix is previous code, first is prefix's first */ + p->first = (p->prefix = oldcp)->first; + p->suffix = p->first; /* Suffix is first of last */ + outcode(p); + if ((avail & codemask) == 0 && avail < MCODE) { + /* increase code size */ + codesize++; + codemask += avail; + } + oldcp = &codetab[code]; + } else + fatal("illegal code in raster data"); +} + +/* + * outcode() -- we finally get the data out of the LZ decompression, and + * fill a buffer until we get a line's worth of data. The loop with x0 + * and x is intended to take advantage of the mostly increasing nature + * of ilevtab[], replacing an O(n**2) loop that was there before. Timing, + * however, shows that the change doesn't affect display time, so the + * performance bottleneck must be elsewhere. Rats. + */ +outcode(p) +codetype *p; +{ + register BYTE *sp = &codestk[0]; + register int x; + static DIRECT int x0 = 0; + + for (; p; p = p->prefix) + *sp++ = p->suffix; + + while (--sp >= &codestk[0]) { + coloruse[arith(*sp)] = TRUE; + if (real_x == 0) { + y_coord = -1; + x = x0; + do { + if (++x >= myheight) + x = 0; + if (ilevtab[x] == real_y) { + x0 = y_coord = x; + break; + } + } while (x != x0); + } + if (y_coord >= 0) { + while (xtab[x_coord] == real_x) + linestor[x_coord++] = arith(*sp); + } + if (++real_x >= imagwid) { + if (y_coord >= 0 && dispon) { + do { + doline(); + } while (ilevtab[++y_coord] == ILEVMISS); + } + real_x = x_coord = 0; + ++real_y; + } + } +} + +DIRECT int bitcount, pixperbyte; +DIRECT char *byteptr; + +doline() +{ + register xlate *p; + register char *rrow; + register int x, addval, scrnum; + cocoscreen *sscan; + + rrow = &randtab[y_coord & 15][0]; + + for (sscan = &screen[scrnum = (flicker ? 2 : 1)]; --sscan, --scrnum >= 0;) + { + actwin = sscan->winpath; + bitcount = pixperbyte; + byteptr = gpbufptr; + if (dfactor > 0) { + for (x = 0; x < mywidth; ++x) { + addval = (realrand) ? rand85(y_coord + x) + : rrow[x & 15]; + for (p = &transtab[linestor[x]][1]; p->addval <= addval; ) + p++; + --p; + addpixel(p->clutval[scrnum]); + } + } else { + for (x = 0; x < mywidth; ++x) + addpixel(transtab[linestor[x]][0].clutval[scrnum]); + } + if (flicker) + select(); + putblk(groupnum, bufnum, 0, y_coord); + flushwin(); + } +} + +addpixel(c) +{ + /* + * *byteptr = (*byteptr << (gmode ? 2 : 4)) | c; + * if (--bitcount == 0) { + * byteptr++; + * bitcount = pixperbyte; + * } + * + * (The spelling discrepancy here is due to the 6809's chopping off + * identifier lengths at a different point than the assembler appears to!) + */ +#asm + ldx <byteptr + ldb ,x + lda <gmode+1 + bne _addpix1 + lslb + lslb +_addpix1 + lslb + lslb + orb 5,s + stb ,x + dec <bitcount+1 + bne _addpix2 + leax 1,x + stx <byteptr + lda <pixperby+1 + sta <bitcount+1 +_addpix2 +#endasm +} + +rand85(n) +int n; +{ + register unsigned result; + + result = rand() % maxdith; + if (n & 1) + result += maxdith + 1; + return result; +} + +readscrn() +{ + char buf[7]; + int x; + register rgbcolor *rp; + + fread(buf, sizeof(*buf), 7, infile); + imagwid = arith(buf[0]) | (buf[1] << 8); + imaghigh = arith(buf[2]) | (buf[3] << 8); + if (infomode != NO_INFO) + printf("%d x %d screen\n", imagwid, imaghigh); + global = (buf[4] & 0x80) != 0; + if (global) { + globbits = (buf[4] & 0x07) + 1; + globcolors = 1 << globbits; + if (infomode != NO_INFO) + printf("global bitmap: %d colors\n", globcolors); + clutpos = ftell(infile); + fread(globclut, 3, globcolors, infile); + if (infomode == MUCH_INFO) { + for (rp = globclut, x = 0; x < globcolors; rp++, x++) { + printf("color %d = %3d,%3d,%3d\n", x, + arith(rp->red), arith(rp->green), arith(rp->blue)); + } + } + } else + fatal("cannot handle non-global bitmaps"); +} + +/* + * newwind() -- the big banana; determine the CoCo CLUT(s) that will + * best display the GIF image given the GIF CLUT. + */ + +newwind() +{ + register cocoscreen *sscan; + register bool *bscan; + register colorcode *cscan; + rgbcolor *rgbp; + bool first; + char blip; + int x, hival, loval, midval; + + fixgmap(); + + if (infomode != NO_INFO) { + printf("Analyzing.."); + fflush(stdout); + } + + loval = -MAXTOL1; + midval = hival = dfactor; + + while (loval <= hival) { + dfactor = midval; + if (setmap()) { + loval = midval + 1; + blip = '+'; + } else { + hival = midval - 1; + blip = '-'; + } + if (infomode != NO_INFO) { + putchar(blip); + fflush(stdout); + } + midval = (loval + hival) / 2; + } + + if (dfactor != hival) { + dfactor = hival; + setmap(); + } + + if (infomode != NO_INFO) { + putchar('\n'); + showdata(); + } + + if (screen[0].clutsize <= 4 && !vefon) { + gmode = TRUE; + mywidth = 640; + pixperbyte = 4; + } else { + gmode = FALSE; + mywidth = 320; + pixperbyte = 2; + } + + first = TRUE; + for (sscan = &screen[(flicker ? 2 : 1)]; --sscan >= screen; ) { + if (dispon) + sscan->winpath = initwin(first, sscan->winpath); + for (cscan = &sscan->pal[x = sscan->clutsize]; --cscan, --x >= 0; ) { + *cscan = colorval(&sscan->clut[x]); + if (dispon) + palette(x, *cscan); + } + if (dispon) { + border(0); + flushwin(); + } + first = FALSE; + } + for (bscan = &coloruse[globcolors]; --bscan >= coloruse; ) + *bscan = FALSE; +} + +/* colorval() -- encode an RGB222 value the way the GIME likes it */ + +colorval(color) +register rgbcolor *color; +{ + static char cocode[] = {'\000', '\001', '\010', '\011'}; + + return (((cocode[color->red & 3] << 1) | + cocode[color->green & 3]) << 1) | cocode[color->blue & 3]; +} + +/* + * showdata() -- display a bunch of information on the CLUTs used + * if it's been asked for + */ +void +showdata() +{ + register rgbcolor *rscan; + register cocoscreen *sscan; + int x, y; + + if (dfactor > 0) + printf("Dithering factor = %d\n", dfactor); + else + printf("Color tolerance = %d\n", -dfactor); + fputs("Resulting coco CLUT: ", stdout); + printf("%d colors", screen[0].clutsize); + if (flicker) + printf(" + %d colors\n", screen[1].clutsize); + else + putchar('\n'); + if (infomode == MUCH_INFO) { + for (x = 0; x < (flicker ? 1 : 2); x++) { + sscan = &screen[x]; + for (rscan = sscan->clut, y = 0; y < sscan->clutsize; y++) { + printf("%2d:%d,%d,%d=%d\n", y, + rscan->red, rscan->green, rscan->blue, colorval(rscan)); + rscan++; + } + putchar('\n'); + } + fputs("Translation table:\n", stdout); + for (x = 0; x < globcolors; ++x) { + if (coloruse[x]) { + printf("%3d:", x); + for (y = 0; y < 4 && transtab[x][y].addval != BOGUSDITH; ++y) { + printf(" %3d=%3d", + transtab[x][y].addval, transtab[x][y].clutval[0]); + if (flicker) + printf(",%3d", transtab[x][y].clutval[1]); + } + putchar('\n'); + } + } + } +} + +/* + * fixgmap() -- scale colors in the GIF image global CLUT in accordance + * with the brightness specification, and in passing, convert to gray + * if requested (either using the average of the components or their + * maximum). + */ +fixgmap() +{ + register rgbcolor *rscan; + int x, r, g, b; + + for (rscan = &globclut[x = globcolors]; --rscan, --x >= 0; ) { + if (coloruse[x]) { + r = arith(rscan->red); + g = arith(rscan->green); + b = arith(rscan->blue); + switch (graytype) { + case AVG_GRAY: + r = g = b = (r + g + b) / 3; + break; + case NTSC_GRAY: + r = g = b = (30 * r + 59 * g + 11 * b) / 100; + break; + case MAX_GRAY: + if (g > r) + r = g; + if (b > r) + r = b; + g = b = r; + break; + } + rscan->red = (britefac * r) >> 4; + rscan->green = (britefac * g) >> 4; + rscan->blue = (britefac * b) >> 4; + } + } +} + +killwind() +{ + mapgpb(screen[flicker].winpath, groupnum, bufnum, 0); + killbuf(groupnum, bufnum); +} + +waituser() +{ + char c; + int x; + register cocoscreen *sscan; + + if (dispon) { + if (pauselen < 0) { + for (x = 5; --x >= 0; ) + bell(); + flushwin(); + } + if (flicker) { + pauselen *= 30; + do { + for (sscan = &screen[2]; --sscan >= screen; ) { + actwin = sscan->winpath; + select(); + flushwin(); + sleep(2); + if (ready(actwin)) { + read(actwin, &c, 1); + if (c == '\n') + return; + } + } + } while (pauselen < 0 || --pauselen >= 0); + } else if (pauselen > 0) { + sleep(60 * pauselen); + } else if (pauselen < 0) { + do { + read(screen[0].winpath, &c, 1); + } while (c != '\n'); + } + } +} + +ready(path) +int path; +{ +#asm + lda 5,s + ldb #SS.Ready + os9 I$GetStt + bcc _ready1 + ldd #0 + bra _ready2 +_ready1 + ldd #1 +_ready2 +#endasm +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/3rdparty/utils/viewgif/viewgif.h Fri May 30 21:13:48 2003 +0000 @@ -0,0 +1,197 @@ +/* + * viewgif.h -- common header fodder for viewgif + */ + +#include <stdio.h> + +#ifdef OSK +/* the OS-9/68000 C compiler knows about void now! */ +#define DIRECT +typedef unsigned char BYTE; +#define arith(byte) (byte) +#else +typedef int void; +#define DIRECT direct +typedef char BYTE; +#define arith(byte) ((byte) & 0xff) +#endif + +/* the canonical dodge for being sure of exactly one defining declaration */ + +#ifndef EXTERN +#define EXTERN extern +#endif + +typedef char bool; /* make up for a C deficiency */ + +#define FALSE (1 == 0) +#define TRUE (!FALSE) + +#define elements(array) (sizeof(array) / sizeof(array[0])) +#define maxnum(bits) ((1 << (bits)) - 1) + +/* + * typedef to let us look at RGB colors two ways--one, as an array of + * components; two, as a structure with nameable components. + */ + +typedef union { + BYTE rgbarr[3]; + struct { + BYTE rval, gval, bval; + } rgbstr; +} rgbcolor; + +#define red rgbstr.rval +#define green rgbstr.gval +#define blue rgbstr.bval + +/* Values and variables related to the GIF spec */ + +#define MGCLUT 256 /* maximum number of colors in a GIF picture */ +#define GBITS 8 /* # of bits in each component of a GIF color */ +#define MCODE 4096 /* number of 12-bit LZ codes */ + +typedef struct cstruct { + struct cstruct *prefix; + char first, suffix; +} codetype; + +EXTERN bool coloruse[MGCLUT]; /* flags colors in use */ +EXTERN bool globuse[MGCLUT]; /* global usage flag */ +EXTERN rgbcolor globclut[MGCLUT]; /* RGB colors in image */ +EXTERN DIRECT int globbits; /* # bits for global color map */ +EXTERN DIRECT int globcolors; /* # possible colors */ +EXTERN DIRECT unsigned imagwid, imaghigh; /* image width/height in pixels */ + +EXTERN codetype codetab[MCODE]; /* LZ code table */ +EXTERN BYTE codestk[MCODE]; /* buffer for decoded bytes */ +EXTERN DIRECT int codesize; /* LZ code size in bits */ +EXTERN DIRECT int codemask; /* LZ code mask */ +EXTERN DIRECT int clear; /* code for code table clear */ +EXTERN DIRECT int eoi; /* code for end of image */ +EXTERN DIRECT int datasize; /* ??? */ + +/* Now for CoCo-related stuff... */ + +#define MCCLUT 16 /* max size of Color Look-Up Table on CoCo 3 */ +#define CBITS 2 /* # of bits in each component of a CoCo 3 color */ +#define MROWS 192 /* max number of rows we can display */ +#define MCOLS 640 /* max number of cols we can display */ + +#define MSCREENS 2 /* number of screens we may cycle among */ + +/* type to hold the CoCo encoding of a color */ + +typedef BYTE colorcode; + +/* + * type to represent the screens that will collectively contain the + * GIF image for display--we add one to the sizes of the arrays for + * palettes to try to speed up the search for color mappings (see + * setmap.c functions) + */ + +typedef struct { + int winpath; /* path # for window to display on */ + int clutsize; /* colors actually used */ + rgbcolor clut[MCCLUT]; /* their RGB values */ + colorcode pal[MCCLUT]; /* their CoCo encodings */ +} cocoscreen; + +typedef struct { + char addval; + char clutval[MSCREENS]; +} xlate; + +EXTERN cocoscreen screen[MSCREENS]; /* screens to be cycled among */ +EXTERN int ilevtab[MROWS + 1]; /* interleave table */ +EXTERN int xtab[MCOLS]; /* ??? */ +EXTERN int linestor[MCOLS]; /* ??? */ +EXTERN xlate transtab[MGCLUT][5]; /* translations of GIF colors */ +EXTERN char randtab[16][16]; /* pseudo-random table */ + +/* non-scan line values for ilevtab[] */ +#define ILEVMISS (-1) /* marks scan lines missed */ + /* in readimag() scaling loops */ +#define ILEVEND (-20) /* end marker guaranteed not */ + /* to match a valid scan line */ + /* or ILEVMISS! */ + +/* conversion between GIF's RGB space and the CoCo's RGB space */ +#define SCALE1 (maxnum(GBITS) / maxnum(CBITS)) +#define SCALE2 (SCALE1 / 2) + +/* limits */ + +/* dithering factor */ +#define MAXDITH1 (SCALE1 / 2) +#define MAXDITH2 (SCALE2 / 2) +#define BOGUSDITH 127 /* end marker for addval */ +/* color tolerance (represented by negative "dithering factor") */ +#define MAXTOL1 SCALE1 +#define MAXTOL2 SCALE2 +/* magnification factor */ +#define MINMAG 1 +#define MAXMAG 64 +/* brightness */ +#define MINBRITE 1 +#define MAXBRITE 16 +/* starting coordinates (units: 64ths of the image size along the axis) */ +#define MINCOORD 1 +#define MAXCOORD 64 + +/* some symbolic names for the values of some twistable knobs */ + +#define NO_INFO 0 +#define SOME_INFO 1 +#define MUCH_INFO 2 + +#define NO_GRAY 0 +#define AVG_GRAY 1 +#define MAX_GRAY 2 +#define NTSC_GRAY 3 + +/* default values */ + +#define D_INFO SOME_INFO +#define D_GRAY NO_GRAY +#define D_BRITE MAXBRITE +#define D_DITHER MAXDITH1 +#define D_MAG MINMAG +#define D_HEIGHT MROWS + +EXTERN DIRECT FILE *infile; /* file containing GIF image */ +EXTERN DIRECT long clutpos; /* position of global CLUT in file */ +EXTERN DIRECT int infomode; /* control amount of commentary */ +EXTERN DIRECT int graytype; /* what kind of gray scale, if any */ +EXTERN DIRECT int dfactor; /* dithering factor */ +EXTERN DIRECT int maxdith; /* upper bound on random dither */ +EXTERN DIRECT int magfact; /* magnification factor */ +EXTERN DIRECT int britefac; /* brightness factor */ +EXTERN DIRECT int startx, starty; /* coord to map to top left corner */ +EXTERN DIRECT bool realrand; /* use random #s instead of table */ +EXTERN DIRECT bool flicker; /* cycle among screens */ +EXTERN DIRECT bool dispon; /* display the image */ +EXTERN DIRECT bool zapmap; /* overwrite unused map colors */ +EXTERN DIRECT bool vefon; /* save the image in VEF fmt */ +EXTERN DIRECT bool aligned; /* align to pixels */ +EXTERN DIRECT bool newscrn; /* switch to new window for display */ +EXTERN DIRECT char *usefname; /* to name of color usage file */ +EXTERN DIRECT char *vefname; /* to name of VEF output file */ +EXTERN DIRECT int mywidth, myheight; /* width, height we will display */ +EXTERN DIRECT int actwin; /* path for buffered gfx data */ +EXTERN DIRECT int groupnum, bufnum; /* get/put buffer information */ +EXTERN DIRECT int framenum; /* frame number--whatever that is */ +EXTERN DIRECT char *gpbufptr; /* pointer to get/put buffer */ +EXTERN DIRECT int gmode; /* graphics mode we're using */ +EXTERN DIRECT int newuse; /* ??? */ +EXTERN DIRECT bool (*approx)(); /* to color approximation function */ +EXTERN DIRECT int minmod; /* modulus for minadd() */ +EXTERN DIRECT int low0, up0; /* default upper/lower limits for */ + /* approximation searches */ +extern bool approx1(); /* one-screen approximation */ +extern bool approx2(); /* two-screen approximation */ + +/* miscellanea for support routines */ +#define fatal(s) error((s), 1) /* fatal error (no natural errno) */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/3rdparty/utils/viewgif/viewvef.c Fri May 30 21:13:48 2003 +0000 @@ -0,0 +1,340 @@ +/* + * ViewVEF 1.0 by Vaughn Cato + * For use in displaying flicker VEF files + */ + +#include <stdio.h> +#include <string.h> + +int actwin; +char *gpbufptr; +char *mapgpb(); + +main(argc, argv) +int argc; +char *argv[]; +{ + int winfile1, winfile2; + int x, groupnum, bufnum, flicker, file, scrnum, pauselen = -1; + char c, newname[128]; + + if (argc < 2) { + printf("Usage: viewvef <vef file> [<pause length>]"); + printf(" Displays normal or flicker VEF files\n"); + exit(1); + } + if (argc == 3) + pauselen = atoi(argv[2]); + for (scrnum = 0; scrnum <= 1; ++scrnum) { + if (scrnum == 0) { + if ((file = open(argv[1], 1)) == -1) { + fprintf(stderr, "Cannot open %s\n", argv[scrnum + 1]); + exit(errno); + } + winfile1 = newwin(); + groupnum = procid(); + bufnum = 1; + getblk(groupnum, bufnum, 0, 0, 639, 1); + flushwin(); + if ((gpbufptr = mapgpb(winfile1, groupnum, bufnum, 1)) == NULL) + exit(errno); + } else { + strcpy(newname, argv[1]); + strcat(newname, ".2"); + if ((file = open(newname, 1)) == -1) + break; + flicker = 1; + winfile2 = newwin(); + } + read(file, &c, 1); + read(file, &c, 1); + for (x = 0; x < 16; ++x) { + read(file, &c, 1); + palette(x, c); + } + for (x = 0; x < 8; ++x) + read(file, gpbufptr, 160); + for (x = 0; x < 192; ++x) { + read(file, gpbufptr, 160); + putblk(groupnum, bufnum, 0, x); + flushwin(); + } + } + if (flicker) { + pauselen *= 30; + for (;;) { + actwin = winfile1; + select(); + flushwin(); + sleep(2); + if (ready(winfile1)) { + read(winfile1, &c, 1); + if (c == 13) + break; + } + actwin = winfile2; + select(); + flushwin(); + sleep(2); + if (ready(winfile2)) { + read(winfile2, &c, 1); + if (c == 13) + break; + } + if (pauselen == 0) + break; + if (pauselen > 0) + --pauselen; + } + } else { + if (pauselen >= 0) { + if (pauselen > 0) + sleep(60 * pauselen); + } else { + do { + read(winfile1, &c, 1); + } while (c != 13); + } + } + mapgpb(winfile1, groupnum, bufnum, 0); + actwin = 1; + select(); + flushwin(); + close(winfile1); + if (flicker) + close(winfile2); +} + +sleep(ticks) +int ticks; +{ +#asm + ldx 4,s + os9 $0a +#endasm +} + +newwin() +{ + int winfile, windesc; + + windesc = attach("w"); + if ((winfile = open("/w", 3)) == -1) + exit(errno); + actwin = winfile; + dwset(8, 0, 0, 40, 24, 0, 0, 0); + curoff(); + select(); + flushwin(); + detach(windesc); + return (winfile); +} + +fcolor(c) + int c; +{ + static char outstr[] = {0x1b, 0x32, 0}; + + outstr[2] = c; + writemem(outstr, sizeof(outstr)); +} + +dwset(sty, cpx, cpy, szx, szy, prn1, prn2, prn3) + int sty, cpx, cpy, szx, szy, prn1, prn2, prn3; +{ + static char outstr[] = {0x1b, 0x20, 0, 0, 0, 0, 0, 0, 0, 0}; + int size; + + outstr[2] = sty; + outstr[3] = cpx; + outstr[4] = cpy; + outstr[5] = szx; + outstr[6] = szy; + if (sty > 0 && sty <= 8) { + outstr[7] = prn1; + outstr[8] = prn2; + outstr[9] = prn3; + size = sizeof(outstr); + } else + size = sizeof(outstr) - 3; + writemem(outstr, size); +} + +getblk(grp, bfn, cpx, cpy, szx, szy) + int grp, bfn, cpx, cpy, szx, szy; +{ + static char outstr[] = {0x1b, 0x2c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + outstr[2] = grp; + outstr[3] = bfn; + *(int *) (&outstr[4]) = cpx; + *(int *) (&outstr[6]) = cpy; + *(int *) (&outstr[8]) = szx; + *(int *) (&outstr[10]) = szy; + writemem(outstr, sizeof(outstr)); +} + +putblk(grp, bfn, cpx, cpy) + int grp, bfn, cpx, cpy; +{ + static char outstr[] = {0x1b, 0x2d, 0, 0, 0, 0, 0, 0}; + + outstr[2] = grp; + outstr[3] = bfn; + *(int *) (&outstr[4]) = cpx; + *(int *) (&outstr[6]) = cpy; + writemem(outstr, sizeof(outstr)); +} + +dwend() +{ + static char outstr[] = {0x1b, 0x24}; + + writemem(outstr, sizeof(outstr)); +} + +select() +{ + static char outstr[] = {0x1b, 0x21}; + + writemem(outstr, sizeof(outstr)); +} + +bell() +{ + char c = 7; + writemem(&c, 1); +} + +palette(prn, ctn) +{ + static char outstr[] = {0x1b, 0x31, 0, 0}; + + outstr[2] = prn; + outstr[3] = ctn; + writemem(outstr, sizeof(outstr)); +} + +curoff() +{ + static char outstr[] = {0x05, 0x20}; + + writemem(outstr, sizeof(outstr)); +} + +writemem(str, size) + char *str; + int size; +{ + while (size-- > 0) + writechr(*str++); +} + +writestr(file, str) + int file; + char *str; +{ + writeln(file, str, strlen(str)); +} + +char outbuf[256]; +char *outptr = outbuf; + +writechr(c) + char c; +{ + if (outptr >= outbuf + sizeof(outbuf)) + flushwin(); + *outptr++ = c; +} + +flushwin() +{ + write(actwin, outbuf, outptr - outbuf); + outptr = outbuf; +} + +attach(str) + char *str; +{ +#asm + lda #3 + ldx 4,s + os9 $80 + bcs _atach1 + tfr u,d + bra _atach2 +_atach1: + clra + std errno,y + ldd #-1 +_atach2: +#endasm +} + +detach(dte) +int dte; +{ +#asm + ldu 4,s + os9 $81 + bcs _detch1 + ldd #0 + bra _detch2 +_detch1: + clra + std errno,y + ldd #-1 +_detch2: +#endasm +} + +char * +mapgpb(path, grp, bfn, action) + int path, grp, bfn, action; +{ +#asm + lda 7,s + ldb 9,s + tfr d,x + lda 5,s + ldb #$84 + pshs y + ldy 10+2,s + os9 $8e + puls y + bcc _mapgpb1 + clra + std errno,y + ldx #0 +_mapgpb1: + tfr x,d +#endasm +} + +ready(path) + int path; +{ +#asm + lda 5,s + ldb #1 + os9 $8d + bcc _ready1 + ldd #0 + bra _ready2 +_ready1: + ldd #1 +_ready2: +#endasm +} + +procid() +{ +#asm + pshs y + os9 $0c + tfr a,b + puls y + clra +#endasm +}