Hello, do anyone know how to convert the C# code to PHP? ms.Position = 0x08; UInt32 Checksum = 0; for (int j = 0; j < 64; j++) { Checksum += Convert.ToUInt32(ms.ReadByte()) + (Convert.ToUInt32(ms.ReadByte()) * 0x100); Checksum = (Checksum - ((Checksum / 0x10000) * 0x10000)); } ms.Position = 0x06; ms.WriteByte(Convert.ToByte((Checksum) - ((Checksum / 0x100) * 0x100))); ms.WriteByte(Convert.ToByte(Checksum / 0x100)); Code (markup):
I'm assuming ms is a filestream... It would be nice if we could see where that's defined/opened, and closed. Also that's crappy code, since divides and multiplies are slow and really all you want to do there is strip off the bottom bits or shift the bits -- and that's & and <<'s job. The original should have been written more like this: ms.Position = 0x08; UInt32 Checksum = 0; for (int j = 0; j < 64; j++) { Checksum += Convert.ToUInt32(ms.ReadByte() + (ms.ReadByte() << 8)); Checksum = Checksum & 0x0000FFFF; } ms.Position = 0x06; ms.WriteByte(Convert.ToByte(Checksum & 0x000000FF)); ms.WriteByte(Convert.ToByte(Checksum >> 8)); Code (markup): Though I'm not sure all those conversions are necessary since readbyte returns int... hell if you typecase to uInt16... and in PHP (with a file open and close) it would be something like this: // I'm going to assume "ms" in your code is a filestream $handle=fopen('filename','r+'); fseek($handle, 0x08); // faster to read all 128 bytes at once $temp=fread($handle, 128); $t=0; $checksum = 0; do { $checksum += ord($temp[$t++]) + (ord($temp[$t++]) << 8); $checksum = $checksum & 0x0000FFFF; } while $t<128; fseek($handle, 0x06); fwrite($handle, chr($checksum & 0x000000FF).chr($checksum >> 8)); fclose($handle); Code (markup): I'm always a bit shocked to see such needlessly convoluted methods of simply pulling a byte or word from a complex data set.
Yeah, in the original, typecasting to unsigned 16 bit works wonders... as it guts out the need for the &. Shame there's no equivalent in PHP. ms.Position = 0x08; UInt16 Checksum = 0; for (int j = 0; j < 64; j++) { Checksum+=ms.ReadByte()+(ms.ReadByte()<<8); } ms.Position = 0x06; ms.WriteByte(Convert.ToByte(Checksum & 0x00FF)); ms.WriteByte(Convert.ToByte(Checksum >> 8)); Code (markup): Far, FAR simpler.
Oh, for laughs, it just occurred to me I have the exact same checksum in a DOS program I wrote in turbo pascal -- as inline 16 bit x86 assembly. type pByte=^byte; function checksum16(data:pByte):word; assembler; asm xor bx,bx les di,data mov cx,64 @repeat: lodsw xchg ah,al // correct for little endian add bx,ax loop @repeat mov ax,bx // TP inline ASM uses AX for function retval end; Code (markup): What makes it funnier is that the smaller 'backwards compatible' 8 and 16 bit versions of the registers actually make x86 far, far faster and more efficient at this than 'true' 32 bit or 64 bit processors -- basically what the RISC-tards harp on CISC about, is what makes this superior to the endless "shifts" and "ands" you'd have to do on something like ARM or PPC. Gah, I've been at this **** for far, FAR too many years.
And when you get to that point, you always have the same thing written in some other language for some other purpose, don't you? Good programmers steal from great programmers. Great programmers steal from themselves. Old programmers don't die, we just shift too many places.
Gets even stranger when you look at that code today, and see further optimizations for it -- like switching the XCHG so that AL is first, since that shaves a byte and as much as 5 clocks (4 for the fetch, 1 EU) off it on the 8088. (most x86 instructions are faster if you make the lowest order bits of the accumulator the main parameter -- AL, AX, EAX) Quite literally XCHG AH,AL = 2 bytes, 4 EU clocks XCHG AL,AH = 1 byte, 3 EU clocks ... and when you figure that fetching a byte takes 4 clock cycles on the 8088/8086 -- clocks that can be spent while the EU is running... that LODSW uses 8 cycles of BIU and 16 cycles total... that change would free up 4 more clocks to fill the BIU with the first byte of the ADD after, the remaining byte only taking one more clock off the XCHG's EU time... wow, that would actually shave 8 clock cycles off inside the loop!
What really gets me is that this is really what programming is all about, but it's probably way over the heads of 95% (or more) of the "programmers" posting here. Ever jump to the second byte of an instruction, because you manipulated the code that way, so the operand and following instruction's opcode formed an opcode and operand that the program could use - shaving 2 bytes off the code? Or set up a "pseudo-cmp" by subtracting in an 8048, because it has no compare (but, saving grace, POP doesn't affect flags)? Programming used to be fun, now it's dragging controls onto forms.