It does, trust me
Some bit theory:
Signed integers are stores using two's complement for negative numbers. That means that not only the bit sign is 1, but the rest of the bits are complemented using that technique. That's why everything gets screwed when trying to shift, rotate, or do bitwise stuff to signed numbers.
INTEGERs are 16 bits, that means that in memory they are comprised of two bytes. The i86 family of computers use big endian, that is, if a number has two bytes it stores first the less significant and then the most significant. "&H0077" in integer, for example, has two bytes: &H00 and &H77, but in memory they are stored "77, 00".
QB's MKI$ creates a string that represents a integer number, that is, it reads the memory address where the number is and it creates a two characters string with a exact copy of the memory there. That means that for number "&H0077" it returns a string CHR$(77) + CHR$(0). My small routine just takes the first byte, assuming that you are always using 8 bits values. The sign is contained in the second byte, 7th bit.
This by itself doesn't look very convincing, but you have to use it combined with my other routine which makes an integer out of two chars (CVI): CVI (CHR$(77) + CHR$(0)) = &H0077.
The pseudocode is the following:
Code:
DO WHILE NOT EOF
Char = GET CHARACTER FROM FILE
' Now we make an always positive number using the char readed,
' No matter if it is positive or negative:
IntegerValue = CVI (Char + CHR$(0))
' Now we do the encription
NewIntegerValue = Do Nasty Things to IntegerValue
' Now we have to convert to a char again:
EncryptedChar = LEFT$( MKI$( IntegerValue ), 1)
' Write to file
PUT CHARACTER TO FILE EncryptedChar
LOOP
This way we get a "unsigned char pseudo-type". IntegerValue is always gonna be in the range 0 - 255. You only have to be careful and not to go out of bounds with calculations in the encryption part.