2. Origins of the First Effects
Developing Demo Effects #2The first executables for bragging and saying hello to computer friends came with the first piracy wave and crack intros on the Apple II in the 1970s, consisting largely of engineers with beards.
Around 1986, there was a second wave consisting of teenagers, almost exclusively. Cracktros remained mostly of the picture + scroll type, but soon the teenagers' energy raised the stakes, meaning that groups would also need coders, artists and musicians for maximum bragging rights!
On Amiga, in 1985 nothing was released, and in 1986, only 18 known intros were released, all of the picture + scroll type. Then, in 1987, things started happening...!
The First Effect
So, which was the first demo that showed effects as we know them? I had to research release lists from swappers, since dates are uncertain before the "demo explosion". The first effect intro for which the release date is known is the Unit A cracktro for "Break!", and the effects in it surprised me very much!
Unit A "Break" cracktro showing a visually correct chessboard effect, with perspective calculations and 3D stars.

The 16-color Hires picture drawn in Deluxe Paint that is the basis for most of the magic.
Perspective
The simplest way to calculate a Z position in perspective on a 2D display is to move the points along an imagined Z axis starting at an offset where the nearest point of the floor is thought to be, and divide a large number by these Z values to get the projected Y position for the copper waits where the chess board colors are inverted. In the case of the stars both X and Y position is scaled this way from the Z values.From the palette you can see that two colors are used for the floor, and that these colors are not used in the multicolored text, so that different RGB colors can "flow" through the letters and through the chessboard independently.
(To create the template for the floor in Deluxe Paint, draw a pattern of vertical lines, cut to brush, double the brush size 6-7 times, and use the perspective mode to tilt it in the Z direction. Not many steps, but the trick is thinking of it!)
Being interested in demos is being interested in techniques. In this intro, Ewing cleverly devised a technique for hundreds of squares to move in 3D - and the chessboard became an effect. An effect that would become widely loved and adopted!
Color cycle
In Deluxe Paint, only the RGB colors inside the palette can be rotated. In a demo, you can create a bank of palette colors as part of a copperlist and copy RGB values from a longer list, from an offset position that you increase at the speed you want. (PokeWords below is a generic routine similar to PokePtrs that I made, which simply copies words from the source into every other word of the copperlist.)
*--- inc color offset ---* move.w ColorOffset(PC),d0 addq.w #1,d0 and.w #127,d0 ;keep count within 0..127 move.w d0,ColorOffset *--- poke palette ---* lea TextColors(PC),a0 lsr.w #1,d0 ;color cycle speed, 50/8 fps and.w #-2,d0 ;make it even add.w d0,a0 lea TextPalette+2,a1 moveq #(15-3)-1,d1 bsr.w PokeWords
Z / Perspective Calculation
This code takes a Z value counter as input, scales it up, adds an offset, and scales it back down to cover the pixel height of the drawn chessboard graphic. A sub-square counter, moved each frame and wrapping at a value corresponding to the Z-length of a full square, is added to the distance.PokeChessWaits: ;a1=destination (after last wait) move.l ChessColorP(PC),a0 ;source for RGB colors *--- sub-square movement ---* move.w ChessZ(PC),d3 sub.w #ZSpeed,d3 ;new square? bpl.s .nowrap add.w #stepspersquare,d3 ;then wrap addq.l #2,a0 ;and toggle RGB cmp.l #ChessColorsE,a0 blt.s .nowrap lea ChessColors(PC),a0 .nowrap: move.w d3,ChessZ move.l a0,ChessColorP *--- poke Y positions ---* move.l #ZScale,d2 mulu #FOVScale,d3 add.w #ZStart,d3 move.w #ZStep,d4 moveq #17-1,d1 ;#squares = WAIT commands to be poked .l1: move.l d2,d0 divu d3,d0 add.w #ChessTopY+horizonadjust,d0 lea -12(a1),a1 move.b d0,(a1) ;wait move.w (a0)+,6(a1) ;color 1 move.w (a0)+,6+4(a1) ;color 2 add.w d4,d3 dbf d1,.l1 rts
Chessboard Copper Splits
The illusion of the chessboard is created by swapping which color register sets the RGB surface color and which sets the black color. The simplest way to do this is creating the copperlist so that for every split (WAIT command), the order of COLOR01 and COLOR02 is alternated. Then, the perspective calculation can poke its vertical stop positions and color values without having a toggle flag.
CopperChess: *--- chess start ---* ;color init at fixed horizon Y .y: SET ChessTopY<<8+$07 ;WAIT for $7407 (these will be poked dc.w .y,$fffe ;with proper perspective Y values) dc.w $184,$337 ;swap order of color registers dc.w $182,$ddf .y: SET .y+$0100 ;next line WAIT *--- to-be-poked copper WAITs ---* REPT 8 dc.w .y,$fffe dc.w $182,$337 dc.w $184,$ddf .y: SET .y+$0800 ;more "dummy" WAIT values dc.w .y,$fffe dc.w $184,$337 ;swap order of color registers dc.w $182,$ddf .y: SET .y+$0800 ENDR CopperChessE:
3D Stars
The original effect uses a list of angles that stay the same, and a list of Z distance counters that wrap at a value which results (after perspective calculation) in a coordinate that is a bit outside the screen, so that no stars are seen to vanish inside the screen bounds. Instead, I decided to implement a correct 3D starfield, where the Z distance also determines the color intensity of each star. I saw this as a soft introduction to the proper 3D object calculations in the coming articles.
The stars (at least the ones that aren't outside the starfield area) are then plotted with the Plot routine from the previous article.
CalcStars: ;a0/a1/d0=source,dest,count subq.w #1,d0 ;decrease for dbf move.w #ZStart,d4 ;stars frontmost Z position move.w #ZStep*starspeed/100,d5 ;star Z movement speed move.w #17*ZStep,d6 ;Z range for stars to stay within .l0: movem.w (a0)+,d1-d3 ;x,y,z (movem.w auto-sign-extends) asl.l #8,d1 ;scale up for div - Y not so much asl.l #6,d2 ;due to the small height and hires mode *--- move star ---* sub.w d5,d3 bpl.s .nowr add.w d6,d3 ;wrap to make sure Z dist is positive .nowr: move.w d3,-(a0) ;write Z value back... *--- x,y 3D->2D ---* add.w d4,d3 divs d3,d1 ;...scale down X and Y... divs d3,d2 *--- set plot color ---* move.w d6,d3 ;...and fetch it for color calculation sub.w (a0)+,d3 ;(invert Z axis - nearer is brighter) divs #ZStep*17/6,d3 ;shrink Z to range 0..6 addq.w #1,d3 ;-> color 1..7 movem.w d1-d3,(a1) ;write plot x,y,color for PlotPoints addq.w #6,a1 dbf d0,.l0 rts