Skip to content

Commit

Permalink
1.5
Browse files Browse the repository at this point in the history
PPtr bool fix
TypeTreeBlob read fix
BinaryReader super use
  • Loading branch information
K0lb3 committed Nov 4, 2020
1 parent 9f9f839 commit 89de7f4
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 201 deletions.
11 changes: 7 additions & 4 deletions UnityPy/AssetsManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def __init__(self, *args):
self.assets = {}
self.resource_file_readers = {}
self.import_files = {}

self.path = "."
self.Progress = Progress()

if args:
Expand All @@ -48,10 +48,13 @@ def __init__(self, *args):
if os.path.splitext(arg)[-1] in [".apk", ".zip"]:
self.load_zip_file(arg)
else:
self.path = os.path.dirname(arg)
self.load_file(arg)
elif os.path.isdir(arg):
self.path = arg
self.load_folder(arg)
else:
self.path = None
self.load_file(arg)

def load_files(self, files: list):
Expand Down Expand Up @@ -111,10 +114,10 @@ def load_assets_file(self, full_name: str, reader: EndianBinaryReader):
if file_name not in self.assets:
logging.info(f"Loading {full_name}")
try:
assets_file = SerializedFile(self, full_name, reader)
self.assets[assets_file.name] = assets_file
assets_file = SerializedFile(self, reader)
self.assets[file_name] = assets_file

for sharedFile in assets_file._externals:
for sharedFile in assets_file.externals:
shared_file_path = os.path.join(
os.path.dirname(full_name), sharedFile.name
)
Expand Down
2 changes: 1 addition & 1 deletion UnityPy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "1.4.6.3"
__version__ = "1.5"

from .environment import Environment

Expand Down
178 changes: 39 additions & 139 deletions UnityPy/classes/PPtr.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from ..streams import EndianBinaryReader, EndianBinaryWriter


def save_ptr(obj, writer: EndianBinaryWriter, version):
if isinstance(obj, PPtr):
writer.write_int(obj.file_id)
Expand All @@ -10,19 +11,22 @@ def save_ptr(obj, writer: EndianBinaryWriter, version):
else:
writer.write_long(obj.path_id)


class PPtr:
def __init__(self, reader: EndianBinaryReader):
self._version = reader.version2
self.index = -2
self.file_id = reader.read_int()
self.path_id = reader.read_int() if self._version < 14 else reader.read_long()
self.path_id = reader.read_int() if self._version < 14 else reader.read_long()
self.assets_file = reader.assets_file
self._obj = None

def save(self, writer: EndianBinaryWriter):
save_ptr(self, writer, self._version)

def __getattr__(self, key):
# get manager
def get_obj(self):
if self._obj != None:
return self._obj
manager = None
if self.file_id == 0:
manager = self.assets_file
Expand All @@ -36,145 +40,41 @@ def __getattr__(self, key):
external_name = external_name.upper()
manager = self.assets_file.parent.files[external_name]

"""
for sharedFile in assets_file.externals:
shared_file_path = os.path.join(
os.path.dirname(full_name), sharedFile.name
)
shared_file_name = sharedFile.name
if shared_file_name not in self.import_files:
if not os.path.exists(shared_file_path):
find_files = [
f
for f in ImportHelper.list_all_files(
os.path.dirname(full_name)
)
if shared_file_name in f
]
if find_files:
shared_file_path = find_files[0]
if os.path.exists(shared_file_path):
self.import_files[shared_file_name] = shared_file_path
"""

if manager and self.path_id in manager.objects:
self = manager.objects[self.path_id]
return getattr(self, key)

if self.index != -2:
raise NotImplementedError("PPtr")

"""
if (!assetsFileIndexCache.TryGetValue(name, out index))
{
index = assetsFileList.FindIndex(x => x.upperFileName == name);
assetsFileIndexCache.Add(name, index);
}
}
if (index >= 0)
{
result = assetsFileList[index];
return true;
}
}
if self.path_id in self.assets_file.objects:
return self.assets_file.objects[self.path_id]
self._obj = manager.objects[self.path_id]
else:
return super(PPtr, self).__new__(self)
"""
self._obj = False

