It may also be that you're rotating by 0x8000 and this code is not. It's creating a mapping that's restricted to non-control, non-surrogate, non-whitespace characters and rotating by half the size of that mapping.
This will break, i.e. two consecutive rotations will no longer be the identity, if the number of valid characters in the BMP ever becomes odd. And there are still a few unallocated code points in the BMP. There is also an overflow in line 39 because of the check i <= BMP_SIZE in line 37 which, I guess, previously used Char.MaxValue instead of BMP_SIZE. But it does no harm here, U+0000 just gets filtered out twice.
https://github.com/rottytooth/rot8000/blob/master/Rottytooth...