|
<?php |
|
|
|
/** |
|
* https://gist.github.com/esterTion/768c646a83a089af9e5fbb83b77a59fc |
|
* Updated for il2cpp-dumper v6.1.2 |
|
* https://github.com/Perfare/Il2CppDumper/releases |
|
*/ |
|
|
|
$dumpcs = file_get_contents('D:\\ida_workplace\\bang\\dump.cs'); |
|
$prog = fopen('D:\\ida_workplace\\bang\\UnityFramework','rb'); |
|
|
|
$definedClass=[]; |
|
$class = $argv[1]; |
|
$outputProtoFile = fopen(__DIR__.'/'.$class.'_gen.proto', 'w'); |
|
fwrite($outputProtoFile, "syntax = \"proto2\";\n"); |
|
function stripClass($s) { |
|
$idx = strrpos($s, '.'); |
|
if ($idx === false) return $s; |
|
return substr($s, $idx + 1); |
|
} |
|
function writeMessage($class, $message) { |
|
global $outputProtoFile; |
|
$class = stripClass($class); |
|
fwrite($outputProtoFile, "message ${class} {\n"); |
|
foreach ($message as $item=>$info) { |
|
$type = stripClass($info[0]); |
|
$tag = $info[1]; |
|
$hint = $info[2]; |
|
$comment = $info[3]; |
|
fwrite($outputProtoFile, " ${hint} ${type} ${item} = ${tag}; // ${comment}\n"); |
|
} |
|
fwrite($outputProtoFile, "}\n"); |
|
} |
|
|
|
function readClass($level, $class) { |
|
global $dumpcs; |
|
global $definedClass; |
|
if (($shownClass = array_search($class, $definedClass)) === false) { |
|
$definedClass[] = $class; |
|
} |
|
$message = []; |
|
//echo str_repeat(" ", $level).$class."\n"; |
|
if (preg_match("(\[ProtoContract\].*\n\w+ class ".$class." [^{}]*?(\{((?>[^{}]+)|(?-2))*\}))", $dumpcs, $classDef) !== 0) { |
|
$classDef=$classDef[0]; |
|
preg_match_all('(\[ProtoMember\((\d+)\)\].*\n \w+ ([^\ \<]+(\<((?>[^\<\>]+)|(?-2))*\>)?) ([^\ ;]+))', $classDef, $propList); |
|
for($i=0;$i<count($propList[0]); $i++) { |
|
$type = jumpType( |
|
$level, |
|
$propList[2][$i], |
|
$propList[5][$i] |
|
); |
|
$message[$type[0]] = [$type[1], $propList[1][$i], $type[2], $type[3]]; |
|
} |
|
if ($class == 'MasterActionSet') { |
|
$message['areaName'] = [ |
|
'string', |
|
6, |
|
'optional', |
|
'manual add' |
|
]; |
|
} |
|
if (!$shownClass) { |
|
echo $class."\n"; |
|
//print_r($message); |
|
writeMessage($class, $message); |
|
} |
|
unset($message); |
|
} else { |
|
echo $class.' not found'; |
|
exit; |
|
} |
|
} |
|
// 1012ECB5C 1 |
|
// 1012ECB70 2 |
|
function jumpType ($level, $type, $name) { |
|
if (substr($type, -2, 2) == '[]') { |
|
// array entry |
|
//echo str_repeat(" ", $level+1).$type."\n"; |
|
$sub = jumpType($level+2, substr($type, 0, -2), 'entry'); |
|
return [$name, $sub[1], 'repeated', 'array']; |
|
} else if (substr($type, 0, 11) == 'Dictionary<') { |
|
// dictionary |
|
preg_match('(<(\w+), (\w+)>)', $type, $subType); |
|
//echo str_repeat(" ", $level+1).'dictarr_'.$name."[]\n"; |
|
$prefix = $subType[1].'_'.$subType[2]; |
|
global $definedClass; |
|
if (($shownClass = array_search($prefix, $definedClass)) === false) { |
|
$definedClass[] = $prefix; |
|
} |
|
$message = []; |
|
$sub = jumpType($level+1, $subType[1], $prefix.'_key'); |
|
$message[$sub[0]] = [$sub[1], 1, $sub[2], $sub[3]]; |
|
$sub = jumpType($level+1, $subType[2], $prefix.'_value'); |
|
$message[$sub[0]] = [$sub[1], 2, $sub[2], $sub[3]]; |
|
if (!$shownClass) { |
|
writeMessage($prefix, $message); |
|
} |
|
return [$name,$prefix, 'repeated', 'dictionary']; |
|
} else if (substr($type, 0, 5) == 'List<') { |
|
// array entry |
|
preg_match('(<(\w+)>)', $type, $subType); |
|
//echo str_repeat(" ", $level+1).'arr_'.$name."[]\n"; |
|
$sub = jumpType($level+1, $subType[1], 'entry'); |
|
return [$name,$sub[1], 'repeated', 'list']; |
|
} else if (array_search($type, |
|
['uint','string','ulong','float','int','double', 'bool','long'] |
|
) !== false){ |
|
// normal type |
|
//echo str_repeat(" ", $level+1).'<'.$type .'> '. $name."\n"; |
|
return [$name,array('uint'=>'uint32','string'=>'string','ulong'=>'uint64','float'=>'float','int'=>'int32','double'=>'double', 'bool'=>'bool','long'=>'int64')[$type], 'optional', 'normal type']; |
|
} else if (substr($type, 0, 9) == 'Nullable<') { |
|
// array entry |
|
//echo str_repeat(" ", $level+1).'<'.$type .'> '. $name."\n"; |
|
//return [$name,$type, 'optional', 'nullable type']; |
|
preg_match('(<(\w+)>)', $type, $subType); |
|
$return = jumpType($level, $subType[1], $name); |
|
$return[3] = 'nullable'; |
|
return $return; |
|
} else { |
|
// sub message |
|
readClass($level+1, $type); |
|
return [$name,$type, 'optional', 'sub class']; |
|
} |
|
} |
|
readClass(0, $class); |
@YumeMichi 不知道为什么更新了一下评论不见了……
现在新版本的il2cpp dumper会直接帮你读属性值,所以直接匹配
dump.cs
里面[ProtoMembere(\d+)]
就能拿key了。同理,原本的
[ProtoContractAttribute]
都变成[ProtoContract()]
了