SUBCOPY PLA STA RETADR PLA STA RETADR+1 PLA STA :MLEN PLA STA :SCNT STA RETLEN PLA STA :SINDEX PLA STA ADDR1 PLA STA ADDR1+1 LDA #RETURN STA ADDR2+1 LDA RETADR+1 PHA LDA RETADR PHA LDA #0 STA :S2LEN ; DESTINATION LENGTH = 0 STA :SCERR ; ASSUME NO ERRORS LDA :SCNT BEQ :OKEXIT ; BR IF 0 BYTES TO COPY, LDA :MLEN BEQ :EREXIT ; ERROR EXIT IF SUBSTR HAS LDA :SINDEX BEQ :EREXIT ; ERROR EXIT IF START IDX = 0 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 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 :RECALC LDA :S1LEN ; RECALCULATE COUNT SEC SBC :SINDEX STA :SCNT INC :SCNT ; CNT = S1LEN - IND + 1 LDA #$0FF STA :SCERR ; INDICATE TRUNCATION :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 :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 :OKEXIT CLC BCC :EXIT :EREXIT SEC :EXIT LDA :S2LEN LDY #0 STA (ADDR2),Y STA RETLEN RTS :S1LEN DS 1 :S2LEN DS 1 :MLEN DS 1 :SCNT DS 1 :SINDEX DS 1 :SCERR DS 1