DissBits Subroutine
Volume Number: 1
Issue Number: 13
Column Tag: Advanced Mac'ing
The DissBits Subroutine 
By Mike Morton, InfoCom, Cambridge, MA
What this routine does
DissBits is like copyBits.It moves one rect to another, in their respective
bitMaps. It doesn't implement the modes of copyBits, nor clipping to a region. what it
DOES do is copy the bits in a pseudo-random order, giving the appearance of
"dissolving" from one image to another. The dissolve is rapid; the entire screen will
dissolve in under four seconds.
CopyBits pays attention to the current clipping. this routine doesn't. Other likely
differences from copyBits:
o The rectangles must have the same extents (not necessarily the same lrbt). If
they are not, the routine will return -- doing nothing! No stretching copy is done
as copyBits would.
o The cursor is hidden during the dissolve, since drawing is done without
quickdraw calls. The cursor reappears when the drawing is finished. For an odd
effect, change it not to hide the cursor. Is this how Bill Atkinson thought of the
spray can in MacPaint?
o CopyBits may be smart enough to deal with overlapping areas of memory. This
routine certainly isn't.
o Because this routine is desperate for speed, it steals the A5 (globals) register,
uses it in the central loop, then restores it before returning. If you have vertical
retrace tasks which run during the dissolve, they'll wake up with the bogus A5.
Since the ROM pulls this trick too, i feel this isn't a bug in MY code, but it IS
more likely to expose bugs in VBL tasks. To correct the problem, have your task
load A5 from the low RAM location " currentA5" immediately upon starting up,
then restore its caller's A5 before returning.
You should know a few implementation details which may help:
o Copying from a dark area (lots of 1 bits) is slower than from a light area. But
just barely (a few per cent).
o There is no way to use this to randomly invert a rectangle. Instead, copyBits it
elsewhere, invert it, and dissBits it back into place.
o There is also no way to slow the dissolve of a small area. To do this, copy a large
area in which the only difference is the area to change.
o If you fade in a solid area, you're likely to see patterns, since the random
numbers are so cheesy. Don't do this fade in nifty patterns which will distract
your viewers.
o Very small areas (less than 2 pixels in either dimension) are actually done with
a call to the real copyBits routine, since the pseudo-random sequence generator
falls apart under those conditions.
Calling from languages other than pascal
This routine uses the standard Lisa Pascal calling sequence. To convert it to most
C compilers, you'll probably just have to delete this instruction from near the end of
the main routine:
add.l #psize,SP ;unstack parameters
I'd be very interested in hearing about successful uses of this routine from other
languages.
Speed of the dissolve
You need to pay attention to this section only if:
(a) You want the dissolve to run as fast as it can OR
(b) You do dissolves of various sizes and want them to take proportionate
lengths of time.
There are 3 levels of speed; the fastest possible one is chosen for you:
(1) An ordinary dissolve will work when moving from any bitmap to any bitmap,
including on the Lisa under MacWorks. This will dissolve at about 49
microseconds per pixel. A rectangle one-quarter the size of the screen will
dissolve in just over two seconds. The speed per pixel will vary slightly, and will
be less if your rect extents are close to but less than powers of 2.
(2) The dissolve will speed up if both the source and destination bitmaps have
rowBytes fields which are powers of two. If you're copying to the screen on a
mac, the rowBytes field already satisfies this. so, make your source bitmap the
right width for a cheap speedup -- about 20% faster.
(3) The fanciest level is intended for copying the whole screen. It'll paint it in about
3.4 seconds (19 microseconds per pixel). Actually, painting any rectangle which
is the full width of the screen will run at this speed, for what that's worth.
Things to think about
o Use a dynamically-built table to avoid the multiply instruction in the general
case. This may not be a great idea since not everyone can afford that much space.
o Adapt the routine to do transfer modes. e specially pattern modes, with no source.