; ****** MOVE & LINE DRAWING ***************************************** ; ; MOVE TO A NEW POINT WITHOUT DRAWING .proc move,2 ; move(x,y :integer) ; RETRN2 .EQU 8 .REF READY pop RETRN2 JSR READY PLA STA YLSB ; WRITE TO VGP PLA ; GET LSB OF POINT STA YMSB ; WRITE TO VGP PLA STA XLSB ; WRITE TO VGP PLA ; GET LSB OF POINT STA XMSB ; WRITE TO VGP push RETRN2 RTS ; DONE IT ; ; MOVE TO A NEW POINT THEN DRAW A SINGLE DOT .proc dot,2 ; .REF move,WCMD pop RETURN JSR move push RETURN LDA #88 JMP WCMD ; ; SELECT LINE TYPE .proc linetype,1 ; parameter 0:solid,1:dots,2:dashes,3:dots & dashes ; .REF READY pop RETURN PLA AND #3 ; 0-3 ONLY ALLOWED STA TEMP1 ; SAVE PLA push RETURN JSR READY LDA CTRL2 ; GET REGISTER AND #0FC ; MASK REGISTER ORA TEMP1 ; AND PUT IN LINE TYPE STA CTRL2 ; AND WRITE BACK RTS ; DONE IT ; ; ROUTINE TO DRAW A LINE BETWEEN ANY TWO POINTS .proc draw,4 ; draw(fromx,fromy,tox,toy :integer); ; .REF MOVE,LINE2 pop RETURN pop YTLSB pop XTLSB JSR MOVE ; SET UP START COORDS JMP LINE2 ; ; ROUTINE TO DRAW A LINE FROM PRESENT POSITION TO SPECIFIED POINT .proc line,2 ; line(tox,toy :integer); ; .REF READY,WCMD,SAVCRD .DEF LINE2,DSMATH pop RETURN pop YTLSB ; AND SAVE pop XTLSB ; AND SAVE LINE2: push RETURN PLOTC: JSR DSMATH ; CALCULATE DISPLACEMENTS TXA ORA DXTMSB ; IS EITHER PROJECTION > 255 BEQ PLAST ; NO, DO LAST PART OF LINE DB2LP: CLC ; DIVIDE DISPLACEMENT BY 2 UNTIL BOTH < 256 ROR DXTMSB ROR DXTLSB CLC ROR DYTMSB ROR DYTLSB LDA DXTMSB ORA DYTMSB ; BOTH < 256 ? BNE DB2LP ; IF NOT DIVIDE AGAIN ; JSR PLAST ; PLOT PART LINE LDA #88 ; FUDGE FOR INVERSE MODE JSR WCMD JMP PLOTC ; THEN DO REST OF LINE ; PLAST: LDA DXTLSB ; GET X PROJECTION STA DELTAX ; WRITE TO VGP LDA DYTLSB ; GET Y PROJECTION STA DELTAY ; WRITE TO VGP LDA ACMDT ; GET COMMAND JMP WCMD ; DRAW THE LINE ; DSMATH: JSR READY ; CALCULATE DISPLACEMENTS JSR SAVCRD ; GET SCREEN POSITION CLD ; NOT DECIMAL MODE SEC ; SET READY FOR SUBTRACT LDA XTLSB ; GET FIRST X SBC TXL ; TAKE FROM POSITION REG TAY ; AND SAVE AS DISPLACEMENT LDA XTMSB ; GET SECOND X SBC TXM ; TAKE FROM POSITION REG JSR CKSIGN ; SAVE AS DISPLACEMENT STA ACMDT ; SAVE FOR CMD GENERATION STY DXTLSB ; SAVE X DISPLACEMENT STX DXTMSB SEC ; SET READY FOR SUBTRACT LDA YTLSB ; GET FIRST Y SBC TYL ; TAKE FROM POSITION REG TAY ; AND SAVE AS DISPLACEMENT LDA YTMSB ; GET SECOND Y SBC TYM ; TAKE FROM POSITION REG JSR CKSIGN ; SAVE AS DISPLACEMENT ASL A ;SHIFT FOR Y COMPONENT OF COMMAND ORA ACMDT ; ADD IN X COMPONENT ORA #11 ; ADD IN BASE COMMAND STA ACMDT ; SAVE COMMAND FOR LATER STY DYTLSB ; SAVE Y DISPLACEMENT STX DYTMSB RTS ; ; CKSIGN - UTILITY FOR PLOT CKSIGN: BPL RET0 ; WORKS OUT CORRECT DISPLACEMENT VALUES EOR #0FF ; IF MINUS, MAKE POSITIVE AND #0F ; LIMIT TO 12 BITS TAX TYA EOR #0FF TAY INY BNE RET2 INX RET2: LDA #2 ; RETURN 2 IF NEGATIVE DISPLACEMENT RTS RET0: AND #0F TAX LDA #0 RTS ; ; DRAW CROSS HAIR CURSOR AT THE CURRENT POSITION .proc cursor,1 ; cursor(size :integer); ; .REF READY,SAVVGP,COLOR,COLCOP,C4COPY .REF RESCRD,RESVGP,RESCOL .DEF SETRMW pop RETURN JSR READY PLA ; PICK UP SIZE STA DELTAX ; TELL VGP STA DELTAY ; IN BOTH PROJECTIONS PLA ; IGNORE MSB push RETURN JSR SAVVGP ; SAVE SCREEN POSITION,CTRL1,CTRL2,CSIZE JSR SETRMW ; SET INVERT COLOUR LDA #00 ; READY TO CLEAR STA CTRL2 ; PRESET MODE FOR CURSOR LDA #03 ; PEN DOWN AND PEN STA CTRL1 ; AND SET IT LDY #3 ; SET COMMAND COUNTER ; CURLOP LDA CMDTBL,Y STA CMD ; GET COMMAND AND WRITE JSR READY ; WAIT TILL DONE JSR RESCRD ; AND RESTORE CENTRE DEY ; POINT TO NEXT BPL CURLOP ; PROCESS THE REST UNTIL ALL COMMANDS SENT JSR RESCOL ; RESTORE COLOUR REGISTERS JMP RESVGP ; & RESTORE VGP STATUS ; ; TABLE OF COMMANDS FOR CURSOR ; CMDTBL .BYTE 12,14,10,16 ; SETRMW: LDA C4COPY ; SET INVERT WRITE MODE AND #18 ORA #4 STA CTRL4 BIT COLOR BPL XSET LDA COLCOP AND #88 ORA #44 STA COLREG XSET: RTS ; ; CIRCLE PLOT ROUTINES ; USING BRESENHAM'S CIRCLE ALGORITHM ; POSITION SET BEFORE CALL IS USED AS THE CENTRE POINT ; POSITION RESET TO CENTRE POINT AFTER CALL ; .proc circle,1 ; circle (radius :integer); .REF CIRDO LDA #0 ; SET OUTLINE MODE JMP CIRDO ; DO CIRCLE ; .proc filled_circle,1 ; filled_circle (radius :integer); CSTAT .EQU 5 .DEF CIRDO .REF WCMD,PLOTB,READY,RESCRD,SAVCRD,SVXCRD LDA #1 ; SET FILLED MODE CIRDO: STA CSTAT ; SAVE OUTLINE/FILL STATUS JSR READY JSR SAVCRD ; GET PRESENT POSITION INTO TXL,TYL LDX #3 ; SAVE CENTRE POINT INTO XC,YC CINLP: LDA TXL,X ; GET PRESENT POSITION STA XCLSB,X DEX BPL CINLP pop RETURN pop DYCLSB ; PICK UP RADIUS push RETURN LDA DYCMSB AND #7F ; RADIUS MUST BE POSITIVE STA DYCMSB ORA DYCLSB BNE RADOK RTS ; RETURN IF RADIUS = 0 RADOK: CLD LDA #0 ; INITIALISE ERROR TERM STA DXCLSB ; TO 3-2*RADIUS STA DXCMSB JSR TSAVE ; COPY INITIAL DXC,DYC INTO TXC,TYC JSR XSUBY ; SUBTRACT RADIUS FROM 0 JSR M2ADD3 ; MULTIPLY BY 2 THEN ADD 3 STY DLSB STX DMSB ; AND STORE ERROR TERM ARCLP: JSR XSUBY ; LOOP WHILE DXC < DYC BCS ARCEND JSR POINTS ; PLOT 8 POINTS AROUND CIRCLE LDA DMSB BMI DLT0 ; IF ERROR < 0 THEN DONT USE RADIUS TERM LDA DYCLSB ; DECREMENT RADIUS TERM BNE RADDEC DEC DYCMSB RADDEC: DEC DYCLSB JSR XSUBY JMP ARC2 DLT0: LDY DXCLSB ; USE DXC TERM ONLY LDX DXCMSB ARC2: JSR M2ADD3 ; MULTIPLY BY 2 THEN ADD 3 TYA ; MULTIPLY BY 2 ASL A TAY TXA ROL A TAX TYA ; ADD ERROR TERM TO OLD ERROR CLC ADC DLSB STA DLSB TXA ADC DMSB STA DMSB INC DXCLSB ; INCREMENT DXC TERM BNE ARCLP INC DXCMSB BNE ARCLP ARCEND: LDA CSTAT BEQ OUTEND TYA BNE LASTDO TXA BNE LASTDO ; IF X <> Y THEN ALWAYS PLOT LAST MINOR LINES LDA TYCLSB ; IF NEW X = OLD Y CMP DXCLSB BNE LASTDO LDA TYCMSB CMP DXCMSB BEQ LMAJOR ; THEN DONT PLOT MINOR LASTDO: JSR PMINOR ; PLOT SAVED LINES IF FILLED MODE JSR XSUBY ; SET UP XY AGAIN OUTEND: TYA ; IF DXC TERM = RADIUS TERM BNE RESXC ; THEN PLOT ONE MORE SET OF POINTS TXA BNE RESXC LMAJOR: JSR POINTS ; RESXC: LDX #3 ; SET POSITION TO XC,YC ENDCLP: LDA XCLSB,X STA TXL,X DEX BPL ENDCLP JSR READY JMP RESCRD ; ; POINTS - PLOTS POINTS OR LINES OF CIRCLE ; XC,YC HOLD CENTRE POINT OF CIRCLE ; DXC,DYC HOLD POSITION IN 1ST OCTANT OF POINT TO ; BE PLOTTED RELATIVE TO CENTRE ; NORMALLY PLOTS EIGHT POINTS (4 LINES) OF CIRCLE ; IF DXC=0 OR DXC=DYC THEN PLOTS FOUR ; POINTS (2 LINES) SINCE THE OTHERS ARE THE SAME ; POINTS: LDA CSTAT ; STATUS ? BEQ DPOINT ; IF OUTLINE THEN PLOT POINTS JSR XSUBY TYA BNE FNEQ ; IF DXC=DYC THEN PLOT MAJOR LINES ONLY TXA BEQ FDO2 FNEQ: LDA TYCLSB ; SAME Y VALUE ? CMP DYCLSB BNE FDO4 LDA TYCMSB CMP DYCMSB BEQ FSAVE ; IF SAME THEN JUST SAVE FOR NEXT TIME FDO4: JSR PMINOR ; PLOT MINOR LINES FSAVE: JSR TSAVE ; TX,TY = DX,DY LDA DXCLSB ; IS X = 0 ? ORA DXCMSB BEQ FDO1 ; IF SO, PLOT DIAMETER FDO2: JSR CYPX JSR PMAJOR ; PLOT CX+Y,CY+X TO CX-Y,CY+X FDO1: JSR CYMX ; PLOT CX+Y,CY-X TO CX-Y,CY-X PMAJOR: JSR CXMY JSR SVXCRD JSR CXPY JMP PLOTB ; DPOINT: LDA DXCLSB ORA DXCMSB BEQ POINT4 ; IF DXC=0 THEN PLOT 4 JSR XSUBY ; DXC-DYC TYA BNE POINT8 TXA BEQ POINT4 ; IF DXC=DYC THEN PLOT 4 ; POINT8: JSR CXPX JSR CYPY ; PLOT CX+DXC,CY+DYC JSR CPOINT JSR CXMY JSR CYPX ; PLOT CX-DYC,CY+DXC JSR CPOINT JSR CXMX JSR CYMY ; PLOT CX-DXC,CY-DYC JSR CPOINT JSR CXPY JSR CYMX ; PLOT CX+DYC,CY-DXC JSR CPOINT ; POINT4: JSR CXPY JSR CYPX ; PLOT CX+DYC,CY+DXC JSR CPOINT JSR CXMX JSR CYPY ; PLOT CX+DXC,CY+DYC JSR CPOINT JSR CXMY JSR CYMX ; PLOT CX-DYC,CY-DXC JSR CPOINT JSR CXPX JSR CYMY ; PLOT CX+DXC,CY-DYC ; CPOINT: LDA #88 JMP WCMD ; PLOT THE POINT ; TSAVE: LDX #3 ; COPY DXC,DYC TO TXC,TYC TSLP: LDA DXCLSB,X STA TXCLSB,X DEX BPL TSLP RTS ; ; PMINOR: JSR SWAP ; SWAP DXC,DYC FOR TXC,TYC JSR CYPY JSR PMIN ; PLOT CX-X,CY+Y TO CX+X,CY+Y JSR CYMY JSR PMIN ; PLOT CX-X,CY-Y TO CX+X,CY-Y ; SWAP: LDX #3 ; SWAP NEW XY FOR OLDVALUE IN TXC,TYC SWAPLP: LDA DXCLSB,X TAY LDA TXCLSB,X STA DXCLSB,X TYA STA TXCLSB,X DEX BPL SWAPLP RTS ; PMIN: JSR CXMX ; PLOT MINOR LINES JSR SVXCRD JSR CXPX JMP PLOTB ; ; CX.. ROUTINES SET X CO-ORD INTO THE VGP ; RETURNS PLUS IF X CO-ORD IS OK ; CXPX: LDA XCLSB ; X CO-ORD OF CENTRE CLC ADC DXCLSB ; PLUS X VALUE OF POINT TAY LDA XCMSB ADC DXCMSB JMP CXEND ; CXMX: LDA XCLSB ; X CO-ORD OF CENTRE SEC SBC DXCLSB ; MINUS X VALUE OF POINT TAY LDA XCMSB SBC DXCMSB JMP CXEND ; CXPY: LDA XCLSB ; X CO-ORD OF CENTRE CLC ADC DYCLSB ; PLUS Y VALUE OF POINT TAY LDA XCMSB ADC DYCMSB JMP CXEND ; CXMY: LDA XCLSB ; X CO-ORD OF CENTRE SEC SBC DYCLSB ; MINUS Y VALUE OF POINT TAY LDA XCMSB SBC DYCMSB CXEND: TAX JSR READY ; WAIT FOR VGP READY STY XLSB ; SET X CO-ORDS IN VGP STX XMSB RTS ; ; CY.. ROUTINES SET Y CO-ORD INTO VGP ; CYPX: LDA YCLSB ; Y CO-ORD OF CENTRE CLC ADC DXCLSB ; PLUS X VALUE OF POINT TAY LDA YCMSB ADC DXCMSB JMP CYEND ; CYMX: LDA YCLSB ; Y CO-ORD OF CENTRE SEC SBC DXCLSB ; MINUS X VALUE OF POINT TAY LDA YCMSB SBC DXCMSB JMP CYEND ; CYPY: LDA YCLSB ; Y CO-ORD OF CENTRE CLC ADC DYCLSB ; PLUS Y VALUE OF POINT TAY LDA YCMSB ADC DYCMSB JMP CYEND ; CYMY: LDA YCLSB ; Y CO-ORD OF CENTRE SEC SBC DYCLSB ; MINUS Y VALUE OF POINT TAY LDA YCMSB SBC DYCMSB ; CYEND: TAX JSR READY STX YMSB STY YLSB ; STORE Y CO-ORD IN VGP RTS ; XSUBY: LDA DXCLSB ; XY = DXC-DYC SEC SBC DYCLSB TAY LDA DXCMSB SBC DYCMSB TAX RTS ; M2ADD3: TYA ; XY = XY + XY + 3 ASL A TAY TXA ROL A TAX TYA CLC ADC #3 TAY BCC NCY INX NCY: RTS