diff --git a/checksum.php b/checksum.php index d77fb9c..04dc707 100644 --- a/checksum.php +++ b/checksum.php @@ -2,7 +2,7 @@ require_once './src/D2Functions.php'; -$filename = "D:\Diablo II\MODS\ironman-dev\save\Sorc.d2s"; +$filename = "D:\Diablo II\MODS\ironman-dev\save\Barb.d2s"; $fp = fopen($filename, "rb+"); fseek($fp, 12); diff --git a/src/D2BitReader.php b/src/D2BitReader.php index da16515..9c7784e 100644 --- a/src/D2BitReader.php +++ b/src/D2BitReader.php @@ -56,7 +56,6 @@ class D2BitReader { public function getBit(string $bitNum): int { if ($bitNum < 0 || $bitNum > strlen($this->bits)) { - return false; } return ((int) $this->bits[$bitNum] ? 1 : 0 ); diff --git a/src/D2Char.php b/src/D2Char.php index 122d7e4..6e684b9 100644 --- a/src/D2Char.php +++ b/src/D2Char.php @@ -191,6 +191,8 @@ class D2Char { fseek($this->fp, $this->sData->wpOffsetsNorm + 4); $a5 = strrev(strtobits(fread($this->fp, 1))); $wp['Norm'] = str_split($a1 . $a2 . $a3 . $a4 . $a5); + + ddump($wp['Norm']); fseek($this->fp, $this->sData->wpOffsetsNM); $a1 = strrev(strtobits(fread($this->fp, 1))); diff --git a/src/D2Functions.php b/src/D2Functions.php index b1ce11c..0b1d063 100755 --- a/src/D2Functions.php +++ b/src/D2Functions.php @@ -85,7 +85,7 @@ function setBit(int $n, int $p, bool $b){ } function getBit(int $b, int $p){ - return intval(($b & (1 << $p)) != 0); + return intval(($b & (1 << $p)) !== 0); } function checksum($fileData) { diff --git a/test.php b/test.php index 3c8e514..7a77392 100644 --- a/test.php +++ b/test.php @@ -1,116 +1,178 @@ data = $data; } - - public function skip(int $numBytes): bool { - if ($numBytes < 0 || $numBytes > strlen($this->data)) return false; + + public function skip(int $numBytes): bool { + if ($numBytes < 0 || $numBytes > strlen($this->data)) + return false; $this->offset += $numBytes; return $true; - } - + public function seek(int $pos): bool { - if ($pos < 0 || $pos > strlen($this->data)) return false; + if ($pos < 0 || $pos > strlen($this->data)) + return false; $this->offset = $pos; - return true; + return true; } - - public function read(int $numBytes, bool $str = true){ + + public function readh(int $numBytes, bool $str = true): string { $bytes = null; for ($i = $this->offset; $i < $this->offset + $numBytes; $i++) { $str ? $bytes .= $this->data[$i] : $bytes[] = $this->data[$i]; - } - return unpack('H*', $bytes); + } + return unpack('H*', $bytes)[1]; } - - public function rewind() : bool { + + public function readc(int $numBytes, bool $str = true): array { + $bytes = null; + for ($i = $this->offset; $i < $this->offset + $numBytes; $i++) { + $str ? $bytes .= $this->data[$i] : $bytes[] = $this->data[$i]; + } + return unpack('C*', $bytes); + } + + public function rewind(): bool { $this->offset = 0; return true; } - - public function write8(int $offset, int $byte){ + + public function writeByte(int $offset, int $byte) { $this->data[$offset] = pack('C', $byte); } - - public function writeBytes(int $offset, string $bytes){ - if ($offset < 0 || $offset > strlen($this->data) || $bytes == '') return false; + + public function writeBytes(int $offset, string $bytes) { + if ($offset < 0 || $offset > strlen($this->data) || $bytes == '') + return false; $_bytes = str_split($bytes, 2); - foreach($_bytes as $k => $byte){ + foreach ($_bytes as $k => $byte) { $pos = $offset + $k; $this->data[$pos] = pack('H*', $byte); } } - public function getData(){ + + public function getData() { return $this->data ? $this->data : false; } + public function getOffset(): int { return $this->offset; } - - /* - @return Byte with Nth bit set to X - */ - public function setBit(int $byte, int $pos, bool $bit){ - return ($bit ? ($byte | (1 << $pos)) : ($byte & ~(1 << $pos)) ); + + public function isHexString(string $str): bool { + if (strlen($str) % 2 == 0 && (ctype_xdigit($str))) { + return true; + } + return false; } + + public function toBits($input): string { + $output = ''; + if ($this->isHexString($input)) { + foreach (str_split($input, 2) as $byte) { + $output .= (strrev(str_pad(decbin(hexdec($byte)), 8, 0, STR_PAD_LEFT))); + } + return $output; + } else if (is_string($input)) { + foreach (str_split($input) as $i) { + $output .= strrev(str_pad(decbin(ord($i)), 8, 0, STR_PAD_LEFT)); + } + return $output; + } else if (is_int($input)) { + return strrev(str_pad(decbin($input), 8, 0, STR_PAD_LEFT)); + } else if (is_array($input)) { + foreach ($input as $i) { + $output .= $this->tobits($i); + } + return $output; + } + } + + public function toBytes(string $bits) { + foreach (str_split($bits, 8) as $byteString) { + $bytes[] = (bindec(strrev($byteString))); + } + foreach ($bytes as $byte) { + dump($byte); + } + } + + public function bitsToHexString(string $bits): string { + $bytes = ''; + foreach (str_split($bits, 8) as $byte) { + $bytes .= (str_pad(dechex((bindec(strrev($byte)))), 2, 0, STR_PAD_LEFT)); + } + return $bytes; + } + + public function bitsToHexArray(string $bits): array { + $bytes = []; + foreach (str_split($bits, 8) as $byte) { + $bytes[] = (str_pad(dechex((bindec(strrev($byte)))), 2, 0, STR_PAD_LEFT)); + } + return $bytes; + } + + public function bitsToIntArray(string $bits): array { + $bytes = []; + foreach (str_split($bits, 8) as $byte) { + $bytes[] = (int) (str_pad(dechex((bindec(strrev($byte)))), 2, 0, STR_PAD_LEFT)); + } + return $bytes; + } + /* - @return Bit at Nth position in Byte - */ - public function getBit(int $byte, int $pos) : int { + @return Byte with Nth bit set to X + */ + + public function setBit(int $byte, int $pos, bool $bit) { + return ($bit ? ($byte | (1 << $pos)) : ($byte & ~(1 << $pos)) ); + } + + /* + @return Bit at Nth position in Byte + */ + + public function getBit(int $byte, int $pos): int { return intval(($byte & (1 << $pos)) != 0); - } + } + } $c = new D2ByteReader($data); -$c->seek(12); -$checksum = $c->read(4); -var_dump($checksum); -$c->write8(12, 0xFF); -$checksum = $c->read(4); -var_dump($checksum); -$c->writeBytes(12, "FFC0FDA1"); // invalid checksum, but just testing write. Works! -$checksum = $c->read(4); -var_dump($checksum); -$c->writeBytes(12, "b5bc59b3"); // Valid checksum, but just testing write. Works! -$checksum = $c->read(4); -var_dump($checksum); +$c->seek(643); +$bytes = $c->readh(5); +$bits = $c->toBits($bytes); -/* +$bits[4] = 1; +$bits[5] = 1; +$bits[8] = 1; -Barely any binary functions, all string manipulation on binary files. Working! +$newBytes = $c->bitsToHexString($bits); +$c->writeBytes(643, $newBytes); -To just modify bits in an aligned byte, use setBit(); -To just get which bit is set in a byte, use getBit(); +$c->writeBytes(12, "00000000"); // zero old checksum +$newChecksum = checksum(unpack('C*', $c->getData())); // get new checksum +dump($newChecksum); +$c->writeBytes(12, $newChecksum); // write new checksum +file_put_contents($file, $c->getData()); // write bytestream to file -To read X arbitary unaligned bits in bytes, - -Seek to offset, -Read X bytes, -Convert X bytes to bits, -Reverse bit order in each byte -Load D2BitReader, -Modify nth Bit, -Return all bits -Convert to bytes -Reverse bit order in byte -Save bytes - -function setBit(int $n, int $p, bool $b){ - return ($b ? ($n | (1 << $p)) : ($n & ~(1 << $p)) ); -} - -function getBit(int $b, int $p){ - return intval(($b & (1 << $p)) != 0); -} - -*/ \ No newline at end of file +//shell_exec("bin\d2scs.exe \"$file\""); \ No newline at end of file