*``````````````````````````````* * SUBCOPY :: COPY SUBSTRING * *- -* * COPY A SUBSTRING FROM A * * STRING TO [RETURN]. * *- -* * CLOBBERS: * * * * FLAGS: ????---- REG: AXYM * *- -* * CYCLES: ??? * * SIZE: * *- -* * USAGE: * * * * LDA #>STR ; SOURCE STRING * * PHA * * LDA #RETURN STA ADDR2+1 * ** RESTORE RETURN ADDRESS * LDA RETADR+1 PHA LDA RETADR PHA * LDA #0 STA :S2LEN ; DESTINATION LENGTH = 0 STA :SCERR ; ASSUME NO ERRORS * ** CHECK FOR ZERO BYTES TO COPY OR ZERO MAX SUBSTR LENGTH * LDA :SCNT BEQ :OKEXIT ; BR IF 0 BYTES TO COPY, ; S2A WILL JUST HAVE ZERO LENGTH LDA :MLEN BEQ :EREXIT ; ERROR EXIT IF SUBSTR HAS ; ZERO MAX LENGTH LDA :SINDEX BEQ :EREXIT ; ERROR EXIT IF START IDX = 0 * ** CHECK IF SRC STR REACHES STARTING INDEX * LDY #0 LDA (ADDR1),Y ; STA :S1LEN ; GET LENGTH OF SOURCE STRING CMP :SINDEX ; COMPARE TO STARTING INDEX BCC :EREXIT ; ERROR EXIT IF INDEX TOO BIG * ** CHECK THAT WE DO NOT COPY BEYOND THE END OF ** THE SOURCE STRING. ** IF INDEX + COUNT -1 > SLEN THEN ** COUNT = SLEN - SINDEX + 1 * LDA :SINDEX CLC ADC :SCNT BCS :RECALC TAX ; BR IF INDEX + COUNT > 255 DEX CPX :S1LEN BCC :CNT10K ; BR IF IND + CNT - 1 < S1LEN BEQ :CNT10K ; OR EQUAL * ** THE CALLER ASKED FOR TOO MANY CHARS SO ** JUST RETURN EVERYTHING BETWEEN INDEX AND ** END OF STRING. SO CNT = S1LEN - INDEX + 1 * :RECALC LDA :S1LEN ; RECALCULATE COUNT SEC SBC :SINDEX STA :SCNT INC :SCNT ; CNT = S1LEN - IND + 1 LDA #$0FF STA :SCERR ; INDICATE TRUNCATION * ** CHECK IF COUNT IS <= THE MAXIMUM LENGTH ** OF THE DEST STRING. IF NOT, THEN SET COUNT TO ** MAX LENGTH. ** IF COUNT > MAXLEN THEN ** COUNT = MAXLEN * :CNT10K LDA :SCNT CMP :MLEN ; IF CNT > M SUBSTR LEN ? BCC :CNT20K ; BR IF CNT < MAXLEN BEQ :CNT20K ; BR IF CNT = MAXLEN LDA :MLEN STA :SCNT ; ELSE CNT = MAXLEN LDA #$0FF STA :SCERR ; INDICATE DEST STR OVERFLOW * ** EVERYTHING IS SET UP SO MOVE THE ** SUBSTRING TO THE DESTINATION STRING * :CNT20K LDX :SCNT ; REG X WILL BE COUNTER BEQ :EREXIT ; ERR IF 0 LDA #1 ; START WITH 1ST CHAR IN DEST STA :S2LEN ; RUNNING DEST INDEX ; __SINDEX IS SRC INDEX :MVLP LDY :SINDEX LDA (ADDR1),Y ; GET NEXT SRC CHAR LDY :S2LEN STA (ADDR2),Y ; MOVE NEXT CHAR TO DEST INC :SINDEX ; INC SRC INDEX INC :S2LEN ; INC DEST INDEX DEX ; DECREMENT COUNTER BNE :MVLP ; CONT UNTIL CNT = 0 DEC :S2LEN ; SUBSTR LEN=FINAL DEST IND-1 LDA :SCERR ; CHECK FOR ANY ERRORS BNE :EREXIT ; BR IF STR TRUNCATED OR OVERFLOW * ** GOOD EXIT * :OKEXIT CLC BCC :EXIT * ** ERROR EXIT * :EREXIT SEC * ** STORE LENGTH BYTE IN FRONT OF SUBSTR * :EXIT LDA :S2LEN LDY #0 STA (ADDR2),Y STA RETLEN RTS * ** DATA * :S1LEN DS 1 :S2LEN DS 1 :MLEN DS 1 :SCNT DS 1 :SINDEX DS 1 :SCERR DS 1 *