Why MacPaint's Original Canvas was 416 Pixels Wide

Back in the mid 80's after we had finished writing GATO for the Macintosh, I took some time to explore the underbelly of the Mac. One of these times I discovered that a single M68k operation determined the way MacPaint was visually designed.

Programmer's Switch circa 1984Image courtesy of Jeff Thompson's blog

This was the time of the Mac 128k and the "Fat Mac", aka, the 512k Mac. Debugging the Mac meant hitting the Programmer's Switch that all of us developers had installed. It would in turn open up a MacsBug session.

On this particular day I was curious how MacPaint was so fast at re-rendering the canvas drawing area. You could especially see this during an undo operation. I knew that it was using an off-screen buffer and had to bitblit it back to the screen. I also knew that this was all done in software. So how to find out? I decided to do lots of undos while quickly hitting the interrupt switch.

I noticed that I landed on a certain piece of code in almost every situation. Here is this same piece of code courtesy of the Computer History Museum's addition of the MacPaint and the QuickDraw source code to its archives. This is nice because we have Bill Atkinson's comments, which I didn't have back in the day.

MacPaint source code for BufToScrn

The key to this really fast render operation was the use of the Motorola 68k's MOVEM command. MOVEM stands for Move Multiple. It can take a range of registers and move bits from an address into the M68k registers or do the reverse.

Here is how this algorithm worked:

MacPaint BufToScrn Illustrated

In this example there are a few "on" bits at the top of the lady's hair. You can see that the MOVEM.L (A0),D0-D7/A2-A6 moves long words (32 bits) from the pointer at A0 (which is the memory location of the portion of the screen buffer being copied). Notice the registers get populated with the bits from the buffer. Registers D4-D7 have lots of 1's which represent a row of her black hair.

The next MOVEM.L D0-D7/A2-A6,(A1) moves the contents of the registers to the screen. A1 points to the start of the screen memory. The (A1) in parenthesis in M68k assembler denotes indirect addressing (btw, I have always felt that M68k assembler was a joy to work with).

Now this is all fine and dandy. But the real epiphany to me was when I discovered this algorithm was the reason the MacPaint drawing area was 416 pixels wide. The drawing area is evenly divisible by 13 long words (13x32=416). This is exactly the number of registers that were available in the loop above for the MOVEM.L operation. (It appears it could have used 14 registers, but I am guessing the extra 32 pixels would have made the drawing area more cramped by reducing the gray whitespace) UPDATE: several readers helpfully pointed out that only 13 registers were truly available. The other was reserved for the stack pointer (and the other two utilized as mentioned above). I remember "knowing" that only 13 were available back then when I discovered this, but when I wrote this article the fog of time had erased the true reason.

It was fascinating to me that this particular M68k operation drove the visual design of the original, iconic, MacPaint application.

Of course one can critique it now and point out well what happens when you add color. And when you have a resizable window? But remember, this was the age of the Mac 128k, running on a 68k at 8Mhz. The ROM itself was just 64k and all of the core graphics (Quickdraw) was squeezed into 24k. This was an algorithm born of necessity. Without this optimization the original MacPaint would have been sluggish in many of its operations (the ScrnToBuf and the BufToScreen are foundational to MacPaint).

UPDATE: There are some good conversations about this article on hacker news and reddit. And if you liked this article, check out A Great Old Timey Game Programming Hack others pointed me to. A fascinating read.