PAGE SBTL 'APPLESOFT VGP][ (C) DIGISOLVE LTD 1984' ; PROGRAMMED BY N.K.WRIGHT ; AND ALAN COAKER ; DATE 9/MARCH/84 ; 8 COLOUR OR MONOCHROME SUPPORT FOR VGP][. ORG $8700+38 ;38 BYTES FOR FILENAME ; SLOT EQU 2 ; CHANGE THIS FOR DIFFERENT SLOTS BASE EQU SLOT*16+$C080 ; CALCULATE VGP ADDRESS FROM SOLT BASE1 EQU SLOT*256+$C000 ; AND SPECIAL REGISTERS NOT IN VGP BASE2 EQU BASE+16 ; FOR COLOUR EXPANDER CARD ; STATUS EQU BASE ; VGP REGISTERS CMD EQU BASE ; CMD IS WRITE ONLY CTRL1 EQU BASE+1 ; REST OF THE REGISTERS CTRL2 EQU BASE+2 ; CONTROL 2 REG CSIZE EQU BASE+3 ; CHARACTER SIZE DELTAX EQU BASE+5 ; X PROJECTION DELTAY EQU BASE+7 ; Y PROJECTION XMSB EQU BASE+8 ; X POSITION MSB XLSB EQU BASE+9 ; X POSITION LSB YMSB EQU BASE+10 ; Y POSITION MSB YLSB EQU BASE+11 ; Y POSITION LSB ; CTRL3 EQU BASE1 ; VGP][ FORMAT CTRL4 EQU BASE1+1 ; WRITE MODE - RED SCROLL EQU BASE1+2 ; SCROLL POSITION REGISTER PAN EQU BASE1+3 ; PAN POSITION COLRR EQU BASE1+4 ; READ RED ; COLRB EQU BASE2 ; READ BLUE COLRG EQU BASE2+1 ; READ GREEN COLREG EQU BASE2+2 ; WRITE MODE - BLUE/GREEN ; ; NOW FOR THE EQUATES TO THE APPLE ; DOSLSB EQU $9D00 ; DOS BUFFER POINTER DOSMSB EQU $9D01 VECTRM EQU $03F7 ; MOST SIGNIFICANT VECTOR ADDRESS VECTRL EQU $03F6 ; LEAST SIGNIFICANT VECTOR ADDRESS REENTR EQU $03D3 ; WHERE TO JUMP TO CONTINE OPERATION GETNUM EQU $E105 ; GET A NUMBER ROUTINE IN APPLE GETCOM EQU $DEBE ; GET TO NEXT COMMA IN APPLESOFT GETINT EQU $DFE3 ; GET ADDRESS OF INTEGER VARIABLE IN APPLESOFT GETSTR EQU $DD7B ; GET NEXT VALID STRING SETSTR EQU $E5FD ; SET UP POINTERS FROM STRING SYNERR EQU $DEC9 ; SYNATX ERROR ROUTINE IN APPLESOFT CHRGET EQU $00B1 ; APPLES CHARACTER GET ROUTINE CHRGOT EQU $00B7 ; RESTORE PREVIOUS GOT CHARACTER GETBYT EQU $E6F8 ; GET NUMBER AS BYTE ; ; APPLESOFT VARIABLE ROUTINES USED BY AS. ; VALLSB EQU $A1 ; VARIABLE GET RETURN REGISTER LSB VALMSB EQU $A0 ; VARIABLE GET RETURN REGISTER MSB STRCHK EQU $11 ; STRING STATUS TEMP1 EQU $55 ; TEMP STORE IN ZERO PAGE TEMP2 EQU $56 ; SOME MORE CMDLEN EQU $2D ; NUMBER OF COMMANDS IN TABLE STKSIZ EQU $FF ; 255 LEVELS OF DATA STACK INTPNT EQU $83 ; POINTER TO INTEGER TOKTO EQU $C1 ; TOKENISED TO VERB ; ; START - EXECUTED WHEN THIS PROGRAM IS 'BRUN' ; ONCE ONLY CODE TRANSFERS THE VGP][ SUPPORT ; PROGRAM TO THE TOP OF MEMORY AND SETS THE ; DOS BUFFERS BELOW THE PROGRAM. ; THE VGP][ IS INITIALISED INTO US FORMAT INTERLACED ; START: LDY #0 ; 1ST MOVE PROGRAM STY TEMP1 ; SET UP POINTERS LDA #$67 ; SOURCE STA TEMP2 STY VALMSB LDA #$8E ; DESTINATION STA VALLSB STY DOSLSB ; SET UP NEW DOS POINTER LDA #$88 STA DOSMSB MVLP: LDA (TEMP1),Y ; MOVE STA (VALMSB),Y INY BNE MVLP INC TEMP2 ; INCREMENT POINTERS INC VALLSB ; CHECK STORE PTR LDA VALLSB CMP #$9D ; WITH TOP OF USABLE MEMORY BNE MVLP ; LDA JUMPL ; SET AMPERSAND HANDLER ADDRESS STA VECTRL LDA JUMPM STA VECTRM ; SET UP MSB APPLE VECTOR JSR NEW ; THEN INITIALISE VGP JMP REENTR ; AND GO TO APPLESOFT ; DS START+$100-* ; ; TEMP STORAGE IN LOCAL RAM ; XTLSB DS 1 ; TEMP X COORD LSB XTMSB DS 1 ; TEMP X COORD MSB YTLSB DS 1 ; TEMP Y COORD LSB YTMSB DS 1 ; TEMP Y COORD MSB DXTLSB DS 1 ; TEMP DELTAX LSB DXTMSB DS 1 ; TEMP DELATX MSB DYTLSB DS 1 ; TEMP DELATY LSB DYTMSB DS 1 ; TEMP DELATY MSB ACMDT DS 1 ; CONSOLIDATED COMMAND TEMP XSIZE DS 1 ; CROSSHAIR CURSOR SIZE TXL DS 1 TXM DS 1 ; FOUR BYTES FOR TYL DS 1 ; STORAGE OF SCREEN POSITION TYM DS 1 DLSB: DS 1 ; CIRCLE TEMP STORE DMSB: DS 1 ; ERROR TERM XCLSB: DS 1 ; CENTRE PT X XCMSB: DS 1 YCLSB: DS 1 ; CENTRE PT Y YCMSB: DS 1 DXCLSB: DS 1 ; TEMP X DXCMSB: DS 1 DYCLSB: DS 1 ; TEMP Y DYCMSB: DS 1 TXCLSB: DS 1 ; SAVE X TXCMSB: DS 1 TYCLSB: DS 1 ; SAVE Y TYCMSB: DS 1 CSTAT: DS 1 ; CIRCLE STATUS , NZ=FILLED ; FMODE: DS 1 ; CAFILL MODE, BIT 2 SET IF BIT MAP FILL FCOLOR: DS 1 ; CAFILL BOUNDARY COLOUR BSTAT: DS 1 ; BOUNDARY STATUS ; PXNLSB: DS 1 ; PREVIOUS LINE LEFT X PT. PXNMSB: DS 1 PXPLSB: DS 1 ; PREVIOUS LINE RIGHT X PT PXPMSB: DS 1 ; STACKO: DS 1 ; SAVE FOR STACKC STACKC: DS 1 ; AREA FILL STACK COUNTER STXLSB: DS 255 ; AREA FILL STACK STXMSB: DS 255 STYLSB: DS 255 STYMSB: DS 255 SOXLSB: DS 255 SOXMSB: DS 255 ; C3COPY DFB 0 ; CTRL3 REGISTER COPY C4COPY DS 1 ; CTRL4 CYCOPY DS 1 ; PAN VALUE COPY CXCOPY DS 1 ; SCROLL VALUE COPY COLCOP DS 1 ; COLREG COPY COLOUR DFB 0 ; MONO/COLOUR SAVE JUMPL DW ENTER ; VECTOR JUMP LSB JUMPM EQU *-1 ; VECTOR JUMP MSB BITDL: DS 1 ; DATA ADDRESS FOR BITMAP BITDM: DS 1 BITX: DS 1 ; BITMAP XSIZE BITY: DS 1 ; BITMAP YSIZE BITM: DFB 0 ; BITMAP MODE ; ; THE FOLLOWING TWO TABLES ARE ; FIRSTLY THE TOKEN TABLE USED TO INTERPRET THE EXTRA COMMANDS ; AS FOUND IN THE TOKENISED INPUT LINE ; AND THE THE CORRESPONDING JUMP TABLE WHICH VECTORS TO THE ; SPECIFIC ROUTINES THAT HANDLE THE COMMANDS ASSOCIATED WITH EACH TOKEN. ; MSB OFF ; CHARACTERS ARE NORMAL TOKTBL DFB 'D' ; LOWER PEN DFB 'U' ; RAISE PEN DFB 'O' ; SELECT CLIPING MODE DFB 'P' ; SELECT PEN DFB 'E' ; SELECT ERASER DFB 151 ; 'HOME' TOKEN DFB 'C' ; SELECT CYCLIC MODE DFB 189 ; 'CLEAR' TOKEN DFB 159 ; 'FLASH' TOKEN DFB 148 ; 'DRAW' TOKEN DFB 137 ; 'TEXT' TOKEN DFB 186 ; 'PRINT' OR '?' TOKEN DFB 141 ; 'PLOT' TOKEN DFB 135 ; 'READ' TOKEN DFB 197 ; 'AT' TOKEN DFB 'M' ; MOVE DFB 168 ; 'STORE' TOKEN DFB 217 ; 'POS' TOKEN DFB 'I' ; INVERT SCREEN DFB 145 ; 'HGR' TOKEN DFB 144 ; 'HGR2' TOKEN DFB 'W' ; ADDITIVE COLOUR DFB 'R' ; INVERT COLOUR DFB 'N' ; ABSOLUTE COLOUR DFB 230 ; 'ASC' A SPECIAL COLOUR DFB 158 ; 'INVERSE' TOKEN DFB 157 ; 'NORMAL' TOKEN DFB 'S' ; CIRCLE DFB 'F' ; FILLED CIRCLE DFB '.' ; PLOT POINT DFB 184 ; 'DEF' TOKEN DFB 'B' ; BIT MAP DFB 'L' ; COMPLEX AREA FILL DFB 'A' ; APPLE VIDEO DFB 'V' ; VGP VIDEO DFB 180 ; 'ON' NON-INTERLACED SUBPAGE DFB 211 ; 'INT' SET INTERLACED / NON DFB 129 ; 'FOR' SET DISPLAY FORMAT DFB 206 ; 'OR' SET BORDER COLOUR DFB 'X' ; SET PAN REGISTER DFB 'Y' ; SET SCROLL REGISTER DFB 200 ; '+' SCROLL UP DFB 201 ; '-' SCROLL DOWN DFB 207 ; '>' PAN RIGHT DFB 209 ; '<' PAN LEFT DFB 191 ; 'NEW' INITIALISE VGP ; ; THE VECTOR TABLE FOR JUMPS TO ; THE ROUTINES TO HANDLE THE ; ABOVE TOKENS NOW FOLLOWS ; JUMPTB DW DOWN ; PEN DOWN JUMPTA EQU *-1 ; FOR SECOND BYTE LOAD DW UP ; RAISE PEN DW CLIP ; SELECT CLIPING MODE DW PEN ; SELECT PEN DW ERASER ; SELECT ERASER DW HOME ; CLEAR AND RESET POSITION DW CYCLIC ; SELECT CYCLIC MODE DW CLEAR ; CLEAR CURRENT SCREEN DW FLASH ; FILL THE SCREEN DW DRAW ; SELECT LINE TYPE DW TEXT ; SELECT TEXT TYPE DW PRINT ; DO CHARACTERS DW PLOT ; DRAW LINES DW READ ; READ THE SCREEN POSITION DW AT ; TEST THE CURRENT POINT DW MOVE ; MOVE TO NEW POINT DW STORE ; SET CURSOR SIZE DW POS ; DRAW CURSOR DW INVERT ; INVERT THE SCREEN DW HGR ; SELECT PAGE 1 DW HGR2 ; SELECT SECOND PAGE DW WPRCNT ; ADDITIVE COLOUR DW INVCNT ; INVERT COLOUR DW DATCNT ; ABSOLUTE COLOUR DW ASC ; A SPECIAL COLOUR DW INVERSE ; SELECT INVERSE MODE DW NORMAL ; SELECT NORMAL MODE DW CIRCLE ; DRAW CIRCLE OUTLINE DW FILLED ; DRAW FILLED CIRCLE DW POINT ; PLOT POINT AT PRESENT POSITION DW BITDEF ; DEFINE BITMAP PARAMETERS DW BITMAP ; DRAW BIT MAP DW CAFILL ; COMPLEX AREA FILL DW APPLEV ; APPLE VIDEO DW VGPV ; VGP VIDEO DW SUBPAG ; SUBPAGE FOR NON-INTERLACED DW INTERL ; SET INTERLACED DW FORMAT ; SET SCREEN FORMAT DW BORDER ; SET BORDER COLOUR DW PANSET ; 'X' SET PAN REGISTER DW SCRSET ; 'Y' SET SCROLL REGISTER DW SCRLUP ; SCROLL UP DW SCRLDN ; SCROLL DOWN DW PANRIT ; PAN RIGHT DW PANLFT ; PAN LEFT DW NEW ; INITIALISE VGP ; ; AMPERSAND HANDLER ROUTINE, ; BASIC ENTERS HERE WHEN THE ; AMPERSAND IS DETECTED FOR ; SPECIAL PROCESSING ; ENTER LDX #CMDLEN ; GET NUMBER OF COMMANDS SEARCH CMP TOKTBL,X ; LOOK IN TABLE BEQ GOTTOK ; FOUND IT DEX ; MOVE TO NEXT BPL SEARCH ; CONTINUE TO LOOK JMP SYNERR ; NO TOKEN FOUND, ERROR ; ; GOTTOK TXA ; DOUBLE OFFSET ASL A ; SHIFT TIMES TWO TAX ; AND MAKE INDEX AGAIN LDA JUMPTA,X ; GET LSB ADDRESS STA JUMPM ; SAVE LDA JUMPTB,X ; GET MSB ADDRESS STA JUMPL ; SAVE JSR READY ; CAN WE DO IT JSR CHRGET ; THROW AWAY SPACES ETC JMP (JUMPL) ; AND DO ROUTINE ; ; ; BIT MAP DEFINE AND DRAW ROUTINES ; TO DEFINE BIT MAP ; CALL FROM BASIC BY: ; &DEF MEM,XSIZE,YSIZE,MODE ; WHERE MEM IS 16 BIT ADDRESS OF START OF BIT MAP ; XSIZE,YSIZE ARE 8 BIT VALUES OF THE SIZE OF THE BIT MAP ; MODE IS EVEN FOR BIT MAP, ODD FOR BYTE MAP ; ; BIT MAP CONTENTS: ; ONE POINT IS DRAWN PER BIT IN THE DATA STRING ; L.S. BIT IS PLOTTED TO THE LEFT ; L.S. BYTE IS TO THE LEFT ; IF BIT IS ON THEN POINT IS DRAWN ; EACH LINE STARTS WITH NEW BYTE OF DATA ; ; BYTE MAP CONTENTS: ; ONE BYTE PER POINT TO BE DISPLAYED ; 2 M.S.BITS SPECIFY OPERATION ; 00 - DONT PLOT POINT ; 01 - SET WRITR TO 6 L.S.BITS THEN PLOT POINT ; 10 - SET INVER THEN PLOT POINT ; 11 - SET DATAR THEN PLOT POINT ; LOWEST ADDRESS OF BIT MAP IS WRITTEN TO THE ; PRESENT POSITION. SUCCESSIVE BYTES ARE PLOTTED ; IN THE X DIRECTION. ; BITDEF: JSR GETNUM ; GET DATA ADDRESS LDA VALLSB STA BITDL LDA VALMSB STA BITDM JSR GETCOM JSR GETNUM ; GET X SIZE LDA VALLSB STA BITX BEQ BITS0 ; INVALID SIZE JSR GETCOM JSR GETNUM ; GET Y SIZE LDA VALLSB BEQ BITS0 STA BITY JSR GETCOM JSR GETNUM ; GET MODE LDA VALLSB STA BITM BITS0: RTS ; ; BIT MAP DRAW ; WRITES BIT MAP TO PRESENT POSITION ; POSITION IS RESTORED ON RETURN TO BASIC ; OUTPUT TO SCREEN IS CLIPPED TO X MARGIN OF SCREEN BITMAP: LDA BITX ; CHECK XSIZE BEQ BITRTS ; RETURN IF 0 LDA BITY BEQ BITRTS STA VALLSB ; TEMP STORE FOR YSIZE LDA BITDL ; TRANSFER DATA POINTER TO 0 PAGE STA TEMP2 LDA BITDM STA TEMP2+1 JSR STACK1 ; GET VGP POSITION ONTO "STACK" LDA BITM ; CHECK MODE ROR A BCC BITVLP ; PLOT BITS ; BYTVLP: LDX BITX ; LOAD XSIZE STX VALMSB ; TEMP SAVE JSR BYTDRW ; DO ONE LINES WORTH DEC VALLSB BEQ BITRSY ; EXIT IF NO MORE LINES JSR NEWLIN JMP BYTVLP ; BITVLP: LDA BITX STA VALMSB ; TEMP SAVE LDA #0 STA TEMP1 ; RESET PLOT FLAG JSR BITDRW ; DO ONE LINES WORTH JSR BTPLOT ; FINISH OFF PLOT DEC VALLSB BEQ BITRSY JSR NEWLIN JMP BITVLP ; BITRSY: JSR DSTACK ; RESTORE POSITION CAFRSY: LDA BITM ; BYTE MODE ? ROR A BCC BITRTS RESCOL: JSR READY LDA C4COPY STA CTRL4 ; RESTORE MONO COLOUR BIT COLOUR BPL BITRTS LDA COLCOP ; IF COLOUR THEN STA COLREG ; RESTORE BLUE & GREEN BITRTS: RTS ; BTPLOT: BIT TEMP1 ; IS PLOT FLAG SET ? BPL BTPLNO JSR XDEC JSR PLOTB ; PLOT TO POSITION - 1 JSR XINC BTPLNO: RTS ; NEWLIN: JSR READY ; RESET X, INC Y LDA STXLSB ; GET X OFF STACK STA XLSB LDA STXMSB STA XMSB INC YLSB ; INCREMENT Y BNE YRTS1 INC YMSB YRTS1: RTS ; GTDATA: LDY #0 ; GET DATA BYTE LDA (TEMP2),Y INC TEMP2 BNE INCD INC TEMP2+1 ; INCREMENT DATA POINTER INCD: RTS ; BYTDRW: LDA VALMSB ; BYTE MODE: DRAW ONE LINES WORTH BEQ BYTHND ; RETURN IF NO. OF POINTS = 0 JSR GTDATA ; GET DATA BYTE CMP #$40 ; DO NOTHING ? BCC JINC ; IF YES, JUST INC VGP ADDRESS ; STA TEMP1 ; SAVE FOR ROTATE ROL A ROL A ROL A ; TRANSFER MODE BITS AND #3 ; AND MASK TAY ; TO PRODUCE OFFSET DEY ; INTO MODE TABLE JSR PUTCOL ; SET COLOUR MODE JSR POINT ; PLOT THE POINT JSR READY ; WAIT FOR COMPLETION ; JINC: JSR XINC ; INC X POSITION DEC VALMSB ; DEC NO. OF POINTS BNE BYTDRW ; LOOP X BYTHND: RTS ; BITDRW: LDA VALMSB ; PLOT WHILE VALMSB <> 0 BEQ BYTHND TAX LDY #0 STY VALMSB ; FOR BORROW CONDITION SEC SBC #8 ; AT LEAST 8 POINTS LEFT ? BCC BITLT8 ; IF NOT THEN JUST DO NO. IN X STA VALMSB ; PUT BACK FOR NEXT TIME LDX #8 BITLT8: JSR GTDATA ; GET DATA BYTE BITDLP: ROR A ; ROTATE DATA FROM LS BITR INTO CARRY PHA ; SAVE ROTATION TXA PHA ; SAVE X BIT TEMP1 ; IS PLOT FLAG ON ? BMI BPLTON BCC BITMVX JSR SVXCRD ; 1ST POINT OF PLOT, SAVE IN TX DEC TEMP1 ; SET PLOT FLAG BMI BITMVX ; ALWAYS BRANCH ; BPLTON: BCS BITMVX JSR BTPLOT ; PLOT BIT LINE INC TEMP1 ; RESET PLOT FLAG ; BITMVX: JSR XINC ; MOVE TO NEXT POINT PLA TAX PLA DEX ; LOOP UNTIL BIT COUNT = 0 BNE BITDLP BEQ BITDRW ; BRANCH ALWAYS ; ; ; COMPLEX AREA FILL ; CALL FROM BASIC BY: ; &L 0 ; MODE 0: FILL WHILE SCREEN COLOUR = INITIAL POINT COLOUR ; ; &L MODE,COLOUR ; MODE 1: FILL WHILE SCREEN COLOUR .NOR. COLOUR = 0 ; MODE 2: FILL WHILE SCREEN COLOUR = COLOUR ; MODE 3: FILL WHILE SCREEN COLOUR <> COLOUR ; COLOUR IS A NUMBER FROM 0 TO 7 ; TO FILL WITH DEFINED BITMAP, ADD 4 TO MODE ; RETURNS WITH POSITION SET TO POSITION ON ENTRY ; CAFILL: JSR GETNUM ; PICK UP MODE PARAMETER LDA VALLSB STA FMODE ; SAVE FOR BIT MAP TEST AND #3 ; MASK OFF UNWANTED ASL A ; SET JUMP ADDRESS FOR TESTP TAX LDA CAFTAB,X ; LSB STA JUMPL LDA CAFTAB+1,X ; MSB STA JUMPM TXA ; MODE 0 ? BEQ INTCOL JSR GETCOM JSR GETNUM ; IF NOT, GET COLOUR PARAMETER LDA VALLSB AND #7 ; MASK OFF BIT COLOUR ; COLOUR VGP ? BMI STACOL AND #1 ; IF MONO THEN LS BIT ONLY BPL STACOL ; BRANCH ALWAYS ; INTCOL: JSR GSETUP ; GET SCREEN COLOUR JSR GETCOL ; STACOL: STA FCOLOR ; AND SAVE FOR TESTP LDA FMODE AND #4 ; BIT MAP FILL ? BEQ CANBIT LDA BITX ; IF SO , CHECK BIT MAP OK BEQ CAFRTS ; RETURN IF EITHER SIZE IS 0 LDA BITY BEQ CAFRTS CANBIT: JSR STACK1 ; SAVE INITIAL POSITION LDA #$FF ; INITIALISE OLD LINE STATUS STA PXNMSB ; SET INITIAL CONDS FOR PREVIOUS LINE STA PXPMSB CAFMLP: JSR TESTL ; PLOT LINES BNE CAFMLP ; LOOP WHILE STACK NOT EMPTY JMP CAFRSY ; RESTORE COLOUR REGISTERS IF BYTE MAP FILL CAFRTS: RTS ; TESTL: JSR GSETUP JSR TESTP ; FILL ANOTHER LINES WORTH BNE DSTACK ; UNLESS ON BOUNDARY NSTACK: LDA STACKC STA STACKO ; SAVE STACK COUNTER JSR SAVCRD ; SAVE PRESENT POSITION JSR GSETUP ; PERFORM SCREEN READ TL1: JSR XDEC ; MOVE TO LEFT UNTIL BOUNDARY BCS TL2 LDA XLSB AND #7 TAY CMP #7 ; IF 7 THEN SCREEN READ JSR TESTMN BEQ TL1 TL2: JSR XINC ; BACK ONTO NON-BOUNDARY JSR SPLOTB ; SAVE POSITION FOR PLOTB JSR GSETUP ; SCREEN READ TL21: JSR XINC BCS TL3 ; MOVE RIGHT UNTIL BOUND JSR TESTPL BEQ TL21 TL3: JSR XDEC ; BACK OFF BOUND JSR CHKLIN ; CHECK LINES ABOVE AND BELOW LDA STACKC ; IS STACK FULL ? CMP #STKSIZ BCC STMPTY LDA #1 ; IF SO, FINISH STA STACKC BNE DSTACK STMPTY: JSR CHKSTK ; CHECK STACKED POINTS JSR CAPLOT ; PLOT THE LINE ; DSTACK: DEC STACKC ; PULL NEXT POINT FROM "STACK" LDX STACKC LDA STYMSB,X ; IF M.S. BIT SET, DSTACK AGAIN BMI DSTACK JSR READY LDA STXLSB,X STA XLSB STA PXNLSB LDA STXMSB,X STA PXNMSB STA XMSB LDA STYLSB,X STA YLSB LDA STYMSB,X STA YMSB LDA SOXLSB,X STA PXPLSB LDA SOXMSB,X STA PXPMSB TXA RTS ; CONSET: LDA #$80 ; SET BOUNDARY STA BSTAT CONCLR: RTS ; CSTACK: JSR TESTPL ; CHECK BOUND BNE CONSET ; IF ON, SET BOUNDARY ASL BSTAT ; CHECK FOR BOUND TO NO BOUND BCC CONCLR ZSTACK: LDX STACKO ; NOW CHECK THRO' STACK FOR CONFLICTS ZSTKLP: DEX BEQ PSTACK ; STACK IF OK LDA STYMSB,X ; POINT DELETED ? BMI ZSTKLP LDA CSTAT ; GET DIRECTION EOR SOXMSB,X ; CHECK DIRECTIONS BPL ZSTKLP ; IF SAME THEN OK LDA STYLSB,X ; CHECK IF SAME Y CMP TYL BNE ZSTKLP LDA STYMSB,X CMP TYM BNE ZSTKLP ; ; Y VALUE IS THE SAME ; NOW CHECK IF WITHIN LINE LIMITS ; SEC LDA XLSB SBC STXLSB,X ; LEFT OF LINE ? LDA XMSB SBC STXMSB,X BCC ZSTKLP ; POINT OK IF LT LINE LDA SOXLSB,X SBC XLSB ; POINT TO RIGHT OF LINE ? LDA SOXMSB,X AND #$0F SBC XMSB BCC ZSTKLP DONTST: RTS ; DISCARD POINT IF ALREADY PLOTTED ; STACK1: LDA #0 ; SET STACKC TO 0 TO STORE VGP POSITION STA STACKC ; ON BOTTOM OF "STACK" JSR READY ; PSTACK: LDX STACKC CPX #STKSIZ BCC PSTKOK ; IF NOT FULL , STACK LDX #1 ; FULL , LOOK THROUGH STACK PSNEXT: LDA STYMSB,X ; ANY DISCARDED POINTS ? BMI PSDUFF INX CPX #STKSIZ BCC PSNEXT RTS ; STACK FAULT PSDUFF: TXA ; YES, MAKE ROOM FOR NEW TAY PSDUF2: DEC STACKC ; ADJUST TOP OF STACK POINTER DEC STACKO INY ; GET NEXT POINT CPY #STKSIZ BCS PSTKOK ; ROOM MADE , STACK POINT LDA STYMSB,Y BMI PSDUF2 ; IF THIS POINT DISCARDED STA STYMSB,X ; ELSE MOVE POINT DETAILS LDA STYLSB,Y ; DOWN THE STACK STA STYLSB,X LDA STXMSB,Y STA STXMSB,X LDA STXLSB,Y STA STXLSB,X LDA SOXMSB,Y STA SOXMSB,X LDA SOXLSB,Y STA SOXLSB,X INX BNE PSDUF2 ; AND DO NEXT ONE ; PSTKOK: LDA XLSB STA STXLSB,X LDA XMSB STA STXMSB,X LDA YLSB STA STYLSB,X LDA YMSB STA STYMSB,X LDA DLSB STA SOXLSB,X LDA CSTAT ; GET DIRECTION ORA DMSB STA SOXMSB,X INC STACKC RTS ; ; ; THE NEXT SECTION TESTS POINTS ON THE STACK ; IF ONE DOES LIE ON THE LINE ABOUT TO BE PLOTTED ; THEN THE POINT IS REMOVED ; CHKSTK: DEC STACKO BEQ CHKDON ; TEST ALL POINTS EXCEPT INITIAL LDX STACKO LDA STYMSB,X CMP TYM ; SAME Y ? BNE CHKSTK LDA STYLSB,X CMP TYL BNE CHKSTK SEC LDA XLSB ; YES, IS IT ON LINE ? SBC STXLSB,X LDA XMSB SBC STXMSB,X BCC CHKSTK ; BRANCH IF PT RIGHT OF LINE LDA STXLSB,X SBC TXL LDA STXMSB,X SBC TXM BCC CHKSTK ; BRANCH IF PT LEFT OF LINE LDA STYMSB,X ; REMOVE PT BY SETTING MS OF Y ORA #$80 STA STYMSB,X CHKDON: RTS ; ; CHKLIN LOOKS AT THE LINES ABOVE ; AND BELOW THE PRESENT LINE ; IT STACKS POINTS ON BOUNDARY ; TO NO BOUNDARY TRANSITIONS ; CMPD: SEC ; COMPARE POSITION WITH LDA DLSB ; SAVED RIGHT LIMIT SBC XLSB ; IF PAST , RETURN CC LDA DMSB SBC XMSB RTS ; CHKLIN: LDA XLSB ; SAVE X POS STA DLSB LDA XMSB STA DMSB LDA PXPMSB BPL CONDEC ; CHECK PREVIOUS LINE JSR YINC BCS CONCHK BCC NOCON ; IF BOUND THEN SKIP CONDEC: JSR YDEC BEQ NOCON2 ; IF BOUND THEN SKIP CONCHK: LDA PXPMSB EOR #$80 ; INVERT DIRECTION BIT AND #$80 STA CSTAT ; AND SAVE FOR CSTACK LDA #$80 STA BSTAT ; SET BOUNDARY FLAG JSR RSXCRD ; SET X POS TO START JSR GSETUP ; SCREEN COLOUR READ CONL1: JSR CMPD ; CHECK FOR END BCC NOCON ; IF END THEN FINISH LDA XLSB ; LOOP WHILE POS < PREVIOUS LEFT SBC PXNLSB LDA XMSB SBC PXNMSB BCS XGEPXN JSR CSTACK ; STACK POINT IF WANTED JSR XINC BCC CONL1 ; XGEPXN: LDA PXPLSB ; SET TO RIGHT OF PREVIOUS LINE STA XLSB LDA PXPMSB STA XMSB JSR XINC ; + 1 BCS NOCON ; END IF BOUND LDA #$80 STA BSTAT ; JSR GSETUP CONL2: JSR CMPD BCC NOCON ; EXIT IF END OF LINE JSR CSTACK ; STACK POINT IF WANTED JSR XINC BCC CONL2 ; NOCON: LDA PXPMSB ; NOW CHECK THE OTHER LINE BPL PROINC JSR YDEC2 BNE PROCHK BEQ XPRO PROINC: INC YLSB BNE NOCON2 INC YMSB NOCON2: JSR YINC BCC XPRO PROCHK: LDA PXPMSB AND #$80 STA CSTAT ; SAVE DIRECTION LDA #$80 STA BSTAT JSR RSXCRD JSR GSETUP PROL1: JSR CMPD BCC XPRO ; EXIT AT END JSR CSTACK JSR XINC BCC PROL1 XPRO: LDA TYL ; RESTORE POSITION STA YLSB LDA TYM STA YMSB LDA DLSB ; RESTORE X POS STA XLSB LDA DMSB STA XMSB RTS ; ; TESTP TESTS SCREEN COLOUR AT PRESENT POSITION ; RETURNS NE IF BOUNDARY ; TESTPL: LDA XLSB AND #7 TAY TESTMN: BNE TESTP LDA #15 JSR WCMD ; READ SCREEN COLOUR JSR READY ; WAIT FOR IT TESTP: JSR GETCOL ; GET SCREEN COLOUR JMP (JUMPL) ; GO TO CAF0 - CAF3 CAFTAB: DW CAF0 ; MODE 0 DW CAF1 ; MODE 1 DW CAF0 ; MODE 2 DW CAF3 ; MODE 3 ; CAF0: CMP FCOLOR ; BOUNDARY IF SCREEN <> SAVED COLOUR RTS CAF1: AND FCOLOR ; BOUNDARY IF SCREEN .AND. COLOUR PARAMETER <> 0 RTS CAF3: CMP FCOLOR ; BOUNDARY IF SCREEN = COLOUR PARAMETER BEQ CAF30 LDA #0 ; SET EQ RTS CAF30: ROL A ; SET NE RTS ; XINC: INC XLSB ; CS IF BOUNDARY BNE XNM LDA XMSB INC XMSB EOR XMSB ; CHECK FOR BOUND CMP #3 RTS ; XDEC: LDA XLSB BNE XDEC1 DEC XLSB ; CS IF BOUNDARY LDA XMSB DEC XMSB EOR XMSB ; CHECK FOR BOUND CMP #3 RTS XDEC1: DEC XLSB XNM: CLC RTS ; YINC: LDA C3COPY ; CHECK SCREEN FORMAT ROR A ; UK / US ? BCC USTEST INC YLSB BNE YNINC INC YMSB EOR YMSB ; EOR INTERLACED BIT WITH MS POSITION ROR A ; CC IF BOUNDARY RTS ; USTEST: INC YLSB BNE TESTYU INC YMSB TESTYU: ROR A ; TEST INTERLACED BCS NOTINT LDA YMSB BEQ YNINC LDA #159 CMP YLSB RTS ; YNINC: SEC RTS ; CC IF GREATER ; NOTINT: LDA #207 CMP YLSB RTS ; CC IF GREATER ; YDEC2: JSR YDEC YDEC: LDA YLSB BNE YSDEC ORA YMSB BEQ YNDEC ; EQ IF BOUNDARY DEC YMSB YSDEC: DEC YLSB ORA #1 ; SET NE YNDEC: RTS ; ; CAPLOT FILLS FROM PRESENT POSITION TO XT,YT ; CAPLOT: LDA FMODE ; CHECK FOR BIT MAP MODE AND #4 BNE CAPBIT ; ; PLOTB PLOTS FROM TX TO VGP X ; PLOTB: JSR SPLOTB ; SWAP TX FOR VGP X PLOTBL: SEC ; GET DISPLACEMENT LDA TXL SBC XLSB TAY ; TEMP STORE FOR < 256 LDA TXM SBC XMSB AND #$0F ; VGP ONLY 12 BITS WIDE BEQ EPLOTB ; LAST PLOT IF < 256 LDY #255 JSR DPLOTB JSR POINT JSR READY JMP PLOTBL EPLOTB: JSR DPLOTB JSR READY JMP RSXCRD ; RESTORE POSITION AT END ; SPLOTB: JSR READY ; SWAP TX FOR VGP X LDX XMSB LDY XLSB JSR RSXCRD ; TXL -> VGP X STY TXL ; SAVE DESTINATION STX TXM RTS ; DPLOTB: STY DELTAX ; SET X DISPLACEMENT LDA #0 STA DELTAY ; Y DISP = 0 LDA #$11 ; PLOT COMMAND STA CMD ; TELL VGP TO DO IT RTS ; CAPBIT: JSR SPLOTB ; BIT MAP MODE INY BNE CAIXY ; INC DESTINATION INX CAIXY: STY XCLSB STX XCMSB ; AND SAVE IN XC ; LDA STXLSB ; COPY INITIAL POINT TO XT,YT FOR MATHS STA XTLSB LDA STXMSB STA XTMSB LDA STYLSB STA YTLSB LDA STYMSB STA YTMSB ; ; GET DISPLACEMENT FROM INITIAL POINT ; THEN DIVIDE THAT BY THE SIZE OF THE BIT MAP ; THE REMAINDERS WILL GIVE THE START POSITION WITHIN THE BIT MAP ; JSR DSMATH ; SETS DXC,DYC TO DISPLACEMENT FROM INITIAL DIVYLP: SEC ; DIVIDE DYC BY BITY LDA DYTLSB TAY ; REMAINDER IS IN Y SBC BITY STA DYTLSB BCS DIVYLP DEC DYTMSB BPL DIVYLP DIVXLP: SEC ; SAME FOR X LDA DXTLSB TAX ; WE ONLY NEED REMAINDER SBC BITX STA DXTLSB BCS DIVXLP DEC DXTMSB BPL DIVXLP ; ; IF DISPLACEMENT IS NEGATIVE THEN SUBTRACT ; REMAINDER FROM BIT MAP SIZE ; TYA BEQ TDIVX ; IF OFFSET 0, THEN OK LDA ACMDT ; PLOT COMMAND AND #4 ; NEQ IF Y NEGATIVE BNE TDIVX SEC LDA BITY STY TEMP2 SBC TEMP2 TAY TDIVX: TXA BEQ TDIVXN LDA ACMDT AND #2 ; NEQ IF X NEGATIVE BNE TDIVXN SEC LDA BITX STX TEMP2 SBC TEMP2 TAX ; ; REGS X,Y HOLD START PT RELATIVE TO START OF BIT MAP ; TDIVXN: STX TEMP1 ; SAVE X VALUE FOR LATER LDA BITX ; GET XSIZE OF BIT MAP STA VALMSB ; TEMP SAVE LDA BITM ; BIT MAP MODE ? ROR A BCS TDBYT ; ; BIT MODE, CALCULATE START POSITION WITHIN BYTE ; TXA AND #7 STA VALLSB ; SAVE BIT START TXA LSR A ; DIVIDE BY 8 FOR BYTE START LSR A LSR A TAX LDA BITX ; GET NO. OF BYTES PER LINE OF BIT MAP LSR A LSR A ; DIVIDE BY 8 LSR A STA VALMSB LDA BITX AND #7 ; PLUS ONE BYTE IF PART USED BEQ TDBYT INC VALMSB ; ; NOW CALCULATE START POSITION WITHIN BIT MAP DATA ; TDBYT: LDA #0 ; CLEAR TEMP2 STA TEMP2 STA TEMP2+1 TDBYLP: CLC ; TEMP2 = ((BYTES/LINE) * Y POSITION TYA BEQ TDBYEX DEY LDA TEMP2 ADC VALMSB STA TEMP2 BCC TDBYLP INC TEMP2+1 BCS TDBYLP ; TDBYEX: LDA TEMP2 ADC BITDL ; ADD IN DATA POINTER STA TEMP2 STA DLSB LDA TEMP2+1 ADC BITDM STA TEMP2+1 STA DMSB ; D = START OF LINE ADDRESS TXA ; TEMP2 = TEMP2 + X REMAINDER ADC TEMP2 STA TEMP2 BCC TDBYEN INC TEMP2+1 ; ; NOW PLOT FROM PRESENT POSITION TO XC-1,YC ; TDBYEN: LDA BITX SEC SBC TEMP1 ; GET NO. OF POINTS LEFT IN THIS LINE OF BIT MAP JSR BITVAL ; CHECK WITH NO. OF POINTS REQUIRED AND ADJUST IF NEEDED LDA BITM ; BIT OR BYTE MODE ? ROR A BCC TDDBIT ; ; BYTE MAP FILL ; TDDBYT: LDA VALMSB BEQ TDDEXT ; EXIT IF NO. OF POINTS = 0 JSR BYTDRW ; DRAW PART OF LINE JSR BITLIN ; SET UP NO. OF POINTS REQD. JMP TDDBYT ; AND SO ON... ; ; BIT MAP FILL ; TDDBIT: SEC ; SET UP FIRST CALL FOR PLOT LDA #8 SBC VALLSB ; SUB NO. OF BITS TO SKIP STA TEMP1 ; TO GET NO. OF BITS THIS BYTE TO PLOT LDA VALMSB ; LOAD MAX BITS TO PLOT TAY ; SAVE IN CASE OF BORROW SBC TEMP1 ; SUB NO. OF BITS THIS BYTE BCS BVALOK STY TEMP1 ; UPDATE NO OF BITS WANTED LDA #0 BVALOK: STA VALMSB ; UPDATE NO. OF BITS TO DO JSR GTDATA ; GET DATA BYTE LDX VALLSB ; GET NO. OF BITS TO SKIP BROTLP: DEX ; ROTATE DATA TO SKIP UNWANTED BITS BMI BROTEX LSR A BPL BROTLP ; BRANCH ALWAYS BROTEX: LDX TEMP1 ; GET NUMBER OF BITS TO PLOT 1ST TIME STY TEMP1 ; RESET PLOT FLAG JSR BITDLP ; JUMP INTO BIT DRAW ROUTINE ; TDBITL: JSR BITLIN ; LOOP UNTIL END OF PLOT LDA VALMSB ; WHEN VALMSB IS 0 BEQ TDIEXT JSR BITDRW JMP TDBITL TDIEXT: JMP BTPLOT ; CHECK PLOT FLAG, IF SET FINISH PLOT TDDEXT: RTS ; BITLIN: LDA DLSB ; INITIALISE FOR A BIT MAP LINE STA TEMP2 LDA DMSB ; RESET DATA POINTER TO START OF X LINE STA TEMP2+1 LDA BITX ; GET BIT MAP X SIZE BITVAL: STA VALMSB ; TEMP STORE JSR READY SEC LDA XCLSB ; DESTINATION + 1 SBC XLSB ; SUBTRACT FROM PRESENT POSITION TAX LDA XCMSB SBC XMSB BCS TDSOME LDX #0 ; NONE LEFT IF OVER THE END TDSOME: BNE TDALL ; PLOT FULL BIT MAP LINE IF > 255 TXA ; MAX REQUIRED CMP VALMSB ; COMPARE WITH BIT MAP SIZE BCS TDALL STA VALMSB ; ADJUST NO. OF POINTS TO PLOT TDALL: RTS ; ; NOW FOR REST OF PROGRAM CHN VGP2EX