Classic Computer Magazine Archive COMPUTE! ISSUE 89 / OCTOBER 1987 / PAGE 92

Dazzlers

Paul W. Carlson

Grab your sunglasses—here come the dazzlers! Several demos are included along with information on how to create your own brilliant, rapidly changing patterns. For the IBM PC/PCjr or compatible with a color/graphics adapter or equivalent hardware. Requires BASICA for the PC, GW-BASIC for compatibles, and Cartridge BASIC for the PCjr.

Everyone has their own favorite graphics demos. "Dazzlers" is a collection of programs, each featuring flowing colors and simulated movement. After seeing these kaleidoscopic displays, you may decide to put a couple of them onto your own favorite demo disk. After you've tried the patterns I've included, you may even want to design some of your own.

Program 1 is the main program for Dazzlers. It cannot be used independently, but must be combined with one of five subroutines (Programs 2–6). Type in and save a copy of Program 1. Then add the lines from one of the subroutines to the program and save it with a unique filename. Run the program. The screen clears; then it's filled with solid white. Next, blocks of color appear on the screen, forming an intricate pattern. And finally, the colors are repeatedly cycled. Press any key after the colors begin changing to clear the screen and end the program.

Waves of color ripple across the screen in "Dazzlers," a set of animated graphics demos.

The Subroutines

Any of the subroutines (Programs 2–5) can be used by merging them with Program 1. There are a number of elements common to each of these subroutines. And for a reason: Once an interesting pattern is created, making only minor changes in the subroutine will create an entirely different and unique pattern. This is an important point to remember when designing your own dazzler subroutines.

Here are a few more points to keep in mind: The subroutine should POKE values from 0 to 15 into every odd-numbered memory location in video page 0 from 1 to 1999. The same numbers must also be POKEd into the odd locations of video page 1 (2049–4047). To make the colors flow properly, adjacent characters (adjacent horizontally, vertically, or diagonally) should have consecutive color numbers.

One method that can be used to generate consecutive color numbers is to enclose a statement such as C = (C + 1) AND 15 in a loop, where the variable C is the color number. This statement will assign to C the repeating sequence of consecutive numbers 0–15.

An almost endless variety of patterns is possible. You can lay out a pattern on graph paper and then write a subroutine that will reproduce the pattern on the screen, or you can simply alter a previous subroutine until you get something totally new. Both methods were used to write the subroutines in this article.

How It Works

At the heart of the program is a short, very fast machine language routine that increments every character's foreground color. Those characters with a foreground color number of 15 receive a foreground color number of zero. For machine language programmers, the figure shows the source code for this program.

Line 10 in the BASIC program reserves an area of memory for the machine language routine. Lines 20–80 POKE the machine language routine into the reserved memory. Line 90 sets up a 40-column color screen with video page 0 the active page and video page 1 the display page. Each page is each 2048 bytes long, although only the first 2000 bytes of each page are used. The even-numbered bytes contain the ASCII code that determines which character will appear on the screen. Line 100 of the program POKEs the number 219, the ASCII code for a solid block, into the even-numbered bytes of both video pages 0 and 1. This is what causes the screen to fill with solid white. Then line 100 executes a GOSUB 1000 which POKEs the foreground color numbers into the odd-numbered bytes of both pages.

Source Code for Color-Changing Routine

; This subroutine increments the foreground color of every

; character on video page 0 or page 1. The subroutine is called

; with the video page offset as the only argument.

;
CSEG	SEGMENT
DAZZLE	PROC	FAR
ASSUME	CS:CSEG
PUSH	ES	;Save the extra segment
MOV	BP, SP	;Make BP point to stack
MOV	AX, 0B800H	;Set extra segment to start of
MOV	ES, AX	; video RAM
MOV	SI, 6[BP]	;SI is address of page offset
MOV	DI, WORD PTR [SI]	; DI is page offset
INC	DI	;Bump DI to attribute byte
MOV	CX,1000	; 1000 bytes to move
MLOOP:	MOV	AL, ES:[DI]	;Get attribute byte
MOV	DL, AL	Copy byte into DL
INC	DL	; Increment attribute byte
AND	DL, 15	DL is new foreground color
AND	AL, 240	Mask out old foreground color
OR	AL, DL	OR in new foreground color
MOV	ES:[DI], AL	;Move new attribute byte to video RAM
INC	DI	;Bump DI to next attribute byte
INC	DI
LOOP	MLOOP	;Get next attribute byte
POP	ES	;Restore the extra segment
RET	2	;Clean up the stack
DAZZLE	ENDP
CSEG	ENDS
END

The odd-numbered bytes contain the color information for each character. Before the subroutine returns, it assigns a value to the variable TD, which controls the time delay. In line 110, the variable A is the address of the machine language routine, and the variables F% and S% are the number of bytes from the beginning of video RAM for video page 0 and page 1. Lines 120 and 130 form a loop in which the foreground colors of the video page not being displayed are incremented. That page is then displayed, a time delay is executed, and the keyboard is checked for a keypress. Line 140 is executed when a key is pressed, clearing the screen and returning the display to 80-column video mode.

For instructions on entering these programs, please refer to "COMPUTE!'s Guide to Typing In Programs" elsewhere in this issue.

Program 1: Dazzlers

