/* fii_lccomp.c - Some C code that mixes with the assembler code in comp.asm and skip.asm to make up compressed pixel packets suitable for incorporation into a FLI file. See also writefli.c */ #include "aai86.h" #include "aaflisav.h" #include "aafii.h" #define INERTIA 4 static char * sbrc_line(s1, s2, cbuf, count) Pixel *s1, *s2, *cbuf; int count; { register int wcount; int i; register char *c; int op_count; int same_count; int next_match; int bcount; op_count = 0; c = cbuf+1; for (;;) { if (count <= 0) { goto OUT; } /* first find out how many bytes to skip... */ wcount = i86_bcompare(s1, s2, count); if ((count -= wcount) <= 0) goto OUT; /* same until the end... */ /* if skip is longer than 255 have to break it up into smaller ops */ while (wcount > 255) { s1 += 255+1; s2 += 255; wcount -= 255+1; /* make dummy copy 1 op */ *c++ = 255; *c++ = 1; *c++ = *s2++; op_count++; } /* save initial skip and move screen pointer to 1st different byte */ *c++ = wcount; s1 += wcount; s2 += wcount; op_count++; /* if have skipped to near the end do a literal copy... */ if (count <= INERTIA) { *c++ = count; i86_bcopy(s2,c,count); c += count; goto OUT; } /* now look for a run of same... */ bcount = count; if (bcount > FLI_MAX_RUN) bcount = FLI_MAX_RUN; wcount = i86_bsame(s2, bcount); if (wcount >= INERTIA) /* it's worth doing a same thing thing */ { next_match = fii_tnskip(s1, s2, wcount,INERTIA); if (next_match < wcount) /* if it's in our space and a decent size */ { /* we'll cut short same run for the skip */ wcount = next_match; } *c++ = -wcount; *c++ = *s2; s1 += wcount; s2 += wcount; count -= wcount; } else /* doing a literal copy. What can we do to make it short? */ { /* figure out how long until the next worthwhile "skip" */ /* Have wcount of stuff we can't skip through. */ wcount = fii_tnsame(s2,fii_tnskip(s1,s2,bcount,INERTIA-1),INERTIA); /* Say copy positive count as lit copy op, and put bytes to copy into the compression buffer */ *c++ = wcount; i86_bcopy(s2,c,wcount); s1 += wcount; s2 += wcount; c += wcount; count -= wcount; } } OUT: *cbuf = op_count; return(i86_norm_ptr(c)); } Cbuf *fii_lccomp(Pixel *s1,Pixel *s2,USHORT *cbuf,int width,int height) { int skip_count, lcount, j; Pixel *c; Pixel *oc; unsigned acc; long total; unsigned last_real; /* find out how many lines of s1 and s2 are the same */ acc = (width>>1); /* SHORTS in line */ j = height; skip_count = 0; total = 0; while (--j >= 0) { if (i86_wcompare(s1, s2, acc) != acc) break; s1 += width; s2 += width; skip_count++; } /* If all same do special case for empty frame*/ if (skip_count == height) return((Cbuf *)(cbuf+1)); /* store offset of 1st real line and set up for main line-at-a-time loop */ *cbuf++ = skip_count; height -= skip_count; c = (char *)(cbuf+1); last_real = 0; /* keep track of last moving line */ for (j=1; j<=height;j++) { oc = c; if (i86_wcompare(s1,s2,acc) == acc) /* whole line is the same */ { *c++ = 0; /* set op count to 0 */ } else /* compress line */ { c = sbrc_line(s1,s2,c,width); last_real = j; } total += i86_ptr_to_long(c) - i86_ptr_to_long(oc); if (total >= 60000L) return(NULL); s1 += width; s2 += width; } /* set # of lines in compression to last real, removing empty bottom lines from buffer */ *cbuf = last_real; c -= height-last_real; return(i86_enorm_ptr(c)); }