private function parseDocumentHeader($string) { $numByte = 44; // skip header and unknown stuff $numDeps = MPQFile::readByte($string, $numByte); // uncertain that this is the number of dependencies, might also be uint32 if it is $numByte += 3; while ($numDeps > 0) { while (MPQFile::readByte($string, $numByte) !== 0) { } $numDeps--; } $numAttribs = MPQFile::readUInt32($string, $numByte); $attribs = array(); while ($numAttribs > 0) { $keyLen = MPQFile::readUInt16($string, $numByte); $key = MPQFile::readBytes($string, $numByte, $keyLen); $numByte += 4; // always seems to be followed by ascii SUne $valueLen = MPQFile::readUInt16($string, $numByte); $value = MPQFile::readBytes($string, $numByte, $valueLen); $attribs[$key] = $value; $numAttribs--; } $this->author = $attribs["DocInfo/Author"]; $this->mapName = $attribs["DocInfo/Name"]; $this->description = $attribs["DocInfo/DescLong"]; $this->shortDescription = $attribs["DocInfo/DescShort"]; }
public function addFakeObserver($obsName) { return false; // this function does not work currently so DO NOT USE! if (!$this->init || $this->getFileSize("replay.initData") == 0) { return false; } $string = $this->readFile("replay.initData"); $numByte = 0; $numPlayers = MPQFile::readByte($string, $numByte); $playerAdded = false; $playerId = 0; for ($i = 1; $i <= $numPlayers; $i++) { $nickLen = MPQFile::readByte($string, $numByte); if ($nickLen > 0) { $numByte += $nickLen; $numByte += 5; } elseif (!$playerAdded) { // first empty slot $playerAdded = true; $numByte--; if ($i == $numPlayers) { $len = 5; } else { $len = 6; } // add the player to the initdata file $obsNameLength = strlen($obsName); $repString = chr($obsNameLength) . $obsName . str_repeat(chr(0), 5); $newData = substr($string, 0, $numByte) . $repString . substr($string, $numByte - $len + strlen($repString)); $numByte += strlen($repString); //$this->replaceFile("replay.initData", $newData); $playerId = $i; $string = $newData; // skip the next null part because it is 1 byte shorter than normal if ($i < $numPlayers) { $i++; $numByte += 4; } } else { $numByte += 5; } } if ($this->debug) { $this->debug(sprintf("Got past first player loop, counter = {$i}, numbyte: %04X", $numByte)); } if ($playerId == 0) { return false; } $numByte += 25; $accountIdentifierLength = MPQFile::readByte($string, $numByte); if ($accountIdentifierLength > 0) { $accountIdentifier = MPQFile::readBytes($string, $numByte, $accountIdentifierLength); } $numByte += 684; // length seems to be fixed, data seems to vary at least based on number of players while (true) { $str = MPQFile::readBytes($string, $numByte, 4); if ($str != 's2ma') { $numByte -= 4; break; } $numByte += 2; // 0x00 0x00 $realm = MPQFile::readBytes($string, $numByte, 2); $this->realm = $realm; $numByte += 32; } // start of variable length data portion $numByte += 2; $numPlayers = MPQFile::readByte($string, $numByte); // need to increment numplayers by 1 $string = substr_replace($string, pack("c", $numPlayers + 1), $numByte - 1, 1); $numByte += 4; for ($i = 1; $i <= $numPlayers; $i++) { $firstByte = MPQFile::readByte($string, $numByte); $secondByte = MPQFile::readByte($string, $numByte); if ($this->debug) { $this->debug(sprintf("Function addFakeObserver: numplayer: %d, first byte: %02X, second byte: %02X", $i, $firstByte, $secondByte)); } switch ($firstByte) { case 0xca: switch ($secondByte) { case 0x20: // player $numByte += 20; break; case 0x28: // player $numByte += 24; break; case 0x4: case 0x2: // spectator // spectator case 0x0: // computer $numByte += 4; break; } break; case 0xc2: switch ($secondByte) { case 0x4: $tmp = MPQFile::readByte($string, $numByte); if ($tmp == 0x5) { $numByte += 4; } $numByte += 20; break; case 0x24: case 0x44: $numByte += 5; break; } break; default: if ($this->debug) { $this->debug(sprintf("Function addFakeObserver: Unknown byte at byte offset %08X, got %02X", $numByte, $firstByte)); } return false; } } // insert join game event and initial camera event for the newly created player $string = $this->readFile("replay.game.events"); $string = substr_replace($string, pack("c3", 0, $playerId, 0xb), 0, 0); $tmpByte = $i * 3 + 5; $camerastring = pack("c2", 0, 0x60 | $playerId) . MPQFile::readBytes($string, $tmpByte, 11); $string = substr_replace($string, $camerastring, $tmpByte, 0); $this->replaceFile("replay.game.events", $string); return $playerId; }
static function parseTimeStamp($string, &$numByte) { $one = MPQFile::readByte($string, $numByte); if (($one & 3) > 0) { // check if value is two bytes or more $two = MPQFile::readByte($string, $numByte); $two = $one >> 2 << 8 | $two; if (($one & 3) >= 2) { $tmp = MPQFile::readByte($string, $numByte); $two = $two << 8 | $tmp; if (($one & 3) == 3) { $tmp = MPQFile::readByte($string, $numByte); $two = $two << 8 | $tmp; } } return $two; } return $one >> 2; }