CJ	1	 "Copyright 1987 COMPUTE! Publications, Inc, All Rights Reserved.
KC	3	 KEY OFF : CLS : LOCATE 10, 34 : PRINT"Copyright 1987" : PRINT TAB(28)"COMPUTE! Publications, Inc." : PRINT TAB (31) " : All Right Reserved. "FOR I = 1 TO 1500 : NEXT I
FA	10	 DEF SEG : CLEAR, &H3FF0 : N = &H4000
HM	20	 READ A$ : IF A$ : IF A$ = "/" THEN 90
DC	30	 POKE N, VAL ("&H" + A$) : N = N + 1 : GOTO 20
MF	40	 DATA 06, 8B, EC, B8, 00, B8, 8E, C0, 8B, 76
DK	50	 DATA 06, 8B, 3C, 47, B9, E8, 03, 26, 8A, 05
BD	60	 DATA 8A, D0, FE, C2, 80, E2, 0F, 24, F0, 0A
IK	70	 DATA C2, 26, 8B, 05, 47, 47, E2. EB, 07, CA
HN	80	 DATA 02, 00,/
FP	90	 WIDTH 40 : SCREEN 0, 1, 0, 1 : CLS : DEF SEG = &HBB00
PN	100	 FOR N = 0 TO 2046 STEP 2 : POKE N, 219 : POKE N + 2048, 219 : NEXT : GOSUB 1000
DB	110	 DEF SEG : A = &H4000 : F% + 0 : S% = 2048
HF	120	 CALL (F%) : SCREEN, , , 0 : FOR N = 1 TO : NEXT : CALL A(S%) : SCREEN, , , 1
DN	130	 FOR N = 1 TO TD : NEXT : 1F INK EY$ = " " THEN 120
BM	140	 WIDTH 80 : CLS : END

Program 2 : Subroutine 1

GA	998	 ‘ Subroutine 1
KJ	999	 ‘
KF	1000	 FOR P = 0 TO 1 : FOR R = 0 TO 12 : C = R : K = 2048 * P
ND	1010	 FOR L = 0 TO 38 STEP 2 : C = (C + 1) AND 15
AE	1020	 POKE 1 + 80 * R + L + K, C : POKE 79 + 80 * R - L + K, C
IH	1030	 POKE 1921 - 80 * R + L + K, C : POKE 199 - 80 * R - L + K, C : NEXT : NEXT : NEXT
MD	1040	 TD = 50 : RETURN

Program 3 : Subroutine 2

IE	998	 ‘ Subroutine 3
KJ	999	 ‘
BH	1000	 FOR P = 0 TO 1 : FOR R = 0 TO 6 : C = R : K = 2048 * P
LB	1010	 FOR L = 0 TO 1B STEP 2 : C = (C + 1) AND 15
MI	1020	 D = 1 + 80 * R + L + K : POKE D, C : POKE D + 40, C : POKE D + 960, C : POKE D + 1000, C
CL	1030	 D = 39 + 80 * R - L + K : POKE D, C : POKE D + 40, C : POKE D + 960, C : POKE D + 1000, C
EG	1040	 D = 961 - 80 * R + L + K : POKE' D, C : POKE D + 40, C : POKE D + 960, C : POKE D + 1000, C
OH	1050	 D = 999 - 80 * R - L + K : POKE D, C : POKE D + 40, C : POKE D + 960, C : POKE D + 1000, C : NEXT NEXT : NEXT
ME	1060	 TD = 50 : RETURN

Program 5 : Subroutine 4

JB	998	 ‘ Subroutine 4
KJ	999	 &lsquo
MC	1000	 FOR P = 0 TO 1 : FOR C = 0 To 11 : N = 2048 * P + 82 * C - 1
EE	1010	 FOR K = C TO 39 - C : N = N + 2 : POKE N, C : NEXT
DF	1020	 FOR K = C TO 23 - C : N = N + B0 : POKE N, C : NEXT
HK	1030	 FOR K = C TO 38 - C : N = N - 2 : POKE N, C : NEXT
GF	1040	 FOR K = C TO 22 - C : N = N - 80 : P
HL	1050	 FOR N = 985 TO 1015 STEP : POKE N + 2048 * P, 12 : NEXT : N
EXT
NK	1060	 TD = 100 : RETURN

Program 6 : Subroutine 5

LI	998	 ‘ Subroutine 5
KJ	999	 ‘
PB	1000	 FOR P = 0 TO 1 : FOR C = 0 TO 11 : N = 2048 * P + 82 * C - 1 : B = 1
PE	1010	 FOR K = C TO 39 - C : N = N + 2 : B = (B + 1) AND 15 : POKE N, B : NEXT : B = 2
LE	1020	 FOR K = C TO 39 - C : N = N + 80 : B = (B + 1) AND 15 : POKE N, B : NEXT : B = 1
CK	1030	 FOR K = C TO 38 - C : N = N - 2 : B = (B + 1) AND 15 : POKE N, B : NEXT : B = 2
ML	1040	 FOR K = C TO 22 - C : N = N - 80 : B = (B + 1) AND 15 : POKE N, B : NEXT : NEXT : B = 17
NK	1050	 FOR N = 958 TO 1015 STEP 2 : B = (B + 1) AND 15 : POKE N + 2048 * P, B : NEXT
NK	1060	 TD = 100 : RETURN