mirror of
https://gitlab.com/hashborgir/d2tools.git
synced 2024-11-30 04:26:03 +00:00
Bytereader working. May not need Bitreader anymore, but it's already in use by D2Item, so we'll leave it.
This commit is contained in:
parent
95bcefe2cf
commit
69d4728d8c
@ -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);
|
||||
|
@ -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 );
|
||||
|
@ -192,6 +192,8 @@ class D2Char {
|
||||
$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)));
|
||||
fseek($this->fp, $this->sData->wpOffsetsNM + 1);
|
||||
|
@ -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) {
|
||||
|
172
test.php
172
test.php
@ -1,116 +1,178 @@
|
||||
<?php
|
||||
// from unpack('H*', file_get_contents("Char.d2s")) for 3v4l.org to read d2s file here
|
||||
$data = hex2bin('55aa55aa60000000f1060000b5bc59b300000000536f72630000000000000000000000002400000001103863000000003cc7ae62ffffffffffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff000000000000570300000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000005e3e9b11000000008888d5f80100000035b70300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000576f6f21060000002a0101000190fd9ffe9ffd9ffe9ffd9f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000057530100000050000201ffffffff7f00000000000000000000000000000000000201ffffffff7f00000000000000000000000000000000000201ffffffff7f0000000000000000000000000000000000017734002e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000067660028083082000a06644000b10252067094c1018082800020292400480a0a0030c202008cc060dcc0f0ca3afa160a0000e03f696600000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000004a4d32004a4d100082006500069226160382af144fb080e03f4a4d1000820065000a9226260302791c00c480e03f4a4d10008000654415c076c606821c7ffff58080010a06fe034a4d1000800065008013268303827e82896086dccb000066c5bcfeffff014a4d1000820065000022f6860782b067b7ec80e03f4a4d1000820065001a922636038249b154da80a025040000c07f4a4d1000a0006500a442665363034a4d1000a0006500fe13367703024a4d1000a0006500de13362703024a4d1000a0006500be13361703024a4d1000a00065009e13360703024a4d1000a00065007e1336a707024a4d1000a00065005e13369707024a4d1000a00065003e1336f706024a4d1000a0006500c013e65606024a4d1000a00065006012d68607024a4d1000a00065000e12d60603024a4d1000a00065006412564306024a4d1000800065001e83179303029920441686e03f4a4d1000a0006500fe12d69606024a4d1000a0006500de12d68606024a4d1000a0006500be12d67606024a4d1000a00065009e12e67606024a4d1000a00065007e12e69606024a4d1000a0006500fc13e6a606024a4d1000a0006500dc13c68603024a4d1000a0006500bc13e6b606024a4d1000800065009c83272303826f9aed3186e03f4a4d1000800065007c8317730302acd0c26e86e03f4a4d1000a00065005c13560603024a4d1000a00065003c13569607024a4d1000a00065001c13464603024a4d1000a00065001212d66607024a4d1000a00865001412d66607024a4d1000a0006500fc1226f606024a4d1000a0006500dc12265607024a4d1000a0086500bc12265607024a4d1000a00865009c12265607024a4d1000a00865007c12265607024a4d1000a0086500fa13265607024a4d1000a0006500da43665363034a4d1000a0086500ba43665363034a4d1000a00065009a53468333064a4d10008000650016421616038245fc36c6822cff014a4d100080006500a032166707028c6e88690101000408052c30c0c00054e03f4a4d10008000650411c026c60602385900c78080010a08fe034a4d1000800065004632166707822c1b5e930001000498042c30c0c00054e03f4a4d1000800065007a8337130382a07c2a5786e03f4a4d1008800065000ec326c60602915c92ea8280010a07e23f4a4d100880046500b23237470612e9b107ed80104b83c140fc3776ece0f80f4a4d1000a00065180010365603024a4d00006a664a4d00006b6600');
|
||||
|
||||
// from unpack('H*', file_get_contents("Char.d2s")) for 3v4l.org to read d2s file here
|
||||
//$data = hex2bin('55aa55aa60000000f1060000b5bc59b300000000536f72630000000000000000000000002400000001103863000000003cc7ae62ffffffffffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff000000000000570300000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000005e3e9b11000000008888d5f80100000035b70300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000576f6f21060000002a0101000190fd9ffe9ffd9ffe9ffd9f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000057530100000050000201ffffffff7f00000000000000000000000000000000000201ffffffff7f00000000000000000000000000000000000201ffffffff7f0000000000000000000000000000000000017734002e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000067660028083082000a06644000b10252067094c1018082800020292400480a0a0030c202008cc060dcc0f0ca3afa160a0000e03f696600000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000004a4d32004a4d100082006500069226160382af144fb080e03f4a4d1000820065000a9226260302791c00c480e03f4a4d10008000654415c076c606821c7ffff58080010a06fe034a4d1000800065008013268303827e82896086dccb000066c5bcfeffff014a4d1000820065000022f6860782b067b7ec80e03f4a4d1000820065001a922636038249b154da80a025040000c07f4a4d1000a0006500a442665363034a4d1000a0006500fe13367703024a4d1000a0006500de13362703024a4d1000a0006500be13361703024a4d1000a00065009e13360703024a4d1000a00065007e1336a707024a4d1000a00065005e13369707024a4d1000a00065003e1336f706024a4d1000a0006500c013e65606024a4d1000a00065006012d68607024a4d1000a00065000e12d60603024a4d1000a00065006412564306024a4d1000800065001e83179303029920441686e03f4a4d1000a0006500fe12d69606024a4d1000a0006500de12d68606024a4d1000a0006500be12d67606024a4d1000a00065009e12e67606024a4d1000a00065007e12e69606024a4d1000a0006500fc13e6a606024a4d1000a0006500dc13c68603024a4d1000a0006500bc13e6b606024a4d1000800065009c83272303826f9aed3186e03f4a4d1000800065007c8317730302acd0c26e86e03f4a4d1000a00065005c13560603024a4d1000a00065003c13569607024a4d1000a00065001c13464603024a4d1000a00065001212d66607024a4d1000a00865001412d66607024a4d1000a0006500fc1226f606024a4d1000a0006500dc12265607024a4d1000a0086500bc12265607024a4d1000a00865009c12265607024a4d1000a00865007c12265607024a4d1000a0086500fa13265607024a4d1000a0006500da43665363034a4d1000a0086500ba43665363034a4d1000a00065009a53468333064a4d10008000650016421616038245fc36c6822cff014a4d100080006500a032166707028c6e88690101000408052c30c0c00054e03f4a4d10008000650411c026c60602385900c78080010a08fe034a4d1000800065004632166707822c1b5e930001000498042c30c0c00054e03f4a4d1000800065007a8337130382a07c2a5786e03f4a4d1008800065000ec326c60602915c92ea8280010a07e23f4a4d100880046500b23237470612e9b107ed80104b83c140fc3776ece0f80f4a4d1000a00065180010365603024a4d00006a664a4d00006b6600');
|
||||
|
||||
require_once './src/D2Functions.php';
|
||||
require_once './src/D2BitReader.php';
|
||||
|
||||
$file = "D:\Diablo II\MODS\ironman-dev\save\Barb.d2s";
|
||||
$data = file_get_contents($file);
|
||||
|
||||
class D2ByteReader {
|
||||
|
||||
private string $data;
|
||||
private int $offset = 0;
|
||||
|
||||
public function __construct(string $data){
|
||||
if (!$data) return false;
|
||||
public function __construct(string $data) {
|
||||
if (!$data)
|
||||
return false;
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
public function skip(int $numBytes): bool {
|
||||
if ($numBytes < 0 || $numBytes > strlen($this->data)) return false;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 Byte with Nth bit set to X
|
||||
*/
|
||||
public function setBit(int $byte, int $pos, bool $bit){
|
||||
|
||||
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 {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
*/
|
||||
//shell_exec("bin\d2scs.exe \"$file\"");
|
Loading…
Reference in New Issue
Block a user