mirror of
https://gitlab.com/hashborgir/d2tools.git
synced 2024-11-30 04:26:03 +00:00
Working copy
This commit is contained in:
parent
eb28039f88
commit
dd662e26f6
@ -2,5 +2,6 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
<mapping directory="$PROJECT_DIR$/docs/ironman-dev_backup" vcs="Git" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
error_reporting(E_ERROR | E_PARSE);
|
|
||||||
set_time_limit(-1);
|
|
||||||
ini_set('max_input_time', '-1');
|
|
||||||
ini_set('max_execution_time', '0');
|
|
||||||
session_start();
|
session_start();
|
||||||
ob_start();
|
ob_start();
|
||||||
|
|
||||||
@ -16,6 +12,11 @@ require_once './src/D2BitReader.php';
|
|||||||
require_once './src/D2Item.php';
|
require_once './src/D2Item.php';
|
||||||
require_once './src/D2Char.php';
|
require_once './src/D2Char.php';
|
||||||
|
|
||||||
|
error_reporting(E_ERROR | E_PARSE);
|
||||||
|
set_time_limit(-1);
|
||||||
|
ini_set('max_input_time', '-1');
|
||||||
|
ini_set('max_execution_time', '0');
|
||||||
|
|
||||||
define('DB_FILE', $_SESSION['modname'] . ".db");
|
define('DB_FILE', $_SESSION['modname'] . ".db");
|
||||||
PDO_Connect("sqlite:" . DB_FILE);
|
PDO_Connect("sqlite:" . DB_FILE);
|
||||||
|
|
||||||
@ -42,10 +43,11 @@ foreach ($ISCData as $k => $v) {
|
|||||||
//$filePath = "D:\Diablo II\MODS\MedianXL2012\save\Test.d2s";
|
//$filePath = "D:\Diablo II\MODS\MedianXL2012\save\Test.d2s";
|
||||||
|
|
||||||
|
|
||||||
$filePath = "Necro.d2s";
|
$filePath = "Test.d2s";
|
||||||
$char = new D2Char($filePath);
|
$char = new D2Char($filePath);
|
||||||
$char->setChar("CharacterStatus", "Died", 0);
|
|
||||||
$char->setChar("CharacterStatus", "Hardcore", 1);
|
//$char->setChar("CharacterStatus", "Died", 0);
|
||||||
|
//$char->setChar("CharacterStatus", "Hardcore", 1);
|
||||||
//$char->setChar("CharacterStatus", "Expansion", 1);
|
//$char->setChar("CharacterStatus", "Expansion", 1);
|
||||||
//$char->setChar("LeftmousebuttonskillID", 223);
|
//$char->setChar("LeftmousebuttonskillID", 223);
|
||||||
|
|
||||||
@ -53,13 +55,21 @@ $char->setAllSkills(1);
|
|||||||
//$char->setSkill(1, 99);
|
//$char->setSkill(1, 99);
|
||||||
//$char->setChar("CharacterClass", "Necromancer"); // 127
|
//$char->setChar("CharacterClass", "Necromancer"); // 127
|
||||||
//$char->setChar("CharacterProgression", 1); // 0 in normal, 1 finished normal, 2 finished nm, 3 finished hell
|
//$char->setChar("CharacterProgression", 1); // 0 in normal, 1 finished normal, 2 finished nm, 3 finished hell
|
||||||
$char->setChar("CharacterLevel", 25);
|
|
||||||
//$char->setStat("strength", 70);
|
//$char->setChar("CharacterStatus", "Died", 1);
|
||||||
//$char->setStat("energy", 70);
|
$char->setChar("CharacterLevel", 99);
|
||||||
//$char->setStat("dexterity", 70);
|
$char->setStat("strength", 270);
|
||||||
//$char->setStat("vitality", 70);
|
$char->setStat("energy", 270);
|
||||||
//$char->setStat("mana", 200);
|
$char->setStat("dexterity", 270);
|
||||||
//$char->setStat("maxmana", 200);
|
$char->setStat("vitality", 270);
|
||||||
|
$char->setStat("hitpoints", 100);
|
||||||
|
$char->setStat("maxhp", 150);
|
||||||
|
$char->setStat("stamina", 280);
|
||||||
|
$char->setStat("maxstamina", 290);
|
||||||
|
$char->setStat("mana", 70);
|
||||||
|
$char->setStat("maxmana", 200);
|
||||||
|
|
||||||
|
|
||||||
//$char->setStat("soulcounter", 80);
|
//$char->setStat("soulcounter", 80);
|
||||||
//
|
//
|
||||||
//$char->setStat("hitpoints", 70);
|
//$char->setStat("hitpoints", 70);
|
||||||
@ -77,4 +87,6 @@ $char->setChar("CharacterLevel", 25);
|
|||||||
unset($char); // destroy $char so we can read it again after writing to it to get updated stats
|
unset($char); // destroy $char so we can read it again after writing to it to get updated stats
|
||||||
|
|
||||||
$char = new D2Char($filePath);
|
$char = new D2Char($filePath);
|
||||||
var_dump($char->cData);
|
|
||||||
|
var_dump($char->cData['CharacterStatus']);
|
||||||
|
var_dump($char->cData['stats']);
|
||||||
|
114
D2Reviver.php
Normal file
114
D2Reviver.php
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once './src/D2Functions.php';
|
||||||
|
require_once './src/D2ByteReader.php';
|
||||||
|
require_once './src/D2BitReader.php';
|
||||||
|
$str = <<<EOT
|
||||||
|
__ __
|
||||||
|
`."._ _,",'
|
||||||
|
`. "-----, .-----" ,'
|
||||||
|
`. / \ ,'
|
||||||
|
\------. _ | |__ ,-.__L | _ _ ,---.
|
||||||
|
\ .--. \ \'-, | ,',.'. \ ._ \ | \'-'/ / .-. \
|
||||||
|
| | | | | | | J /__\ L | |_)( | | | f / \ l
|
||||||
|
| | | | | | | | | ] ] | .-. \ | | | , t \ / j
|
||||||
|
/ '--' / ,'_'. |.'_'. F F / |__)/ | / '--'/ \ '-' /
|
||||||
|
/_,----' " " | " " /,' "-----' | "-----' '---'
|
||||||
|
(' | |'" | |
|
||||||
|
_,-" "-._ _,-" "-._ (C) HCB https://im.stoned.io
|
||||||
|
<_____________> <_____________> https://d2mods.org
|
||||||
|
EOT;
|
||||||
|
$cbits = [
|
||||||
|
0 => 10, 1 => 10, 2 => 10, 3 => 10, 4 => 10, 5 => 8, 6 => 21, 7 => 21, 8 => 21, 9 => 21, 10 => 21,
|
||||||
|
11 => 21, 12 => 7, 13 => 32, 14 => 25, 15 => 25, 37 => 31, 39 => 31, 41 => 31, 43 => 31, 45 => 31,
|
||||||
|
183 => 31, 184 => 31, 185 => 31]; // CSvBits to skip
|
||||||
|
|
||||||
|
$exp = [
|
||||||
|
0, 500, 1500, 3750, 7875, 14175, 22680, 32886, 44396, 57715, 72144, 90180, 112725, 140906, 176132, 220165, 275207, 344008,
|
||||||
|
430010, 537513, 671891, 839864, 1049830, 1312287, 1640359, 2050449, 2563061, 3203826, 3902260, 4663553, 5493363, 6397855,
|
||||||
|
7383752, 8458379, 9629723, 10906488, 12298162, 13815086, 15468534, 17270791, 19235252, 21376515, 23710491, 26254525, 29027522,
|
||||||
|
32050088, 35344686, 38935798, 42850109, 47116709, 51767302, 56836449, 62361819, 68384473, 74949165, 82104680, 89904191, 98405658,
|
||||||
|
107672256, 117772849, 128782495, 140783010, 153863570, 168121381, 183662396, 200602101, 219066380, 239192444, 261129853, 285041630,
|
||||||
|
311105466, 339515048, 370481492, 404234916, 441026148, 481128591, 524840254, 572485967, 624419793, 681027665, 742730244, 809986056,
|
||||||
|
883294891, 963201521, 1050299747, 1145236814, 1248718217, 1361512946, 1484459201, 1618470619, 1764543065, 1923762030, 2097310703,
|
||||||
|
2286478756, 2492671933, 2717422497, 2962400612, 3229426756, 3520485254, 3837739017];
|
||||||
|
|
||||||
|
//$file = "D:\Diablo II\MODS\ironman-dev\save\Necro.d2s";
|
||||||
|
$file = $argv[1];
|
||||||
|
if (!file_exists($file))
|
||||||
|
die("$file does not exist!");
|
||||||
|
|
||||||
|
// create ByteReader object from file binary data
|
||||||
|
$BR = new D2ByteReader(file_get_contents($file));
|
||||||
|
$data = $BR->getData();
|
||||||
|
|
||||||
|
// offset 36
|
||||||
|
// 7 6 5 4 3 2 1 0
|
||||||
|
// unknown Expansion Character unknown Died Hardcore unknown
|
||||||
|
$statusByte = unpack('C', $data[36])[1];
|
||||||
|
$dBit = getBit($statusByte, 3);
|
||||||
|
|
||||||
|
// if Character is dead, then make it alive, reduce 5 levels as penalty
|
||||||
|
|
||||||
|
if ($dBit) {
|
||||||
|
// using {} for better readability
|
||||||
|
{
|
||||||
|
$gf = strposX($data, 'gf', 1) + 2; // find gf and skip it
|
||||||
|
$if = strposX($data, 'if', 1);
|
||||||
|
$len = $if - $gf;
|
||||||
|
// create bitstream
|
||||||
|
$stats = new D2BitReader($BR->toBits($BR->readh($gf, $len)));
|
||||||
|
// remove 0x1FF from end
|
||||||
|
$bits = $stats->getBits();
|
||||||
|
$cleanbits = substr($bits, 0, -11);
|
||||||
|
$stats->setBits($cleanbits);
|
||||||
|
$bits = $stats->getBits();
|
||||||
|
// rewind bitstream
|
||||||
|
$stats->rewind();
|
||||||
|
// get bit offsets for each stat
|
||||||
|
$offsets = [];
|
||||||
|
for ($i = 0; $i < count($cbits); $i++) {
|
||||||
|
$id = hexdec($BR->toBytesR($stats->readb(9)));
|
||||||
|
$offsets[$id] = $stats->getOffset();
|
||||||
|
$stats->skip($cbits[$id]);
|
||||||
|
}
|
||||||
|
$offsets[0] = 9;
|
||||||
|
// get current character level
|
||||||
|
$level = unpack('C', $data[43])[1];
|
||||||
|
$stats->seek($offsets[12]);
|
||||||
|
$_level = hexdec($BR->toBytesR($stats->readb(7)));
|
||||||
|
// reduce current character level by 5, no penalty if < 6
|
||||||
|
if ($_level >= 80) {
|
||||||
|
$level -= 10;
|
||||||
|
} else if ($_level >= 5 || $level <= 80) {
|
||||||
|
$level -= 5;
|
||||||
|
} else if ($_level <= 5) {
|
||||||
|
$level = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$data[43] = pack('C', $level);
|
||||||
|
$statusByteNew = setBit($statusByte, 3, 0); // make character alive
|
||||||
|
$data[36] = pack('C', $statusByteNew); // make character alive
|
||||||
|
|
||||||
|
$bitsToWriteLevel = strrev(str_pad(decbin(intval($level)), $cbits[12], 0, STR_PAD_LEFT));
|
||||||
|
$bitsToWriteExp = strrev(str_pad(decbin(intval($exp[$level])), $cbits[13], 0, STR_PAD_LEFT));
|
||||||
|
|
||||||
|
$_newBitsTemp = $stats->writeBits($bits, $bitsToWriteLevel, $offsets[12]);
|
||||||
|
$newBits = $stats->writeBits($_newBitsTemp, $bitsToWriteExp, $offsets[13]) . "11111111100";
|
||||||
|
$bytes = $BR->toBytes($newBits);
|
||||||
|
|
||||||
|
$BR->setData($data);
|
||||||
|
$BR->writeBytes($gf, $bytes);
|
||||||
|
$BR->writeBytes(12, "00000000");
|
||||||
|
$checksum = checksum(unpack('C*', $BR->getData()));
|
||||||
|
$BR->writeBytes(12, $checksum);
|
||||||
|
$data = $BR->getData();
|
||||||
|
file_put_contents($file, $data);
|
||||||
|
|
||||||
|
echo "<pre>$str\n\n\nCharacter is now alive. Go take some mushrooms!\n";
|
||||||
|
echo "Previous Level: $_level\n";
|
||||||
|
echo "Revive Penalty: " . $_level - $level . "\n";
|
||||||
|
echo "New Level: $level\n";
|
||||||
|
} else {
|
||||||
|
echo "<pre>$str\n\n\nCharacter is not dead. Have you been taking mushrooms lately?";
|
||||||
|
}
|
BIN
bin/D2SC.exe
Normal file
BIN
bin/D2SC.exe
Normal file
Binary file not shown.
@ -107,10 +107,9 @@ if (file_exists(APP_DB)) {
|
|||||||
processFilesManuallyInSqlite();
|
processFilesManuallyInSqlite();
|
||||||
processFilesManuallyInSqliteLinux();
|
processFilesManuallyInSqliteLinux();
|
||||||
|
|
||||||
|
|
||||||
function toPngAll() {
|
function toPngAll() {
|
||||||
$q = realpath("bin\qdc6.exe");
|
$q = realpath("bin\qdc6.exe");
|
||||||
$iPath = $_SESSION['modpath']."\data\global\items";
|
$iPath = $_SESSION['modpath'] . "\data\global\items";
|
||||||
$oPath = realpath("docs\\{$_SESSION['modname']}\img\\items");
|
$oPath = realpath("docs\\{$_SESSION['modname']}\img\\items");
|
||||||
exec("$q --first-frame-only \"$iPath\" -o \"$oPath\"");
|
exec("$q --first-frame-only \"$iPath\" -o \"$oPath\"");
|
||||||
}
|
}
|
||||||
@ -127,33 +126,35 @@ if (file_exists(APP_DB)) {
|
|||||||
|
|
||||||
toPngAll();
|
toPngAll();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Process tbl files
|
Process tbl files
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
$tbl = $_SESSION['tbl'];
|
$tbl = $_SESSION['tbl'];
|
||||||
|
|
||||||
// ddump($tbl);
|
// ddump($tbl);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
$string = D2Tbl::getStrings($tbl."string.tbl");
|
$string = D2Tbl::getStrings($tbl."string.tbl");
|
||||||
$stringExpansion = D2Tbl::getStrings($tbl."expansionstring.tbl");
|
$stringExpansion = D2Tbl::getStrings($tbl."expansionstring.tbl");
|
||||||
$stringPatch = D2Tbl::getStrings($tbl."patchstring.tbl");
|
$stringPatch = D2Tbl::getStrings($tbl."patchstring.tbl");
|
||||||
|
|
||||||
$strings = array_merge($stringPatch, $stringExpansion, $string);
|
$strings = array_merge($stringPatch, $stringExpansion, $string);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$strs = ["dummy" => "dummy"];
|
$strs = ["dummy" => "dummy"];
|
||||||
foreach (glob($tbl . "*.tbl") as $filename) {
|
foreach (glob($tbl . "*.tbl") as $filename) {
|
||||||
$strings = D2Tbl::getStrings($filename);
|
$strings = D2Tbl::getStrings($filename);
|
||||||
if (!empty($strings))
|
if (!empty($strings))
|
||||||
$strs = array_merge($strs, $strings);
|
$strs = array_merge($strs, $strings);
|
||||||
}
|
}
|
||||||
|
|
||||||
$db->writeTbl($strs);
|
$db->writeTbl($strs);
|
||||||
|
|
||||||
|
// write each table to invidual db table
|
||||||
|
$tbl = $_SESSION['tbl'];
|
||||||
|
foreach (glob($tbl . "*.tbl") as $filename) {
|
||||||
|
$tblName = pathinfo($filename)['filename'];
|
||||||
|
$strings = D2Tbl::getStrings($filename);
|
||||||
|
if (!empty($strings)) {
|
||||||
|
$db->writeTbls($tblName, $strings);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// if config db does not exist, go to configure page
|
// if config db does not exist, go to configure page
|
||||||
header("Location: /src/D2Config.php");
|
header("Location: /src/D2Config.php");
|
||||||
|
@ -54,6 +54,7 @@ class D2BitReader {
|
|||||||
* @return array|string|string[]
|
* @return array|string|string[]
|
||||||
*/
|
*/
|
||||||
public function writeBits(string $bits, string $bitsToWrite, int $offset) {
|
public function writeBits(string $bits, string $bitsToWrite, int $offset) {
|
||||||
|
//$this->bits = substr_replace($bits, $bitsToWrite, $offset, strlen($bitsToWrite));
|
||||||
return substr_replace($bits, $bitsToWrite, $offset, strlen($bitsToWrite));
|
return substr_replace($bits, $bitsToWrite, $offset, strlen($bitsToWrite));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +64,7 @@ class D2BitReader {
|
|||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function readb(int $numBits = 0, bool $str = true): string {
|
public function readb(int $numBits = 0, bool $str = true): string {
|
||||||
$bits = null;
|
$bits = '';
|
||||||
for ($i = $this->offset; $i < $this->offset + $numBits; $i++) {
|
for ($i = $this->offset; $i < $this->offset + $numBits; $i++) {
|
||||||
$str ? $bits .= $this->bits[$i] : $bits[] = $this->bits[$i];
|
$str ? $bits .= $this->bits[$i] : $bits[] = $this->bits[$i];
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,22 @@ class D2ByteReader {
|
|||||||
* @param bool $str
|
* @param bool $str
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function readh(int $offset, int $numBytes, bool $str = true): string {
|
public function read(int $offset, int $numBytes) {
|
||||||
|
$this->seek($offset);
|
||||||
|
$bytes = null;
|
||||||
|
for ($i = $this->offset; $i < $this->offset + $numBytes; $i++) {
|
||||||
|
$bytes .= $this->data[$i];
|
||||||
|
}
|
||||||
|
return $bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $offset
|
||||||
|
* @param int $numBytes
|
||||||
|
* @param bool $str
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function readh(int $offset, int $numBytes, bool $str = true) {
|
||||||
$this->seek($offset);
|
$this->seek($offset);
|
||||||
$bytes = null;
|
$bytes = null;
|
||||||
for ($i = $this->offset; $i < $this->offset + $numBytes; $i++) {
|
for ($i = $this->offset; $i < $this->offset + $numBytes; $i++) {
|
||||||
@ -69,7 +84,7 @@ class D2ByteReader {
|
|||||||
* @param bool $str
|
* @param bool $str
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function readc(int $offset, int $numBytes, bool $str = true): array {
|
public function readc(int $offset, int $numBytes, bool $str = true) {
|
||||||
$this->seek($offset);
|
$this->seek($offset);
|
||||||
$bytes = null;
|
$bytes = null;
|
||||||
for ($i = $this->offset; $i < $this->offset + $numBytes; $i++) {
|
for ($i = $this->offset; $i < $this->offset + $numBytes; $i++) {
|
||||||
@ -187,6 +202,7 @@ class D2ByteReader {
|
|||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function toBytesR(string $bits) : string {
|
public function toBytesR(string $bits) : string {
|
||||||
|
$bytes = '';
|
||||||
foreach (str_split($bits, 8) as $byteString) {
|
foreach (str_split($bits, 8) as $byteString) {
|
||||||
$bytes .= strtoupper(str_pad(dechex(bindec(($byteString))), 2, 0, STR_PAD_LEFT));
|
$bytes .= strtoupper(str_pad(dechex(bindec(($byteString))), 2, 0, STR_PAD_LEFT));
|
||||||
}
|
}
|
||||||
|
@ -219,7 +219,7 @@ WHERE sk.charclass = '$class'";
|
|||||||
unset($this->items);
|
unset($this->items);
|
||||||
//unset($this->bData);
|
//unset($this->bData);
|
||||||
unset($this->sData);
|
unset($this->sData);
|
||||||
unset($this->fp);
|
//unset($this->fp);
|
||||||
|
|
||||||
return $this->cData;
|
return $this->cData;
|
||||||
}
|
}
|
||||||
@ -292,7 +292,7 @@ WHERE sk.charclass = '$class'";
|
|||||||
$bytes = $this->ByteReader->toBytes($bits);
|
$bytes = $this->ByteReader->toBytes($bits);
|
||||||
|
|
||||||
$stats->rewind();
|
$stats->rewind();
|
||||||
for ($i = 0; $i <= strlen($bits); $i++) {
|
for ($i = 0; $i <= count($this->ISC); $i++) {
|
||||||
$id = hexdec($this->ByteReader->toBytesR($stats->readb(9)));
|
$id = hexdec($this->ByteReader->toBytesR($stats->readb(9)));
|
||||||
if ($this->ISC[$id]['CSvBits'] !== NULL && $this->ISC[$id]['CSvBits'] !== '') {
|
if ($this->ISC[$id]['CSvBits'] !== NULL && $this->ISC[$id]['CSvBits'] !== '') {
|
||||||
$stats->skip($this->ISC[$id]['CSvBits']);
|
$stats->skip($this->ISC[$id]['CSvBits']);
|
||||||
@ -314,8 +314,8 @@ WHERE sk.charclass = '$class'";
|
|||||||
$values['maxmana'] = (int) round($values['maxmana'] >> 11);
|
$values['maxmana'] = (int) round($values['maxmana'] >> 11);
|
||||||
$values['stamina'] = (int) round($values['stamina'] >> 11);
|
$values['stamina'] = (int) round($values['stamina'] >> 11);
|
||||||
$values['maxstamina'] = (int) round($values['maxstamina'] >> 11);
|
$values['maxstamina'] = (int) round($values['maxstamina'] >> 11);
|
||||||
$values['soulcounter'] = (int) round($values['soulcounter'] / 2);
|
// $values['soulcounter'] = (int) round($values['soulcounter'] / 2);
|
||||||
$values['killcounter'] = (int) round($values['killcounter'] / 2);
|
// $values['killcounter'] = (int) round($values['killcounter'] / 2);
|
||||||
|
|
||||||
$this->cData['stats'] = $values;
|
$this->cData['stats'] = $values;
|
||||||
}
|
}
|
||||||
@ -463,7 +463,7 @@ WHERE sk.charclass = '$class'";
|
|||||||
}
|
}
|
||||||
$stats .= "000011111111100";
|
$stats .= "000011111111100";
|
||||||
|
|
||||||
dump($stats);
|
//dump($stats);
|
||||||
|
|
||||||
$gf = strposX($this->data, 'gf', 1) + 2; // find gf and skip it
|
$gf = strposX($this->data, 'gf', 1) + 2; // find gf and skip it
|
||||||
$if = strposX($this->data, 'if', 1);
|
$if = strposX($this->data, 'if', 1);
|
||||||
|
@ -140,6 +140,24 @@ class D2Database {
|
|||||||
$res = PDO_Execute($sql);
|
$res = PDO_Execute($sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $data
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function writeTbls($table,$data) {
|
||||||
|
$sql = "CREATE TABLE IF NOT EXISTS `$table` (`Key` VARCHAR(255), `String` VARCHAR(255));";
|
||||||
|
$res = PDO_Execute($sql);
|
||||||
|
|
||||||
|
$sql = "INSERT INTO `$table` (`Key`,`String`) VALUES ";
|
||||||
|
foreach ($data as $k => $v) {
|
||||||
|
$sql .= "(\"$k\",\"$v\"),";
|
||||||
|
}
|
||||||
|
$sql = rtrim($sql, ", ");
|
||||||
|
$sql .= ";";
|
||||||
|
|
||||||
|
$res = PDO_Execute($sql);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $key
|
* @param $key
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
42
test.php
42
test.php
@ -1,42 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
Diablo 2 D2S Save File Checksum Calculator
|
|
||||||
By Hash Borgir (https://www.psychedelicsdaily.com)
|
|
||||||
@date 6/4/2022
|
|
||||||
|
|
||||||
Checksum field is at byte 12.
|
|
||||||
Bytes 12/13/14/15 as a uint32.
|
|
||||||
Set this to 0.
|
|
||||||
After clearing the checksum field add up the values of all the bytes in the file and rotate the running total one bit to the left before adding the next byte.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function swapEndianness(string $hex) {
|
|
||||||
return implode('', array_reverse(str_split($hex, 2)));
|
|
||||||
}
|
|
||||||
|
|
||||||
function checksum($fileData) {
|
|
||||||
$nSignature = 0;
|
|
||||||
foreach ($fileData as $k => $byte) {
|
|
||||||
if ($k == 12 || $k == 13 || $k == 14 || $k == 15) {
|
|
||||||
$byte = 0;
|
|
||||||
}
|
|
||||||
$nSignature = ((($nSignature << 1) | ($nSignature >> 31)) + $byte & 0xFFFFFFFF);
|
|
||||||
}
|
|
||||||
return swapEndianness(str_pad(dechex($nSignature), 8, 0, STR_PAD_LEFT));
|
|
||||||
}
|
|
||||||
|
|
||||||
$filename = "D:\Diablo II\MODS\ironman-dev\save\Necro.d2s";
|
|
||||||
$fp = fopen($filename, "r+b");
|
|
||||||
|
|
||||||
fseek($fp, 12); // go to byte 12
|
|
||||||
fwrite($fp, pack('I', 0)); // clear the checksum field uInt32
|
|
||||||
|
|
||||||
$fileData = unpack('C*', file_get_contents($filename)); // open file and unpack
|
|
||||||
|
|
||||||
|
|
||||||
var_dump(checksum($fileData));
|
|
||||||
|
|
||||||
fseek($fp, 12); // go to byte 12
|
|
||||||
fwrite($fp, pack('H8', checksum($fileData))); // write new checksum
|
|
||||||
fclose($fp);
|
|
Loading…
Reference in New Issue
Block a user