Reply 2180 of 2419, by hail-to-the-ryzen
Given the overflow does not occur, would this work:
if (sizeof(Type) == 1) {
const Bit8u xr = signeddata ? 0x00 : 0x80;
+ Bit8s d;
len--;
- current[0] = ((Bit8s)((*data++) ^ xr)) << 8;
+ d = (Bit8s)((*data++) ^ xr);
+ current[0] = d > xr ? (d << 8) | (2 * d + 1) : d << 8;
- if (stereo)
+ if (stereo) {
- current[1] = ((Bit8s)((*data++) ^ xr)) << 8;
+ d = (Bit8s)((*data++) ^ xr);
+ current[1] = d > xr ? (d << 8) | (2 * d + 1) : d << 8;
+ }
else
current[1] = current[0];
This is based on kcgen's work at https://github.com/dosbox-staging/dosbox-staging/pull/1005.
Tested with modified test code from kcgen:
// gcc convert-8bit-16bit.c -o convert-8bit-16bit.exe
short scale_uto16(unsigned char val) {
if (val > 128)
return (((char)(val ^0x80)) << 8) | (2 * ((char)(val ^0x80)) + 1);
else
return (char)(val ^0x80) << 8;
}
short scale_sto16(char val) {
if (val > 0)
return (val << 8) | (2 * val + 1);
else
return (val << 8);
}
void main()
{
int x;
printf("%8s %12s\n", "value", "int-shift");
unsigned char unsigned_val[] = { 0, 15, 16, 31, 32, 33, 96, 127, 128, 129, 168, 254, 255 };
for (x = 0; x < 13; x++)
printf("%8u %12d\n", unsigned_val[x], scale_uto16(unsigned_val[x]));
printf("\n%8s %12s\n", "value", "int-shift");
char signed_val[] = { -128, -96, -63, -64, -65, -33, -32, -1, 0, 1, 32, 33, 63, 64, 65, 96, 126, 127 };
for (x = 0; x < 18; x++)
printf("%8d %12d\n", signed_val[x], scale_sto16(signed_val[x]));
}