So here's a classic 255 vs. -1 story: a bit stream of 1111 1111 can be interpreted as either an unsigned byte as 255, or a signed byte, as -1.
Many programming languages have signed 8-bit variable types, or "signed bytes". For the ones that don't, here's a simple and efficient way to convert a logical signed byte that's unpacked as unsigned, into a signed 16-bit small endian variable.
First a quick review on the interpretation of two's complement. If the highest bit, or "sign bit" is 0, we leave the number as is. If the sign bit is 1, we invert all the digits and add 1 to it. For example
2's complement: 1111 1111
Inverted digits: 0000 0000
Add 1: 000 0001 (the negative value of 0xFF is 1)
Logical value: -1 (so 0xFF is negative one)
Suppose we have two variables:
unsigned byte $b
unsigned short $result
We can use the efficient bit-wise operations to extract the required bits:
// $b=255 //unpacked from binary stream
$result=$b; //default to 0 or positive values
if ($b lshift 7) $result=-1* ($b xor 0xFF) +1