Mercurial > hg > Members > kono > nitros9-code
view 3rdparty/utils/viewgif/viewgif.c @ 3210:6353bb024571
Created makefile and defsfile for NoCan RAMMER module driver and descriptor
Updated rammer.asm in the NoCan driver folder to build the NoCan version of the Driver
Updated r0.asm file to create the 6MB version of the descriptor.
The makefile creates a disk image with two sets of the required drivers for
the 6309 and 6809's in their respective module folders.
/NITROS9/6309_L2/MODULES/RBF
for the 6309 files
and
/NITROS9/6809_L2/MODULES/RBF
for the 6809 files.
This will make it easier for doing a dsave from this disk image into a
normal distro disk image so people have these drivers ready for when
new memory upgrades allow compatible usage of the NoCan registers.
author | David Ladd <drencor-xeen@users.sourceforge.net> |
---|---|
date | Wed, 20 Dec 2017 15:15:49 -0600 |
parents | aaae5eac20e1 |
children |
line wrap: on
line source
/* 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 }