def __repr__(self):
return self.__class__.__name__
return self._obj

def __bool__(self):
return False

"""
def TryGetAssetsFile(self):
result = None
if m_FileID == 0:
return self.assets_file
def __getattr__(self, key):
return getattr(self._obj, key)

if m_FileID > 0 and m_FileID - 1 < len(self.assets_file.externals):
var assetsManager = assetsFile.assetsManager
var assetsFileList = assetsManager.assetsFileList
var assetsFileIndexCache = assetsManager.assetsFileIndexCache
def __repr__(self):
return "<%s %s>" % (self.__class__.__name__, self._obj.__class__.__repr__(self.get_obj()) if self.get_obj() else "Not Found")

if self.index == -2:
external_name = self.assets_file.eternals[self.file_id - 1].filename
if (!assetsFileIndexCache.TryGetValue(name, out index))
{
index = assetsFileList.FindIndex(x => x.upperFileName == name);
assetsFileIndexCache.Add(name, index);
}
}
if (index >= 0)
{
result = assetsFileList[index];
return true;
}
}
return false;
}
public bool TryGet(out T result)
{
if (TryGetAssetsFile(out var sourceFile))
{
if (sourceFile.Objects.TryGetValue(m_PathID, out var obj))
{
if (obj is T variable)
{
result = variable;
return true;
}
}
}
result = null;
return false;
}
public bool TryGet<T2>(out T2 result) where T2 : Object
{
if (TryGetAssetsFile(out var sourceFile))
{
if (sourceFile.Objects.TryGetValue(m_PathID, out var obj))
{
if (obj is T2 variable)
{
result = variable;
return true;
}
}
}
result = null;
return false;
}
public void Set(T m_Object)
{
var name = m_Object.assetsFile.upperFileName;
if (string.Equals(assetsFile.upperFileName, name, StringComparison.Ordinal))
{
m_FileID = 0;
}
else
{
m_FileID = assetsFile.m_Externals.FindIndex(x => string.Equals(x.fileName, name, StringComparison.OrdinalIgnoreCase));
if (m_FileID == -1)
{
assetsFile.m_Externals.Add(new FileIdentifier
{
fileName = m_Object.assetsFile.fileName
});
m_FileID = assetsFile.m_Externals.Count;
}
else
{
m_FileID += 1;
}
}
var assetsManager = assetsFile.assetsManager;
var assetsFileList = assetsManager.assetsFileList;
var assetsFileIndexCache = assetsManager.assetsFileIndexCache;
if (!assetsFileIndexCache.TryGetValue(name, out index))
{
index = assetsFileList.FindIndex(x => x.upperFileName == name);
assetsFileIndexCache.Add(name, index);
}
m_PathID = m_Object.m_PathID;
}
public bool IsNull => m_PathID == 0 || m_FileID < 0;
}
}
"""
def __bool__(self):
return True if self.get_obj() else False
68 changes: 27 additions & 41 deletions UnityPy/files/SerializedFile.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def __init__(self, reader: EndianBinaryReader):
self.version = reader.read_u_int()
self.data_offset = reader.read_u_int()


class LocalSerializedObjectIdentifier: # script type
local_serialized_file_index: int
local_identifier_in_file: int
Expand Down Expand Up @@ -180,10 +181,7 @@ def __init__(self, reader: EndianBinaryReader, environment=None, parent=None):

if header.version >= 8:
self._m_target_platform = reader.read_int()
try:
self.target_platform = BuildTarget(self._m_target_platform)
except KeyError:
self.target_platform = BuildTarget.UnknownPlatform
self.target_platform = BuildTarget(self._m_target_platform)

if header.version >= 13:
self._enable_type_tree = reader.read_boolean()
Expand Down Expand Up @@ -269,12 +267,12 @@ def read_serialized_type(self):
if self._enable_type_tree:
type_tree = []
if self.header.version >= 12 or self.header.version == 10:
type_.string_data = self.read_type_tree5(type_tree)
type_.string_data = self.read_type_tree_blob(type_tree)
else:
self.read_type_tree(type_tree)

