'OPTIMIZATIONS '- [DONE] DRAW LINE SEGMENTS INSTEAD OF PIXELS '- [IN PROGRESS] DRAW BLOCKS INSTEAD OF SEGMENTS USING THE FILL COMMAND ' - USES "FILL A,8,C0", WORKS ONLY FOR CENTER BLOCKS (THEY DON'T NEED OVERLAY) ' - IS GOING TO MORE THAN DOUBLE THE SPEED AGAIN ' - BUT IT HAS TO BE INTEGRATED IN EACH SHAPE '- REPEAT A GENERATED SHAPE DOWN (RECTANGLES) 'I GUESS THE HORIZONTAL LINES ARE GOOD FOR FLOOD FILL TOO 'S E T U P 'DEFINE ROM FOR FASTER PIXEL PROCESSING DIM GLOBAL LLINE_ROM(7),RLINE_ROM(7),PIXEL_ROM(7),YADDR_ROM(127),XCELL_ROM(127) FOR I=0 TO 7 LLINE_ROM(I)= 255 XOR 2^(7-I)-1 RLINE_ROM(I)= 2^(8-I)-1 PIXEL_ROM(I)= 2^(7-I) NEXT I FOR I=0 TO 127 YADDR_ROM(I)=$8000+(I\8)*256+(I MOD 8) XCELL_ROM(I)=(I\8)*8*2 NEXT I 'TOUCHSCREEN 'POKE $FF72,80 BG VIEW OFF 1 'ON RASTER CALL RASTERFX SUB RASTERFX SCROLL 0,0,RASTER MOD 4 END SUB CALL VIEW_CHARACTERS(2,0,0,255) 'CALL HLINE(30,20,50,3) 'CALL BAR(97,45,13,90,RND(3)) 'CALL BAR(60,80,10,20,1) 'CALL DIAMOND(50,50,50,1) 'CALL CIRCLE(RND(127),RND(127),RND(63),RND(2)+1) 'CALL CIRCLE(50,50,50,1) 'CALL TRIANGE(RND(127),RND(127),RND(127),RND(127),RND(127),RND(127),RND(2)+1) DO 'TRACE TOUCH.X-80 'CALL BAR(RND(255),RND(255),RND(255),RND(255),RND(3)) 'FOR I=0 TO 27 STEP 10 'CALL BAR(20+I,30+I,40+I,50+I,RND(3)) 'NEXT I 'FOR I=0 TO 27 'CALL HLINE(20+I,0+I,50+I,RND(3)) 'NEXT I 'FOR I=0 TO 256 'CALL HLINE(RND(255),RND(255),RND(255),RND(3)) 'WAIT VBL 'NEXT I 'CALL BAR(RND(127),RND(127),RND(127),RND(127),RND(2)+1) 'CALL DIAMOND(RND(127),RND(127),RND(63),RND(2)+1) 'CALL CIRCLE(RND(127),RND(127),RND(62)+1,RND(2)+1) CALL TRIANGE(RND(127),RND(127),RND(127),RND(127),RND(127),RND(127),RND(2)+1) 'WAIT VBL 'CALL TRIANGE(50,60,70,80,TOUCH.X,TOUCH.Y,RND(2)+1) 'CALL TRIANGE(50,60,70,80,TOUCH.X,TOUCH.Y,1) 'WAIT VBL 'FILL $8000,$1000 'WAIT 60 'REPEAT 'WAIT VBL 'UNTIL TAP 'FOR I=0 TO 0 'CALL BAR(RND(127),RND(127),RND(127),RND(127),RND(2)+1) 'NEXT I 'WAIT VBL 'WAIT 10 'FILL $8000,$1000 LOOP 'S U B P R O G R A M S SUB BAR(X1,Y1,X2,Y2,C) DY=-(Y2-Y1>0)*2-1 FOR Y=Y1 TO Y2 STEP DY 'CALL HLINE_XOR(X1,Y,X2,C) CALL HLINE(X1,Y,X2,C) NEXT Y END SUB SUB DIAMOND(X,Y,R,C) FOR I=0 TO R-1 J=R-I CALL HLINE(X-I,Y-J,X+I,C) CALL HLINE(X-I,Y+J,X+I,C) NEXT I CALL HLINE(X-R,Y,X+R,C) END SUB SUB CIRCLE(CX,CY,R,C) 'R_SQUARED=R*R DR=1/R I=0 FOR Y=1 TO R 'XX=SQR(R_SQUARED-Y*Y) 'IF I>1 OR I<-1 THEN TRACE I A=ASIN(I) XX=INT(COS(A)*R) X1=CX-XX X2=CX+XX CALL HLINE(X1,CY+Y,X2,C) CALL HLINE(X1,CY-Y,X2,C) I=MIN(I+DR,1) NEXT Y CALL HLINE(CX-R,CY,CX+R,C) END SUB SUB TRIANGE(X0,Y0,X1,Y1,X2,Y2,C) 'OPTIMALIZATION: '- ONE LINE IS ALWAYS ACTIVE '- THE OTHER LINE GETS SWAPPED '- START POINT '- SWAP POINT 'SORT IF Y0>Y1 THEN SWAP Y0,Y1 SWAP X0,X1 END IF IF Y1>Y2 THEN SWAP Y1,Y2 SWAP X1,X2 END IF IF Y0>Y1 THEN 'BUG MEMORIAL: THIS WAS COPIED WITHOUT MODIFYING, ALSO IT WAS WRONG BECAUSE Y2 BECAME Y1 SWAP Y0,Y1 SWAP X0,X1 END IF 'PREPARE LINES: HEIGHT DIFFERENCE (DY), 1/(DY/WIDTH DIFFERENCE), START VALUE DY0=Y1-Y0 DY1=Y2-Y1 DY2=Y2-Y0 IF DY0<>0 THEN DD0=(X1-X0)/DY0 ELSE DD0=0 IF DY1<>0 THEN DD2=(X2-X1)/DY1 ELSE DD2=0 IF DY2<>0 THEN DD1=(X2-X0)/DY2 ELSE DD1=0 XX0=X0 XX1=X0 XX2=X1 C0=C MOD 2 C1=C\2 C0L=C0*255 C1L=C1*255 'EXIT SUB: 0.1% CPU 'START 'DRASTIC OPTIMIZATIONS: FOR STEP 2 WITH RASTER (TRIANGLES NEED TO BE Y0=Y0 XOR 1) FOR Y=Y0 TO Y1 ADD XX0,DD0 ADD XX1,DD1 'CALL HLINE(INT(XX0),Y,INT(XX1),C) CALL HLINE_FASTER(INT(XX0),Y,INT(XX1),C0,C1,C0L,C1L) NEXT Y 'LINE SWAP FOR Y=Y1 TO Y2 ADD XX1,DD1 ADD XX2,DD2 'CALL HLINE(INT(XX1),Y,INT(XX2),C) CALL HLINE_FASTER(INT(XX1),Y,INT(XX2),C0,C1,C0L,C1L) NEXT Y 'CC=MAX(1,(C+1)MOD 3) 'CC=2 'CALL PLOT(X0,Y0,CC) 'CALL PLOT(X1,Y1,CC) 'CALL PLOT(X2,Y2,CC) 'Y = A*X + B 'X = (Y-B)/A 'X = Y/A - B/A 'X0 = 0/A - B/A 'X0 = - B/A 'XN = X0 + N*(1/A) 'B = Y - A*X 'B0=Y0 - (1/DD0)*X0 'XX0=-B0*DD0 'XX0=X0-Y0*DD0 'XX0=(Y-Y0)*DD0 'XX1=(Y-Y1)*DD1 'XX2=(Y-Y2)*DD2 END SUB SUB QUAD(X0,Y0,X1,Y1,X2,Y2,C) END SUB SUB OVERLAY2(A0,C0,C1) A1=A0+8 B0=PEEK(A0) B1=PEEK(A1) M=255 XOR (C0 OR C1) POKE A0,(B0 AND M) OR C0 POKE A1,(B1 AND M) OR C1 END SUB SUB OVERLAY2_FASTER(A0,A1,C0,C1) B0=PEEK(A0) B1=PEEK(A1) M=255 XOR (C0 OR C1) POKE A0,(B0 AND M) OR C0 POKE A1,(B1 AND M) OR C1 END SUB SUB XOR_MIX(A0,C0,C1) A1=A0+8 B0=PEEK(A0) B1=PEEK(A1) 'M=255 XOR (C0 OR C1) 'M=255 'POKE A0,(B0 AND M) XOR C0 'POKE A1,(B1 AND M) XOR C1 POKE A0,B0 XOR C0 POKE A1,B1 XOR C1 END SUB SUB PLOT(X,Y,C) A=$8000+(Y\8)*256+(X\8)*16+(Y MOD 8) N=2^(7-(X MOD 8)) 'IF C MOD 2 THEN POKE A ,PEEK(A ) OR N 'IF C\2 THEN POKE A+8,PEEK(A+8) OR N C0=N*(C MOD 2 ) C1=N*(C\2) CALL OVERLAY2(A,C0,C1) 'POKE A ,PEEK(A ) OR (2^N * C MOD 2) 'POKE A+8,PEEK(A+8) OR (2^N * C\2) END SUB SUB HLINE(X0,Y,X1,C) 'SAFETY: RECTIFY ORDER AND BOUNDARIES IF X0>X1 THEN SWAP X0,X1 X0=MAX(0,MIN(127,X0)) X1=MAX(0,MIN(127,X1)) Y =MAX(0,MIN(127,Y )) 'PREPARE: COLOR, 8-PIXEL SEGMENT, ADDRESS, QUANTIZED COORDINATES 'EXIT SUB: 30% CPU C0=C MOD 2 C1=C\2 C0L=C0*255 C1L=C1*255 A0=$8000+(Y\8)*256+(Y MOD 8) X0Q=(X0\8)*8 X1Q=(X1\8)*8 'EXIT SUB: 60% CPU IF X0Q=X1Q THEN A=$8000+(Y\8)*256+X0Q*2+(Y MOD 8) N0=RLINE_ROM(X0 MOD 8) N1=LLINE_ROM(X1 MOD 8) N=N0 AND N1 'N=N0 CALL OVERLAY2(A,N*C0,N*C1) EXIT SUB END IF 'LEFT SEGMENT: ADDRESS, BINARY LINE, DRAW A=A0+X0Q*2 N=RLINE_ROM(X0 MOD 8) CALL OVERLAY2(A,N*C0,N*C1) 'LINE: ADDRESS, DRAW (DOESN'T NEED OVERLAY AND SEGMENT IS ALWAYS 255) FOR X=X0Q+8 TO X1-8 STEP 8 A=A0+X*2 POKE A ,C0L POKE A+8,C1L NEXT X 'RIGHT SEGMENT A=A0+X1Q*2 N=LLINE_ROM(X1 MOD 8) CALL OVERLAY2(A,N*C0,N*C1) 'REQUIRED ROM DEFINITIONS: 'RLINE_ROM(I MOD 8) = 2^(8-(I MOD 8))-1 'LLINE_ROM(I MOD 8) = 255 XOR 2^(7-(I MOD 8))-1 'BUG MEMORIAL: (X0\8)*8 INSTEAD OF X0, FIRST CASE WAS SHOVED UNDER THE RUG BY OFFSETS 'DEBUGGING TOOL: 'CALL PLOT(X0,Y,3) 'CALL PLOT(X1,Y,3) END SUB SUB HLINE_FASTER(X0,Y,X1,C0,C1,C0L,C1L) 'SAFETY: RECTIFY ORDER AND BOUNDARIES IF X0>X1 THEN SWAP X0,X1 'EXIT SUB: 15% CPU X0=MAX(0,MIN(127,X0)) X1=MAX(0,MIN(127,X1)) Y =MAX(0,MIN(127,Y )) 'PREPARE: ADDRESSES (GENERAL, LEFT, RIGHT), EDGE PIXEL SEGMENTS 'EXIT SUB: 30% CPU A0=YADDR_ROM(Y) A1=A0+XCELL_ROM(X0) A2=A0+XCELL_ROM(X1) 'EXIT SUB: 42% CPU N0=RLINE_ROM(X0 MOD 8) N1=LLINE_ROM(X1 MOD 8) 'EXIT SUB: 50% CPU IF A1=A2 THEN N=N0 AND N1 CALL OVERLAY2(A1,N*C0,N*C1) EXIT SUB END IF 'LEFT SEGMENT CALL OVERLAY2(A1,N0*C0,N0*C1) 'RIGHT SEGMENT CALL OVERLAY2(A2,N1*C0,N1*C1) 'EXIT SUB: 100% CPU 'LINE: ADDRESS, DRAW (DOESN'T NEED OVERLAY AND SEGMENT IS ALWAYS 255) 'BOTH BYTES NEED TO BE WRITTEN FOR PROPER OVERWRITE (IS OVERLAY) FOR A=A1+16 TO A0+X1*2-16 STEP 16 POKE A ,C0L POKE A+8,C1L NEXT A 'REQUIRED ROM DEFINITIONS: 'RLINE_ROM(I MOD 8) = 2^(8-(I MOD 8))-1 'LLINE_ROM(I MOD 8) = 255 XOR 2^(7-(I MOD 8))-1 'BUG MEMORIAL: X0 INSTEAD OF (X0\8)*8, FIRST CASE WAS SHOVED UNDER THE RUG BY OFFSETS 'DEBUGGING TOOL: 'CALL PLOT(X0,Y,3) 'CALL PLOT(X1,Y,3) END SUB 'HLINE_QUEUE ' DRAW THE EDGE AND RECORD THE SHAPE AND FILL SHAPES WHEN READY ' CELL Y IS ALREADY KNOWN (STILL UP TO DATE) ' RECORDING: ' - LEFTMOST CELL X ' - RIGHTMOST CELL X ' - LEFTMOST CELL X OF CONSTANT BLOCK ' - RIGHTMOST CELL X OF CONSTANT BLOCK ' - START HEIGHT FOR EACH CELL ' - STOP HEIGHT FOR EACH CELL ' EVERY 8 LINES IT'S FILL TIME 'NEW BAR DRAWING SUB '- IS A MODIFICATION OF HLINE ' - PREPARATIONS (NOW IT DOESN'T MATTER WHEN THE EDGES ARE DRAWN ' - LOOP FOR Y ' - DRAW EDGES ' EXIT SUB NOT ALLOWED ' - LOOP FOR X ' - IF VERY FLAT: FILL FLAT, EXIT SUB ' - FILL TOP ' - FILL BOTTOM ' - LOOP FOR Y, =(Y/8)*8 (Y AND NOT(7)) STEP 8 ' - FILL A,8,V 'MERGE THE LOOPS SOMEHOW 'ALTERNATIVE TRIANGLE DRAWING METHODS 'CHARACTER THAT HAS A MINIATURE TRIANGLE (SAME STEEPNESSES) 'SPRITES WITH THAT CHARACTER FILL THE SHAPE OF A BIG TRIANGLE 'TRIANGLES DON'T FIT VERY WELL ON TRIANGLES WITHOUT ROTATING SUB HLINE_XOR(X0,Y,X1,C) IF X0>X1 THEN SWAP X0,X1 X0=MAX(0,MIN(127,X0)) X1=MAX(0,MIN(127,X1)) Y =MAX(0,MIN(127,Y )) 'PREPARE: COLOR, 8-PIXEL SEGMENT, ADDRESS, QUANTIZED COORDINATES C0=C MOD 2 C1=C\2 C0L=C0*255 C1L=C1*255 A0=$8000+(Y\8)*256+(Y MOD 8) X0Q=(X0\8)*8 X1Q=(X1\8)*8 IF X0Q=X1Q THEN A=$8000+(Y\8)*256+X0Q*2+(Y MOD 8) N0=RLINE_ROM(X0 MOD 8) N1=LLINE_ROM(X1 MOD 8) N=N0 AND N1 'N=N0 CALL XOR_MIX(A,N*C0,N*C1) EXIT SUB END IF 'LEFT SEGMENT: ADDRESS, BINARY LINE, DRAW A=A0+X0Q*2 N=RLINE_ROM(X0 MOD 8) CALL XOR_MIX(A,N*C0,N*C1) 'LINE: ADDRESS, DRAW (DOESN'T NEED OVERLAY AND SEGMENT IS ALWAYS 255) FOR X=X0Q+8 TO X1-8 STEP 8 A=A0+X*2 'POKE A ,C0L 'POKE A+8,C1L CALL XOR_MIX(A,C0L,C1L) NEXT X 'RIGHT SEGMENT A=A0+X1Q*2 N=LLINE_ROM(X1 MOD 8) CALL XOR_MIX(A,N*C0,N*C1) 'REQUIRED ROM DEFINITIONS: 'RLINE_ROM(I MOD 8) = 2^(8-(I MOD 8))-1 'LLINE_ROM(I MOD 8) = 255 XOR 2^(7-(I MOD 8))-1 'BUG MEMORIAL: (X0\8)*8 INSTEAD OF X0, FIRST CASE WAS SHOVED UNDER THE RUG BY OFFSETS 'DEBUGGING TOOL: 'CALL PLOT(X0,Y,3) 'CALL PLOT(X1,Y,3) END SUB SUB HLINE_ORIGINAL(X0,Y,X1,C) 'SPLIT COLOR VALUE C0=C MOD 2 C1=C\2 'PREPARE ADDRESS A0=$8000+(Y\8)*256+(Y MOD 8)-8 'LEFT SEGMENT X=X0 A=A0+X*2 'N=2^(8-(X MOD 8))-1 N=RLINE_ROM(X MOD 8) CALL XOR_MIX(A,N*C0,N*C1) 'LINE (DOESN'T NEED OVERLAY OR SEGMENT GENERATION) FOR X=X0+8 TO X1 STEP 8 A=A0+X*2 POKE A ,255*C0 POKE A+8,255*C1 NEXT X 'RIGHT SEGMENT A=A0+X*2 X=X1 'N=255 XOR 2^(7-(X MOD 8))-1 N=LLINE_ROM(X MOD 8) CALL XOR_MIX(A,N*C0,N*C1) END SUB SUB VIEW_CHARACTERS(X,Y,C0,C1) CY0=C0\16 CY1=C1\16 CX0=C0 MOD 16 CX1=C1 MOD 16 FOR IY=CY0 TO CY1 FOR IX=0-(IY=CY0)*CX0 TO 15-(IY=CY1)*(CX1-15) CELL X+IX,Y+IY-CY0,IX+IY*16 NEXT IX NEXT IY END SUB #0:BYE BYE DEFAULT FONT 00 #1:MAIN PALETTES 002B160100383400003C0C00003F3C00 003F2A15003F2A15003F2A15003F2A15 #2:MAIN CHARACTERS 00000000000000000000000000000000 55110101000000005511010100000000 55110100000000005511010000000000 55110101010000005511010101000000 55110100000000005511010000000000 55110101000000005511010100000000 55110100000000005511010000000000 55110101010100005511010101010000 55110100000000005511010000000000 55110101000000005511010100000000 55110100000000005511010000000000 55110101010000005511010101000000 55110100000000005511010000000000 55110101000000005511010100000000 55110100000000005511010000000000 55110101010101005511010101010100