 p** tHIS IS THE FILLED POLYGON ROUTINE FOR THE* 3d GRAPHICS LIBRARY.  iT IS BASED ON THE POLYGONAMY* ROUTINE, IMPROVED IN SOME PLACES AND MODIFIED IN OTHERS* TO SAVE MEMORY, BUT IT OUGHT TO BE well WITHIN A FACTOR* OF TWO SPEED-WISE.** tO USE:*   - sET UP A LIST OF POINTS BLAH BLAH*   - YAK YAK YAK* pOINTS MAY LIE IN RANGE YADA YADA YADA** wRITTEN OVER THE 4TH OF jULY WEEKEND.** (pLUS A FEW EVENINGS :)** slj 7/97** V2 -- nEW VARIABLES, LATER WILL ADD MULTICOLOR MODE*       dy > 255 NOW ALLOWED*       rOUTINES TO PLOT POINTS AND LINES* V2MC -- mULTICOLOR VERSION!* slj 3/99* rel dsk '@0:POLYFILLMC'multlo1 = $b1 ;pOINTERS TO MULTIPLICATIONmultlo2 = $b3 ;TABLESmulthi1 = $b5multhi2 = $b7bitmap = $b9 ;pOINTER TO BASE OF BITMAP (HI)fillpat = $bb ;pOINTER TO FILL PATTERNplistxlo = $bd ;pointer TO LIST OF X COORDS (LO)plistxhi = $bfplistylo = $c1 ;pOINTER TO LIST OF Y COORDSplistyhi = $c3temp1 = $55 ;tEMPORARY VARtemp2 = $56lbits = $57 ;fILL PATTERNnumpts = $58rempts = $59 ;rEMAINING NUMBER OF POINTSlindex = $5a ;lEFT POINT INDEXrindex = $5b ;rIGHT POINT INDEX* ldy AND rdy AREN'T USED ANYWHERE* ldy = $5c ;lEFT DY* rdy = $5d ;rIGHT DYyleft = $5c ;rEMAINING POINTS LEFTyright = $5e ;REMAINING POINTS RIGHTldxint = $60 ;lEFT DX, INTEGER PARTldxrem = $61 ;REMAINDERrdxint = $62rdxrem = $63leftxlo = $64 ;lEFT X COORDINATEleftxhi = $65leftrem = $66 ;REMAINDERrightxlo = $67rightxhi = $68rightrem = $69ycount = $6a ;cOUNTER = 0..7yrow = $6b ;cURRENT ROWlcol = $6c ;cOLUMN, LEFT COORDINATEbpoint = $6d ;pOINTER TO BITMAProwhigh = $6f ;aCTUAL HIGH BYTE OF BITMAP POINTERdivxlo = $70 ;dIVISION: divx/divydivxhi = $71divy = $72divtemp = multlo1 ;hIGH BYTE OF dylog = $cc00 ;lOGARITHM TABLEexp = $cd00 ;eXPONENTIAL TABLEnegexp = $ce00 ;E^-Xpq = $0200 ;pOINT INDEX QUEUE** sOME TABLES** a LITTLE WASTEFUL, SINCE NOW X=0..160xcolumn ;XCOLUMN(X)=X/4]blah = 0 lup 64 dfb ]blah,]blah,]blah,]blah]blah = ]blah+1 --^* bELOW ARE eor #$ff FOR MERGING INTO THE BITMAP, INSTEAD* OF JUST oraING INTO THE BITMAP.lbitp ;lEFT BIT PATTERNS lup 64 dfb 00,$c0,$f0,$fc --^rbitp ;RIGHT BIT PATTERNS lup 64* dfb $80,$c0,$e0,$f0,$f8,$fc,$fe,$ff dfb $3f,$0f,$03,$00 --^** tHE FILL ROUTINE.  iT JUST BLASTS INTO THE BITMAP,* WITH SELF-MODIFYING CODE DETERMINING THE ENTRY AND* EXIT POINTS.*fillmain]blah = 0 ;tHIS ASSEMBLES TO lup 32 ;ldy #00  sta (bpoint),y ldy #]blah ;ldy #08  sta (bpoint),y sta (bpoint),y ;...]blah = ]blah+8 ;ldy #248 sta (bpoint),y --^ inc bpoint+1 ;aDVANCE POINTER TO COLUMN 32col32 ldy #00 sta (bpoint),y ldy #08 ;33 sta (bpoint),y ldy #16 sta (bpoint),y ldy #24 sta (bpoint),y ldy #32 sta (bpoint),y ldy #40 ;37 sta (bpoint),y ldy #48 sta (bpoint),y ldy #56 ;cOLUMN 39 sta (bpoint),yfillend rts ;64+256=320fill jmp fillmain ;166 BYTES** tABLES OF HIGH AND LOW BITMAP ROW OFFSETS*lobrow dfb 00,64,128,192,00,64,128,192 dfb 00,64,128,192,00,64,128,192 dfb 00,64,128,192,00,64,128,192 dfb 00hibrow dfb 00,01,02,03,05,06,07,08 dfb 10,11,12,13,15,16,17,18 dfb 20,21,22,23,25,26,27,28 dfb 30coltab ;COLTAB(X)=X*8 dfb 0,8,16,24,32,40,48,56,64,72,80 dfb 88,96,104,112,120,128,136,144 dfb 152,160,168,176,184,192,200 dfb 208,216,224,232,240,248 dfb 0,8,16,24,32,40,48,56* nOW ON A PAGE BOUNDARY!** tHE JUMP TABLE FOR THE 3D LIBRARY ROUTINES** wE SHOULD BE AT $8a00*calcmat extlocrot extglobrot extaccrotx extaccroty extaccrotz ext jmp calcmat jmp accrotx jmp accroty jmp accrotz jmp globrot jmp locrot jmp polyfill jmp plot jmp drawlineversion lda #$82 ;vERSION NUMBER rts** tABLE OF ENTRY POINT OFFSETS INTO FILL ROUTINE.* tHE IDEA IS TO ENTER ON AN ldy*fillent dfb 0,4,8,12,16,20,24,28,32,36,40 ;0-10 dfb 44,48,52,56,60,64,68,72,76,80 ;11-20 dfb 84,88,92,96,100,104,108,112   ;21-28 dfb 116,120,124,128               ;29-32 dfb 134 ;sKIP OVER inc bpoint+1 dfb 138,142,146,150,154,158 ;34-39 dfb 162 ;rEMEMBER THAT WE USE fillent+1** tABLE OF rts POINTS IN FILL ROUTINE.* tHE IDEA IS TO RTS AFTER THE next ldy #XX SO AS TO* GET THE CORRECT POINTER TO THE RIGHTMOST COLUMN.** tHUS, THESE ENTRIES ARE JUST THE ABOVE +2*fillrts dfb 2,6,10,14,18,22,26,30,34,38,42 ;0-10 dfb 46,50,54,58,62,66,70,74,78,82  ;11-20 dfb 86,90,94,98,102,106,110,114,118,122,126 dfb 132 ;sKIP OVER inc dfb 136,140,144,148,152,156,160    ;33-39** tHERE ARE TWO TYPES OF LINES: ONES THAT MOVE RIGHT AND* ONES THAT MOVE LEFT.  tHEY MAY HAVE EITHER POSITIVE* OR NEGATIVE SLOPE, FOR A TOTAL OF FOUR ROUTINES.** eACH LINE REQUIRES TWO PARTS: THE INITIAL COMPUTATION* OF DX/DY, AND THE ACTUAL UPDATING OF THE LINE.  wHEN* DY=0 THE NEXT SET OF POINTS MUST BE MOVED TO.  tHE* INITIAL STEP IS ALWAYS DX/2, TO MAKE NICE LOOKING LINES,* BUT THE INITIAL COLUMN/BIT PATTERN MUST BE HANDLED* CAREFULLY, DEPENDING ON THE SLOPE.** tHE COMPLEMENTARY ROUTINE JUMP ADDRESS MUST BE PASSED* IN, FOR NEGATIVE CHANGES IN SLOPE.*** pART 1: cOMPUTE DY** sINCE THE VERY LAST POINT MUST BE PLOTTED IN A SPECIAL* WAY (ELSE NOT BE PLOTTED AT ALL), ]1=ADDRESS OF ROUTINE* TO HANDLE LAST POINT.*dylinel mac  ;lINE WITH LEFT POINTSbegin ldx lindexl1 dec rempts ;rEMAINING LINES TO PLOT bpl l2 ;zERO IS STILL PLOTTED inc yleft lda rempts cmp #$ff ;lAST POINT bcs ]1exit rts* jmp alldone ;iF WE HIT ZEROl2 jsr calcdyl bmi exit ;(SOMETIMES POINTS GET SCREWED UP) ora yleft beq l1 ;iF dy=0 THEN SKIP TO NEXT POINT stx lindex <<<dyliner mac ldx rindexl1 dec rempts bpl l2 lda rempts ;mIGHT HAVE TO HANDLE ENDPOINT cmp #$fe bcs ]1rrts rts ;wE REALLY SHOULD NEVER GET HEREl3 ldx #00 ;wRAP AROUNDl2 cpx numpts bcs l3 ldy pq,x sty temp1 lda (plistyhi),y pha lda (plistylo),y ;sTART POINT inx sec ldy pq,x sty temp2 sbc (plistylo),y ;nEXT POINT sta yright sta divy pla sbc (plistyhi),y sta yright+1 sta divtemp bmi rrts ;(SOMETIMES POINTS GET SCREWED UP) ora divy beq l1 ;aDVANCE IF DY=0 stx rindex <<<** pART 2: cOMPUTE DX.  iF DX HAS NEGATIVE THE EXPECTED* SIGN THEN JUMP TO THE COMPLEMENTARY ROUTINE.** DX>0 MEANS FORWARDS POINT IS TO THE RIGHT OF THE* CURRENT POINT, AND VICE-VERSA.*linelm mac  ;lEFT LINE, DX<0 ldy temp1 lda (plistxhi),y sta leftxhi lda (plistxlo),y ;cURRENT POINT sta leftxlo ldy temp2 sec ;cARRY CAN BE CLEAR IF JUMPED TO sbc (plistxlo),y ;nEXT POINT sta divxlo lda leftxhi sbc (plistxhi),y bpl cont1 ;iF DX>0 THEN JUMP OUT jmp ]1 ;eNTRY ADDRESScont1 sta divxhi jsr linelm2done <<< ;nOW .x=LOW BYTE, .a=HIGH BYTE ;(OF ADVANCED POINT) ;AND CARRY=CLEARlinelp mac  ;lEFT LINE, DX>0 ldy temp2 lda (plistxhi),y tax lda (plistxlo),y ;nEXT POINT ldy temp1 sec ;cARRY CAN BE CLEAR IF JUMPED TO sbc (plistxlo),y ;cURRENT POINT sta divxlo txa sbc (plistxhi),y bpl cont1 ;iF DX<0 THEN JUMP OUT jmp ]1 ;eNTRY ADDRESScont1 sta divxhi lda (plistxlo),y ;cURRENT POINT sta leftxlo lda (plistxhi),y sta leftxhi jsr linelp2done2 <<< ;nOW .x=LOW BYTE, .a=HIGH BYTE ;OF CURRENT POINT** nOW DO THE SAME FOR THE RIGHT LINES*linerp mac  ;rIGHT LINE, DX>0 ldy temp2 lda (plistxhi),y tax lda (plistxlo),y ;nEXT POINT ldy temp1 sec sbc (plistxlo),y ;cURRENT POINT sta divxlo txa sbc (plistxhi),y bpl cont1 ;iF DX<0 THEN JUMP OUT jmp ]1 ;eNTRY ADDRESScont1 sta divxhi lda (plistxlo),y ;cURRENT POINT (dey ABOVE) sta rightxlo lda (plistxhi),y sta rightxhi jsr linerp2done <<< ;nOW .x=LOW BYTE, .a=HIGH BYTE ;CARRY=CLEARlinerm mac  ;rIGHT LINE, DX<0 ldy temp1 lda (plistxhi),y sta rightxhi lda (plistxlo),y ;cURRENT POINT sta rightxlo ldy temp2 sec sbc (plistxlo),y ;nEXT POINT sta divxlo lda rightxhi sbc (plistxhi),y bpl cont1 ;iF DX<0 THEN JUMP OUT jmp ]1 ;eNTRY ADDRESScont1 sta divxhi jsr linerm2done <<< ;nOW .x=LOW BYTE, .a=HIGH BYTE** nEXT, THE PARTS WHICH UPDATE THE x COORDINATES* FOR POSITIVE AND NEGATIVE DX (IN REAL SPACE, OF* COURSE -- THE STORED VALUE OF DX IS ALWAYS POSITIVE)** pARAMETERS PASSED IN ARE:*   ]1 = LO BYTE X COORD*   ]2 = HIGH BYTE X COORD*   ]3 = REMAINDER*   ]4 = DY (UNUSED!)*   ]5 = DX/DY, INTEGER*   ]6 = DX/DY, REMAINDER*pupdate mac ;DX>0 lda ]3 clc adc ]6 sta ]3 lda ]1 ;X=X+DX/DY adc ]5 tax sta ]1 bcc cont inc ]2 ;hIGH BYTE, X clccont lda ]2 <<< ;cARRY IS clear ON EXIT ;.x = LO BYTE XCOORD ;.a = HI BYTEmupdate mac ;DX<0 lda ]3 ;REMAINDER sec sbc ]6 sta ]3 lda ]1 ;X=X-DX/DY sbc ]5 sta ]1 tax bcs cont dec ]2 ;HIGH BYTEcont lda ]2 clc <<< ;CARRY IS CLEAR ;.x=X-COORD LOW BYTE ;.a=HIGH BYTE** cOMPUTE THE COLUMNS AND PLOT THE ENDPOINTS** .x CONTAINS THE LOW BYTE OF THE X-COORD* .a WAS just LOADED WITH THE HIGH BYTE** cARRY IS ASSUMED TO BE clear*lcolumn mac* lda leftxhi beq cont bmi negpos lda #$ff ;cOLUMN FLAG sta lcol bne doneneg lda #00 ;iF NEGATIVE, COLUMN=0 sta lcol sta lbits ;(WILL BE eor #$ff'ED) lda #4 ;sTART FILLING AT COLUMN 1 sta fill+1 bne donecont cpx #128 bcc adc inc bpoint+1 ;gREATER THAN COL 32 SO ADVANCE cpx #160 bcs posadc adc xcolumn,x sta lcol tay lda lbitp,x sta lbits ;fOR LATER USE IN rcolumn lda fillent+1,y ;gET FILL ENTRY ADDRESS sta fill+1done <<< ;bY PUSHING OFF THE PLOT UNTIL ;LATER, THINGS LIKE SHARED ;COLUMNS WON'T HOSE OTHER THINGS ;ON THE SCREEN.** nOTE THAT rcolumn DOES THE ACTUAL FILLING** oN ENTRY, .x = LO BYTE X-COORD, AND .a WAS just LOADED*   WITH THE HIGH BYTE.** cARRY MUST BE clear.*rcolumn mac* lda rightxhi beq cont bmi jdone ;sKIP PLOT+FILL IF X<0pos ldx lcol bmi jdone ;sKIP IF LCOL>40! ldy ycount ;pLOT THE LEFT EDGE lda (fillpat),y sta temp1 ldy coltab,x ;gET COLUMN INDEX eor (bpoint),y ;mERGE INTO THE BITMAP and lbits ;BITS eor #$ff eor temp1 ;VOILA! sta (bpoint),y lda temp1 jsr fill ;jUST FILL TO LAST COLUMNjdone jmp doneunder ldy lcol ;iT IS POSSIBLE THAT, DUE TO bmi done ;ROUNDING, ETC. THE LEFT COLUMN ldx #00 ;GOT AHEAD OF THE RIGHT COLUMN ;X=0 WILL FORCE LOAD OF $ffsame lda rbitp,x ;iF ZERO, THEY SHARE COLUMN eor lbits sta lbits ldy ycount lda (fillpat),y sta temp1 ldx lcol ldy coltab,x eor (bpoint),y ;mERGE and lbits eor temp1 sta (bpoint),y ;AND PLOT jmp donecont cpx #160 ;cHECK RANGE bcs pos adc xcolumn,x cmp lcol ;mAKE SURE WE WANT TO FILL bcc under beq same ldy rbitp,x sty temp1 ldx lcol sta lcol ;rIGHT COLUMN ldy ycount ;pLOT THE LEFT EDGE lda (fillpat),y sta temp2 ldy coltab,x ;gET COLUMN INDEX eor (bpoint),y ;mERGE INTO BITMAP and lbits eor temp2 sta (bpoint),y ldy lcol ;RIGHT COLUMN ldx fillrts,y ;FILL TERMINATOR lda #$60 ;rts sta fillmain,x lda temp2 ;fILL PATTERN jsr fill eor (bpoint),y and temp1 ;rIGHT BITS eor temp2 ;mERGE sta (bpoint),y lda #$91 ;sta (),y sta fillmain,x ;fILL LEAVES .x UNCHANGED ;aND LEAVES .y WITH CORRECT OFFSETdone <<<** fINALLY, WE NEED TO DECREASE THE y COORDINATE AND* UPDATE THE POINTER IF NECESSARY.** aLSO, SINCE bpoint MAY HAVE BEEN ALTERED, WE NEED* TO RESTORE THE HIGH BYTE.** ]1 = LOOP ADDRESS*upyrs mac lda rowhigh sta bpoint+1 dec bpoint dec ycount bmi fixit jmp ]1fixit lda #7 sta ycount ldy yrow beq exit ;iF Y<0 THEN EXIT dey sty yrow ora lobrow,y sta bpoint lda hibrow,y clc adc bitmap sta bpoint+1 sta rowhigh jmp ]1exit rts <<<** lIKE THE ABOVE, BUT FOR THE Y>=200 ROUTINE*bigfix mac* lda rowhigh* sta bpoint+1* dec bpoint dec ycount bmi fixit jmp ]1fixit lda #7 sta ycount dec yrow ldy yrow ora lobrow,y sta bpoint lda hibrow,y clc adc bitmap sta bpoint+1 sta rowhigh cpy #24 beq exit ;iF Y<0 THEN EXIT jmp ]1exit <<< ;dON'T LEAVE THIS HANGING :)** yAY, TIME TO CODE!** lOAD x WITH THE NUMBER OF POINTS IN THE POINT LIST*polyfill stx numpts stx rempts lda #00 ;fIRST FIND THE LARGEST y sta temp1 sta temp2 sta lindex:loop ldy pq,x lda (plistylo),y cmp temp1 lda (plistyhi),y bmi :skip sbc temp2 bcc :skip stx lindex lda (plistylo),y sta temp1 lda (plistyhi),y sta temp2:skip dex bne :loop ldx lindex bne gogogo ;pOSSIBLE THAT ALL y<0rtsmp rtsgogogo stx rindex ldy pq,x lda (plistxlo),y sta leftxlo sta rightxlo lda (plistxhi),y sta leftxhi sta rightxhi lda temp1 lsr temp2 ;cOMPUTE INITIAL ROW ror lsr temp2 ror lsr temp2 ror sta yrow tax lda temp1 ;iNITIAL BIT PATTERN and #$07 sta ycount ora lobrow,x ;iNITIAL BITMAP ADDRESS sta bpoint lda hibrow,x clc adc bitmap sta bpoint+1 sta rowhigh** hIDDEN FACE CHECK.  sINCE POINT ORDER IS INVARIANT* UNDER ROTATIONS BUT REVERSED BY REFLECTIONS, ALL THAT* IS REQUIRED IS TO MAKE SURE THE POINTS ARE IN ORDER,* I.E. CHECK THE LINE SLOPES.* >>> dylinel,rtsmpcheckmp >>> linelm,checkpp jsr chklcol ;tO SAVE SOME MEMORY >>> linerp,checkmm sta temp2 ;pOSSIBLE TO FAIL IF DY=0 lda leftxlo sec sbc rightxlo sta divxlo ;TEMP lda leftxhi sbc rightxhi sta divxhi lda divxlo sec sbc ldxint bcs :c1 dec divxhi sec:c1 sbc rdxint sta divxlo lda divxhi sbc #00 bmi :ok ;sKIP UNLESS LEFTX <= RIGHTX ora divxlo beq :ok:rts1 rts:ok ldy yrow cpy #25 bcs :oops lda temp2 ;rESTORE a=HIGH BYTE X jmp rcolmp ;jUMP INTO RIGHT COLUMN UPDATE:oops tay ;sET FLAGS clc jmp bcmp ;rUN CALCULATION UNTIL y<200** sIGH... NEED TO SAVE SOME MEMORY, SO THIS IS NOW HERE.*chklcol >>> lcolumn ;uPDATE COLUMN INFO >>> dyliner,chexit rtschexit pla ;really EXIT. pla rtscheckpp >>> linelp,checkmp jsr chklcol >>> linerp,checkpm sta temp2 lda leftxlo sec sbc rightxlo sta divxlo ;TEMP lda leftxhi sbc rightxhi sta divxhi lda divxlo clc adc ldxint bcc :c1 inc divxhi:c1 sec sbc rdxint sta divxlo lda divxhi sbc #00 bmi :ok ;iF >= THEN PUNT ora divxlo bne :rts lda ldxrem ;iF 0, THEN COMPARE SLOPES sec sbc rdxrem lda ldxint sbc rdxint bcc :ok:rts rts:ok ldy yrow cpy #25 bcs :oops lda temp2 ;rESTORE a=HIGH BYTE X jmp rcolpp ;jUMP INTO RIGHT COLUMN UPDATE:oops lda temp2 ;sET FLAGS clc jmp bcpp ;rUN CALCULATION UNTIL y<200checkmm >>> linerm,checkmp sta temp2 lda leftxlo sec sbc rightxlo sta divxlo ;TEMP lda leftxhi sbc rightxhi sta divxhi lda divxlo sec sbc ldxint bcs :c1 dec divxhi:c1 clc adc rdxint sta divxlo lda divxhi adc #00 bmi :ok ;iF >= THEN PUNT ora divxlo bne :toast lda rdxrem sec sbc ldxrem lda rdxint sbc ldxint bcc :ok:toast rts:ok ldy yrow cpy #25 bcs :oops lda temp2 ;rESTORE a=HIGH BYTE X jmp rcolmm ;jUMP INTO RIGHT COLUMN UPDATE:oops lda temp2 ;sET FLAGS clc jmp bcmm ;rUN CALCULATION UNTIL y<200checkpm >>> linerm,checkpm ;iT'S POSSIBLE, IF DY=0 sta temp2 ;rEMEMBER THAT WE'VE ADVANCED lda leftxlo sec sbc rightxlo sta divxlo ;TEMP lda leftxhi sbc rightxhi sta divxhi lda divxlo clc adc ldxint bcc :c1 inc divxhi clc:c1 adc rdxint lda divxhi adc #00 bmi :ok ;iF >= THEN PUNT rts:ok ldy yrow cpy #25 bcs :oops lda temp2 ;rESTORE a=HIGH BYTE X jmp rcolpm ;jUMP INTO RIGHT COLUMN UPDATE:oops lda temp2 ;sET FLAGS clc jmp bcpm ;rUN CALCULATION UNTIL y<200** aND FINALLY, THE MAIN ROUTINE!  (yAY :)** lEFT LINES MINUS, RIGHT LINES POSITIVEdyl1 dec yleft+1 bpl ul1 >>> dylinel,endmpleftmp >>> linelm,leftpp jmp lcolmpendmp rts ;aCTUALLY, WE DON'T WANT TO GET HERE!loop1 dec yleft beq dyl1ul1 >>> mupdate,leftxlo;leftxhi;leftrem;temp1;ldxint;ldxremlcolmp >>> lcolumn dec yright bne ur1 dec yright+1 bpl ur1 >>> dyliner,endmprightmp >>> linerp,rightmm jmp rcolmpur1 >>> pupdate,rightxlo;rightxhi;rightrem;temp1;rdxint;rdxremrcolmp >>> rcolumn >>> upyrs,loop1* lEFT POSITIVE, RIGHT POSITIVE** eNDPOINT: LEFT ADVANCES, RIGHT=CURRENT POINTdyl2 dec yleft+1 bpl ul2 >>> dylinel,ul2leftpp >>> linelp,leftmp jmp lcolpploop2 dec yleft beq dyl2ul2 >>> pupdate,leftxlo;leftxhi;leftrem;temp1;ldxint;ldxremlcolpp >>> lcolumn dec yright bne ur2 dec yright+1 bpl ur2 >>> dyliner,endpprightpp >>> linerp,rightpm jmp rcolppendpp ldy pq,x lda (plistxlo),y ;lAST POINT tax lda (plistxhi),y clc jmp rcolppur2 >>> pupdate,rightxlo;rightxhi;rightrem;temp1;rdxint;rdxremrcolpp >>> rcolumn >>> upyrs,loop2* lEFT POSITIVE, RIGHT NEGATIVE** eND: LEFT AND RIGHT ADVANCE NORMALLYdyl3 dec yleft+1 bpl ul3 >>> dylinel,ul3leftpm >>> linelp,leftmm jmp lcolpmloop3 dec yleft beq dyl3ul3 >>> pupdate,leftxlo;leftxhi;leftrem;temp1;ldxint;ldxremlcolpm >>> lcolumn dec yright bne ur3 dec yright+1 bpl ur3 >>> dyliner,ur3rightpm >>> linerm,rightpp jmp rcolpmur3 >>> mupdate,rightxlo;rightxhi;rightrem;temp1;rdxint;rdxremrcolpm >>> rcolumn >>> upyrs,loop3* lEFT NEGATIVE, RIGHT NEGATIVE** eND: LEFT=CURRENT POINT, RIGHT ADVANCESexitmm ;x POINTS TO THE LAST POINT inc yright ;sNEAKY! ldy pq,x lda (plistxlo),y tax lda (plistxhi),y clc jmp lcolmmdyl4 dec yleft+1 bpl ul4 >>> dylinel,exitmmleftmm >>> linelm,leftpm jmp lcolmmloop4 dec yleft beq dyl4ul4 >>> mupdate,leftxlo;leftxhi;leftrem;temp1;ldxint;ldxremlcolmm >>> lcolumn dec yright bne ur4 dec yright+1 bpl ur4 >>> dyliner,ur4rightmm >>> linerm,rightmp jmp rcolmmur4 >>> mupdate,rightxlo;rightxhi;rightrem;temp1;rdxint;rdxremrcolmm >>> rcolumn >>> upyrs,loop4** rOUTINES TO ADVANCE BUT NOT PLOT*bigloop1 dec yleft bne bl1 dec yleft+1 bpl bl1 >>> dylinel,bendmpbiglmp >>> linelm,biglpp jmp bc1bendmp rts ;aCTUALLY, WE DON'T WANT TO GET HERE!bl1 >>> mupdate,leftxlo;leftxhi;leftrem;temp1;ldxint;ldxrembc1 dec yright bne br1 dec yright+1 bpl br1 >>> dyliner,bendmpbigrmp >>> linerp,bigrmm jmp bc2br1 >>> pupdate,rightxlo;rightxhi;rightrem;temp1;rdxint;rdxrembcmp ;eNTRY POINT FROM HIDDEN CHECKbc2 >>> bigfix,bigloop1 jmp loop1bigloop2 dec yleft bne bl2 dec yleft+1 bpl bl2 >>> dylinel,bl2biglpp >>> linelp,biglmp jmp bc3bl2 >>> pupdate,leftxlo;leftxhi;leftrem;temp1;ldxint;ldxrembc3 dec yright bne br2 dec yright+1 bpl br2 >>> dyliner,bendppbigrpp >>> linerp,bigrpm jmp bc4bendpp rtsbr2 >>> pupdate,rightxlo;rightxhi;rightrem;temp1;rdxint;rdxrembcppbc4 >>> bigfix,bigloop2 jmp loop2bigloop3 dec yleft bne bl3 dec yleft+1 bpl bl3 >>> dylinel,bendppbiglpm >>> linelp,biglmm jmp bc5bl3 >>> pupdate,leftxlo;leftxhi;leftrem;temp1;ldxint;ldxrembc5 dec yright bne br3 dec yright+1 bpl br3 >>> dyliner,br3bigrpm >>> linerm,bigrpp jmp bc6br3 >>> mupdate,rightxlo;rightxhi;rightrem;temp1;rdxint;rdxrembcpmbc6 >>> bigfix,bigloop3 jmp loop3bigrts rtsbigloop4 dec yleft bne bl4 dec yleft+1 bpl bl4 >>> dylinel,bigrtsbiglmm >>> linelm,biglpm jmp bc7bl4 >>> mupdate,leftxlo;leftxhi;leftrem;temp1;ldxint;ldxrembc7 dec yright bne br4 dec yright+1 bpl br4 >>> dyliner,br4bigrmm >>> linerm,bigrmp jmp bc8br4 >>> mupdate,rightxlo;rightxhi;rightrem;temp1;rdxint;rdxrembcmmbc8 >>> bigfix,bigloop4 jmp loop4** cALLED BY dylineX MACROS.  iT CHECKS FOR NEGATIVE DY.* yEP, IT'S HERE TO SAVE ON MEMORY.** V2 -- HANDLED AUTOMATICALLY NOW THAT DY>255 IS ALLOWED do 0flowchk ldy temp1 lda (plistyhi),y ldy temp2 sbc (plistyhi),y rts fin** cALLED BY dylineX MACROS -- COMPUTES LEFT dy ETC.** rIGHT LINE WILL FOLLOW, IF MORE MEM IS NEEDED.*cdyl2 pla ldx numptscalcdyl ldy pq,x sty temp1 lda (plistyhi),y pha lda (plistylo),y ;rEMEMBER, Y -DECREASES- dex bmi cdyl2 ;lOOP AROUND IF NEEDED ldy pq,x sty temp2 sec sbc (plistylo),y sta yleft sta divy pla sbc (plistyhi),y sta yleft+1 sta divtemp rts** cALLED BY linelm MACRO*linelm2 jsr divxy ;rETURNS INT,REM = .x,.a stx ldxint cmp #$ff ;IF DY=1 bne :not1 ;THEN x=DX/2 stx temp2 ;JUST TWO STEPS OF DX/2 lda #00 ror ;gET CARRY BIT FROM DX/2 sta ldxrem bcc :cont2:not1 sta ldxrem txa ;X=X-DXDY/2 lsr sta temp2:cont2 lda #$80 sta leftrem ;REM = 1/2 lda leftxlo sec sbc temp2 sta leftxlo tax ;x=ADVANCED POINT lda leftxhi sbc #00 sta leftxhi clc rts** cALLED BY linelp MACRO*linelp2 jsr divxy ;rETURNS INT,REM = .x,.a stx ldxint cmp #$ff ;IF DY=1 bne :not1 ;THEN a=DX/2 lda #00 ror ;gET CARRY BIT FROM DX/2 sta ldxrem lda #$80 sta leftrem ldx leftxlo lda leftxhi bcc :rts ;aND START FROM CURRENT POINT:not1 sta ldxrem lda #$80 sta leftrem ;iNITIALIZE REMAINDER TO 1/2 txa ;X=X-DXDY/2 lsr sta temp2 lda leftxlo tax ;.x = CURRENT POINT sec sbc temp2 sta leftxlo lda leftxhi bcs :done dec leftxhi tay ;sET/CLEAR z FLAG:done clc:rts rts** cALLED BY linerp MACRO*linerp2 jsr divxy ;rETURNS INT,REM = .x,.a stx rdxint cmp #$ff bne :not1 lda #00 ror sta rdxrem lda #$80 sta rightrem txa bcc :cont2 ;aDVANCE BY DXDY/2:not1 sta rdxrem lda #$80 ;-1/2 sta rightrem txa ;X=X+DXDY/2 lsr clc:cont2 adc rightxlo sta rightxlo tax ;mOVE RIGHT AND USE NEW POINT lda rightxhi adc #00 sta rightxhi clc ;wHAT IF RIGHTX EQUALED -1? rts** cALLED BY linerm*linerm2 jsr divxy ;rETURNS INT,REM = .x,.a stx rdxint cmp #$ff bne :not1 lda #00 ror sta rdxrem lda #$80 sta rightrem ldx rightxlo ;aDVANCE FROM CURRENT POINT lda rightxhi bcc :done:not1 sta rdxrem lda #$80 sta rightrem ;1/2 txa ;X=X+DXDY/2 ldx rightxlo ;.x = CURRENT POINT lsr clc adc rightxlo sta rightxlo lda rightxhi bcc :done inc rightxhi tay ;rESET z clc:done rts** divxy** tHIS GUY IS THE OLD PREDICTOR-CORRECTOR METHOD,* MODIFIED SLIGHTLY TO BE MORE GENERAL.** iT COMPUTES 2x/2y AS THE PREDICTOR, THEN CORRECTS* IN BOTH DIRECTIONS.  bOTH x AND y MUST BE POSITIVE.* x IS ASSUMED TO BE 9-BITS AND y IS 8-BITS.** iNPUTS: .x=DX/2 .a=DY/2, DX AND DY ARE IN XDIVLO ETC.** rESULT IS RETURNED IN x=INTEGER PART, a=REMAINDER** rEMAINDER IS NOW A FRACTION OF 256.** dx AND dy CAN NOW BE HUGE -- THEY ARE SIMPLY SHIFTED* RIGHT UNTIL dx < 512 AND dy < 256.*divshift lsr divtemp ror divy lsr divxhi ror divxlodivxy lda divtemp ;dIV BY 2 IF DY>255 bne divshift lda divxhi cmp #2 bcs divshift ;oR IF DX>511 lsr ;cOMPUTE DX/2 lda divxlo ror tax lda divy lsr ;DY/2 beq :twostep ;iF y=1 THEN HANDLE SPECIAL tay lda log,x ;tHIS IS THE DIVISION PART sec sbc log,y bcc :neg tax lda exp,x tax  ;nOW WE HAVE INT ESTIMATE sta multlo1 sta multhi1 eor #$ff adc #00 ;cARRY IS GUARANTEED SET sta multlo2 sta multhi2 ldy divy lda (multlo1),y sec sbc (multlo2),y ;A=n*DY sta temp1 lda (multhi1),y sbc (multhi2),y sta temp2 lda divxlo ;r=DX-A sbc temp1 ;c SET sta temp1 lda divxhi sbc temp2 lda temp1 ;a=REMAINDER bcc :rneg ;iF r>0 THEN ASSUME r<255 ;(TRUE UNLESS DX>500 OR SO):rpos cmp divy ;iF r>=DY THEN bcc :done:l1 inx  ;A=A+1 sbc divy ;r=r-DY cmp divy bcs :l1:done ;nOW x CONTAINS INTEGER, a REM ;Y=DY** cOMPUTE REMAINDER AS A FRACTION OF 256, I.E.* 256*R/DY** cURRENTLY, A SMALL ERROR MAY OCCUR FOR LARGE R* (CUMULATIVE ERROR OF 1-2 PIXELS, UP TO 4 IN RARE CASES)*:fracrem stx temp1 tax beq :zero lda log,x sec sbc log,y tax lda negexp,x:zero ldx temp1 rts ;aND, IF r<0 THEN ASSUME ;r>-255:rneg dex adc divy bcc :rneg jmp :fracrem:neg ldx #00 ;sINCE LOG IS MONOTONIC, AND lda divxlo ;WE /2, THERE IS NO CHANCE ldy divy jmp :fracrem ;OF UNDERSHOOTING.:twostep lda divxhi ;iF y=1 lsr lda divxlo ;THEN JUST TWO STEPS OF SIZE ror ;DX/2 tax lda #255 rts*-------------------------------** pLOT AND LINE COMMANDS*x1 = $60y1 = $62x2 = $64y2 = $66dx = $68dy = $6anpoints = $6cpoint = $6exc = $70yc = $71bitp = $72temp = $5flinepat = $5ebits dfb $c0,$30,$0c,$03** plot -- PLOT A POINT!** oN ENTRY: POINT IN (X1,Y1), BITMAP IN bitmap*   mULTICOLOR VERSION: USES fillpat!** oN EXIT: PLOTTED POINT!*plot sta linepat lda x1+1 bne :exit ldx x1 ;cHECK RANGE cpx #160 bcs :exit ldy y1+1 bne :exit lda y1 cmp #200 bcs :exit lsr lsr lsr tay jsr setpoint ;cOMPUTE ADDRESS lda x1 and #$03 tax lda bits,x ;cHANGE IN LIB3D and (fillpat),y ora (point),y sta (point),y:exit rts** dRAWIN' A LINE.  a FAHN LAHN.** tHE SAME ROUTINES ARE USED FOR ON-SCREEN AND OFF-SCREEN* COORDINATES, BUT WHEN OFF-SCREEN, sta (bitmap),y IS* CHANGED TO bit XX.  sLOWER, BUT MUCH MORE COMPACT.** mULTICOLOR VERSION -- uSES fillpat!*lineswap ldx #3:l1 lda x1,x ;iF NOT, SWAP p1 AND p2 ldy x2,x sta x2,x tya sta x1,x dex bpl :l1 pladrawline pha lda x2 ;mAKE SURE X1<X2 sec sbc x1 sta dx lda x2+1 sbc x1+1 bmi lineswap:cont sta dx+1 pla sta linepat ldx #$c8 ;iny lda y2 ;cALCULATE DY sec sbc y1 sta dy lda y2+1 sbc y1+1 bpl :dypos ;iS Y2>=Y1? lda y1 ;oTHERWISE DY=Y1-Y2 sec sbc y2 sta dy lda y1+1 sbc y2+1 ldx #$88 ;dey:dypos sta dy+1 stx yincdec stx xincdec lda x1 sta xc ;nEXT COMPUTE COLUMN and #$03 ;bIT PATTERN tax lda bits,x sta bitp lda x1+1 lsr ror xc lsr ror xc ;x COLUMN:cont1 lda y1 ;nOW DO THE SAME FOR y sta yc lda y1+1 lsr ror yc lsr ror yc lsr ror yc ldx dy cpx dx ;wHO'S BIGGER: DY OR DX? lda dy+1 sbc dx+1 bcc stepinx ;iF DX, THEN...** y-DIRECTION STEPPING:*   Y=Y+1*   A=A-DX*   IF A<0 THEN A=A+DY:X=X+1*stepiny* ldx dy stx npoints lda dy+1 jsr linsetup lda dy ;iNIT COUNTER TO DY/2 lsr** mAIN LOOP*yloop sta temp lda (fillpat),y and bitp ora (point),y ;oTHERWISE PLOTysta sta (point),yyincdec iny ;aDVANCE y COORDINATE cpy #8 bcc :cont ;nO PROB IF y=0..7 jsr fixy:cont lda temp ;rESTORE a sec sbc dx bcs ycont adc dy lsr bitp lsr bitp bcc ycont jsr xcplus1ycont dex ;x IS COUNTER bne yloop dec npoints+1 beq yloop rts** bIG STEPS IN x DIRECTION*stepinx ldx dx lda dx+1 jsr linsetup lda dx ;iNIT COUNTER TO DX/2 lsrxloop sta temp lda (fillpat),y and bitp ora (point),y ;oTHERWISE PLOTxsta sta (point),y lda temp sec sbc dy bcs xlsr adc dxxincdec iny cpy #8 bcc xlsr sta temp jsr fixy lda tempxlsr lsr bitp lsr bitp bcc :c1 jsr xcplus1:c1 dex ;COUNTER bne xloop dec npoints+1 beq xloop rts** sET UP LINES FOR DRAWING*linsetup stx npoints sta npoints+1; jsr fixdxdy ;iF dx OR dy > 256 THEN /2 ;iF dx OR dy > 256 THEN /2:shift lda dy+1 ora dx+1 beq :c1 lsr dy+1 ror dy lsr dx+1 ror dx jmp :shift:c1 jsr setsta ldx npoints ;nUMBER OF POINTS inx ;+1 FOR ENDPOINT ldy yc; jmp setpoint** setpoint -- cOMPUTE BITMAP ADDRESS** oN ENTRY: X-COOORD IN x1*           Y-column IN .y** oN EXIT: .y -> y1 and #$07 (READY FOR PLOTTING)** bOTH X AND Y ARE ASSUMED TO BE IN RANGE!** mULTICOLOR VERSION*setpoint; ldy ycol ;cOMPUTE COLUMN lda x1 and #$fc asl php ;sAVE HIGH BIT clc adc lobrow,y ;bASE ROW sta point lda #00 adc hibrow,y plp adc bitmap sta point+1 lda y1 and #$07 tay rts** uPDATE COLUMNS*xcplus1 ;iNCREASE X-COLUMN sta temp lda #$c0 sta bitp lda point adc #7 ;cARRY IS set sta point bcc :c1 inc point+1 clc:c1 lda x1 ;x1 NEEDED TO COMPUTE adc #4 ;BITMAP ADDRESS sta x1 bcc :c2 inc x1+1:c2 inc xc bmi :lda bne :c3 ;eNTERED LEFT SIDE OF SCREEN, sty y1 ldy yc jsr setsta ;SO CALCULATE POINTERS jsr setpoint:c3 lda xc cmp #40 bcs plaexit:lda lda temp rts** sUBROUTINE TO FIX UP POINTER WHEN y DECREASES THROUGH* ZERO OR INCREASES THROUGH 7.*fixy iny ;y=255 OR y=8 beq :decptr:incptr inc yc bmi :ldy0 bne :c1 jsr setsta ;jUST ENTERED SCREEN:c1 ldy yc cpy #25 bcs plaexit ;sEE-YA! jsr setpoint:ldy0 ldy #00 rts:decptr dec yc bmi plaexit ldy yc cpy #24 ;JUST ENTERED SCREEN bne :bcs jsr setsta clc:bcs bcs :ldy jsr setpoint:ldy ldy #7 rtsplaexit pla ;rEMOVE OLD RETURN ADDRESS pla rts** iF POINT IS ON-SCREEN, THEN sta TO BITMAP.* oTHERWISE, bit*setsta lda xc cmp #40 ;POS AND NEG bcs :bit lda yc cmp #25 bcs :bit lda #$91 ;sta (),y dfb $2c:bit lda #$24 ;bit ZP sta ysta sta xsta rts
