/* * JIFF.H */ #define XMAX 640 #define LOXMAX 320 #define YMAX 200 #define XASPECT 5 #define YASPECT 11 /* * EA handy make a long from 4 chars macros redone to work with Aztec */ #define MAKE_ID(a, b, c, d)\ ( ((long)(a)<<24) | ((long)(b)<<16) | ((long)(c)<<8) | (long)(d) ) /* * These are the IFF types I deal with */ #define FORM MAKE_ID('F', 'O', 'R', 'M') #define ILBM MAKE_ID('I', 'L', 'B', 'M') #define BMHD MAKE_ID('B', 'M', 'H', 'D') #define CMAP MAKE_ID('C', 'M', 'A', 'P') #define BODY MAKE_ID('B', 'O', 'D', 'Y') /* * And these are the IFF types I ignore but don't squawk about */ #define GRAB MAKE_ID('G', 'R', 'A', 'B') #define DEST MAKE_ID('D', 'E', 'S', 'T') #define SPRT MAKE_ID('S', 'P', 'R', 'T') #define CAMG MAKE_ID('C', 'A', 'M', 'G') #define CRNG MAKE_ID('C', 'R', 'N', 'G') #define CCRT MAKE_ID('C', 'C', 'R', 'T') #define EVEN(x) (((x) + 1) & ~1) #define MANDEL /* * Some macros for raster memory allocation ... redefine if you're * sensible and manage memory locally */ #ifndef MANDEL /* * ralloc - raster alloc */ # define ralloc(amount) (PLANEPTR)AllocMem((long)(amount), MEMF_CHIP) /* * rfree - raster free */ # define rfree(pt, amount) FreeMem( (pt), (long)(amount) ) #else /* MANDEL */ # include /* * We don't want to allocate a complete raster for the picture, since we * already have a screen with a window where we want to have it. * Therefore, we allocate some small buffers, which get blitted into our * window as soon as they fill up. */ # define MAXPLANESIZE 1040L /* * ralloc - raster alloc */ # define ralloc(amount) (PLANEPTR)AllocMem(MAXPLANESIZE, MEMF_CHIP | MEMF_CLEAR) /* * rfree - raster free */ # define rfree(pt, amount) FreeMem( (pt), MAXPLANESIZE ) #endif /* !MANDEL */ /* * line_bytes = the number of words * 2 (for bytes) a raster line takes up */ #define line_bytes(width) ((((width) + 15) >> 3) & ~0x0001) /* * psize - plane size in bytes (an even number) of a raster given width * and height */ #define psize(width, height) ( line_bytes(width)*height) /* * The place to throw excess bits */ #define bit_bucket(file, length) fseek(file, (long)EVEN(length), 1) union bytes4 { char b4_name[4]; LONG b4_type; }; struct iff_chunk { union bytes4 iff_type; LONG iff_length; }; struct form_chunk { union bytes4 fc_type; /* == FORM */ LONG fc_length; union bytes4 fc_subtype; }; struct CommodoreAmiga { struct iff_chunk camg_iffc; /* == CAMG */ LONG camg_data; }; #ifndef MANDEL /* We have this already in Mandel.h */ struct BitMapHeader { UWORD w, h; UWORD x, y; UBYTE nPlanes; UBYTE masking; UBYTE compression; UBYTE pad1; UWORD transparentColor; UBYTE xAspect, yAspect; WORD pageWidth, pageHeight; }; /* * ILBM_info is the structure win_read_iff returns, and is hopefully all * you need to deal with out of the iff reader routines below */ struct ILBM_info { struct BitMapHeader header; UBYTE cmap[MAXCOL * 3]; struct BitMap bitmap; #ifdef MANDEL struct Mand *mand; long mandsize; #endif }; #endif /* !MANDEL */ /*- * I sure wish C function "prototypes" were real and not just ANSI * * extern struct ILBM_info *win_read_iff(); * win_read_iff( char *filename, short just_colors, int MandSize, * APTR MandPointer ); * extern void free_planes(); free_planes( struct BitMap *bitmap); * extern int write_iff(); * write_iff(char *name, unsigned char *colors, struct Window *window, * short xoff, short yoff, short compressed); */ /* * Anyone know where some useful minterms are defined? */ #define COPY_MINTERM 0x0C0L /*** A meditation for the guru from the Diamond Sutra - So shall you think of all this fleeting world: A star at dawn, a bubble in a stream; A flash of lightning in a summer cloud, A flickering lamp, a phantom, and a dream. ***/ /* * jiff.c Jim Kent's iff - ilbm reader * * This is the (sortof) short (sortof) simple no-frills IFF reader to get * something out of DPaint, Images, or the Animator. It works well with * the Aztec C compiler. It should work with Lattice but you never know * until you try it. I haven't. * * I've included a simple main program. This is just to make it stand alone. * Since amiga screen initializations are massive, all it does as is is * read it into a BitMap, and then free up the BitMap. Should crash it if * it's gonna crash though. * * The main interface to this is through the routine win_read_iff(filename). * This returns a ILBM_info structure-pointer on success, and NULL on * failure. It cleans up after itself on failure. * * I hope you will find this useful and easy to use. Please forgive my funky * indentation style? Well at least I'm consistent! (* Run through the * C-Beautifier by Olaf Seibert !! *) * * To demonstrate what a nice guy I am even though I'm far from wild about * the IFF standard I'm placing this in the public domain. When you * remove the DEBUG and PARANOID definitions the code is only 1536 bytes * long. * * -Jim Kent April 22, 1986 */ #include #include #include #include #include #include /* #include "jiff.h" */ /* * This is an all too common state of software development. Get rid of * this define as soon as it runs. */ #undef DEBUG /* #define DEBUG/* */ /* * This is the normal state of software development. Seriously undefine * this to make it shut up about errors and reduce code size half way * through beta testing... */ #undef PARANOID /* * This is nice if you want to use a debugger on the STATIC data and * routines in this file. Redefine only if you don't need a debugger. */ #ifdef DEBUG # undef STATIC # define STATIC #endif STATIC struct ILBM_info *win_read_ilbm(); STATIC struct ILBM_info *win_read_body(); /* * OK this code is almost re-entrant. Pass this guy from above to make it * really re-entrant. (Why do you need a reentrant ILBM reader though?? * Maybe for Dale ... ) Well, look in the IFF specs for instance... [Olaf * Seibert, KosmoSoft] */ STATIC struct ILBM_info root_info; /* static so get initialized to * zero */ #ifdef PARANOID /* * a little paranoid routine that say's where we got before EOF */ STATIC void iff_truncated(where) int where; { printf("ILBM truncated %d\n", where); free_planes(&root_info.bitmap); } #endif PARANOID struct ILBM_info * win_read_iff(name, just_colors, window, MandSize, MandPointer) char *name; short just_colors; struct Window *window; int MandSize; APTR MandPointer; { struct ILBM_info *info = &root_info; FILE *file; struct form_chunk chunk; if ((file = fopen(name, "r")) == 0) { #ifdef PARANOID printf("couldn't fopen %s to read\n", name); #endif PARANOID return NULL; } if (fread(&chunk, sizeof (struct form_chunk), 1, file) != 1) { #ifdef PARANOID iff_truncated(0); #endif PARANOID fclose(file); return NULL; } if (chunk.fc_type.b4_type != FORM) { #ifdef PARANOID printf("not a FORM - %s\n", name); #endif PARANOID fclose(file); return NULL; } if (chunk.fc_subtype.b4_type != ILBM) { #ifdef PARANOID printf("FORM not an ILBM - %s\n", name); #endif PARANOID fclose(file); return NULL; } #ifdef DEBUG printf("FORM %ld ILBM\n", chunk.fc_length); #endif DEBUG #ifdef MANDEL info->mand = (struct Mand *) MandPointer; info->mandsize = MandSize; info->mand->MandID = 0; /* we have not yet read it */ #endif info = win_read_ilbm(file, info, chunk.fc_length - sizeof (chunk), just_colors, window); #ifdef DEBUG printf("info = %lx\n", info); #endif DEBUG #ifdef MANDEL /* * Backward compatibility with non-standard code: We may want to read * the extra MAND if we have not read it by now. */ if (info && MandSize && info->mand->MandID != MAND) { fread(MandPointer, 1, MandSize, file); info->mand->Size -= 2 * sizeof (long); /* patch bug */ } #endif MANDEL fclose(file); return info; } STATIC struct ILBM_info * win_read_ilbm(file, info, length, just_colors, window) FILE *file; struct ILBM_info *info; long length; short just_colors; struct Window *window; { struct iff_chunk chunk; int i; long read_in = 0; int got_header = FALSE; /* To make sure gots the header * first */ int got_cmap = FALSE; /* Make sure get cmap before * "BODY" */ /* * Make sure the Planes are all NULL so can free up memory easily on * error abort */ for (i = 0; i < 8; i++) info->bitmap.Planes[i] = NULL; while (read_in < length) { if (fread(&chunk, sizeof (chunk), 1, file) != 1) { #ifdef PARANOID iff_truncated(1); #endif PARANOID return NULL; } switch (chunk.iff_type.b4_type) { case BMHD: #ifdef DEBUG printf("\tBMHD %ld\n", chunk.iff_length); #endif DEBUG if (fread(&info->header, sizeof (info->header), 1, file) != 1) { #ifdef PARANOID iff_truncated(2); #endif PARANOID return NULL; } got_header = TRUE; break; case CMAP: #ifdef DEBUG printf("\tCMAP %ld\n", chunk.iff_length); #endif DEBUG if (!got_header) { #ifdef PARANOID printf("CMAP before BMHD\n"); #endif PARANOID return NULL; } if (chunk.iff_length <= 3 * MAXCOL) { if (fread(info->cmap, (int) chunk.iff_length, 1, file) != 1) { #ifdef PARANOID iff_truncated(3); #endif PARANOID return NULL; } } else { #ifdef PARANOID printf("warning, more than %d colors in ILBM CMAP\n", MAXCOL); #endif PARANOID if (fread(info->cmap, (int) 3 * MAXCOL, 1, file) != 1) { #ifdef PARANOID iff_truncated(4); #endif PARANOID return NULL; } bit_bucket(file, chunk.iff_length - 3 * MAXCOL); } got_cmap = TRUE; if (just_colors) return info; break; case MAND: #ifdef DEBUG printf("\tMAND %ld\n", chunk.iff_length); #endif DEBUG if (chunk.iff_length + sizeof (chunk) <= info->mandsize) { if (fread((char *) info->mand + sizeof (chunk), (int) chunk.iff_length, 1, file) != 1) { #ifdef DEBUG printf("fread MAND fails; filepos %ld ferror %d\n", (long) ftell(file), (int) ferror(file)); #endif return NULL; } *(struct iff_chunk *) info->mand = chunk; /* * skip padding byte */ if (chunk.iff_length & 1) getc(file); } else { #ifdef DEBUG printf("skipping MAND; too large for buffer (%ld)\n", (long) info->mandsize); #endif bit_bucket(file, chunk.iff_length); } break; case BODY: if (!got_cmap) { #ifdef PARANOID printf("BODY before CMAP\n"); #endif PARANOID return NULL; } #ifdef DEBUG printf("\tBODY %ld\n", chunk.iff_length); #endif DEBUG return win_read_body(file, info, chunk.iff_length, window); default: /* Squawk about unknown types if PARANOID */ #ifdef PARANOID printf("\t unknown type %lx of b4_type\n", chunk.iff_type.b4_type); case GRAB: /* Ignore documented but unwanted types */ case DEST: case SPRT: case CAMG: case CRNG: case CCRT: #endif PARANOID bit_bucket(file, chunk.iff_length); break; } read_in += EVEN(chunk.iff_length) + sizeof (chunk); } #ifdef PARANOID printf("no BODY in ILBM\n"); #endif PARANOID return NULL; } STATIC struct ILBM_info * win_read_body(file, info, length, window) FILE *file; register struct ILBM_info *info; long length; struct Window *window; { struct ILBM_header *header; struct BitMap *bm; int i, j; int rlength; int plane_offset; ULONG YSize, DestX, DestY; #ifdef DEBUG printf("win_read_body( %lx %lx %ld)\n", file, info, length); #endif DEBUG #ifdef PARANOID /* * When paranoid do a little error checking first ... fail fast! */ if (info->header.nPlanes > 8) { printf("Whoa, woe Dale only speaks 8 planes boy, not %d\n", info->header.nPlanes); return NULL; } #endif PARANOID /* * Ok a little more error checking */ if (info->header.compression != 0 && info->header.compression != 1) { #ifdef PARANOID printf("unrecognized compression type %d\n", info->header.compression); #endif PARANOID return NULL; } /* * Set up the bitmap part that doesn't involve memory allocation first * - hey this part does get done, and let's be optimistic... */ info->bitmap.BytesPerRow = line_bytes(info->header.w); info->bitmap.Rows = info->header.h; info->bitmap.Depth = info->header.nPlanes; info->bitmap.Flags = info->bitmap.pad = 0; rlength = info->bitmap.Rows * info->bitmap.BytesPerRow; for (i = 0; i < info->header.nPlanes; i++) { if ((info->bitmap.Planes[i] = ralloc(rlength)) == NULL) { #ifdef PARANOID printf("couldn't alloc plane %d in win_read_body\n", i); #endif PARANOID free_planes(&info->bitmap); return NULL; } } plane_offset = 0; YSize = (MAXPLANESIZE / info->bitmap.BytesPerRow); if (window->Flags & GIMMEZEROZERO) { DestX = 0; DestY = 0; } else { DestX = window->BorderLeft; DestY = window->BorderTop; } for (i = 0; i < info->bitmap.Rows; i++) { /* * This test should be in the inner loop for shortest code, in the * outer loop for greatest speed, so sue me I compromised */ if (info->header.compression == 0) { for (j = 0; j < info->bitmap.Depth; j++) { if (fread(info->bitmap.Planes[j] + plane_offset, info->bitmap.BytesPerRow, 1, file) != 1) { #ifdef PARANOID iff_truncated(6); #endif PARANOID free_planes(&info->bitmap); return NULL; } } } else { register char *dest, value; register int so_far, count; /* How much have unpacked so far */ for (j = 0; j < info->bitmap.Depth; j++) { so_far = info->bitmap.BytesPerRow; dest = (char *) info->bitmap.Planes[j] + plane_offset; while (so_far > 0) { if ((value = getc(file)) == 128) { #ifdef DEBUG printf("NOP\n"); #endif DEBUG } else if (value > 0) { count = (int) value + 1; so_far -= count; if (fread(dest, count, 1, file) != 1) { #ifdef PARANOID iff_truncated(7); #endif PARANOID free_planes(&info->bitmap); return NULL; } dest += count; } else { count = (int) -value + 1; so_far -= count; value = getc(file); while (--count >= 0) /* This is fastest loop on * the 68000 */ *dest++ = value; } } if (so_far != 0) { #ifdef PARANOID printf("compression quite screwed up, aborting %d\n", so_far); #endif PARANOID free_planes(&info->bitmap); return NULL; } } } plane_offset += info->bitmap.BytesPerRow; if (plane_offset > MAXPLANESIZE - info->bitmap.BytesPerRow) { BltBitMapRastPort(&info->bitmap, 0L, 0L, window->RPort, DestX, DestY, info->bitmap.BytesPerRow * 8L, YSize, COPY_MINTERM); plane_offset = 0; DestY += YSize; } } if (plane_offset) { BltBitMapRastPort(&info->bitmap, 0L, 0L, window->RPort, DestX, DestY, info->bitmap.BytesPerRow * 8L, (long) plane_offset / info->bitmap.BytesPerRow, COPY_MINTERM); } if (length & 1) { /* * Skip padding byte */ getc(file); } free_planes(&info->bitmap); return info; } void free_planes(bmap) register struct BitMap *bmap; { PLANEPTR plane; long length; short i; length = bmap->BytesPerRow * bmap->Rows; for (i = bmap->Depth; --i >= 0;) { if ((plane = bmap->Planes[i]) != NULL) { rfree(plane, length); bmap->Planes[i] = NULL; } } } #undef DEBUG /* #define DEBUG/* */ #undef PARANOID /*----------------------------------------------------------------------* * jpacker.c Convert data to "cmpByteRun1" run compression. * * pack_row() is an adaptation of PackRow() * by Jerry Morrison and Steve Shaw, Electronic Arts, * modified and tweaked by Jim Kent, Dancing Flame 05/02/86 * * control bytes: * [0..127] : followed by n+1 bytes of data. * [-1..-127] : followed by byte to be repeated(-n)+1 times. * -128 : NOOP. * * * write_iff() is the only function you can access in this module. *----------------------------------------------------------------------*/ /*- #include #include #include #include "jiff.h" */ #define DUMP 0 #define RUN 1 #define MINRUN 3 #define MAXRUN 128 #define MAXDAT 128 /* * pack_row - pass source line pointer, length of line, and file. Returns * # of bytes after compression. Returns 0 on write error. Pass file = * NULL to just find out length, otherwise will write compressed row to * file. */ STATIC unsigned int pack_row(file, source, size) FILE *file; char *source; int size; { char c, lastc = '\0'; short mode = DUMP; short nbuf = 0; /* Number of chars in buffer */ short rstart = 0; /* Buffer index current run starts */ unsigned short putsize; #if OLD char buf[MAXDAT * 3 / 2]; /* I think MAXDAT+1 would * suffice */ #else /* * And I think that buf can be changed into a pointer to the source * line, to the beginning of a dump. Saves stack space and copying. */ char *buf; #endif putsize = 0; #if OLD buf[0] = lastc = *source++; /* So have valid lastc */ #else buf = source; lastc = *source++; /* So have valid lastc */ #endif nbuf = 1; size--; /* Since one byte eaten */ for (; size; --size) { #if OLD buf[nbuf++] = c = *source++; #else nbuf++; c = *source++; #endif switch (mode) { case DUMP: /* * If the buffer is full, write the length byte, then the data */ if (nbuf > MAXDAT) { if (file != NULL) { if (putc(nbuf - 2, file) == EOF) return 0; if (fwrite(buf, nbuf - 1, 1, file) != 1) return 0; } putsize += nbuf; #if OLD buf[0] = c; #else buf = source - 1; /* Undo the previous source++ */ #endif nbuf = 1; rstart = 0; break; } if (c == lastc) { if (nbuf - rstart >= MINRUN) { if (rstart > 0) { if (file != NULL) { if (putc(rstart - 1, file) == EOF) return 0; if (fwrite(buf, rstart, 1, file) != 1) return 0; } putsize += rstart + 1; } mode = RUN; } else if (rstart == 0) mode = RUN; /* * No dump in progress, so can't lose by making these 2 a * run. */ } else rstart = nbuf - 1; /* First of run */ break; case RUN: if ((c != lastc) || (nbuf - rstart > MAXRUN)) { /* * Output run */ if (file != NULL) { if (putc(-(nbuf - rstart - 2), file) == EOF) return 0; if (putc(lastc, file) == EOF) return 0; } putsize += 2; #if OLD buf[0] = c; #else buf = source - 1; /* Undo the previous source++ */ #endif nbuf = 1; rstart = 0; mode = DUMP; } break; } lastc = c; } switch (mode) { case DUMP: if (file != NULL) { if (putc(nbuf - 1, file) == EOF) return 0; if (fwrite(buf, nbuf, 1, file) != 1) return 0; } putsize += nbuf + 1; break; case RUN: if (file != NULL) { if (putc(-(nbuf - rstart - 1), file) == EOF) return 0; if (putc(lastc, file) == EOF) return 0; } putsize += 2; break; } return putsize; } /* * write_row - pass source line pointer, length of line, and file. Returns * # of bytes after not compressing. Returns 0 on write error. Pass file * = NULL to just find out length, otherwise will write non-compressed row * to file. */ STATIC unsigned int write_row(file, source, size) FILE *file; char *source; int size; { if (file) { if (fwrite(source, size, 1, file) != 1) return 0; } return size; } STATIC unsigned long pack_window(file, window, writer) FILE *file; register struct Window *window; register unsigned int (*writer) (); { unsigned short i, j; unsigned row_length; unsigned long compressed_length; unsigned plane_offset; int BytesPerRow; int YSize; ULONG SrcX, SrcY; struct RastPort Rp; struct BitMap Bitmap; #ifdef DEBUG printf("pack_window( %lx %lx)\n", file, window); #endif DEBUG compressed_length = 0; plane_offset = 0; BytesPerRow = line_bytes(window->GZZWidth); Bitmap.Depth = window->WScreen->BitMap.Depth; if (window->Flags & GIMMEZEROZERO) { SrcX = 0; SrcY = 0; } else { SrcX = window->BorderLeft; SrcY = window->BorderTop; } YSize = MAXPLANESIZE / BytesPerRow; InitBitMap(&Bitmap, (ULONG) Bitmap.Depth, (ULONG) (8 * BytesPerRow), (ULONG) YSize); /* * Make sure the Planes are all NULL so can free up memory easily on * error abort */ for (i = 0; i < 8; i++) Bitmap.Planes[i] = NULL; for (i = 0; i < Bitmap.Depth; i++) { if ((Bitmap.Planes[i] = ralloc(MAXPLANESIZE)) == NULL) { #ifdef DEBUG printf("couldn't alloc plane %d in pack_window\n", i); printf("pack_window: aborting; free_planes\n"); #endif free_planes(&Bitmap); return 0; } } InitRastPort(&Rp); Rp.BitMap = &Bitmap; #ifdef DEBUG printf("pack_window BytesPerRow=%ld Depth=%ld\n", (long) BytesPerRow, (long) Bitmap.Depth); #endif for (i = 0; i < window->GZZHeight; i++) { if (plane_offset == 0) { #ifdef DEBUG printf("pack_window ClipBlit SrcX=%ld SrcY=%ld YSize=%ld\n", SrcX, SrcY, (ULONG) YSize); #endif #define DestX 0L #define DestY 0L ClipBlit(window->RPort, SrcX, SrcY, &Rp, DestX, DestY, (ULONG) window->GZZWidth, (ULONG) YSize, COPY_MINTERM); #undef DestX #undef DestY SrcY += YSize; } for (j = 0; j < Bitmap.Depth; j++) { if ((row_length = (*writer) (file, Bitmap.Planes[j] + plane_offset, BytesPerRow)) == 0) { #ifdef DEBUG printf("error packing row %d plane %d\n", i, j); printf("pack_window: aborting; free_planes\n"); #endif free_planes(&Bitmap); return 0; } compressed_length += row_length; } plane_offset += BytesPerRow; if (plane_offset > MAXPLANESIZE - BytesPerRow) plane_offset = 0; } #ifdef DEBUG printf("pack_window: free_planes\n"); #endif free_planes(&Bitmap); if (compressed_length & 1) {/* Check to see odd length */ if (file != NULL) { if (putc(0, file) == EOF) { return 0; } } /* * compressed_length++; Deleted!!! Padding should NOT be included * in the chunk size !!! */ } return compressed_length; } int write_iff(name, colors, window, xoff, yoff, compressed, MandSize, MandPointer) char *name; unsigned char *colors; register struct Window *window; short xoff, yoff; short compressed; int MandSize; APTR MandPointer; { FILE *file; struct form_chunk chunk; struct iff_chunk ichunk; struct BitMapHeader header; long bits_size; short i; int width = 0; int Depth; int BytesPerRow; #ifdef DEBUG printf("write_iff\n"); #endif if ((file = fopen(name, "w")) == 0) { #ifdef PARANOID printf("couldn't fopen %s to write\n", name); #endif PARANOID goto abort; } /* * Say its a FORM ILBM */ chunk.fc_type.b4_type = FORM; chunk.fc_subtype.b4_type = ILBM; #ifdef MANDEL chunk.fc_length = 4 + 3 * sizeof (struct iff_chunk) + MAXCOL * 3 + sizeof (struct BitMapHeader) + sizeof (struct CommodoreAmiga) + MandSize; #else chunk.fc_length = 4 + 3 * sizeof (struct iff_chunk) + MAXCOL * 3 + sizeof (struct BitMapHeader) + sizeof (struct CommodoreAmiga); #endif MANDEL if (window) { width = window->GZZWidth; BytesPerRow = line_bytes(width); Depth = window->WScreen->BitMap.Depth; if (compressed) { #ifdef DEBUG printf("write_iff: call pack_window for sizing\n"); #endif if ((bits_size = pack_window(NULL, window, pack_row)) == 0) goto abort; } else { bits_size = BytesPerRow * window->GZZHeight * Depth; } chunk.fc_length += bits_size; if (bits_size & 1) chunk.fc_length++; } if (fwrite(&chunk, sizeof (chunk), 1, file) != 1) goto abort; /* * Here comes a BitMapHeader */ { struct iff_chunk ichunk; ichunk.iff_type.b4_type = BMHD; ichunk.iff_length = sizeof (header); if (fwrite(&ichunk, sizeof (ichunk), 1, file) != 1) goto abort; } /* * Initialize the BitMapHeader to normal values */ header.masking = 0; header.pad1 = 0; header.transparentColor = 0; if (compressed) header.compression = 1; else header.compression = 0; header.pageWidth = width; header.pageHeight = window ? window->GZZHeight : YMAX; header.xAspect = width > LOXMAX ? XASPECT : XASPECT * 2; header.yAspect = YASPECT; /* * If it's not just a color map give the dimensions of rasters */ if (window) { header.w = width; header.h = window->GZZHeight; header.nPlanes = Depth; header.x = xoff; header.y = yoff; } if (fwrite(&header, sizeof (header), 1, file) != 1) goto abort; /* * Squirt out the color map */ { struct iff_chunk ichunk; ichunk.iff_type.b4_type = CMAP; ichunk.iff_length = MAXCOL * 3; if (fwrite(&ichunk, sizeof (ichunk), 1, file) != 1) goto abort; if (fwrite(colors, (int) 3 * MAXCOL, 1, file) != 1) goto abort; } /* * Write a CAMG chunk with ViewPort modes */ { struct CommodoreAmiga camg; camg.camg_iffc.iff_type.b4_type = CAMG; camg.camg_iffc.iff_length = sizeof (camg) - sizeof (camg.camg_iffc); camg.camg_data = window->WScreen->ViewPort.Modes; if (fwrite(&camg, sizeof (camg), 1, file) != 1) goto abort; } #ifdef MANDEL /* * We want to write our own private MAND chunk */ if (MandSize) { if (fwrite(MandPointer, MandSize, 1, file) != 1) goto abort; } #endif MANDEL /* * If they be bits then squirt out the bits */ if (window) { struct iff_chunk ichunk; ichunk.iff_type.b4_type = BODY; ichunk.iff_length = bits_size; if (fwrite(&ichunk, sizeof (ichunk), 1, file) != 1) goto abort; #ifdef DEBUG printf("write_iff: call pack_window for real\n"); #endif if (compressed) { if (pack_window(file, window, pack_row) == 0) goto abort; } else { if (pack_window(file, window, write_row) == 0) goto abort; } } fclose(file); return 1; abort: #ifdef DEBUG printf("write_iff: aborting !!!\n"); #endif fclose(file); return 0; } /* * put_ea_cmap given an ea-type color map: * * an array of unsigned chars of form ea_cmap[] = {r, g, b, r, g, b...} * * turn it into an amiga-type color map: * * an array of unsigned short of form amiga_cmap = {0xrgb, 0xrgb, ...} * * and then tell Dale this is the colors we want for our viewport */ void put_ea_cmap(ea_cmap, colors, Screen) unsigned char *ea_cmap; int colors; struct Screen *Screen; { unsigned short amy_cmap[MAXCOL]; register int i; register short color; if (colors > MAXCOL) /* Color clipping */ colors = MAXCOL; for (i = 0; i < colors; i++) { color = (*ea_cmap++ & 0xF0) << 4; color |= *ea_cmap++ & 0xF0; color |= (*ea_cmap++ & 0xF0) >> 4; amy_cmap[i] = color; } LoadRGB4(&Screen->ViewPort, amy_cmap, (long) colors); } void get_ea_cmap(ea_cmap, colors, Screen) unsigned char *ea_cmap; int colors; struct Screen *Screen; { register long i; register unsigned short rgb; if (colors > MAXCOL) /* Color clipping */ colors = MAXCOL; for (i = 0; i < colors; i++) { rgb = GetRGB4(Screen->ViewPort.ColorMap, i); *ea_cmap++ = (rgb & 0xF00) >> 4; *ea_cmap++ = (rgb & 0x0F0); *ea_cmap++ = (rgb & 0x00F) << 4; } }