I'm not entirely sure what the correct code should be… but if the intention is for Checksum(Header)
to return f705, and it's returning 08fb, here's the problem:
x = ( ~( x % 0x10000 ) ) + 1
The short version is that you want this:
x = (( ~( x % 0x10000 ) ) + 1) % 0x10000
The problem here isn't that ~
means something different. As the documentation says, ~x
returns "the bits of x
inverted", which is effectively the same thing it means in C (at least on 2s-complement platforms, which includes all Windows platforms).
You can run into a problem with the difference between C and Python types here (C integral types are fixed-size, and overflow; Python integral types are effectively infinite-sized, and grow as needed). But I don't think that's your problem here.
The problem is just a matter of how you convert the result to a string.
The result of calling Checksum(Header)
, up to the formatting, is -2299, or -0x08fb, in both versions.
In C, you can pretty much treat a signed integer as an unsigned integer of the same size (although you may have to ignore warnings to do so, in some cases). What exactly that does depends on your platform, but on a 2s-complement platform, signed short -0x08fb is the bit-for-bit equivalent of unsigned 0xf705. So, for example, if you do sprintf(buf, "%04hx", -0x08fb)
, it works just fine—and it gives you (on most platforms, including everything Windows) the unsigned equivalent, f705
.
But in Python, there are no unsigned integers. The int -0x08fb has nothing to do with 0xf705. If you do "%04hx" % -0x08fb
, you'll get -8fb
, and there's no way to forcibly "cast it to unsigned" or anything like that.
Your code actually does hex(-0x08fb)
, which gives you -0x8fb
, which you then split
on the x
, giving you 8fb
, which you zfill
to 08fb
, which makes the problem a bit harder to notice (because that looks like a perfectly valid pair of hex bytes, instead of a minus sign and three hex digits), but it's the same problem.
Anyway, you have to explicitly decide what you mean by "unsigned equivalent", and write the code to do that. Since you're trying to match what C does on a 2s-complement platform, you can write that explicit conversion as % 0x10000
. If you do "%04hx" % (-0x08fb % 0x10000)
, you'll get f705
, just as you did in C. And likewise for your existing code.