2. Origins of the First Effects

Developing Demo Effects #2
The 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

Clearing the Screen Fast!

If you remember, in the previous article I asked you to think of a faster way to clear the screen than using the Blitter to clear all bitplanes. You can find the answer in this source: by modifying the Plot routine to invert pixels instead of setting them, I can clear the screen by calling the Plot routine again, with the x, y, and color values left from the previous frame. This results in a big time gain!
  • Developing Demo Effects #2 Source Download