*``````````````````````````````*
* STRCAT :: STRING CONCATENATE *
*-                            -*
* CONCATENATE TWO STRINGS INTO *
* A SINGLE STRING STORE WHERE  *
* THE FIRST STRING IS LOCATED. *
* ADDITIONALLY COPIES CONCAT'D *
* STRING TO [RETURN].          *
*-                            -*
* CLOBBERS:                    *
*                              *
* FLAGS:  ????----  REG: AXYM  *
*-                            -*
* CYCLES: ???                  *
* SIZE:                        *
*-                            -*
* USAGE:                       *
*                              *
*   LDA #>CATSTR               *
*   PHA                        *
*   LDA #<CATSTR               *
*   PHA                        *
*   LDA #>CATSTR2              *
*   PHA                        *
*   LDA #<CATSTR2              *
*   PHA                        *
*   LDA #7 ; MAX SIZE OF CAT   *
*   PHA                        *
*   JSR STRCAT                 *
*                              *
* CATSTR  STR "ABC"            *
* BLANK   STR "    "           *
* CATSTR2 STR "DEF"            *
*-                            -*
* ENTRY                        *
*                              *
* TOP OF STACK                 *
*                              *
* LOW BYTE OF RETURN ADDRESS   *
* HI BYTE OF RETURN ADDRESS    *
* MAXIMUM LENGTH OF CONCAT STR *
* LOW BYTE OF STR2 ADDRESS     *
* HIGH BYTE OF STR2 ADDRESS    *
* LOW BYTE OF STR1 ADDRESS     *
* HIGH BYTE OF STR1 ADDRESS    *
*-                            -*
* EXIT                         *
*                              *
* TOP OF STACK                 *
*                              *
* LOW BYTE OF RETURN ADDRESS   *
* HI BYTE OF RETURN ADDRESS    *
*                              *
* .Y = CLOBBERED; TRASH        *
* .X = LENGTH OF FINAL STRING  *
* .A = 1 IF OVERFLOW, 0 IF NO  *
* [RETURN] = CONCAT'D STRING   *
* [RETLEN] = LENGTH OF NEW STR *
*-                            -*
* ADAPTED FROM LEVANTHAL AND   *
* WINTHROP'S /6502 ASSEMBLY    *
* LANGUAGE ROUTINES/.          *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
STRCAT
*
** SAVE RETURN ADDRESS
*
         PLA
         STA   RETADR
         PLA
         STA   RETADR+1
*
** GET PARAMETERS
*
         PLA
         STA   :MLEN      ; MAXIMUM CONCAT LENGTH
*
         PLA
         STA   ADDR2      ; STRING 1 ADDRESS
         PLA              ; IN ZERO PAGE
         STA   ADDR2+1
         PLA
         STA   ADDR1      ; STRING 2 ADDRESS
         PLA              ; IN ZERO PAGE
         STA   ADDR1+1
*
** DETERMINE WHERE TO START
*
         LDY   #0
         LDA   (ADDR1),Y  ; GET CUR LGTH OF S1, STORE
         STA   :S1LEN
         STA   :S1IND
         INC   :S1IND     ; START CONCAT AT END OF S1
         LDA   (ADDR2),Y  ; GET LENGTH OF S2, STORE
         STA   :S2LEN
         LDA   #1
         STA   :S2IND     ; START CONCAT AT BEGIN OF S2
*
** DETERMINE NUMBER OF CHAR
*
         LDA   :S2LEN     ; GET S2 LENGTH
         CLC
         ADC   :S1LEN     ; ADD TO LENGTH OF S1
         STA   :S3LEN     ; STORE CONCAT LENGTH
         BCS   :TOOLONG   ; BR IF LENGTH > 255
         CMP   :MLEN      ; CHECK AGAINST MAX LENGTH
         BEQ   :LENOK     ; BR IF LENGTH < MAX
         BCC   :LENOK
*
** RESULTING STRING WILL BE TOO LONG SO
** INDICATE A STRING OVERFLOW, __SOVF = 0FF
** SET NUMBER OF CHARS TO CONCAT = MLEN - S1LEN
** SET LENGTH OF STRING 1 TO MAX LENGTH
*
:TOOLONG
         LDA   #$0FF
         STA   :SOVF      ; INDICATE OVERFLOW
         LDA   :MLEN
         SEC
         SBC   :S1LEN
         BCC   :EXIT
                          ; EXIT IF MLEN < S1LEN
         STA   :SCNT      ; ORIG STR WAS TOO LONG
         LDA   :MLEN
         STA   :S1LEN     ; SET STR1 LENGTH TO MAX
         JMP   :DOCAT
*
** RESULTING LENGTH DOES NOT EXCEED MAX
** LENGTH OF STRING 1 = S1LEN + S2LEN
** INDICATE NO OVERFLOW, __SOVF = 0
** SET NUM OF CHARS TO CONCAT TO LENGTH OF STR 2
*
:LENOK
         STA   :S1LEN
         LDA   #0         ; SAVE SUM OF 2 LENGTHS
         STA   :SOVF      ; INDICATE NO OVERFLOW
         LDA   :S2LEN
         STA   :SCNT      ; COUNT = LENGTH OF STRING 2
*
** CONCAT STRINGS
*
:DOCAT
         LDA   :SCNT
         BEQ   :EXIT      ; EXIT IF NO BYTES LEFT
*
:CATLP
         LDY   :S2IND
         LDA   (ADDR2),Y  ; GET NEXT BYTE FROM S2
         LDY   :S1IND
         STA   (ADDR1),Y  ; MOVE IT TO END OF STR 1
         INC   :S1IND     ;INC STRING 1 INDEX
         INC   :S2IND     ; INC STRING 2 INDEX
         DEC   :SCNT      ; DECREMENT COUNTER
         BNE   :CATLP     ; CONT UNTIL __SCNT = 0
*
:EXIT
*
** UPDATE STRING1 LENGTH
*
         LDA   :S1LEN
         LDY   #0
         STA   (ADDR1),Y
         LDA   :SOVF
         ROR   A
*
** RESTORE RETURN ADDRESS
*
         LDA   RETADR+1
         PHA
         LDA   RETADR
         PHA
*
** COPY TO [RETURN]
*
         LDY   #0
         LDA   (ADDR1),Y  ; LENGTH OF STRING
         STA   RETLEN
         LDA   #1
:RLP
         LDA   (ADDR1),Y
         STA   RETURN,Y
         CPY   RETLEN
         INY
         BNE   :RLP
         LDA   RETLEN
         LDY   #0
         STA   (ADDR1),Y
*
         LDX   :S3LEN     ; RETURN FINAL LENGTH
*
         RTS
*
** DATA
*
:S3LEN   DS    1
:S1LEN   DS    1
:S1IND   DS    1
:S2LEN   DS    1
:S2IND   DS    1
:MLEN    DS    1
:SCNT    DS    1
:SOVF    DS    1
*