if self.header.version >= 21:
type_.type_dependencies = reader.read_int_array()
type_.type_dependencies = self.reader.read_int_array()

type_.nodes = type_tree

Expand Down Expand Up @@ -305,48 +303,35 @@ def read_type_tree(self, type_tree, level=0):
for i in range(children_count):
self.read_type_tree(type_tree, level + 1)

def read_type_tree5(self, type_tree):
def read_type_tree_blob(self, type_tree):
reader = self.reader
number_of_nodes = self.reader.read_int()
string_buffer_size = self.reader.read_int()

node_size = 24
if self.header.version > 19:
node_size = 32

self.reader.Position += number_of_nodes * node_size
string_buffer_reader = EndianBinaryReader(self.reader.read(string_buffer_size))
self.reader.Position -= number_of_nodes * node_size + string_buffer_size

for i in range(number_of_nodes):
type_tree_node = TypeTreeNode()
type_tree.append(type_tree_node)
type_tree_node.version = self.reader.read_u_short()
type_tree_node.level = self.reader.read_byte()
type_tree_node.is_array = self.reader.read_boolean()
type_tree_node.type_str_offset = self.reader.read_u_int()
type_tree_node.name_str_offset = self.reader.read_u_int()
type_tree_node.byte_size = self.reader.read_int()
type_tree_node.index = self.reader.read_int()
type_tree_node.meta_flag = self.reader.read_int()
for _ in range(number_of_nodes):
node = TypeTreeNode()
type_tree.append(node)
node.version = reader.read_u_short()
node.level = reader.read_byte()
node.is_array = reader.read_boolean()
node.type_str_offset = reader.read_u_int()
node.name_str_offset = reader.read_u_int()
node.byte_size = reader.read_int()
node.index = reader.read_int()
node.meta_flag = reader.read_int()

if self.header.version > 19:
type_tree_node.ref_type_hash = self.reader.read_u_long()

type_tree_node.type = read_string(
string_buffer_reader, type_tree_node.type_str_offset
)
type_tree_node.name = read_string(
string_buffer_reader, type_tree_node.name_str_offset
)
node.ref_type_hash = reader.read_u_long()

self.reader.Position += string_buffer_size

if self.header.version >= 21:
self.unknown_ttr5 = self.reader.read_u_int()
string_buffer_reader = EndianBinaryReader(
reader.read(string_buffer_size), reader.endian)
for node in type_tree:
node.type = read_string(string_buffer_reader, node.type_str_offset)
node.name = read_string(string_buffer_reader, node.name_str_offset)

return string_buffer_reader.bytes

def save(self, packer: str="none") -> bytes:
def save(self, packer: str = "none") -> bytes:
# Structure:
# 1. header
# file header
Expand Down Expand Up @@ -514,7 +499,7 @@ def save_type_tree(self, nodes: list, writer: EndianBinaryWriter):

# calc children count
children_count = 0
for node2 in nodes[i + 1 :]:
for node2 in nodes[i + 1:]:
if node2.level == node.level:
break
if node2.level == node.level - 1:
Expand Down Expand Up @@ -642,7 +627,8 @@ def __init__(self, assets_file, reader):
if header.version < 16:
self.class_id = reader.read_u_short()
if types:
self.serialized_type = [x for x in types if x.class_id == self.type_id][0]
self.serialized_type = (
x for x in types if x.class_id == self.type_id).next()
else:
self.serialized_type = SerializedType()
else:
Expand Down
5 changes: 1 addition & 4 deletions UnityPy/files/WebFile.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,7 @@ def __init__(self, reader: EndianBinaryReader, environment=None):
offset = reader.read_int()
length = reader.read_int()
path_length = reader.read_int()
name = reader.read_bytes(path_length)
if isinstance(name, memoryview):
name = name.tobytes()
name = name.decode("utf-8")
name = bytes(reader.read_bytes(path_length)).decode("utf-8")
files.append((name, offset, length))

# read file data and convert it
Expand Down

0 comments on commit 89de7f4

Please sign in to comment.