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