|
<?php |
|
|
|
if (!function_exists('mb_ord')) { |
|
function mb_ord($v) { |
|
$k = mb_convert_encoding($v, 'UCS-2LE', 'UTF-8'); |
|
$k1 = ord(substr($k, 0, 1)); |
|
$k2 = ord(substr($k, 1, 1)); |
|
return $k2 * 256 + $k1; |
|
} |
|
function mb_chr($num){ |
|
return mb_convert_encoding('&#'.intval($num).';', 'UTF-8', 'HTML-ENTITIES'); |
|
} |
|
} |
|
|
|
require 'UnityBundle.php'; |
|
|
|
$sndFile = 'MD_Costume'; |
|
$sndMemberType = parseMemberType('osososoioioiososoioioioioiosoioioioioiosososososososososososososososoioioioiososososososososososososoiososoioi'); |
|
$sndMemberName = ['_ID','_Name','_Detail','_IsShowCollection','_ShowCollectionNo','_Default','_GraphicID','_CanEquipCharacterIds','_Rarity','_WeaponKind','_ItemKindID','_InitMaxLevel','_MaxLevel','_ExpTableID','_Element','_HPLevel1','_HPLevelMax','_AttackLevel1','_AttackLevelMax','_ActiveSkillID','_ActiveSkillIDLB1','_ActiveSkillIDLB2','_ActiveSkillIDLB3','_ActiveSkillIDLB4','_ActiveSkillID2','_ActiveSkillID2LB1','_ActiveSkillID2LB2','_ActiveSkillID2LB3','_ActiveSkillID2LB4','_LeaderSkillID','_LeaderSkillIDLB1','_LeaderSkillIDLB2','_LeaderSkillIDLB3','_LeaderSkillIDLB4','_GainExp','_SellGameCoin','_SellDollsPoint','_SellRealCoinFree','_UnLockSubScenarioID','_SpecialID','_HeadAvatarID','_FaceAvatarID','_EarAvatarID','_UpBodyAvatarID','_LowBodyAvatarID','_AnotherHeadAvatarID','_AnotherFaceAvatarID','_AnotherEarAvatarID','_AnotherUpBodyAvatarID','_AnotherLowBodyAvatarID','_CostumeVersion','_LimitbreakBonusHPID','_LimitbreakBonusATKID','_MaxLimitbreakCount','_IsSubLimited']; |
|
//$sndFile = 'MD_AssetbundleDLPackVer'; |
|
//$sndMemberType = 'siissas'; |
|
|
|
$dat = file_get_contents($sndFile.'.snd'); |
|
$mdkey = 'j6GWCVK9UMKKd3pnNDtxYFSZ4zHiQ9xD'; |
|
$mdiv = 'dQATZ4QY7gahQaT5'; |
|
|
|
$dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $mdkey, $dat, MCRYPT_MODE_CBC, $mdiv); |
|
$pad = ord(substr($dec, -1, 1)); |
|
|
|
$dec = substr($dec, 0, -$pad); |
|
file_put_contents($sndFile.'-dec.snd.gz', $dec); |
|
|
|
file_put_contents($sndFile.'-dec.snd', gzdecode($dec)); |
|
|
|
$st = new FileStream($sndFile.'-dec.snd'); |
|
$st->littleEndian = true; |
|
$st->long; |
|
$entries = $st->long; |
|
$st->long;$st->long; |
|
$map = []; |
|
echo "$entries\n"; |
|
for ($i=0; $i<$entries; $i++) { |
|
$val = []; |
|
for ($j=0; $j<count($sndMemberType); $j++) { |
|
$name = $sndMemberName[$j]; |
|
$value = readValue($sndMemberType[$j], $st); |
|
$val[$name] = $value; |
|
} |
|
$map[$val['_ID']] = $val['_Name']; |
|
echo "\r$i"; |
|
} |
|
file_put_contents($sndFile.'-dec.json', json_encode($map)); |
|
|
|
function parseMemberType($typeStr) { |
|
$val = []; |
|
for ($i=0; $i<strlen($typeStr); $i++) { |
|
//$isArray = false; |
|
$isObfuscated = false; |
|
/*if ($typeStr[$i] == 'a') { |
|
$isArray = true; |
|
$i++; |
|
}*/ |
|
if ($typeStr[$i] == 'o') { |
|
$isObfuscated = true; |
|
$i++; |
|
} |
|
$val[] = [ |
|
'type' => $typeStr[$i], |
|
//'isArray' => $isArray, |
|
'isObfuscated' => $isObfuscated |
|
]; |
|
} |
|
return $val; |
|
} |
|
|
|
function readValue($type, Stream $stream) { |
|
switch ($type['type']) { |
|
case 's' : { |
|
$len = ord($stream->byte); |
|
$str = $stream->readData($len); |
|
if ($type['isObfuscated']) { |
|
// SimpleModules__Shift(string source, int shift, int step) |
|
$output = ''; |
|
$shift = 11; $step = 3; |
|
for ($i=0; $i<mb_strlen($str, 'UTF-8'); $i++) { |
|
$v9 = mb_ord(mb_substr($str, $i, 1, 'UTF-8')); |
|
$v11 = ($v9 + $shift); |
|
$output .= mb_chr($v11); |
|
$shift += $step; |
|
} |
|
$str = $output; |
|
} |
|
return $str; |
|
} |
|
case 'i': { |
|
$val = $stream->long; |
|
if ($type['isObfuscated']) { |
|
$val ^= 0x7fef; |
|
} |
|
return $val; |
|
} |
|
default: { |
|
throw new Exception("unknown type {$type[$index]}"); |
|
} |
|
} |
|
} |