PAGE SBTTL "--- I/O ROUTINES ---" ; ----- ; SHOWN ; ----- ; DISPLAY NEGATIVE ICON [ARG3] AT X=[ARG1], Y=[ARG2] ; IF [ARG4] IS GIVEN IT POINTS TO THE MASK TO BE USED GSHOWN: LDA #$FF STA NEGATE ; SET NEGATE FLAG BNE SHOWI ; AND DO A "SHOWI" ; ----- ; SHOWI ; ----- ; DISPLAY ICON [ARG3] AT X=[ARG1], Y=[ARG2] ; IF [ARG4] IS GIVEN IT POINTS TO THE MASK TO BE USED GSHOWI: LDA #0 STA NEGATE ; DISABLE NEGATE ; ****************NEW ROUTINE******************** SHOWI: LDA #0 STA MSKFLG ; DISABLE MASKING UNTIL FURTHER NOTICE LDA NARGS CMP #3 BEQ NOMASK ; DO THE NORMAL THING LDX ARG4+LO ; GET MASK INFO LDA ARG4+HI JSR ISU ; THIS ENTRY INTO [ISETUP] WILL PUT ; THE DATA FOR ICON [ARG4] INTO ; IX2,IY2,IADR2 ETC. ; AND RETURN WITH DATA FROM ICON [ARG3] ; IN IX1,IY1 ETC. ; * NOTE IT WILL NOT DETECT DIFFERENT * ; * BLOCKSETS IT USES THE BSET FROM * ; * [ARG3] * LDA IX1 CMP IX2 ; IF THE WIDTH AND HEIGHT ARE NOT BNE DRAWEX ; DO NOTHING LDA IY1 CMP IY2 BNE DRAWEX LDA #$FF ; SET MASK FLAG STA MSKFLG BNE ITENT ; GOTO RIGHT PLACE NOMASK: LDX ARG3+LO ; SET UP LDA ARG3+HI ; BSET, ITERS, IX1, IY1, IADR1+LO, IADR1+HI JSR GETI ITENT: LDA #0 STA TOPCUT ; ZERO THIS STA MUH ; THIS TOO STA SIDCUT ; AND THIS ; STA MDYCUT ; AND THIS STA MDXCUT ; AND THIS LDX ARG2+LO ; ICON Y1 POS LO LDA ARG2+HI BEQ DRAWI1 ; ICON STARTS ON WINDOW PAGE (YPOS= 00 XX) CMP #$FF BNE DRAWEX ; ICON WILL NOT BE DISPLAYED ;STARTS ON PAGE BEFORE WINDOW PAGE TXA ; PUT LO YPOS IN EOR #$FF ; C=1 FROM CMP #$FF ADC WINDY1 ; FIND DISTANCE FROM ICON Y1-> WINDOW Y1 BCC DRAWI2 ; FALL THRU DISTANCE > MAX SIZE OF 255 DRAWEX: RTS ; GENERAL PURPOUS EXIT FROM DRAW ICON DRAWI3: LDA WINDY2 ; * [WINDY2] IS ONE GREATER THAN LAST * SEC ; * LINE OF WINDOW TO DISPLAY * SBC ARG2+LO ; * IF THIS MAKES A DIFFERANCE TAKE * BCC DRAWEX ; AMOUNT TO CUT FROM ROWS DISPLAYED CMP IY1 ; * THE SEC MIGHT FIX * BCS DRAWI4 STA IY1 ; EXIT WHEN ICON STARTS BELOW WINDOW BCC DRAWI4 ; THE ABOVE SECTION OCCURS IF THE ICON STARTS INDSIDE THE WINDOW ; AND FINDS THE NUMBER ROWS TO DRAW DRAWI1: SEC ; ICON ON ZERO PAGE LDA WINDY1 SBC ARG2+LO ; FIND (WINDY1-ICONY1) BCC DRAWI3 ; IF NEGATIVE ICON STARTS AFTER WINDOW Y1 DRAWI2: STA TOPCUT ; OTHERWISE CUT THIS AMOUNT FROM TOP OF ICON DRAWI4: LDA IY1 ; HEIGHT OF ICON SEC SBC TOPCUT ; DO CUT BEQ DRAWEX BCC DRAWEX ; NO ICON LEFT TO DRAW. GOOD BYE STA YDEX1 ; *** NEED TO USE OTHER NAME???? *** SBC WINDH ; *(+-1) SET IN WINDSET (HEIGHT OF WINDOW) BCC DRAWI5 ; ICON SMALLER THAN WINDOW (DISPLAY ALL) LDA WINDH ; DISPLAY A WINDOWS WORTH OF ICON STA YDEX1 ; MULTIPLY TOPCUT AND ICON WIDTH, ADD TO ICON POINTER TO POINT ; AT FIRST DISPLAYED ROW BLOCK DRAWI5: LDA TOPCUT ; * NOT NEEDED IF NOT CHANGED LATER * STA MUSHFT ; * JUST USE TOPCUT * CLC ADC ARG2+LO ; CHANGE STARY YPOS OF ICON TO REFLECT STA YPOS+LO ; TOPCUT LDY #7 ; SHIFT COUNTER LDX IX1 ; WIDTH COEFICIANT DEX ; LESS ONE SO ADC C=0 SAME AS ADC C=1 DRAWI6: TXA ; GET IX1 BACK IN FOR ADD LSR MUSHFT ; SHIFT BIT 0 INTO BCC DRAWI7 ; C=0 SAME AS ADDING 0 ADC MUH STA MUH ; ADD IXA TO TOTAL DRAWI7: ROR MUH ; MUTIPLY BY 2 ROR MUL DEY BPL DRAWI6 ; DO 8 TIMES (8 BITS) GET IT? ; LDA IADR1+LO ; CLC ; ADC MUL ; ADD OFFSET INTO ICON ; STA IADR1+LO ; LDA IADR1+HI ; ADC MUH ; STA IADR1+HI ;*** LDA MUH LDX MUL JSR ADDIA1 LDA MSKFLG ; IF MASK ENABLED BEQ NOMSK1 LDA MUH ; X IS STILL MUL JSR ADDIA2 ;*** ; COMPUTE THE DISPLAYED WIDTH AND THE IXSKIP NOMSK1: LDA IX1 ; KLUDGE STA MDXCUT LDX ARG1+LO ; ICON X CORDINATE LDA ARG1+HI BEQ DRAWI8 ; ICON STARTS ON WINDOW PAGE (XPOS= 00 XX) CMP #$FF BNE DRAWE2 ; ICON WILL NOT BE DISPLAYED ; STARTS ON PAGE BEFORE WINDOW PAGE TXA ; PUT LO XPOS IN EOR #$FF ; C=1 FROM CMP #$FF ADC WINDX1 ; FIND DISTANCE FROM ICON X1-> WINDOW X1 BCC DRAWI9 ; FALL THRU DISTANCE > MAX ICON SIZE OF 255 DRAWE2: RTS ; AN EXIT FROM DRAW ICON DRAWIA: LDA WINDX2 ; ICON STARTS INSIDE WINDOW SEC SBC ARG1+LO ; CHECK IF ICON STARTS TO RIGHT OF WINDOW BCC DRAWE2 ; FOR LATER CMP IX1 BCS DRAWIB STA IX1 ; STARTS TO RIGHT DON T BOTHER BCC DRAWIB DRAWI8: LDA WINDX1 ; ICON STARTS ON ZERO PAGE SEC SBC ARG1+LO ; FIND (WINDX2-ICONX1) BCC DRAWIA ; IF NEGATIVE ICON STARTS AFTER WINDOW X1 DRAWI9: STA SIDCUT ; OTHERWISE CUT THIS FROF LEFT OF ICON DRAWIB: LDA IX1 ; WIDTH OF ICON SEC SBC SIDCUT ; DO CUT BEQ DRAWE2 BCC DRAWE2 ; NO ICON TO DRAW BYE BYE STA XDEX1 SBC WINDW ; IF ICON SMALLER THAN WINDOW DISPLAY ALL BCC DRAWIC LDA WINDW ; OTHERWISE DISPLAY WINDOW WIDTH OF ICON STA XDEX1 ;DRAWIC: LDA IADR1+LO ; CLC ; ADC SIDCUT ; STA IADR1+LO ; BCC DRAWID ; INC IADR1+HI ;*** DRAWIC: LDA #00 LDX SIDCUT JSR ADDIA1 ;*** LDA MSKFLG ; IS MASK ENABLED BEQ DRAWID LDA #00 ; X IS STILL SIDCUT JSR ADDIA2 DRAWID: LDA MDXCUT SEC SBC XDEX1 STA IXSKIP LDA XDEX1 STA IX1 ; SET THE COUNTER REFRESH VALUE LDA ARG1+LO CLC ADC SIDCUT STA XPOS+LO STA XPSAV+LO ;************************************** LDA BSET ; GET REQUIRED BLOCK SET INTO RAM JSR GETBS LDA MSKFLG ; IF ENABLED GO DO THE MASK THING BNE DOMASK ; DRAW THE ICON ITERATION AT [IADR1] DRAW: LDA IADR1+LO ; POINT [VPC] TO NEXT ICON BYTE STA VPCL LDA IADR1+HI STA VPCH ;*** LDA IADR10 STA VPC0 ;*** LDA #0 STA VPCFLG ; INVALIDATE [VPC] JSR GETBYT ; GET BLOCK ID INTO [A] JSR GETBLK ; GET BLOCK [A] INTO [BLOCK] LDX XPOS+LO ; GET SCREEN COORDINATES LDA YPOS+LO ; INTO [X] AND [A] JSR DUMP ; DUMP [BLOCK] AT X=[X], Y=[A] DEC XDEX1 ; DEC INDEX OF DISPLAYED WIDTH BEQ CLPRI2 ; OUT OF COLUMNS: DO NEXT ROW INC XPOS+LO ; INCREMENT X CORDINATE ;*** JSR INCIA1 ;*** JMP DRAW CLPRI2: LDA IX1 ; REFRESH STA XDEX1 ; X-COUNT LDA XPSAV+LO ; RESET X-POS STA XPOS+LO ;*** LDA #0 LDX IXSKIP JSR ADDIA1 JSR INCIA1 ;*** INC YPOS+LO ; INCREMENT DEC YDEX1 ; OUT OF Y'S YET? BNE DRAW ; NO, KEEP DUMPING RTS ; TILL EMPTY ; DRAW THE ICON ITERATION AT [IADR1] WITH MASK AT [IADR2] DOMASK: LDA IADR2+LO ; POINT [VPC] TO NEXT MASK BYTE STA VPCL LDA IADR2+HI STA VPCH LDA IADR20 STA VPC0 LDA NEGATE ; SAVE NEGATE STATUS PHA LDA #00 STA VPCFLG ; INVAL FLAG STA NEGATE ; NEVER NEGATE THE MASK JSR GETBYT ; GET MASK BLOCK JSR GETBLK ; GET MASK INTO [BLOCK] JSR B2MASK ; COPY [BLOCK] INTO [MASK] LDA IADR1+LO ; POINT [VPC] TO NEXT ICON BYTE STA VPCL LDA IADR1+HI STA VPCH LDA IADR10 STA VPC0 PLA ; RESTORE THE NEGATE STA NEGATE LDA #0 STA VPCFLG ; INVALIDATE [VPC] JSR GETBYT ; GET BLOCK ID INTO [A] JSR GETBLK ; GET BLOCK [A] INTO [BLOCK] LDX XPOS+LO ; GET SCREEN COORDINATES LDA YPOS+LO ; INTO [X] AND [A] JSR DMPMSK ; DRAW [BLOCK] AGAINST [MASK] AT X=[X], Y=[A] DEC XDEX1 ; DEC INDEX OF DISPLAYED WIDTH BEQ CLPRIA ; OUT OF COLUMNS: DO NEXT ROW INC XPOS+LO ; INCREMENT X CORDINATE ;*** JSR INCIA1 JSR INCIA2 ;*** JMP DOMASK CLPRIA: LDA IX1 ; REFRESH STA XDEX1 ; X-COUNT LDA XPSAV+LO ; RESET X-POS STA XPOS+LO ;*** LDA #0 LDX IXSKIP JSR ADDIA1 JSR INCIA1 LDA #0 JSR ADDIA2 JSR INCIA2 ;*** INC YPOS+LO ; INCREMENT DEC YDEX1 ; OUT OF Y'S YET? BNE DOMASK ; NO, KEEP DUMPING RTS ; TILL EMPTY ; ------ ; B2MASK ; ------ B2MASK: LDX #7 B2MLP: LDA BLOCK,X STA MASK,X DEX BPL B2MLP RTS ; ---- ; SETI ; ---- ; COPY ICON [ARG3] INTO ICON [ARG4] WITH ; TOP LEFT CORNER AT X=[ARG1], Y=[ARG2]; ; RETURN ZERO IF RANGE ERROR, ONE IF OKAY GSETI: JSR ISETUP ; GET STATS OF SOURCE & DEST JSR DOFIT ; WILL SOURCE FIT IN DEST? BCC SI0 ; CARRY CLEAR IF OKAY JMP RET0 ; ELSE RETURN A ZERO ; [IADR2] HAS ABS ADDR OF SUB-ICON ; [VPC] POINTS TO 1ST BYTE OF SOURCE ICON SI0: LDA #0 STA I+LO ; INIT X-ROW POINTER SI1: JSR GETBYT ; GET A BYTE FROM SOURCE LDY I+LO STA (IADR2),Y ; STORE IN DEST INC I+LO ; UPDATE ROW POINTER DEC XDEX1 ; OUT OF SOURCE X'S YET? BNE SI1 ; NO, MOVE ANOTHER BYTE LDA IX1 ; ELSE REFRESH STA XDEX1 ; X-COUNT LDA IX2 ; GET X-SIZE OF DEST CLC ADC IADR2+LO ; ADD TO BASE ADDR OF SUB-ICON STA IADR2+LO ; TO GET ADDR OF NEXT SUB-ROW BCC SI3 INC IADR2+HI SI3: DEC YDEX1 ; OUT OF Y'S YET? BNE SI0 ; RESET X-INDEX AND LOOP TILL EMPTY LDA #1 JMP PUTBYT ; RETURN A 1 FOR SUCCESS ; ----- ; SWAPI ; ----- ; SAME AS "SETI" EXCEPT ICON [ARG4] SUB-DATA IS COPIED ; BACK INTO ICON [ARG3] GSWAPI: JSR ISETUP LDA IADR1+HI ; MAKE SURE SOURCE ICON CMP IPURE ; IS IN I-PRELOAD BCC GSW0 ; ERROR IF NOT ; *** ERROR #14: PURITY VIOLATION (SETI/SWAPI) *** PRERR2: LDA #14 JMP GERROR GSW0: JSR DOFIT ; WILL SOURCE FIT IN DEST? BCC GSW1 ; CARRY CLEAR IF OKAY JMP RET0 ; ELSE RETURN A ZERO GSW1: LDA IADR1+HI ; MAKE [IADR1] ABSOLUTE SEC SBC ISTART ; STRIP OFF VIRTUAL OFFSET ;*** LSR IADR10 ROL IADR1+LO ROL A ;*** CLC ADC ICODE+HI ; ADD BASE ADDR OF I-PRELOAD STA IADR1+HI ; LSB NEEDN'T CHANGE GSW2: LDA #0 ; INIT ROW INDEX STA I+LO GSW3: LDY I+LO ; GET ROW INDEX LDA (IADR1),Y ; GET BYTE FROM SOURCE ICON STA I+HI ; SAVE IT HERE LDA (IADR2),Y ; GET BYTE FROM DEST ICON STA (IADR1),Y ; MOVE IT TO SOURCE ICON LDA I+HI ; RETRIEVE SOURCE BYTE STA (IADR2),Y ; AND MOVE IT TO DEST ICON INC I+LO ; UPDATE ROW INDEX DEC XDEX1 ; OUT OF X'S YET? BNE GSW3 ; NO, KEEP LOOPING LDA IX1 ; ELSE REFRESH X-COUNT STA XDEX1 LDA IX2 ; ADD X-SIZE OF DEST CLC ; TO BASE ADDR OF SUB-ICON ADC IADR2+LO ; TO GET ADDR OF NEXT ROW STA IADR2+LO BCC GSW4 INC IADR2+HI GSW4: LDA IX1 ; ADD X-SIZE OF SOURCE CLC ; TO BASE ADDR OF SOURCE ADC IADR1+LO ; TO GET ADDR OF NEXT ROW STA IADR1+LO BCC GSW5 INC IADR1+HI GSW5: DEC YDEX1 ; OUT OF Y'S YET? BNE GSW2 ; RESET ROW INDEX & LOOP TILL EMPTY LDA #1 JMP PUTBYT ; RETURN A 1 FOR SUCCESS ; ------ ; WINDOW ; ------ X1 EQU ARG1 Y1 EQU ARG2 X2 EQU ARG3 Y2 EQU ARG4 GWIND: LDY #6 ; SET INDEX TO DO ALL ARGS WILP: LDX #0 ; TO ZERO ARGS LATER LDA X1+HI,Y ; TEST IF - OR >255 BEQ WISK1 ; IF 0 DONT ADJUST GOTO NEXT ARG BPL WISK2 ; IF PLUS ADJUST TO 255 STX X1+LO,Y ; CLIP FROM NEGATIVE TO ZERO BMI WISK1 ; BRANCH WISK2: DEX ; [X] = 255 STX X1+LO,Y ; IF > 255 CLIP TO 255 WISK1: DEY DEY ; 2 DEYS FOR NEXT ARG (WORD) BPL WILP ; DO Y2-X1 LDX #39 ; MAXIMUM X-VALUE LDY #23 ; MAXIMUM Y-VALUE LDA X1+LO ; CLIP X1 CMP #40 BCC WISK3 STX X1+LO WISK3: LDA X2+LO ; CLIP X2 CMP #40 BCC WISK4 STX X2+LO WISK4: LDA Y1+LO ; CLIP Y1 CMP #24 BCC WISK5 STY Y1+LO WISK5: LDA Y2+LO ; CLIP Y2 CMP #24 BCC WISK6 STY Y2+LO ; SWITCH IF NEEDED WISK6: LDX X1+LO LDY X2+LO CPX X2+LO ; IS X1 > X2? BCS WISK7 ; BRANCH YES STX WINDX1 ; SET X1 = X1 STY WINDX2 ; SET X2 = X2 BCC WISK8 ; BRANCH WISK7: STX WINDX2 ; SWAP STY WINDX1 ; X1 AND X2 WISK8: LDX Y1+LO ; GET Y1 AND LDY Y2+LO ; Y2 CPX Y2+LO ; IS Y1 > Y2? BCS WISK9 ; BRANCH YES STX WINDY1 ; SET Y1 = Y1 STY WINDY2 ; SET Y2 = Y2 BCC WISKA ; BRANCH WISK9: STX WINDY2 ; SWAP STY WINDY1 ; Y1 AND Y2 WISKA: INC WINDX2 ; THIS IS SO A BCC WILL WORK ON CLIP INC WINDY2 ; SAME LDA WINDY2 ; COMPUTE HEIGHT SEC SBC WINDY1 STA WINDH LDA WINDX2 ; COMPUTE WIDTH SBC WINDX1 ; C=1 FROM ABOVE STA WINDW RTS MULXY STY MUSHFT LDY #7 LDA #0 STA MUH TXA ; TEST 0 BEQ MU0 DEX MULP1: TXA LSR MUSHFT BCC MUSK1 ADC MUH STA MUH MUSK1: ROR MUH ROR MUL DEY BPL MULP1 RTS MU0: STA MUL RTS END