home *** CD-ROM | disk | FTP | other *** search
- /* Auto: make
- */
-
- IMPORT BPTR SnapFile;
- IMPORT BYTE TranspBuf[];
-
- #define ID(a,b,c,d) ((a << 24L) | (b << 16L) | (c << 8L) | (d))
-
- struct ckHdr {
- LONG ChunkName;
- LONG ChunkSize;
- };
-
- struct BitMapHeader
- {
- UWORD w,h;
- WORD x,y;
- UBYTE nPlanes;
- UBYTE masking;
- UBYTE compression;
- UBYTE pad1;
- UWORD transparentColor;
- UBYTE xAspect, yAspect;
- WORD pageWidth, pageHeight;
- };
-
- struct ckHdr FORM = {
- ID('F','O','R','M'),
- 0L
- };
- LONG TYPE = ID('I','L','B','M');
-
- struct ckHdr BMHD = {
- ID('B','M','H','D'),
- sizeof(struct BitMapHeader)
- };
- struct BitMapHeader BMHdr = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
-
- struct ckHdr CAMG = {
- ID('C','A','M','G'),
- 4L
- };
- ULONG ViewMode = NULL;
-
- struct ckHdr CMAP = {
- ID('C','M','A','P'),
- 0L
- };
-
- struct ckHdr BODY = {
- ID('B','O','D','Y'),
- 0L
- };
-
- UBYTE *buf;
- WORD bufcnt;
- ULONG totalsize;
-
- WORD bumpmode;
- #define BUMP_CALC 1
- #define BUMP_SAVE 2
-
- WORD bump(cnt, dataptr, size)
- WORD cnt;
- UBYTE *dataptr;
- WORD size;
- {
- REGISTER LONG tsize = size;
- if (tsize) {
- totalsize += tsize + 1; /* Don't forget the count-byte */
- }
- if (bumpmode == BUMP_CALC) { /* Just calculating? */
- return 1; /* Don't do the save */
- }
- if (bufcnt + tsize + 1 >= 4096 || tsize == 0) {
- if (Write(SnapFile, buf, (LONG)bufcnt) == -1L) {
- return 0;
- }
- bufcnt = 0;
- }
- buf[bufcnt++] = cnt;
- CopyMem((char *)dataptr, (char *)&buf[bufcnt], tsize);
- bufcnt += tsize;
- return 1;
- }
-
- ULONG WriteBody(BM)
- struct BitMap *BM;
- {
- WORD scanline, plane;
- REGISTER WORD bpr = BM->BytesPerRow;
- REGISTER WORD i, j;
- LONG offset = 0L;
- REGISTER UBYTE data;
- REGISTER UBYTE *bd;
-
- totalsize = 0L;
-
- if (!(buf = AllocMem(4096L, MEMF_PUBLIC))) {
- return NULL;
- }
-
- bufcnt = 0;
- for (scanline = 0; scanline < BM->Rows; ++scanline) {
- for (plane = 0; plane < BM->Depth; ++plane) {
- bd = BM->Planes[plane]+offset;
- i = 1;
- j = bpr - 1;
- data = bd[0];
- while (j) {
- if (bd[i] == data) { /* Equal bytes? */
- --i; /* First equal byte */
- if (i > 0) { /* Old "random" data to save */
- if (!bump((WORD)(i - 1), bd, i)) {
- return NULL;
- }
- }
- bd = &bd[i]; /* Start of equal bytes */
- i = 2; /* 0 & 1 is equal */
- --j;
- while (i < 128 && j && bd[i] == data) {
- ++i;
- --j;
- }
- if (!bump((WORD)-(i - 1), &bd[i - 1], 1)) {
- return NULL;
- }
- goto new_block;
- } else { /* Not equal. Check block range */
- if (i == 128) { /* Block limit */
- if (!bump((WORD)(i - 1), bd, i)) {
- return NULL;
- }
- new_block:
- bd = &bd[i]; /* Start new block */
- i = 0;
- if (j == 0) {
- break;
- }
- }
- }
- /* Different byte or a new start */
- data = bd[i]; /* New possible equal */
- next_byte:
- ++i;
- --j;
- }
- if (i != 0) { /* Data to save */
- if (!bump((WORD)(i - 1), bd, i)) {
- return NULL;
- }
- }
- }
- offset += BM->BytesPerRow;
- }
- if (!bump(0, NULL, 0)) { /* Flush any bytes left if the buffer */
- return NULL;
- }
- FreeMem(buf, 4096L);
- return totalsize;
- }
-
- WORD SaveGS(GS)
- struct GfxSnap *GS;
- {
- ULONG BODYPos;
- UBYTE *oldtitle;
-
- oldtitle = GS->window->Title;
- SetWindowTitles(GS->window, "Saving...", NULL);
-
- bumpmode = BUMP_SAVE;
-
- BMHdr.w = GS->BM.BytesPerRow * 8;
- BMHdr.h = GS->height;
- BMHdr.x = BMHdr.y = 0;
- BMHdr.nPlanes = GS->depth;
- BMHdr.masking = 0;
- BMHdr.compression = 1;
- BMHdr.transparentColor = dectoint(TranspBuf);
- BMHdr.xAspect = BMHdr.xAspect = 1;
- BMHdr.pageWidth = GS->pagew;
- BMHdr.pageHeight = GS->pageh;
- ViewMode = GS->viewmode;
-
- CMAP.ChunkSize = (LONG)3 * (GS->viewmode & HAM ? 16 : 1L << GS->depth);
-
- if (Write(SnapFile, (char *)&FORM,
- (LONG)(sizeof(FORM) + sizeof(TYPE) +
- sizeof(BMHD) + sizeof(BMHdr) +
- sizeof(CAMG) + sizeof(ViewMode) +
- sizeof(CMAP))) == -1L) {
- return 0;
- }
- if (Write(SnapFile, (char *)&GS->rgb[0], CMAP.ChunkSize) == -1L) {
- return 0;
- }
- BODYPos = Seek(SnapFile, 0L, OFFSET_CURRENT);
- if (Write(SnapFile, (char *)&BODY, (LONG)sizeof(BODY)) == -1L) {
- return 0;
- }
- if (!(BODY.ChunkSize = WriteBody(&GS->BM))) {
- return 0;
- }
- FORM.ChunkSize = BODYPos - sizeof(FORM) + sizeof(BODY) + BODY.ChunkSize;
- if (FORM.ChunkSize & 1) { /* Odd size */
- if (Write(SnapFile, "X", 1L) == -1L) {
- return 0;
- }
- ++FORM.ChunkSize;
- }
- Seek(SnapFile, 0L, OFFSET_BEGINNING);
- Write(SnapFile, (char *)&FORM, (LONG)sizeof(FORM));
- Seek(SnapFile, BODYPos, OFFSET_BEGINNING);
- Write(SnapFile, (char *)&BODY, (LONG)sizeof(BODY));
- SetWindowTitles(GS->window, oldtitle, NULL);
- return 1;
- }
-