v50 Steam/Premium information for editors
- v50 information can now be added to pages in the main namespace. v0.47 information can still be found in the DF2014 namespace. See here for more details on the new versioning policy.
- Use this page to report any issues related to the migration.
This notice may be cached—the current version can be found here.
Difference between revisions of "User:Quietust/wtf23a.php"
Jump to navigation
Jump to search
(add 23a Weird Text Format tool; also works on saved games (and shrinks them down by a noticeable amount)) |
m (make a few tweaks) |
||
Line 1: | Line 1: | ||
− | <nowiki> | + | <nowiki><?php |
− | <?php | ||
function readByte ($file) | function readByte ($file) | ||
{ | { | ||
Line 58: | Line 57: | ||
} | } | ||
− | function | + | function _readCrypt ($file) |
{ | { | ||
+ | // read mt state | ||
+ | $state = array(); | ||
+ | for ($i = 0; $i < 625; $i++) | ||
+ | $state[$i] = readLong($file); | ||
+ | if (feof($file)) | ||
+ | return false; | ||
+ | |||
+ | // read header | ||
+ | $len = readLong($file); | ||
+ | $data = range(0, $len - 1); | ||
+ | |||
$rng = new rng; | $rng = new rng; | ||
− | |||
// read data, skipping dummy bytes | // read data, skipping dummy bytes | ||
− | $rng->init($ | + | $rng->init($state); |
for ($i = $len - 1; $i >= 0; $i--) | for ($i = $len - 1; $i >= 0; $i--) | ||
{ | { | ||
Line 76: | Line 85: | ||
// decode data | // decode data | ||
− | $rng->init($ | + | $rng->init($state); |
for ($i = $len - 1; $i >= 0; $i--) | for ($i = $len - 1; $i >= 0; $i--) | ||
$data[$i] -= $rng->get(10); | $data[$i] -= $rng->get(10); | ||
Line 85: | Line 94: | ||
$out .= chr($data[$i] & 0xFF); | $out .= chr($data[$i] & 0xFF); | ||
return $out; | return $out; | ||
+ | } | ||
+ | |||
+ | function _writeCrypt ($file, $data) | ||
+ | { | ||
+ | // write mt state | ||
+ | for ($i = 0; $i < 625; $i++) | ||
+ | writeLong($file, 0); | ||
+ | |||
+ | // write header | ||
+ | $len = strlen($data); | ||
+ | writeLong($file, $len); | ||
+ | |||
+ | // write data | ||
+ | // since mt state is null, this is much simpler than above | ||
+ | for ($i = $len; $i > 0; $i--) | ||
+ | fwrite($file, $data[$i-1], 1); | ||
} | } | ||
Line 92: | Line 117: | ||
{ | { | ||
$data = fread($in, 20000); | $data = fread($in, 20000); | ||
− | |||
− | |||
$comp = gzcompress($data, 9); | $comp = gzcompress($data, 9); | ||
if ($comp === FALSE) | if ($comp === FALSE) | ||
return false; | return false; | ||
− | + | ||
− | + | _writeCrypt($out, $comp); | |
− | |||
− | |||
if (feof($in)) | if (feof($in)) | ||
break; | break; | ||
Line 111: | Line 132: | ||
while (1) | while (1) | ||
{ | { | ||
− | $ | + | $block = _readCrypt($in); |
− | + | if ($block === FALSE) | |
− | |||
− | if | ||
break; | break; | ||
− | |||
− | |||
$decomp = gzuncompress($block); | $decomp = gzuncompress($block); | ||
if ($decomp === FALSE) | if ($decomp === FALSE) |
Revision as of 20:44, 14 April 2014
<?php function readByte ($file) { $x = fread($file, 1); $pck = @unpack('Cdata', $x); return $pck['data']; } function readLong ($file) { $x = fread($file, 4); $pck = @unpack('Vdata', $x); return $pck['data']; } function writeLong ($file, $data) { $x = @pack('V', $data); fwrite($file, $x, 4); } class rng { var $data = array(); var $index = 0; function init ($data) { for ($i = 0; $i < 624; $i++) $this->data[$i] = $data[$i]; $this->index = $data[624] / 4; } function get ($i) { $x = $this->next(); if ($x < 0) return (int)fmod($x + 4294967296.0, $i); return $x % $i; } function next() { if ($this->index == 624) $this->generate(); return $this->data[$this->index++]; } function generate() { for ($i = 0; $i < 624; $i++) { $y = ($this->data[$i] & 0x80000000) | ($this->data[($i+1) % 624] & 0x7FFFFFFF); $this->data[$i] = $this->data[($i + 397) % 624] ^ (($y >> 1) & 0x7FFFFFFF); if ($y & 1) $this->data[$i] ^= 0x9908b0df; } $this->index = 0; } } function _readCrypt ($file) { // read mt state $state = array(); for ($i = 0; $i < 625; $i++) $state[$i] = readLong($file); if (feof($file)) return false; // read header $len = readLong($file); $data = range(0, $len - 1); $rng = new rng; // read data, skipping dummy bytes $rng->init($state); for ($i = $len - 1; $i >= 0; $i--) { $data[$i] = readByte($file); if ($rng->get(2)) { $rng->get(256); readByte($file); } } // decode data $rng->init($state); for ($i = $len - 1; $i >= 0; $i--) $data[$i] -= $rng->get(10); // convert to string $out = ''; for ($i = 0; $i < $len; $i++) $out .= chr($data[$i] & 0xFF); return $out; } function _writeCrypt ($file, $data) { // write mt state for ($i = 0; $i < 625; $i++) writeLong($file, 0); // write header $len = strlen($data); writeLong($file, $len); // write data // since mt state is null, this is much simpler than above for ($i = $len; $i > 0; $i--) fwrite($file, $data[$i-1], 1); } function compress_file ($in, $out) { while (1) { $data = fread($in, 20000); $comp = gzcompress($data, 9); if ($comp === FALSE) return false; _writeCrypt($out, $comp); if (feof($in)) break; } return true; } function decompress_file ($in, $out) { while (1) { $block = _readCrypt($in); if ($block === FALSE) break; $decomp = gzuncompress($block); if ($decomp === FALSE) return false; fwrite($out, $decomp); } return true; } function unpack_file ($in, $out) { $numrecords = readLong($in); for ($i = 0; $i < $numrecords; $i++) { $len = readLong($in); if ($len < 1) return false; $str = fread($in, $len); if (feof($in)) return false; if ($out) fwrite($out, "$str\r\n"); else echo "$str\n"; fread($in, 1); } return true; } function pack_file ($in, $out) { $data = explode("\n", trim(stream_get_contents($in))); $numrecords = count($data); writeLong($out, $numrecords); for ($i = 0; $i < $numrecords; $i++) { $line = trim($data[$i]); $len = strlen($line); writeLong($out, $len); fwrite($out, $line, $len); fwrite($out, chr(0), 1); } return true; } function decompack_file ($in, $out) { $tmp = tmpfile(); if (!decompress_file($in, $tmp)) return false; rewind($tmp); if (!unpack_file($tmp, $out)) return false; fclose($tmp); return true; } function compack_file ($in, $out) { $tmp = tmpfile(); if (!pack_file($in, $tmp)) return false; rewind($tmp); if (!compress_file($tmp, $out)) return false; fclose($tmp); return true; } function copy_file ($in, $out) { while (!feof($in)) { $data = fread($in, 1048576); fwrite($out, $data); } return true; } function error ($str) { fprintf(STDERR, "ERROR: %s\n", $str); exit(2); } function usage ($command = '') { global $argv; switch ($command) { case 'decompress': fprintf(STDERR, "Syntax: %s decompress <infile> [outfile]\n", $argv[0]); fprintf(STDERR, "Omit [outfile] to decompress the file in-place.\n"); break; case 'compress': fprintf(STDERR, "Syntax: %s compress <infile> [outfile]\n", $argv[0]); fprintf(STDERR, "Omit [outfile] to compress the file in-place.\n"); break; case 'recompress': fprintf(STDERR, "Syntax: %s recompress <file>\n", $argv[0]); break; case 'unpack': fprintf(STDERR, "Syntax: %s unpack <infile> [outfile]\n", $argv[0]); fprintf(STDERR, "Omit [outfile] to unpack the file in-place.\n"); fprintf(STDERR, "Specify an outfile of '-' to print directly to the screen.\n"); break; case 'pack': fprintf(STDERR, "Syntax: %s pack <infile> [outfile]\n", $argv[0]); fprintf(STDERR, "Omit [outfile] to pack the file in-place.\n"); break; case 'decompack': fprintf(STDERR, "Syntax: %s decompack <infile> [outfile]\n", $argv[0]); fprintf(STDERR, "Omit [outfile] to decompress and unpack the file in-place.\n"); fprintf(STDERR, "Specify an outfile of '-' to print directly to the screen.\n"); break; case 'compack': fprintf(STDERR, "Syntax: %s compack <infile> [outfile]\n", $argv[0]); fprintf(STDERR, "Omit [outfile] to pack and compress the file in-place.\n"); break; default: fprintf(STDERR, "Syntax: %s <command> args...\n", $argv[0]); fprintf(STDERR, "Valid commands:\n"); fprintf(STDERR, " decompress <infile> [outfile] - decrypts and extracts a binary file.\n"); fprintf(STDERR, " compress <infile> [outfile] - compresses and encrypts a binary file.\n"); fprintf(STDERR, " recompress <file> - recompresses a compressed a binary file in place.\n"); fprintf(STDERR, " unpack <infile> [outfile] - converts packed text into plain text.\n"); fprintf(STDERR, " pack <infile> [outfile] - converts plain text into packed text.\n"); fprintf(STDERR, " decompack <infile> [outfile] - decrypts, extracts, and unpacks text.\n"); fprintf(STDERR, " compack <infile> [outfile] - packs, compresses, and encrypts text.\n"); break; } exit(1); } function operation ($infn, $inmode, $outfn, $outmode, $op1, $op1desc, $op2, $op2desc) { $in_place = ($infn == $outfn); $ts = filemtime($infn); $infile = fopen($infn, $inmode); if (!$infile) error("Unable to open input file '$infn'!"); if ($in_place) $outfile = tmpfile(); else { if ($outfn) { $outfile = fopen($outfn, $outmode); if (!$outfile) error("Unable to create output file '$outfn'!"); } else $outfile = NULL; } if (!$op1($infile, $outfile)) error("Failed to $op1desc '$infn'!"); fclose($infile); if ($in_place) { $infile = $outfile; rewind($infile); $outfile = fopen($outfn, $outmode); if (!$op2($infile, $outfile)) error("Failed to $op2desc '$outfn'!"); fclose($infile); } if ($outfile) { fclose($outfile); touch($outfn, $ts); } } if ($argc < 2) usage(); switch ($argv[1]) { case 'decompress': if ($argc < 3) usage($argv[1]); $infn = $argv[2]; $outfn = ($argc < 4) ? $infn : $argv[3]; operation($infn, 'rb', $outfn, 'wb', 'decompress_file', 'decompress', 'copy_file', 'copy output back to'); break; case 'compress': if ($argc < 3) usage($argv[1]); $infn = $argv[2]; $outfn = ($argc < 4) ? $infn : $argv[3]; operation($infn, 'rb', $outfn, 'wb', 'compress_file', 'compress', 'copy_file', 'copy output back to'); break; case 'recompress': if ($argc < 3) usage($argv[1]); $fn = $argv[2]; operation($fn, 'rb', $fn, 'wb', 'decompress_file', 'decompress', 'compress_file', 'recompress'); break; case 'unpack': if ($argc < 3) usage($argv[1]); $infn = $argv[2]; $outfn = ($argc < 4) ? $infn : (($argv[3] == '-') ? '' : $argv[3]); operation($infn, 'rb', $outfn, 'w', 'unpack_file', 'unpack', 'copy_file', 'copy output back to'); break; case 'pack': if ($argc < 3) usage($argv[1]); $infn = $argv[2]; $outfn = ($argc < 4) ? $infn : $argv[3]; operation($infn, 'r', $outfn, 'wb', 'pack_file', 'unpack', 'copy_file', 'copy output back to'); break; case 'decompack': if ($argc < 3) usage($argv[1]); $infn = $argv[2]; $outfn = ($argc < 4) ? $infn : (($argv[3] == '-') ? '' : $argv[3]); operation($infn, 'rb', $outfn, 'w', 'decompack_file', 'decompress and unpack', 'copy_file', 'copy output back to'); break; case 'compack': if ($argc < 3) usage($argv[1]); $infn = $argv[2]; $outfn = ($argc < 4) ? $infn : $argv[3]; operation($infn, 'r', $outfn, 'wb', 'compack_file', 'pack and compress', 'copy_file', 'copy output back to'); break; default: fprintf(STDERR, "Invalid command '%s'!\n", $mode); break; } ?>