p** tHE 3d SECTION.** tHESE ARE ROUTINES FOR THE 3D LIBRARY, INCLUDING* CALCULATING THE ROTATION MATRIX, ROTATING INDIVIDUAL* POINTS, ROTATING CENTERS, AND PROJECTION.** vERSION 2.0: 2/99*   - aCCUMULATING ROUTINES NOW USE POINTER TO MATRIX*   - globrot REDONE TO BE MORE EFFICIENT*   - rotproj PERFORMS TWO MATRIX MULTIPLICATIONS,*             TO CALCULATE r' m p + r' c*             sTORES Z-COORD IN plistzlo/hi ($6f/$71)*   - mULTICOLOR** mULTICOLOR VERSION -- MULTIPLY Y-COORDS BY 5/4* rel dsk '@0:ROTMATMC' lst off*------------------------------- do 0 org $6000 jmp calcmat lda #00 sta $69 sta $6b sta $6d lda #$50 ;pOINTS AT $5000 sta $6a lda #$51 sta $6c lda #$52 sta $6e jmp rotproj lda #00 ;dORKY SETUP ROUTINE sta $63 sta $65 sta $67 sta $69 sta $6b sta $6d ldx #$40 stx $64 inx stx $66 inx stx $68 inx stx $6a inx stx $6c inx stx $6e jmp globrot fin*-------------------------------sin equ $cf00cos equ $cf20projtab equ $ca00 ;pROJECTION TABLEprojrem equ $cb00 ;REMAINDERcdel equ $c600 ;X*COS(DELTA)cdelrem equ $c700 ;REMAINDERsdel equ $c800sdelrem equ $c900xoffset equ $53 ;cENTER OF THE SCREENyoffset equ $54matmult = $af ;pOINTER TO MATRIX MULT. TABLEScxlo = $a3 ;pOINTERS TO LIST OF (ROTATED)cxhi = $a5 ;CENTERS.cylo = $a7cyhi = $a9czlo = $abczhi = $admultlo1 equ $b1 ;sAME TABLES USED BY polyfillmultlo2 equ $b3multhi1 equ $b5multhi2 equ $b7* vARIABLES USED BY calcmatt1 equ $57 ;tEMPORARY VARIABLESt2 equ $58t3 equ $59t4 equ $5at5 equ $5bt6 equ $5ct7 equ $5dt8 equ $5et9 equ $5ft10 equ $60temp = $61thetax equ $62 ;aNGLESthetay equ $63thetaz equ $64a11 equ $41 ;lOCAL ROTATION MATRIXb12 equ $42c13 equ $43d21 equ $44e22 equ $45f23 equ $46g31 equ $47h32 equ $48i33 equ $49va11 equ $4a ;vIEWPOINT ROTATION MATRIXvb12 equ $4bvc13 equ $4cvd21 equ $4dve22 equ $4evf23 equ $4fvg31 equ $50vh32 equ $51vi33 equ $52* globrot VARIABLEScount equ $55sign equ $56cx equ $57 ;tEMPORARY VARIABLES FOR CENTERScxsgn equ $59cy equ $5acysgn equ $5ccz equ $5dczsgn equ $5ftemp1 = $60temp2 = $61temp3 = $62c0xlo equ $63 ;cENTERS, ORIGINAL POINTSc0xhi equ $65c0ylo equ $67c0yhi equ $69c0zlo equ $6bc0zhi equ $6dtm1 equ $6f ;tEMPORARY STORAGE FORtm2 equ $71 ;MULTIPLICATION* rotproj VARIABLES* count equ $55index equ $56 ;cENTER INDEXauxp equ $60 ;aUXILIARY POINTERtempx equ $62tempy equ $64tempz equ $66rotflag equ $68 ;rOTATE OR ROTATE+PROJECT. ;aLSO USED BY accrotx ETC.p0x equ $69 ;pOINTS TO BE ROTPROJEDp0y equ $6b ;(POINTERS)p0z equ $6dplistzlo equ $8b ;pLACE TO STORE ROTATED Z-COORDSplistzhi equ $8d ;NOTE CLOBBERED BY globrotplistxlo equ $bd ;pLACE TO STORE ROTPROJEDplistxhi equ $bf ;POINT (SAME AS USED BY polyfill)plistylo equ $c1plistyhi equ $c3 txt 'KHAAAN!'** cALCULATE THE LOCAL MATRIX** pASS IN: a,x,y = ANGLES AROUND Z,X,Y AXIS** sTRATEGY: m = rY rX rZ WHERE rZ=ROLL, rX=PITCH, rY=YAW** iDEA: gIVEN*   T1 = TX+TY*   T2 = TX-TY*   T3 = TX+TZ*   T4 = TX-TZ*   T5 = TX+TY+TZ = T3+TY*   T6 = TX-TY-TZ = T4-TY*   T7 = TX+TY-TZ = T1-TZ*   T8 = TX-TT+TZ = T2+TZ*   T9 = TY+TZ*   T10 = TY-TZ** THEN THE ROTATION ELEMENTS ARE*   a11=.5(COS(T9)+C(T10))-.25(SIN(T7)+S(T8)-S(T5)-S(T6))*   b12=.5(S(T9)-S(T10)) - .25(C(T8)-C(T7) + C(T6)-C(T5))*   c13=.5(SIN(T2)-SIN(T1))*   d21=.5(SIN(T4)-SIN(T3))*   e22=.5(COS(T3)+COS(T4))*   f23= SIN(TX)*   g31=.5(S(T9)+S(T10)) - .25(C(T7)-C(T8) + C(T6)-C(T5))*   h32=.5(C(T10)-C(T9)) - .25(S(T5)+S(T6) + S(T7)+S(T8))*   i33=.5(COS(T1)+COS(T2))* cyc on ;lET'S COUNT CYCLEScalcmat ent sta thetaz stx thetax sty thetay clc adc thetax and #$7f tax ;T3 lda thetax sec sbc thetaz and #$7f tay ;T4 lda cos,x clc adc cos,y sta e22 lda sin,y sec sbc sin,x sta d21 ;tHESE ARE THE T3/T4 ELEMENTS txa clc adc thetay and #$7f tax ;T5 tya sec sbc thetay and #$7f tay ;T6 lda sin,x clc adc sin,y cmp #$80 ;sET c IF NEGATIVE, CLEAR OTW. ;(PRETTY SNEAKY, EH? :) ror ;.25(SIN(T5)+...) sta a11 ;PARTIAL RESULT lda cos,y sec sbc cos,x cmp #$80 ror sta b12 ;PARTIAL RESULT lda thetax clc adc thetay and #$7f tax ;T1 lda thetax sec sbc thetay and #$7f tay ;T2 lda sin,y sec sbc sin,x sta c13 lda cos,x clc adc cos,y sta i33 txa sec sbc thetaz and #$7f tax ;T7 tya clc adc thetaz and #$7f tay ;T8 lda sin,x clc adc sin,y cmp #$80 ror sta temp clc adc a11 sta h32 ;ST5+ST6+ST7+ST8 lda temp sec sbc a11 ;ST7+ST8-ST5-ST6 sta a11 lda cos,x sec sbc cos,y cmp #$80 ror sta temp clc adc b12 sta g31 ;CT7-CT8 + CT6-CT5 lda b12 sec sbc temp sta b12 ;CT6-CT5 + CT8-CT7 lda thetay clc adc thetaz and #$7f tax ;T9 lda thetay sec sbc thetaz and #$7f tay ;T10 lda cos,x clc adc cos,y sec sbc a11 sta a11 lda cos,y sec sbc cos,x sec sbc h32 sta h32 lda sin,x sec sbc sin,y clc adc b12 sta b12 lda sin,x clc adc sin,y clc adc g31 sta g31 lda thetax ;fINALLY, LITTLE f23 and #$7f tax lda sin,x asl sta f23 rts ;eASY-PEASY! cyc off txt '"WHEN ANY MORTAL(EVEN THE MOST ODD)/' txt 'CAN JUSTIFY THE WAYS OF MAN TO gOD/' txt 'ILL THINK IT STRANGE THAT NORMAL MORTALS CAN/' txt 'NOT JUSTIFY THE WAYS OF gOD TO MAN"' txt ' -- E.E.CUMMINGS'** tHE NEXT THREE PROCEDURES ROTATE THE ACCUMULATION* MATRIX (MULTIPLY BY rX, rY, OR rZ).** cARRY CLEAR MEANS ROTATE BY POSITIVE AMOUNT, CLEAR* MEANS ROTATE BY NEGATIVE AMOUNT.** oN ENTRY: (.a,.y) = (LO,HI) POINTER TO MATRIX*   (BYTES 0-8 = INTEGER, 9-17=REMAINDER)*matp = t1remp = t3comrot ;cOMMON TO ALL ROTATIONS ror rotflag sta matp sty matp+1 clc adc #9 sta remp tya adc #00 sta remp+1 rtsaccrotz ent ;ROWS 1 AND 2 jsr comrot ldy #00 ldx #3 bne accrotx2accrotx ent jsr comrot ldy #3 ldx #6accrotx2 ;accrotx AND accrotz FUNCTION ;IDENTICALLY stx :cpy+1:loop sty count lda (remp),y ;ROW 2, REMAINDER sta auxp lda (matp),y tax ;.x = ROW 2, INTEGER iny ;+3 iny iny lda (remp),y ;ROW 3, REMAINDER sta auxp+1 lda (matp),y ;.y = ROW 3 tay jsr rotxy lda tempx ldy count sta (remp),y lda tempx+1 sta (matp),y iny iny iny lda tempy sta (remp),y lda tempy+1 sta (matp),y dey dey:cpy cpy #6 bcc :loop rtsaccroty ent ;ROWS 3 AND 1 jsr comrot ldy #6:loop sty count lda (remp),y ;ROW 3, REMAINDER sta auxp lda (matp),y tax ;.x = ROW 3, INTEGER tya sec sbc #6 tay lda (remp),y ;ROW 1, REMAINDER sta auxp+1 lda (matp),y ;.y = ROW 1 tay jsr rotxy lda tempx ldy count sta (remp),y lda tempx+1 sta (matp),y tya sec sbc #6 tay lda tempy sta (remp),y lda tempy+1 sta (matp),y ldy count iny cpy #9 bcc :loop rts*------------------------------- do 0accroty ent ror rotflag ldx #2:loop stx count lda g31rem,x ;ROWS 3 AND 1 sta auxp lda a11rem,x sta auxp+1 ldy a11,x ;.y = ROW 1 lda g31,x ;.x = ROW 3 tax jsr rotxy ldx count lda tempx sta g31rem,x lda tempx+1 sta g31,x lda tempy sta a11rem,x lda tempy+1 sta a11,x dex bpl :loop rtsaccrotz ent ror rotflag ldx #2:loop stx count lda a11rem,x ;ROWS 1 AND 2 sta auxp lda d21rem,x sta auxp+1 ldy d21,x ;.y = ROW 2 lda a11,x ;.x = ROW 1 tax jsr rotxy ldx count lda tempx sta a11rem,x lda tempx+1 sta a11,x lda tempy sta d21rem,x lda tempy+1 sta d21,x dex bpl :loop rts fin*-------------------------------** rOTATE .x,auxp .y,auxp+1 -> tempx,+1 tempy,+1** iF FLAG IS SET FOR NEGATIVE ROTATIONS, SWAP x AND y* AND SWAP DESTINATIONS (tempx tempy)*rotxy lda rotflag bpl :cont stx tempx ;sWAP x AND y sty tempy ldx auxp ldy auxp+1 stx auxp+1 sty auxp ldx tempy ldy tempx:cont lda cdelrem,x clc adc sdelrem,y sta tempx lda cdel,x ;X*COS(DELTA) adc sdel,y ;+Y*SIN(DELTA) sta tempx+1 lda tempx clc adc auxp sta tempx bcc :next inc tempx+1:next lda cdelrem,y sec sbc sdelrem,x sta tempy lda cdel,y ;Y*COS - X*SIN sbc sdel,x sta tempy+1 lda tempy clc adc auxp+1 sta tempy bcc :done inc tempy+1:done ldx rotflag bpl :rts ldx tempx sta tempx stx tempy lda tempx+1 ldx tempy+1 sta tempy+1 stx tempx+1:rts rts** pERFORM A GLOBAL ROTATION, I.E. ROTATE THE CENTERS* (16-BIT SIGNED VALUE) BY THE ROTATION MATRIX.** tHE MULTIPLICATION MULTIPLIES TO GET A 24-BIT RESULT* AND THEN DIVIDES THE RESULT BY 64 (MULT BY 4).  tO* PERFORM THE SIGNED MULTIPLICATION:*   - MULTIPLY c*Y AS NORMAL*   - IF Y<0 THEN SUBTRACT 256*c*   - IF c<0 THEN SUBTRACT 2^16*Y** pARAMETERS: .y = NUMBER OF POINTS TO ROTATE** V2 -- REWRITTEN FOR EFFICIENCY.  oLD VERSION COMPUTED*              1/64 ROW1*(CX,CY,CZ) + 1/64 ROW2*(CX,CY,CZ) + ...*       nEW VERSION COMPUTES*              [ CX*COLUMN1 + CY*COLUMN2 + CZ*COLUMN3 ] / 64* aCTUALLY, ABOVE SEEMS COMPLICATED, AND DOESN'T OFFER* A HUGE ADVANTAGE, SO HAS BEEN SKIPPED FOR NOW 3/5/99.*multay mac ;mULTIPLY a*y, STORE IN VAR1, a sta multlo1 ;a <> 0 sta multhi1 eor #$ff clc adc #01 sta multlo2 sta multhi2 lda (multlo1),y sec sbc (multlo2),y sta ]1 lda (multhi1),y sbc (multhi2),ydone <<<qmultay mac ;aSSUMES POINTERS ALREADY SET UP lda (multlo1),y sec sbc (multlo2),y sta ]1 lda (multhi1),y sbc (multhi2),y <<<* fIX SIGN AND DIVIDE BY 64divfix mac ;iF mIJ<0 SUBTRACT 256*c ldy multlo1 ;iF c<0 SUBTRACT 2^16*mIJ bpl posm sta temp3 lda temp2 sec sbc ]1 ;cENTER sta temp2 lda temp3 sbc ]1+1 ;HIGH BYTEposm ldy ]1+1 bpl div sec sbc multlo1 ;sUBTRACT mIJdiv asl temp1 ;dIVIDE BY 64 rol temp2 rol asl temp1 rol temp2 rol ldy temp2 <<< ;.a, .y = FINAL RESULT* mAIN ROUTINEglobrot entgloop dey sty count lda (c0xlo),y sta cx lda (c0xhi),y sta cx+1 lda (c0ylo),y sta cy lda (c0yhi),y sta cy+1 lda (c0zlo),y sta cz lda (c0zhi),y sta cz+1 lda va11 ;rOW1 ldx vb12 ldy vc13 jsr multrow ;rETURNS RESULT IN .x .a = LO HI ldy count sta (cxhi),y txa sta (cxlo),y lda vd21 ;rOW2 ldx ve22 ldy vf23 jsr multrow ldy count sta (cyhi),y txa sta (cylo),y lda vg31 ;rOW3 ldx vh32 ldy vi33 jsr multrow ldy count sta (czhi),y txa sta (czlo),y tya beq :done jmp gloop:done rts do 0 txt 'ONE OF THESE DAYS, ' txt 'BABY! MILKSHAKE! BOOM!' fin txt 'CRACKING TOAST, GROMMIT!' lst on cyc** mULTIPLY A ROW BY cx cy cz* (a pROCEDURE TO SAVE AT LEAST A little MEMORY...)*m1 equ cxsgn ;cxsgn ETC. NO LONGER USED.m2 equ cysgnm3 equ czsgnmultrow sta m1 stx m2 sty m3 tay beq :skip1 ldy cx+1 >>> multay,temp2 sta temp3 ldy cx >>> qmultay,temp1 clc adc temp2 sta temp2 lda temp3 adc #00 >>> divfix,cx ;aDJUST RESULT AND /64:skip1 sty tm1 sta tm1+1 lda m2 beq :skip2 ldy cy+1 ;AND MULTIPLY BY cy >>> multay,temp2 sta temp3 ldy cy >>> qmultay,temp1 clc adc temp2 sta temp2 lda temp3 adc #00 >>> divfix,cy tax tya ;LOW BYTE clc adc tm1 sta tm1 txa ;HIGH BYTE adc tm1+1 sta tm1+1:skip2 lda m3 beq :zero ldy cz+1 >>> multay,temp2 sta temp3 ldy cz >>> qmultay,temp1 clc adc temp2 sta temp2 lda temp3 adc #00 >>> divfix,cz sta temp3 tya clc adc tm1 tax lda temp3 adc tm1+1 rts:zero ldx tm1 lda tm1+1uprts rts ;.x .a = LO HI BYTES OF ROW MULT cyc off lst off** rotproj -- pERFORM LOCAL ROTATION AND PROJECT POINTS.** sETUP NEEDS:*   rOTATION MATRIX*   pOINTER TO MATH TABLE (matmult = $af-$b0)*   pOINTERS TO POINT LIST (p0x-p0z = $69-$6e)*   pOINTERS TO FINAL DESTINATIONS (plistylo ... = $bd...)*     (sAME AS USED BY polyfill)*   pOINTERS TO LISTS OF CENTERS (cxlo cxhi... = $a3-$ae)*   .y = nUMBER OF POINTS TO ROTATE (0..n-1)*   .x = oBJECT CENTER INDEX (INDEX TO CENTER OF OBJECT)** nEW ADDITION:*   c SET MEANS ROTATE AND PROJECT, BUT c CLEAR MEANS JUST*   ROTATE.  iF c=0 THEN NEED POINTERS TO ROTATION*   DESTINATIONS rotpx,rotpy,rotpz=$59-$5e.** V2: nOW TWO ROTATION MATRICES, LOCAL AND VIEWPOINT.*     pOINTS ARE ROTATED BY LOCAL MATRIX; IF PROJECTING,*     POINTS ARE NOW ROTATED BY VIEWPOINT MATRIX, THEN*     PROJECTED.**     rOTATED Z-COORDS STORED IN plistzlo/hi FOR*     DEPTH-SORTING, ETC.**     iF NOT PROJECTING, LOW BYTES ARE JUST STORED IN*     plistxlo ETC., AS THIS SEEMS A PRETTY USELESS*     FUNCTION NOW.*smult mac ;sIGNED MULTIPLICATION sta matmult eor #$ff clc adc #01 sta auxp lda (matmult),y sec sbc (auxp),y <<<qmult mac ;mULTIPLICATION THAT ASSUMES lda (matmult),y ;POINTERS ARE ALREADY INITIALIZED sec sbc (auxp),y <<<add mac ;sIMPLE ADDITION clc adc ]1 sta ]1 <<<locrot entrotproj lda matmult+1 sta auxp+1 stx index sty count ror rotflag bpl rotloop ;iF c=0 THEN JUST ROTATE. ldy index lda (cxlo),y ;cENTERS sta cx lda (cxhi),y sta cx+1 lda (cylo),y sta cy lda (cyhi),y sta cy+1 lda (czlo),y sta cz lda (czhi),y sta cz+1rotloop ldy count beq uprts dey sty count ldx #00 ;uSE LOCAL MATRIX lda (p0z),y ;tHIS WAY, CAN RE-USE ROUTINE pha lda (p0y),y pha lda (p0x),yrotloop2 bne :c1 sta tempx sta tempy sta tempz beq :c2:c1 ldy a11,x ;cOLUMN 1 >>> smult sta tempx ldy d21,x >>> qmult sta tempy ldy g31,x >>> qmult sta tempz  ;cOLUMN 2:c2 pla ;pY beq :c3 ldy b12,x >>> smult >>> add,tempx ldy e22,x >>> qmult >>> add,tempy ldy h32,x >>> qmult >>> add,tempz ;cOLUMN 3:c3 pla ;pZ beq addc ldy c13,x >>> smult >>> add,tempx ldy f23,x >>> qmult >>> add,tempy ldy i33,x >>> qmultaddc clc adc tempz ldy rotflag bmi :rot2 ldy count ;iF JUST ROTATING, THEN JUST sta (plistzlo),y ;STORE! lda tempy sta (plistylo),y lda tempx sta (plistxlo),y jmp rotloop:rot2 cpx #9 beq :proj ldx #9 ;uSE VIEWPOINT MATRIX pha lda tempy pha lda tempx jmp rotloop2:proj ldy #00 ;.y = SIGN tax bpl :pos1 dey:pos1 clc ;aDD IN CENTERS adc cz sta tempz tya adc cz+1 sta tempz+1 ;aSSUME THIS IS POSITIVE! ldx #00 ldy #00 lda tempy bpl :pos2 dey:pos2 clc adc cy sta tempy tya adc cy+1 sta tempy+1 bpl :c1 dex:c1 stx cysgn ;nEED SIGN FOR LATER ldx #00 ldy #00 lda tempx bpl :pos3 dey:pos3 clc adc cx sta tempx tya adc cx+1 sta tempx+1 bpl :c2 dex:c2 stx cxsgn ldy count lda tempz sta (plistzlo),y lda tempz+1 sta (plistzhi),y beq proj:blah lsr ;sHIFT EVERYTHING UNTIL ror tempz ;z=8-BITS lsr cxsgn ror tempx+1 ;pROJECTION THUS LOSES ACCURACY ror tempx ;FOR FAR-AWAY OBJECTS. lsr cysgn ror tempy+1 ;(bIG WHOOP) ror tempy tax bne :blahproj ldx tempz lda projtab,x ;pROJECTION CONSTANT bne :c1 ;lOTS OF 0'S AND 1'S, SO SPECIAL sta tm1 ;CASE THEM. sta tm1+1 sta tm2 sta tm2+1 ldy tempy+1 jmp :noint:easy1 ldy tempx sty tm1 ldy tempx+1 sty tm1+1 ldy tempy sty tm2 ldy tempy+1 sty tm2+1 bcs :noint ;aLWAYS TAKEN:c1 cmp #1 beq :easy1 ldy tempx >>> multay,tm1 ;AL*n ldy tempx+1 clc adc (multlo1),y ;+256*AH*n (MIDDLE BYTE) sec sbc (multlo2),y sta tm1+1 ldy tempy >>> qmultay,tm2 ldy tempy+1 clc adc (multlo1),y sec sbc (multlo2),y sta tm2+1:noint lda projrem,x beq :norm:crem sta multlo1 ;.y = tempy+1 sta multhi1 eor #$ff clc adc #01 sta multlo2 sta multhi2 lda (multlo1),y ;AH*R sec sbc (multlo2),y tax lda (multhi1),y sbc (multhi2),y cpy #$80 bcc :posrem sbc multlo1 ;sUBTRACT 256*R IF NEG ;(CLEARS CARRY):posrem tay txa adc tm2 sta tm2 tya adc tm2+1 sta tm2+1 ldy tempy lda (multlo1),y sec sbc (multlo2),y lda (multhi1),y ;AL*R, HI BYTE sbc (multhi2),y clc adc tm2 ;aDD REMAINDER sta tm2 bcc :conx inc tm2+1:conx* dO THE SAME FOR X ldy tempx+1 lda (multlo1),y ;AH*R sec sbc (multlo2),y tax lda (multhi1),y sbc (multhi2),y cpy #$80 bcc :posxrem sbc multlo1 ;sUBTRACT 65536*R IF NEG ;(CLEARS CARRY):posxrem tay txa adc tm1 sta tm1 tya adc tm1+1 sta tm1+1 ldy tempx lda (multlo1),y sec sbc (multlo2),y lda (multhi1),y ;AL*R, HI BYTE sbc (multhi2),y clc adc tm1 ;aDD REMAINDER sta tm1 ;AND STORE bcc :norm inc tm1+1:norm ;bEFORE ADDING, MULTIPLY y BY 5/4 lda tm2 ;(NORMALIZE FOR MULTICOLOR) sta tempy lda tm2+1 cmp #$80 ror ror tempy cmp #$80 ror ror tempy pha lda tempy clc adc tm2 sta tm2 pla adc tm2+1 sta tm2+1 ldy count lda xoffset ;sCREEN OFFSETS clc adc tm1 sta (plistxlo),y lda tm1+1 adc #00 sta (plistxhi),y lda yoffset clc adc tm2 sta (plistylo),y lda tm2+1 adc #00 sta (plistyhi),y jmp rotloop ;aND ON TO THE NEXT POINT! txt 'KLINGON SONS; YOU KILLED MY BASTARD!' do 0 txt 'I HATE BROCCOLI.  AND YET, IN A CERTAIN ' txt 'SENSE, I AM BROCCOLI. -TICK' fin