Thanks very much, you've helped me quite a bit. I did not want to use the linked unit because it was really messy and confusing, on top of being non-standard for the encryption. It's not true XTea, but some kind of variant. You can compare the math to the main code on the Wiki page.

I have one question though, and it's really puzzling me. I take and encrypt a block of text bigger than 256 in length, such as your post, and just encrypt with "0123456789abcdef" and the text gets garbled something odd in the middle of the decryption. The encryption stops somewhere in the middle, then during decryption the very last 8 character block is not decrypted. Like so:

Start:
is not the correct way to copy a string. This is the primary reason why this routine will not work with ansi or wide strings. Using Result := Source will not work with ansi or wide strings either, because you want Result to be a unique copy of Source (because the Result copy gets modified). Hence you should use a function that generates a unique copy of the string. I believe there is a UniqueStr() function in the RTL or something similar.

In CipherDataXTEA, the loop will not execute at all for strings with less than 8 characters. It will also not encrypt any remaining bytes after the last eight-byte block. The same goes for DecipherDataXTEA.

Also, and this might affect both, I believe that the C >> operator is a logical shift (bits fall off the end) and the Delphi shr operator is an arithmetic shift (bits wrap around). I seem to remember we found this when porting Quake 2 to Delphi.
Encrypted:
Àú¬æ?ª{?î?? uqo- ?é+L‚Äú?ü?±?üBd
I?Ǭºu¬¨V‚ÄôS?éol&?õ¬æ?ïM?å¬?¬æ/b¬±¬êo¬¨‚Ä¢N.\ r07‚Äò1S¬§¬æ?ìa?•Ç ?ø[?ß?µ?¢?Ç?æt!‚Ćb¬®‚Ä°Àú^M¬??í(¬±?î??LH¬??ìÀú6KGÀ ܬÅ7?Ä?£¬æ‚Äô?°RaN¬±‚Ä°T> h¬±?ä?º?£ ?ɂĢ?ë?û‚Ǩ?Ü?ü‚ÄìOKJ?ØR¬£‚Ä°Àú^M¬??í(¬±?î??LH¬ ??ìÀú6KGÀܬÅ7?Ä?£¬æ‚Äô?°Ra e0¬ê¬??º?ë?™$?ëy‚Äì2¬¨¬çg?ô?¨?™?ɂ݂Ģ?â¬?E¬£+ ‚ÄòE‚Ä?Pu?¥d‚Äî
s_EL¬®?ø??¬µ?æd¬øz?ç[¬µ¬Åd‚Ñ¢l¬?P
?ñ¬º¬¨+P¬?+,?µ?í‚Ǩa?í?á2&}1‚Ä??± ?㬵r¬?5c??¬?¬?m82¬??å?ûf?ä‚Äî#??W:?í'-¬±l=¬è?ô?î?ê‚Äù ?ô¬•c??li¬?9?ô(?Ü,a?®M¬?*¬??º!3‚Ä°?Ü<6Vui"?åG?• ??¬µ?æd¬øz?ç[?úK6??~?£?®‚Äî?¨?嬮¬èf2nO?Ä??.YR9|??g>+?° ?•)?í?ç{?ø¬?¬?=nY?Ƭ±??xc?éCJ!N¬±?†(¬º&?}?â?¨?æ? ±‚Äú?ÇEE #
Decrypted:
is not the correct way to copy a string. This is the primary reason why this routine will not work with ansi or wide strings. Using Result := Source will not work with ansi or wide strings either, because you want Result to be a unique copy of Source (because the Result copy gets modified). Hence you should use a function that generates a unique copy of the string. I believe there is a UniqueStr() function in the RTL or ‚Äù¬? ¬°?®??
What might be going on here? I really don't get how that thing could happen. Even with the length change you gave me, which slightly helped, the algorithm is not working right. Even odder is that with the same password and longer text, the result sometimes is a cryptic 2 characters. I don't even know what they were. An attempt at decryption results in a crash, as you'd expect.

In the loop should I use the n/b comparison to assign to a temporary value for the 2 Move calls and the ending increment? Would that help, perhaps?