p*********************************                              ** sTEPHEN jUDD                 ** gEORGE tAYLOR                ** sTARTED: 7/11/94             ** fINISHED: 7/19/94            ** V2.0 cOMPLETED: 12/17/94     ** V3.0 cOMPLETED: 3/20/95      ** V3.1 cOMPLETED: 6/14/95      ** V3.2 cOMPLETED: 6/15/95      **                              ** wELL, IF ALL GOES WELL THIS  ** PROGRAM WILL ROTATE A CUBE.  **                              ** V2.0 + nEW AND iMPROVED!     ** nOW WITH FASTER ROUTINES,    ** HIDDEN SURFACES, FILLED      ** FACES, AND EXTRA TOP SECRET  ** TEXT MESSAGES!               **                              ** V3.0 + fAST CHUNKY LINE      ** ROUTINE.                     **                              ** V3.1 + gENERAL POLYGON PLOT  ** WITH HIDDEN FACES (x-PRODUCT)** AND ZOOM FEATURE.            **                              ** V3.2 + eor-BUFFER FILLING    **                              ** tHIS PROGRAM IS INTENDED TO  ** ACCOMPANY THE ARTICLE IN     ** c=hACKING, jUN. 95 ISSUE.    ** fOR DETAILS ON THIS PROGRAM, ** READ THE ARTICLE!            **                              ** wRITE TO US!                 **                              ** mYSELF WHEN YOUNG DID        ** EAGERLY FREQUENT             ** dOCTOR AND sAINT, AND HEARD  ** GREAT aRGUMENT               **  aBOUT IT AND ABOUT: BUT     **  EVERMORE                    ** cAME OUT BY THE SAME dOOR    ** AS IN i WENT.                **    - rUBAIYAT                **                              ** tHOUGH i SPEAK WITH THE      ** TONGUES OF MEN AND OF ANGLES ** AND HAVE NOT LOVE, i AM      ** BECOME AS SOUNDING BRASS, OR ** A TINKLING CYMBAL.           **    - 1 cORINTHIANS 13        **                              ** p.s. tHIS WAS WRITTEN USING  **      mERLIN 128.             ********************************* org $8000* cONSTANTSbuff1 equ $3000 ;fIRST CHARACTER SETbuff2 equ $3800 ;sECOND CHARACTER SETeorbuf equ $4000 ;eor-BUFFERbuffer equ $a3 ;pRESUMABLY THE TAPE WON'T BE RUNNINGx1 equ $fb ;pOINTS FOR DRAWING A LINEy1 equ $fc ;tHESE ZERO PAGE ADDRESSESx2 equ $fd ;DON'T CONFLICT WITH basicy2 equ $feoldx equ $fdchunk equ $fedx equ $67 ;tHIS IS SHARED WITH t1 BELOWdy equ $68temp1 equ $fb ;oF COURSE, COULD CONFLICT WITH X1temp2 equ $fc ;tEMPORARY VARIABLESztemp equ $02 ;uSED FOR BUFFER SWAP.  dON'T TOUCH.z1 equ $22 ;uSED BY MATH ROUTINEz2 equ $24 ;dON'T TOUCH THESE EITHER!z3 equ $26z4 equ $28k equ $b6 ;cONSTANT USED FOR HIDDEN   ;SURFACE DETECTION - DON'T TOUCHhide equ $b5 ;aRE SURFACES HIDDEN?fill equ $50 ;aRE WE USING eor-FILL?angmax equ 120 ;tHERE ARE 2*PI/ANGMAX ANGLES* vicvmcsb equ $d018bkgnd equ $d020border equ $d021sstart equ 1344 ;ROW 9 IN SCREEN MEMORY AT 1024* kERNALchrout equ $ffd2getin equ $ffe4* sOME VARIABLESglobxmin = $3f ;tHESE ARE USED IN CLEARING THEglobxmax = $40 ;DRAWING (GLOBAL) BUFFERglobymin = $41globymax = $42locxmin = $57 ;tHESE ARE USED IN CLEARING THElocxmax = $58 ;eor (LOCAL) BUFFERlocymin = $59locymax = $60p1x = $92 ;tHESE ARE TEMPORARY STORAGEp1y = $93 ;uSED IN PLOTTING THE PROJECTIONp1z = $94p2x = $95 ;tHEY ARE HERE SO THAT WEp2y = $96 ;DON'T HAVE TO RECALCULATE THEM.p2z = $aep3x = $af ;tHEY MAKE LIFE EASY.p3y = $b0p3z = $b1 ;wHY ARE YOU LOOKING AT ME LIKE THAT?p1t = $b2 ;dON'T YOU TRUST ME?p2t = $b3p3t = $b4 ;hAVING ANOTHER CHILD WASN'T MY IDEA.index = $51countpts = $52zoom = $71 ;zOOM FACTORdsx = $61 ;dsx IS THE INCREMENT FOR   ;ROTATING AROUND Xdsy = $62 ;sIMILAR FOR dsy, dszdsz = $63sx = $64 ;tHESE ARE THE ACTUAL ANGLES IN X Y AND Zsy = $65sz = $66t1 = $67 ;tHESE ARE USED IN THE ROTATIONt2 = $68t3 = $69 ;sEE THE ARTICLE FOR MORE DETAILSt4 = $6at5 = $6bt6 = $6ct7 = $6dt8 = $6et9 = $6ft10 = $70a11 = $a5 ;tHESE ARE THE ELEMENTS OF THE ROTATION MATRIXb12 = $a6 ;xyzc13 = $a7d21 = $a8 ;tHE NUMBER DENOTES (ROW,COLUMN)e22 = $a9f23 = $aag31 = $abh32 = $aci33 = $ad*** mACROSmove mac lda ]1 sta ]2 <<<getkey mac  ;wAIT FOR A KEYPRESSwait jsr getin cmp #00 beq wait <<<debug mac  ;pRINT A CHARACTER do 0  ;dON'T ASSEMBLE lda #]1 jsr chrout cli >>> getkey ;aND WAIT TO CONTINUE cmp #'S' ;mY SECRECT SWITCH KEY bne l1 jsr cleanup jmp donel1 cmp #'X' ;mY SECRET ABORT KEY bne done jmp cleanup findone <<<debuga mac do 0 lda ]1 sta 1024 findonea <<<*------------------------------- lda #$00 sta bkgnd sta border lda vmcsb and #%00001111 ;sCREEN MEMORY TO 1024 ora #%00010000 sta vmcsb ldy #00 lda #<ttext sta temp1 lda #>ttext sta temp2 jmp titlettext hex 9305111111 ;CLEAR SCREEN, WHITE, CRSR DN txt '             CUBE3D V3.2',0D,0D txt '                  BY',0D hex 9f ;CYAN txt '    STEPHEN JUDD' hex 99 txt '    GEORGE TAYLOR',0D,0D hex 9b txt '  CHECK OUT THE JAN. 95 ISSUE OF',0D hex 96 txt '  C=HACKING' hex 9b txt ' FOR MORE DETAILS!',0D hex 0d1d1d9e12 txt 'F1/F2',92 txt ' - INC/DEC X-ROTATION',0D hex 1d1d12 txt 'F3/F4',92 txt ' - INC/DEC Y-ROTATION',0D hex 1d1d12 txt 'F5/F6',92 txt ' - INC/DEC Z-ROTATION',0D hex 1d1d12 txt ' F7  ',92 txt ' - RESET',0D hex 1d1d12 txt ' +/- ',92 txt ' - ZOOM IN/OUT',0D hex 1d1d12 txt '  H  ',92 txt ' - TOGGLE HIDDEN SURFACES',0D hex 1d1d12 txt 'SPACE',92 txt ' - TOGGLE SURFACE FILLING',0D,0D txt '  PRESS Q TO QUIT',0D hex 0d05 txt '      PRESS ANY KEY TO BEGIN',0D hex 00title lda (temp1),y beq :cont jsr chrout iny bne title inc temp2 jmp title:cont >>> getkey**** sET UP TABLES(?)* tABLES ARE CURRENTLY SET UP IN basic* AND BY THE ASSEMBLER.tables lda #>tmath1 sta z1+1 sta z2+1 lda #>tmath2 sta z3+1 sta z4+1**** cLEAR SCREEN AND SET UP "BITMAP"setup lda #$01 ;wHITE sta $d021 ;tHIS IS DONE SO THAT OLDER lda #147 ;MACHINES WILL SET UP jsr chrout lda #$00 ;CORRECTLY sta $d021 lda #<sstart adc #12 ;tHE GOAL IS TO CENTER THE GRAPHICS sta temp1 ;cOLUMN 12 lda #>sstart ;rOW 9 sta temp1+1 ;sstart POINTS TO ROW 9 lda #00 ldy #00 ldx #00 ;X WILL COUNT 16 ROWS FOR US clc:loop sta (temp1),y iny adc #16 bcc :loop clc lda temp1 adc #40 ;nEED TO ADD 40 TO THE BASE POINTER sta temp1 ;tO JUMP TO THE NEXT ROW lda temp1+1 adc #00 ;tAKE CARE OF CARRIES sta temp1+1 ldy #00 inx txa  ;x IS ALSO AN INDEX INTO THE CHARACTER NUMBER cpx #16 bne :loop ;nEED TO DO IT 16 TIMES**** cLEAR BUFFERS lda #<buff1 sta buffer lda #>buff1 sta buffer+1 ldy #$00 ldx #24 ;aSSUMING ALL THREE BUFFERS ARE lda #$00 ;BACK-TO-BACK:bloop sta (buffer),y iny bne :bloop inc buffer+1 dex bne :bloop**** sET UP BUFFERS lda #<buff1 sta buffer lda #>buff1 sta buffer+1 sta ztemp ;ZTEMP WILL MAKE LIFE SIMPLE FOR US lda vmcsb and #%11110001 ;sTART HERE SO THAT SWAP BUFFERS WILL WORK RIGHT ora #%00001110 sta vmcsb**** sET UP INITIAL VALUESinit lda #00 sta locxmin sta locxmax sta locymin sta locymax sta globxmin sta globymin sta globxmax sta globymax sta dsx sta dsy sta dsz sta sx sta sy sta sz sta fill lda #01 sta hide lda #64 sta zoom*-------------------------------* mAIN LOOP**** gET KEYPRESSmain clikpress jsr getin cmp #133 ;f1? bne :f2 lda dsx cmp #angmax/2 ;nO MORE THAN PI beq :cont1 inc dsx ;OTHERWISE INCREASE X-ROTATION jmp :cont:f2 cmp #137 ;f2? bne :f3 lda dsx beq :cont1 dec dsx jmp :cont:f3 cmp #134 bne :f4 lda dsy cmp #angmax/2 beq :cont1 inc dsy ;iNCREASE Y-ROTATION jmp :cont:f4 cmp #138 bne :f5 lda dsy beq :cont1 dec dsy jmp :cont:f5 cmp #135 bne :f6 lda dsz cmp #angmax/2 beq :cont1 inc dsz ;Z-ROTATION jmp :cont:f6 cmp #139 bne :f7 lda dsz beq :cont1 dec dsz jmp :cont:f7 cmp #136 bne :plus jmp init:cont1 jmp :cont:plus cmp #'+' bne :minus inc zoom ;bAH, WHO NEEDS ERROR CHECKING? inc zoom jmp :cont:minus cmp #'-' bne :h dec zoom dec zoom bpl :cont inc zoom inc zoom jmp :cont:h cmp #'H' bne :space lda hide eor #$01 sta hide jmp :cont:space cmp #' ' bne :q lda fill eor #$01 sta fill jmp :cont:q cmp #'Q' ;Q QUITS bne :cont jmp cleanup:cont sei  ;sPEED THINGS UP A BIT**** uPDATE ANGLESupdate clc lda sx adc dsx cmp #angmax ;aRE WE >= MAXIMUM ANGLE? bcc :cont1 sbc #angmax :iF SO, RESET:cont1 sta sx clc lda sy adc dsy cmp #angmax bcc :cont2 sbc #angmax ;sAME DEAL:cont2 sta sy clc lda sz adc dsz cmp #angmax bcc :cont3 sbc #angmax:cont3 sta sz**** rOTATE COORDINATESrotate*** fIRST, CALCULATE T1,T2,...,T10** tWO MACROS TO SIMPLIFY OUR LIFEadda mac  ;aDD TWO ANGLES TOGETHER clc lda ]1 adc ]2 cmp #angmax ;iS THE SUM > 2*PI? bcc done sbc #angmax ;iF SO, SUBTRACT 2*PIdone <<<suba mac  ;sUBTRACT TWO ANGLES sec lda ]1 sbc ]2 bcs done adc #angmax ;oOPS, WE NEED TO ADD 2*PIdone <<<** nOW CALCULATE T1,T2,ETC. >>> suba,sy;sz sta t1 ;T1=SY-SZ >>> adda,sy;sz sta t2 ;T2=SY+SZ >>> adda,sx;sz sta t3 ;T3=SX+SZ >>> suba,sx;sz sta t4 ;T4=SX-SZ >>> adda,sx;t2 sta t5 ;T5=SX+T2 >>> suba,sx;t1 sta t6 ;T6=SX-T1 >>> adda,sx;t1 sta t7 ;T7=SX+T1 >>> suba,t2;sx sta t8 ;T8=T2-SX >>> suba,sy;sx sta t9 ;T9=SY-SX >>> adda,sx;sy sta t10 ;T10=SX+SY* eT VOILA!*** nEXT, CALCULATE a,b,c,...,i** aNOTHER USEFUL LITTLE MACROdiv2 mac  ;dIVIDE A SIGNED NUMBER BY 2;iT IS ASSUMED THAT THE NUMBER bpl pos ;IS IN THE ACCUMULATOR clc eor #$ff ;wE NEED TO UN-NEGATIVE THE NUMBER adc #01 ;BY TAKING IT'S COMPLEMENT lsr  ;DIVIDE BY TWO clc eor #$ff adc #01 ;mAKE IT NEGATIVE AGAIN jmp donedivpos lsr  ;nUMBER IS POSITIVEdonediv <<<mul2 mac  ;mULTIPLY A SIGNED NUMBER BY 2 bpl posm clc eor #$ff adc #$01 asl clc eor #$ff adc #$01 jmp donemulposm asldonemul <<<** nOTE THAT WE ARE CURRENTLY MAKING A MINOR LEAP** OF FAITH THAT NO OVERFLOWS WILL OCCUR.:calca clc ldx t1 lda cos,x ldx t2 adc cos,x sta a11 ;a=(COS(T1)+COS(T2))/2:calcb ldx t1 lda sin,x sec ldx t2 sbc sin,x sta b12 ;b=(SIN(T1)-SIN(T2))/2:calcc ldx sy lda sin,x >>> mul2 sta c13 ;c=SIN(SY):calcd sec ldx t8 lda cos,x ldx t7 sbc cos,x sec ldx t5 sbc cos,x clc ldx t6 adc cos,x ;dI=(COS(T8)-COS(T7)+COS(T6)-COS(T5))/2 >>> div2 clc ldx t3 adc sin,x sec ldx t4 sbc sin,x sta d21 ;d=(SIN(T3)-SIN(T4)+dI)/2:calce sec ldx t5 lda sin,x ldx t6 sbc sin,x sec ldx t7 sbc sin,x sec ldx t8 sbc sin,x ;eI=(SIN(T5)-SIN(T6)-SIN(T7)-SIN(T8))/2 >>> div2 clc ldx t3 adc cos,x clc ldx t4 adc cos,x sta e22 ;e=(COS(T3)+COS(T4)+eI)/2:calcf ldx t9 lda sin,x sec ldx t10 sbc sin,x sta f23 ;f=(SIN(T9)-SIN(T10))/2:calcg ldx t6 lda sin,x sec ldx t8 sbc sin,x sec ldx t7 sbc sin,x sec ldx t5 sbc sin,x ;gI=(SIN(T6)-SIN(T8)-SIN(T7)-SIN(T5))/2 >>> div2 clc ldx t4 adc cos,x sec ldx t3 sbc cos,x sta g31 ;g=(COS(T4)-COS(T3)+gI)/2:calch clc ldx t6 lda cos,x ldx t7 adc cos,x sec ldx t5 sbc cos,x sec ldx t8 sbc cos,x ;hI=(COS(T6)+COS(T7)-COS(T5)-COS(T8))/2 >>> div2 clc ldx t3 adc sin,x clc ldx t4 adc sin,x sta h32 ;h=(SIN(T3)+SIN(T4)+hI)/2:whew clc ldx t9 lda cos,x ldx t10 adc cos,x sta i33 ;i=(COS(T9)+COS(T10))/2** iT'S ALL DOWNHILL FROM HERE.downhill**** cLEAR BUFFER* a LITTLE MACROsetbuf mac  ;pUT BUFFERS WHERE THEY CAN BE HURT lda #00 sta buffer lda ztemp ;hIGH BYTEstabuf sta buffer+1 <<< >>> setbufclrdraw ldx #08 lda #00:fool ldy #00:dope sta (buffer),y iny bne :dope inc buffer+1 dex bne :fool**** mY GOODNESS BUT i'M A DOPE*clrdraw lda globxmin* lsr  ;nEED TO GET INTO THE RIGHT COLUMN* bcc :even ;eXPLAINED IN MORE DETAIL BELOW* ldy #$80* sty buffer ;pRESUMABLY THIS WILL BE A LITTLE* clc  ;MORE EFFICIENT.*:even adc buffer+1* sta buffer+1* lda globxmax* sec* sbc globxmin* tax* inx* ldy globymax* beq :reset*:yay lda #$00* ldy globymax*:blah sta (buffer),y* dey* cpy globymin* bcs :blah* lda buffer* eor #$80* sta buffer* bne :whopee* inc buffer+1*:whopee dex* bne :yay*:reset lda #0 ;nEED TO RESET THESE GUYS* sta globxmax* sta globymax* lda #$ff* sta globxmin* sta globymin**** nEXT, READ AND DRAW POLYGONSreaddraw ldy #00 sty indexobjloop ldy index lda polylist,y ;fIRST, THE NUMBER OF POINTS bne :cont ;bUT IF NUMPOINTS IS ZERO THEN jmp objdone ;WE ARE AT THE END OF THE LIST:cont sta countpts inc index* rOTATE PROJECT AND DRAW THE POLYGON* mAKE SURE BUFFER BEING DRAWN TO IS CLEAR!:doit jsr rotproj* cONVERT XMIN AND XMAX TO COLUMNS lda locxmin lsr lsr lsr  ;X MOD 8 sta locxmin cmp globxmin bcs :nah sta globxmin:nah lda locymin cmp globymin bcs :uhuh sta globymin:uhuh lda locxmax lsr lsr lsr sta locxmax cmp globxmax bcc :noway sta globxmax:noway lda locymax cmp globymax bcc eorfill sta globymax* iF USING THE eor-BUFFER, COPY INTO DRAWING BUFFER* aND THEN CLEAR THE eor-BUFFEReorfill lda fill beq objloop >>> setbuf lda #<eorbuf sta temp1 lda #>eorbuf sta temp1+1 lda locxmin ;locxmin NOW CONTAINS COLUMN lsr  ;eACH COLUMN IS 128 BYTES bcc :even ;sO THERE MIGHT BE A CARRY ldy #$80 sty buffer sty temp1 clc:even sta t2 adc buffer+1 sta buffer+1 ;eACH COLUMN IS 128 BYTES lda t2 adc temp1+1 ;nOW WE WILL START AT THE sta temp1+1 ;COLUMN lda locxmax sec sbc locxmin tax ;tOTAL NUMBER OF COLUMNS TO DO inx  ;E.G. FILL COLUMNS 1..3 ldy locymax bne :foop inc locymax:foop ldy locymax lda #00:goop eor (temp1),y ;eor-BUFFER pha* mAYBE PUT AN eor BELOW? eor (buffer),y sta (buffer),y lda #00 ;mIGHT AS WELL CLEAR IT NOW sta (temp1),y pla dey cpy locymin bcs :goop lda buffer eor #$80 sta buffer sta temp1 bne :boop inc buffer+1 inc temp1+1:boop dex bne :foop jmp objloopobjdone**** sWAP BUFFERSswapbuf lda vmcsb eor #$02 ;pRETTY TRICKY, EH? sta vmcsb lda #$08 eor ztemp ;ZTEMP=HIGH BYTE JUST FLIPS sta ztemp ;BETWEEN $30 AND $38 jmp main ;aROUND AND AROUND WE GO... txt 'gEE bRAIN, WHAT DO YOU WANT TO DO ' txt 'TONIGHT?'** rOTATE, PROJECT, AND STORE THE POINTS** tHIS PART IS A SIGNIFICANT CHANGE SINCE* V2.0.  nOW IT IS A COMPLETELY GENERAL POLYGON PLOTTER.* a SET OF POINTS IS READ IN, ROTATED AND PROJECTED, AND* PLOTTED INTO THE DRAWING BUFFER (eor OR NORMAL).rotproj* a NEAT MACROneg mac  ;cHANGE THE SIGN OF A TWO'S COMPLEMENT clc lda ]1 ;NUMBER. eor #$ff adc #$01 <<<*-------------------------------* tHESE MACROS REPLACE THE PREVIOUS PROJECTION* SUBROUTINE.smult mac ;mULTIPLY TWO SIGNED 8-BIT ;NUMBERS: a*y/64 -> a sta z3 clc  ;tHIS MULTIPLY IS FOR NORMAL eor #$ff ;NUMBERS, I.E. X=-64..64 adc #$01 sta z4 lda (z3),y sec sbc (z4),y <<<  ;aLL DONE :)smultz mac ;mULTIPLY TWO SIGNED 8-BIT   ;NUMBERS: a*y/64 -> a sta z1 clc  ;aND THIS MULTIPLY IS SPECIFICALLY eor #$ff ;FOR THE PROJECTION PART, WHERE adc #$01 ;NUMBERS ARE -110..110 AND 0..40 sta z2 lda (z1),y sec sbc (z2),y <<<  ;aLL DONE :)project mac  ;tHE ACTUAL PROJECTION ROUTINE;tHE ROUTINE TAKES THE POINT;]1 ]2 ]3, ROTATES AND;PROJECTS IT, AND STORES THE;RESULT IN ]1 ]2 ]3. ldy ]1 ;mULTIPLY FIRST ROTATION COLUMN lda a11 >>> smult sta p1t lda d21 >>> smult sta p2t lda g31 >>> smult sta p3t ldy ]2 ;sECOND COLUMN lda b12 >>> smult clc adc p1t sta p1t lda e22 >>> smult clc adc p2t sta p2t lda h32 >>> smult clc adc p3t sta p3t ldy ]3 ;tHIRD COLUMN lda c13 >>> smult clc adc p1t sta p1t lda f23 >>> smult clc adc p2t sta p2t lda i33 >>> smult clc adc p3t sta ]3 ;rOTATED z tax ldy zdiv,x ;tABLE OF D/(Z+Z0)   ;nOW y CONTAINS PROJECTION CONST lda p1t >>> smultz ldx zoom cpx #64 beq contx sty temp1 ldy zoom >>> smult ldy temp1contx clc adc #64 ;oFFSET THE COORDINATE sta ]1 ;rOTATED AND PROJECTED cmp locxmin ;sEE IF IT IS A LOCAL MINIMUM bcs notxmin sta locxminnotxmin cmp locxmax bcc notxmax sta locxmaxnotxmax lda p2t >>> smultz cpx #64 beq conty ldy zoom >>> smultconty clc adc #64 sta ]2 ;rOTATED AND PROJECTED y cmp locymin bcs notymin sta locyminnotymin cmp locymax bcc notymax sta locymaxnotymax <<<  ;aLL DONE* lda #<eorbuf ;fIRST WE NEED TO CLEAR THE* sta buffer ;eor BUFFER* lda #>eorbuf* sta buffer+1 lda #0 ;rESET yMIN AND yMAX sta locymax sta locxmax lda #$ff sta locymin sta locxminreadpts ldy index lda polylist,y sta p1x iny lda polylist,y sta p1y iny lda polylist,y sta p1z iny dec countpts lda polylist,y sta p2x iny lda polylist,y sta p2y iny lda polylist,y sta p2z iny dec countpts lda polylist,y sta p3x iny lda polylist,y sta p3y iny lda polylist,y sta p3z iny sty index >>> project,p1x;p1y;p1z >>> project,p2x;p2y;p2z >>> project,p3x;p3y;p3z lda hide beq :doit lda p2x ;hIDDEN FACE CHECK sec sbc p1x tay  ;y=(X2-X1) lda p3y sec sbc p2y ;a=(Y3-Y2) >>> smult sta temp1 lda p3x sec sbc p2x tay lda p2y sec sbc p1y >>> smult cmp temp1 ;iF X1*Y2-Y1*X2 > 0 THEN FACE bmi :doit ;IS VISIBLE dec countpts ;oTHERWISE READ IN REMAINING beq :abort ;POINTS AND RETURN:poop inc index inc index inc index dec countpts bne :poop:abort rts:doit lda p1x sta x1 lda p1y sta y1 lda p2x sta x2 lda p2y sta y2 jsr draw lda p2x sta x1 lda p2y sta y1 lda p3x sta x2 lda p3y sta y2 jsr draw dec countpts bne polyloop ;iS IT JUST A TRIANGLE? jmp polydonepolyloop ldy index lda polylist,y sta p2x iny lda polylist,y sta p2y iny lda polylist,y sta p2z iny sty index >>> project,p2x;p2y;p2z lda p2x sta x1 lda p2y sta y1 lda p3x sta x2 lda p3y sta y2 jsr draw lda p2x sta p3x lda p2y sta p3y dec countpts beq polydone jmp polylooppolydone lda p1x ;cLOSE THE POLYGON sta x2 lda p1y sta y2 lda p3x sta x1 lda p3y sta y1 jsr draw rts txt 'sAME THING WE DO EVERY NIGHT, pINKY: ' txt 'TRY TO TAKE OVER THE WORLD!'*-------------------------------* gENERAL QUESTIONABLE-VALUE ERROR PROCEDURE*choke ldx #00*:loop lda :ctext,x* beq :done* jsr chrout* inx* jmp :loop*:done rts*:ctext hex 0d ;cr* txt 'SOMETHING CHOKED :('* hex 0d00* txt 'nARF!'*-------------------------------* dRAWIN' A LINE.  a FAHN LAHN.*** sOME USEFUL MACROScinit mac  ;mACRO TO INITIALIZE THE COUNTER lda ]1 ;DX OR DY lsr <<<  ;tHE DX/2 MAKES A NICER LOOKING LINE***** mACRO TO TAKE A STEP IN xxstep mac ldx dx ;nUMBER OF LOOP ITERATIONS >>> cinit,dxxloop lsr chunk beq fixc ;uPDATE COLUMN sbc dy bcc fixy ;tIME TO STEP IN y dex bne xloopdone lda oldx ;pLOT THE LAST CHUNK eor chunk ora (buffer),y sta (buffer),y rtsfixc pha lda oldx ora (buffer),y ;pLOT sta (buffer),y lda #$ff ;uPDATE CHUNK sta oldx sta chunk lda #$80 ;iNCREASE THE COLUMN eor buffer sta buffer bne c2 inc buffer+1c2 pla sbc dy bcs cont adc dx if i,]1 ;dO WE USE iny OR dey? iny else dey fincont dex bne xloop jmp donefixy adc dx pha lda oldx eor chunk ora (buffer),y sta (buffer),y lda chunk sta oldx pla if i,]1 ;uPDATE y iny else dey fin dex bne xloop rts <<<  ;eND OF mACRO XSTEP***** tAKE A STEP IN yystep mac ldx dy ;nUMBER OF LOOP ITERATIONS beq done ;iF DY=0 IT'S JUST A POINT >>> cinit,dy secyloop pha lda oldx ora (buffer),y sta (buffer),y pla if i,]1 iny else dey fin sbc dx bcc fixx dex bne yloopdone lda oldx ora (buffer),y sta (buffer),y rtsfixx adc dy lsr oldx sec  ;iMPORTANT! beq fixc dex bne yloop jmp donefixc pha lda #$80 sta oldx eor buffer sta buffer bne c2 inc buffer+1c2 pla dex bne yloop jmp done <<<  ;eND OF mACRO YSTEP* tAKE AN X STEP IN THE eor BUFFER* tHE SOLE CHANGE IS TO USE eor INSTEAD OF oraeorxstep mac ldx dx ;nUMBER OF LOOP ITERATIONS >>> cinit,dxxloop lsr chunk beq fixc ;uPDATE COLUMN sbc dy bcc fixy ;tIME TO STEP IN y dex bne xloopdone lda oldx ;pLOT THE LAST CHUNK eor chunk eor (buffer),y sta (buffer),y rtsfixc pha lda oldx eor (buffer),y ;pLOT sta (buffer),y lda #$ff ;uPDATE CHUNK sta oldx sta chunk lda #$80 ;iNCREASE THE COLUMN eor buffer sta buffer bne c2 inc buffer+1c2 pla sbc dy bcs cont adc dx if i,]1 ;dO WE USE iny OR dey? iny else dey fincont dex bne xloop jmp donefixy adc dx pha lda oldx eor chunk eor (buffer),y sta (buffer),y lda chunk sta oldx pla if i,]1 ;uPDATE y iny else dey fin dex bne xloop rts <<<  ;eND OF mACRO XSTEP* tAKE A Y-STEP IN THE eor-BUFFER* cHANGES FROM ABOVE ARE: ONLY PLOT LAST PART OF EACH* VERTICAL CHUNK, DON'T PLOT LAST POINT, PLOT WITH eoreorystep mac ldx dy ;nUMBER OF LOOP ITERATIONS beq done ;iF DY=0 IT'S JUST A POINT >>> cinit,dy sec*yloop pha* lda oldx* ora (buffer),y* sta (buffer),y* playloop if i,]1 iny else dey fin sbc dx bcc fixx dex bne yloop*done lda oldx* ora (buffer),y* sta (buffer),ydone rtsfixx adc dy pha  ;wE ONLY PLOT THE LAST PART OF EACH CHUNK lda oldx eor (buffer),y sta (buffer),y pla lsr oldx sec  ;iMPORTANT! beq fixc dex bne yloop jmp donefixc pha lda #$80 sta oldx eor buffer sta buffer bne c2 inc buffer+1c2 pla dex bne yloop jmp done <<<  ;eND OF mACRO YSTEP**** iNITIAL LINE SETUP** tHE COMMENTED LINES BELOW ARE NOW TAKEN CARE OF BY THE** CALLING ROUTINE.*draw >>> move,tx1;x1  ;mOVE STUFF INTO ZERO PAGE* >>> move,tx2;x2  ;wHERE IT CAN BE MODIFIED* >>> move,ty1;y1* >>> move,ty2;y2draw lda fill bne :seteor >>> setbuf jmp :setup:seteor lda #<eorbuf ;uSE eor BUFFER INSTEAD OF sta buffer ;DISPLAY BUFFER FOR DRAWING lda #>eorbuf sta buffer+1:setup sec  ;mAKE SURE X1<X2 lda x2 sbc x1 bcs :cont lda y2 ;iF NOT, SWAP p1 AND p2 ldy y1 sta y1 sty y2 lda x1 ldy x2 sty x1 sta x2 sec sbc x1 ;nOW a=DX:cont sta dx ldx x1 ;pUT X1 INTO x, NOW WE CAN TRASH x1column txa ;fIND THE FIRST COLUMN FOR x lsr lsr  ;tHERE ARE X1/8 128 BYTE BLOCKS lsr  ;wHICH MEANS X1/16 256 BYTE BLOCKS lsr bcc :even ;wITH A POSSIBLE EXTRA 128 BYTE BLOCK ldy #$80 ;IF SO, SET THE HIGH BIT sty buffer clc:even adc buffer+1 ;aDD IN THE NUMBER OF 256 BYTE BLOCKS sta buffer+1 sec lda y2 ;cALCULATE DY sbc y1 bcs :cont2 ;iS Y2>Y1? eor #$ff ;oTHERWISE DY=Y1-Y2 adc #$01:cont2 sta dy cmp dx ;wHO'S BIGGER: DY OR DX? bcc stepinx ;iF DX, THEN... jmp stepinystepinx ldy y1 cpy y2 lda bitp,x ;x CURRENTLY CONTAINS X1 sta oldx sta chunk bcc xincy ;dO WE STEP FORWARDS OR BACKWARDS IN y? jmp xdecyxincy lda fill beq normxinc >>> eorxstep,inynormxinc >>> xstep,inyxdecy lda fill beq normxdec >>> eorxstep,deynormxdec >>> xstep,deystepiny ldy y1 lda bitp,x ;x=X1 sta oldx lsr  ;y DOESN'T USE CHUNKS eor oldx ;sO WE JUST WANT THE BIT sta oldx cpy y2 bcs ydecyyincy lda fill beq norminc >>> eorystep,inynorminc >>> ystep,inyydecy lda fill beq normdec >>> eorystep,deynormdec >>> ystep,dey*-------------------------------* cLEAN UPcleanup lda vmcsb ;sWITCH CHAR ROM BACK IN and #%11110101 ;DEFAULT sta vmcsb rts  ;BYE! txt 'SPINAL CRACKER ' txt 'SLJ 6/95'*-------------------------------* sET UP BIT TABLE ds ^ ;cLEAR TO END OF PAGE   ;sO THAT TABLES START ON A PAGE BOUNDARYbitp lup 16 ;128 eNTRIES FOR x dfb %11111111 dfb %01111111 dfb %00111111 dfb %00011111 dfb %00001111 dfb %00000111 dfb %00000011 dfb %00000001 --^sin ;tABLE OF SINES, 120 BYTEScos equ sin+128 ;tABLE OF COSINES   ;bOTH OF THESE TRIG TABLES ARE   ;CURRENTLY SET UP FROM basiczdiv equ cos+128 ;dIVISION TABLEtmath1 equ zdiv+384 ;mATH TABLE OF F(X)=X*X/256tmath2 equ tmath1+512 ;sECOND MATH TABLEpolylist equ tmath2+512 ;lIST OF POLYGONS