IBM Screen Swapping (COMPUTE! Magazine February 1986 by Paul W. Carlson) You can achieve many interesting effects, including animation, by rapidly switching between several graphics screens stored in memory. This capability isn't a standard feature of the IBM PC. With help from two short machine language subroutines, however, you can write programs that swap screens almost instantly. The subroutines copy the video bitmap to or from an array in about five thousandths of a second, much too fast for the eye to see. In fact, this is even faster than the video monitor can display a frame, so the effect is instantaneous. To get started, type in Program 1 below. It creates two files, SCRNARRY.BAS and ARRYSCRN.BAS, which contain the two machine language subroutines. The first routine copies the video bitmap to an array, and the second copies the contents of an array to the video bitmap. The routines achieve their speed by treating the bitmap as a continuous string of 16,192 bytes. For an example of how to use these routines in your own programs, type in Program 2 and save it on the same disk with SCRNARRY.BAS and ARRYSCRN.BAS. Before running Program 2, make sure the disk is in the active drive; it accesses the two routines as it runs. After typing RUN, don't press any keys until you want to halt the program. You should see three multicolored spirals on the screen. The first two disappear as soon as they're completed, and the third seems to rotate. The rotation, of course, is an illusion. Here's what happens: In the split-second between the time the first two spirals are completed and then erased, each screen is copied into an array by SCRNARRY.BAS. The third spiral is also copied into an array. Finally, the contents of all three arrays are repeatedly copied to the screen by ARRYSCRN.BAS to get the rotating effect. Actually, the program requires a time-delay loop to keep the screen-flipping from happening too fast. You can load a graphics screen from disk directly into an array the same way Program 2 loads the machine language into arrays. Why would you want to do this? Suppose you had saved graphics screens from three different programs on disk using statements such as this: DEF SEG=&HB800:BSAVE"filename",0,16192 with filenames of PIC1, PIC2 and PIC3. You could then use Program 3 to display a "slide show" of your creations. This interesting program displays one screen while loading another. Pressing the space bar (after giving the next screen time to load) displays the next picture. The program could be extended to accomodate any number of screens, even prompting you to change disks if necessary. It needs only one array to store the screens no matter how many you want to display, since it stores only one screen at any moment. Notice tha the statement LA=0 in line 10 of Program 3 prevents the address of the ATOS array from changing after it is assigned a value for PUTSCRN in line 30. Program 1: Screen Swapping Routines 10 DIM M(7),J(6):DEF SEG 20 FOR N=0 TO 26:READ B 30 POKE VARPTR(M(0))+N,B:NEXT 40 BSAVE"SCRNARRY",VARPTR(M(0)),27 50 FOR N=0 TO 22:READ B 60 POKE VARPTR(J(0))+N,B:NEXT 70 BSAVE"ARRYSCRN",VARPTR(J(0)),23:END 80 DATA 6,30,7,30,139,236,184,0 90 DATA 184,142,216,185,160,31,51,246 100 DATA 139,126,8,252,243,165,31,7 110 DATA 202,2,0,6,139,236,184,0 120 DATA 184,142,192,185,160,31,51,255 130 DATA 139,118,6,252,243,165,7,202 140 DATA 2,0 Program 2: Spiral Demo 10 DIM SCRN1(4048),SCRN2(4048),SCRN3(4048),STOA(7),ATOS(6) 20 DEF SEG:BLOAD"SCRNARRY",VARPTR(STOA(0)) 30 BLOAD"ARRYSCRN",VARPTR(ATOS(0)) 40 KEY OFF:SCREEN 1:COLOR 0,0 50 FOR C=1 TO 3:W=C:CLS 60 TP=6.283185:F=80/TP:DA=TP/9:DB=TP/20:A=0 70 FOR I=1 TO 9:B=0:A=A+DA:PSET(160,100) 80 FOR J=1 TO 20:B=B+DB:R=F*B 90 X=160+1.2*R*SIN(A+B):Y=100+R*COS(A+B) 100 LINE -(X,Y),3:NEXT J,I 110 CIRCLE(160,100),96,3:A=DA/2 120 FOR I=1 TO 9:A=A+DA 130 X=160+1.18*R*SIN(A):Y=100+.96*R*COS(A) 140 C=C MOD 3+1:PAINT(X,Y),C,3:NEXT I 150 GETSCRN=VARPTR(STOA(0)) 160 ON W GOTO 170,180,190 170 CALL GETSCRN(SCRN1(0)):GOTO 200 180 CALL GETSCRN(SCRN2(0)):GOTO 200 190 CALL GETSCRN(SCRN3(0)) 200 NEXT C 210 PUTSCRN=VARPTR(ATOS(0)) 220 CALL PUTSCRN(SCRN1(0)):FOR J=0 TO 100:NEXT 230 CALL PUTSCRN(SCRN2(0)):FOR J=0 TO 100:NEXT 240 CALL PUTSCRN(SCRN3(0)):FOR J=0 TO 100:NEXT 250 IF INKEY$="" THEN 220 260 CLS:SCREEN 0:WIDTH 80:KEY ON:END Program 2 Explanation Line Description 20,30 Loads the machine language subroutines into the STOA and ATOS arrays 40-140 Draws and paints three spirals, each with the colors shifted 150 GETSCRN is the entry point for the subroutine that copies the screen to an array. No new simple variables can be assigned from the point GETSCRN is computed to the point it is used in a CALL statement. Assigning simple variables causes array address to move. 160-200 Copies the screen to array SCRN1, SCRN2 or SCRN3 after each spiral is complete. 210 PUTSCRN is the entry point for the subroutine that copies an array to the screen. The same note for line 150 applies here also. 220-250 Repeatedly copies the arrays SCRN1, SCRN2 and SCRN3 to the screen until a key is pressed. Program 3: Slide Show Demo 10 DIM SCRN(4048),ATOS(6):LA=0 20 DEF SEG:BLOAD"ARRYSCRN",VARPTR(ATOS(0)) 30 PUTSCRN=VARPTR(ATOS(0)):LA=VARPTR(SCRN(0)) 40 BLOAD"PIC1",LA 50 KEY OFF:CLS:SCREEN 1:COLOR 0,1 60 CALL PUTSCRN(SCRN(0)):BLOAD"PIC2",LA 70 IF INKEY$<>" " THEN 70 80 CALL PUTSCRN(SCRN(0)):BLOAD"PIC3",LA 90 IF INKEY$<>" " THEN 90 100 CALL PUTSCRN(SCRN(0)) 110 IF INKEY$<>" " THEN 110 120 CLS:SCREEN 0:WIDTH 80:KEY ON:END Programs 4 and 5 show the source code for the SCRNARRY and ARRYSCRN subroutines. They aren't required for use with Programs 1-3; they're provided so machine language programmers can observe the techniques involved. An assembler is required to enter these listings. Program 4: SCRNARRY Source Code ; This subroutine copies 16192 bytes from the video display into a ; BASIC array. CSEG SEGMENT STOA PROC FAR ASSUME CS:CSEG PUSH ES ; Save extra segment PUSH DS ; Set the extra segment POP ES ; equal to the data segment PUSH DS ; Save the data segment MOV BP,SP ; Make BP point to the stack MOV AX,0B800H ; Set data segment to beginning MOV DS,AX ; of video RAM MOV CX,8096 ; Initialize move counter XOR SI,SI ; Initialize source index MOV DI,8[BP] ; Init destination index to array offset CLD ; Set direction flag REP MOVSW ; Move the display to the array POP DS ; Restore the data segment POP ES ; Restore the extra segment RET 2 ; Clean up the stack STOA ENDP CSEG ENDS END Program 5: ARRYSCRN Source Code ; This subroutine copies 16192 bytes from a BASIC array to the video ; display. CSEG SEGMENT ATOS PROC FAR ASSUME CS:CSEG PUSH ES ; Save extra segment MOV BP,SP ; Make BP point to stack MOV AX,0B800H ; Set extra segment to beginning MOV ES,AX ; of video RAM MOV CX,8096 ; Initialize move counter XOR DI,DI ; Initialize destination index MOV SI,6[BP] ; Init source index to array offset CLD ; Set direction flag REP MOVSW ; Move the array to the screen POP ES ; Restore extra segment RET 2 ; Clean up stack ATOS ENDP CSEG ENDS END