diff --git a/Il2CppInspector.Common/Outputs/CppScaffolding.cs b/Il2CppInspector.Common/Outputs/CppScaffolding.cs index 6dfbccc..43bcb2a 100644 --- a/Il2CppInspector.Common/Outputs/CppScaffolding.cs +++ b/Il2CppInspector.Common/Outputs/CppScaffolding.cs @@ -38,13 +38,15 @@ namespace Il2CppInspector.Outputs using var fs = new FileStream(typeHeaderFile, FileMode.Create); _writer = new StreamWriter(fs, Encoding.ASCII); + const string decompilerIfDef = "#if !defined(_GHIDRA_) && !defined(_IDA_) && !defined(_IDACLANG_)"; + using (_writer) { writeHeader(); // Write primitive type definitions for when we're not including other headers - writeCode($$""" - #if defined(_GHIDRA_) || defined(_IDA_) + writeCode($""" + #if defined(_GHIDRA_) || defined(_IDA_) || defined(_IDACLANG_) typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; @@ -55,13 +57,16 @@ namespace Il2CppInspector.Outputs typedef __int64 int64_t; #endif + #if defined(_GHIDRA_) || defined(_IDACLANG_) + typedef int{_model.Package.BinaryImage.Bits}_t intptr_t; + typedef uint{_model.Package.BinaryImage.Bits}_t uintptr_t; + #endif + #if defined(_GHIDRA_) - typedef __int{{_model.Package.BinaryImage.Bits}} size_t; - typedef size_t intptr_t; - typedef size_t uintptr_t; + typedef uint{_model.Package.BinaryImage.Bits}_t size_t; #endif - #if !defined(_GHIDRA_) && !defined(_IDA_) + {decompilerIfDef} #define _CPLUSPLUS_ #endif """); @@ -101,7 +106,7 @@ namespace Il2CppInspector.Outputs } // C does not support namespaces - writeCode("#if !defined(_GHIDRA_) && !defined(_IDA_)"); + writeCode($"{decompilerIfDef}"); writeCode("namespace app {"); writeCode("#endif"); writeLine(""); @@ -111,7 +116,7 @@ namespace Il2CppInspector.Outputs writeTypesForGroup("Application types from usages", "types_from_usages"); writeTypesForGroup("Application unused value types", "unused_concrete_types"); - writeCode("#if !defined(_GHIDRA_) && !defined(_IDA_)"); + writeCode($"{decompilerIfDef}"); writeCode("}"); writeCode("#endif"); } diff --git a/Il2CppInspector.Common/Outputs/ScriptResources/Targets/Ghidra.py b/Il2CppInspector.Common/Outputs/ScriptResources/Targets/Ghidra.py index 54b61be..5759ea0 100644 --- a/Il2CppInspector.Common/Outputs/ScriptResources/Targets/Ghidra.py +++ b/Il2CppInspector.Common/Outputs/ScriptResources/Targets/Ghidra.py @@ -5,24 +5,18 @@ from ghidra.app.util.cparser.C import CParserUtils from ghidra.program.model.data import ArrayDataType from ghidra.program.model.symbol import SourceType -def SetName(addr, name): +def set_name(addr, name): createLabel(toAddr(addr), name, True) -def MakeFunction(start, name=None, addrMax=None): +def make_function(start, end = None): addr = toAddr(start) # Don't override existing functions fn = getFunctionAt(addr) - if fn is not None and name is not None: - # Set existing function name if name available - fn.setName(name, SourceType.USER_DEFINED) - elif fn is None: + if fn is None: # Create new function if none exists - createFunction(addr, name) - # Set header comment if name available - if name is not None: - setPlateComment(addr, name) + createFunction(addr, None) -def MakeArray(addr, numItems, cppType): +def make_array(addr, numItems, cppType): if cppType.startswith('struct '): cppType = cppType[7:] @@ -32,18 +26,18 @@ def MakeArray(addr, numItems, cppType): removeDataAt(addr) createData(addr, a) -def DefineCode(code): +def define_code(code): # Code declarations are not supported in Ghidra # This only affects string literals for metadata version < 19 # TODO: Replace with creating a DataType for enums pass -def SetFunctionType(addr, sig): - MakeFunction(addr) +def set_function_type(addr, sig): + make_function(addr) typeSig = CParserUtils.parseSignature(None, currentProgram, sig) ApplyFunctionSignatureCmd(toAddr(addr), typeSig, SourceType.USER_DEFINED, False, True).applyTo(currentProgram) -def SetType(addr, cppType): +def set_type(addr, cppType): if cppType.startswith('struct '): cppType = cppType[7:] @@ -52,13 +46,13 @@ def SetType(addr, cppType): removeDataAt(addr) createData(addr, t) -def SetComment(addr, text): +def set_comment(addr, text): setEOLComment(toAddr(addr), text) -def SetHeaderComment(addr, text): +def set_header_comment(addr, text): setPlateComment(toAddr(addr), text) -def CustomInitializer(): +def script_prologue(status): # Check that the user has parsed the C headers first if len(getDataTypes('Il2CppObject')) == 0: print('STOP! You must import the generated C header file (%TYPE_HEADER_RELATIVE_PATH%) before running this script.') @@ -70,5 +64,10 @@ def CustomInitializer(): if currentProgram.getExecutableFormat().endswith('(ELF)'): currentProgram.setImageBase(toAddr(%IMAGE_BASE%), True) -def GetScriptDirectory(): +def script_epilogue(status): + pass + +def get_script_directory(): return getSourceFile().getParentFile().toString() + +class StatusWrapper(BaseStatusHandler): pass \ No newline at end of file diff --git a/Il2CppInspector.Common/Outputs/ScriptResources/Targets/IDA.py b/Il2CppInspector.Common/Outputs/ScriptResources/Targets/IDA.py index 1d29c9f..c09b01b 100644 --- a/Il2CppInspector.Common/Outputs/ScriptResources/Targets/IDA.py +++ b/Il2CppInspector.Common/Outputs/ScriptResources/Targets/IDA.py @@ -1,58 +1,174 @@ # IDA-specific implementation -import idaapi +import ida_kernwin +import ida_name +import ida_idaapi +import ida_typeinf +import ida_bytes +import ida_nalt +import ida_ida +import ida_ua -def SetName(addr, name): - ret = idc.set_name(addr, name, SN_NOWARN | SN_NOCHECK) - if ret == 0: - new_name = name + '_' + str(addr) - ret = idc.set_name(addr, new_name, SN_NOWARN | SN_NOCHECK) +try: # 7.7+ + import ida_srclang + IDACLANG_AVAILABLE = True +except ImportError: + IDACLANG_AVAILABLE = False -def MakeFunction(start, name=None, addrMax=None): - ida_funcs.add_func(start) - #limit end function to maxAddr if any - if addrMax is None: +import datetime + +def set_name(addr, name): + ida_name.set_name(addr, name, ida_name.SN_NOWARN | ida_name.SN_NOCHECK | ida_name.SN_FORCE) + +def make_function(start, end = None): + ida_bytes.del_items(start, ida_bytes.DELIT_SIMPLE, 12) # Undefine x bytes which should hopefully be enough for the first instruction + ida_ua.create_insn(start) # Create instruction at start + if not ida_funcs.add_func(start, end if end is not None else ida_idaapi.BADADDR): # This fails if the function doesn't start with an instruction + print(f"failed to mark function {hex(start)}-{hex(end) if end is not None else '???'} as function") + +TYPE_CACHE = {} + +def get_type(typeName): + if typeName not in TYPE_CACHE: + info = ida_typeinf.idc_parse_decl(None, typeName, ida_typeinf.PT_RAWARGS) + if info is None: + print(f"Failed to create type {typeName}.") + return None + + TYPE_CACHE[typeName] = info[1:] + + return TYPE_CACHE[typeName] + +TINFO_DEFINITE = 0x0001 # These only exist in idc for some reason, so we redefine it here + +def set_type(addr, cppType): + cppType += ';' + + info = get_type(cppType) + if info is None: return - addrEnd = idc.get_func_attr(start,FUNCATTR_END) - if addrEnd == idaapi.BADADDR: + + if ida_typeinf.apply_type(None, info[0], info[1], addr, TINFO_DEFINITE) is None: + print(f"set_type({hex(addr)}, {cppType}); failed!") + +def set_function_type(addr, sig): + set_type(addr, sig) + +def make_array(addr, numItems, cppType): + set_type(addr, cppType) + + flags = ida_bytes.get_flags(addr) + if ida_bytes.is_struct(flags): + opinfo = ida_nalt.opinfo_t() + ida_bytes.get_opcode(opinfo, addr, 0, flags) + entrySize = ida_bytes.get_data_elsize(addr, flags, opinfo) + tid = opinfo.tid + else: + entrySize = ida_bytes.get_item_size(addr) + tid = ida_idaapi.BADADDR + + ida_bytes.create_data(addr, flags, numItems * entrySize, tid) + +def define_code(code): + ida_typeinf.idc_parse_types(code) + +def set_comment(addr, comment, repeatable = True): + ida_bytes.set_cmt(addr, comment, repeatable) + +def set_header_comment(addr, comment): + func = ida_funcs.get_func(addr) + if func is None: return - if addrEnd > addrMax: - idc.set_func_end(start,addrMax) -def MakeArray(addr, numItems, cppType): - SetType(addr, cppType) - idc.make_array(addr, numItems) + ida_funcs.set_func_cmt(func, comment, True) -def DefineCode(code): - idc.parse_decls(code) +cached_genflags = 0 -def SetFunctionType(addr, sig): - SetType(addr, sig) +def script_prologue(status): + global cached_genflags + # Disable autoanalysis + cached_genflags = ida_ida.inf_get_genflags() + ida_ida.inf_set_genflags(cached_genflags & ~ida_ida.INFFL_AUTO) -def SetType(addr, cppType): - if not cppType.endswith(';'): - cppType += ';' - tinfo = idc.parse_decl(cppType,idaapi.PT_RAWARGS) - ret = None - if not(tinfo is None): - ret = idc.apply_type(addr,tinfo) - if ret is None: - ret = idc.SetType(addr, cppType) - if ret is None: - print('SetType(0x%x, %r) failed!' % (addr, cppType)) + # Unload type libraries we know to cause issues - like the c++ linux one + PLATFORMS = ["x86", "x64", "arm", "arm64"] + PROBLEMATIC_TYPELIBS = ["gnulnx"] -def SetComment(addr, text): - idc.set_cmt(addr, text, 1) + for lib in PROBLEMATIC_TYPELIBS: + for platform in PLATFORMS: + ida_typeinf.del_til(f"{lib}_{platform}") -def SetHeaderComment(addr, text): - SetComment(addr, text) + # Set name mangling to GCC 3.x and display demangled as default + ida_ida.inf_set_demnames(ida_ida.DEMNAM_GCC3 | ida_ida.DEMNAM_NAME) -def CustomInitializer(): - print('Processing Types') + status.update_step('Processing Types') - original_macros = ida_typeinf.get_c_macros() - ida_typeinf.set_c_macros(original_macros + ";_IDA_=1") - idc.parse_decls(os.path.join(GetScriptDirectory(), "%TYPE_HEADER_RELATIVE_PATH%"), idc.PT_FILE) - ida_typeinf.set_c_macros(original_macros) + if IDACLANG_AVAILABLE: + header_path = os.path.join(get_script_directory(), "%TYPE_HEADER_RELATIVE_PATH%") + ida_srclang.set_parser_argv("clang", "-x c++ -D_IDACLANG_=1") + ida_srclang.parse_decls_with_parser("clang", None, header_path, True) + else: + original_macros = ida_typeinf.get_c_macros() + ida_typeinf.set_c_macros(original_macros + ";_IDA_=1") + ida_typeinf.idc_parse_types(os.path.join(get_script_directory(), "%TYPE_HEADER_RELATIVE_PATH%"), ida_typeinf.PT_FILE) + ida_typeinf.set_c_macros(original_macros) -def GetScriptDirectory(): +def script_epilogue(status): + # Reenable auto-analysis + global cached_genflags + ida_ida.inf_set_genflags(cached_genflags) + +def get_script_directory(): return os.path.dirname(os.path.realpath(__file__)) + +class StatusHandler(BaseStatusHandler): + def __init__(self): + self.step = "Initializing" + self.max_items = 0 + self.current_items = 0 + self.start_time = datetime.datetime.now() + self.step_start_time = self.start_time + self.last_updated_time = datetime.datetime.min + + def initialize(self): + ida_kernwin.show_wait_box("Processing") + + def update(self): + if self.was_cancelled(): + raise RuntimeError("Cancelled script.") + + current_time = datetime.datetime.now() + if 0.5 > (current_time - self.last_updated_time).total_seconds(): + return + + self.last_updated_time = current_time + + step_time = current_time - self.step_start_time + total_time = current_time - self.start_time + message = f""" +Running IL2CPP script. +Current Step: {self.step} +Progress: {self.current_items}/{self.max_items} +Elapsed: {step_time} ({total_time}) +""" + + ida_kernwin.replace_wait_box(message) + + def update_step(self, step, max_items = 0): + print(step) + + self.step = step + self.max_items = max_items + self.current_items = 0 + self.step_start_time = datetime.datetime.now() + self.last_updated_time = datetime.datetime.min + self.update() + + def update_progress(self, new_progress = 1): + self.current_items += new_progress + self.update() + + def was_cancelled(self): + return ida_kernwin.user_cancelled() + + def close(self): + ida_kernwin.hide_wait_box() \ No newline at end of file diff --git a/Il2CppInspector.Common/Outputs/ScriptResources/shared-main.py b/Il2CppInspector.Common/Outputs/ScriptResources/shared-main.py index 893bdce..20c44e4 100644 --- a/Il2CppInspector.Common/Outputs/ScriptResources/shared-main.py +++ b/Il2CppInspector.Common/Outputs/ScriptResources/shared-main.py @@ -1,155 +1,177 @@ # Shared interface -def AsUTF8(s): - return s if sys.version_info[0] > 2 else s.encode('utf-8') +def from_hex(addr): return int(addr, 0) -def ParseAddress(d): - return int(d['virtualAddress'], 0) +def parse_address(d): return from_hex(d['virtualAddress']) -def DefineILMethod(jsonDef): - addr = ParseAddress(jsonDef) - SetName(addr, AsUTF8(jsonDef['name'])) - SetFunctionType(addr, AsUTF8(jsonDef['signature'])) - SetHeaderComment(addr, AsUTF8(jsonDef['dotNetSignature'])) +def define_il_method(jsonDef): + addr = parse_address(jsonDef) + set_name(addr, jsonDef['name']) + set_function_type(addr, jsonDef['signature']) + set_header_comment(addr, jsonDef['dotNetSignature']) -def DefineILMethodInfo(jsonDef): - addr = ParseAddress(jsonDef) - SetName(addr, AsUTF8(jsonDef['name'])) - SetType(addr, r'struct MethodInfo *') - SetComment(addr, AsUTF8(jsonDef['dotNetSignature'])) +def define_il_method_info(jsonDef): + addr = parse_address(jsonDef) + set_name(addr, jsonDef['name']) + set_type(addr, r'struct MethodInfo *') + set_comment(addr, jsonDef['dotNetSignature']) -def DefineCppFunction(jsonDef): - addr = ParseAddress(jsonDef) - SetName(addr, AsUTF8(jsonDef['name'])) - SetFunctionType(addr, AsUTF8(jsonDef['signature'])) +def define_cpp_function(jsonDef): + addr = parse_address(jsonDef) + set_name(addr, jsonDef['name']) + set_function_type(addr, jsonDef['signature']) -def DefineString(jsonDef): - addr = ParseAddress(jsonDef) - SetName(addr, AsUTF8(jsonDef['name'])) - SetType(addr, r'struct String *') - SetComment(addr, AsUTF8(jsonDef['string'])) +def define_string(jsonDef): + addr = parse_address(jsonDef) + set_name(addr, jsonDef['name']) + set_type(addr, r'struct String *') + set_comment(addr, jsonDef['string']) -def DefineFieldFromJson(jsonDef): - DefineField(jsonDef['virtualAddress'], jsonDef['name'], jsonDef['type'], jsonDef['dotNetType']) +def define_field(addr, name, type, ilType = None): + addr = from_hex(addr) + set_name(addr, name) + set_type(addr, type) + if ilType is not None: + set_comment(addr, ilType) -def DefineField(addr, name, type, ilType = None): - addr = int(addr, 0) - SetName(addr, AsUTF8(name)) - SetType(addr, AsUTF8(type)) - if (ilType is not None): - SetComment(addr, AsUTF8(ilType)) +def define_field_from_json(jsonDef): + define_field(jsonDef['virtualAddress'], jsonDef['name'], jsonDef['type'], jsonDef['dotNetType']) -def DefineArray(jsonDef): - addr = ParseAddress(jsonDef) - MakeArray(addr, int(jsonDef['count']), AsUTF8(jsonDef['type'])) - SetName(addr, AsUTF8(jsonDef['name'])) +def define_array(jsonDef): + addr = parse_address(jsonDef) + make_array(addr, int(jsonDef['count']), jsonDef['type']) + set_name(addr, jsonDef['name']) -def DefineFieldWithValue(jsonDef): - addr = ParseAddress(jsonDef) - SetName(addr, AsUTF8(jsonDef['name'])) - SetComment(addr, AsUTF8(jsonDef['value'])) +def define_field_with_value(jsonDef): + addr = parse_address(jsonDef) + set_name(addr, jsonDef['name']) + set_comment(addr, jsonDef['value']) # Process JSON -def ProcessJSON(jsonData): - - # Method definitions - print('Processing method definitions') - for d in jsonData['methodDefinitions']: - DefineILMethod(d) - - # Constructed generic methods - print('Processing constructed generic methods') - for d in jsonData['constructedGenericMethods']: - DefineILMethod(d) - - # Custom attributes generators - print('Processing custom attributes generators') - for d in jsonData['customAttributesGenerators']: - DefineCppFunction(d) - - # Method.Invoke thunks - print('Processing Method.Invoke thunks') - for d in jsonData['methodInvokers']: - DefineCppFunction(d) - - # String literals for version >= 19 - print('Processing string literals') - if 'virtualAddress' in jsonData['stringLiterals'][0]: - for d in jsonData['stringLiterals']: - DefineString(d) - - # String literals for version < 19 - else: - litDecl = 'enum StringLiteralIndex {\n' - for d in jsonData['stringLiterals']: - litDecl += " " + AsUTF8(d['name']) + ",\n" - litDecl += '};\n' - DefineCode(litDecl) - - # Il2CppClass (TypeInfo) pointers - print('Processing Il2CppClass (TypeInfo) pointers') - for d in jsonData['typeInfoPointers']: - DefineFieldFromJson(d) - - # Il2CppType (TypeRef) pointers - print('Processing Il2CppType (TypeRef) pointers') - for d in jsonData['typeRefPointers']: - DefineField(d['virtualAddress'], d['name'], r'struct Il2CppType *', d['dotNetType']) - - # MethodInfo pointers - print('Processing MethodInfo pointers') - for d in jsonData['methodInfoPointers']: - DefineILMethodInfo(d) - - # FieldInfo pointers, add the contents as a comment - print('Processing FieldInfo pointers') - for d in jsonData['fields']: - DefineFieldWithValue(d) - - # FieldRva pointers, add the contents as a comment - print('Processing FieldRva pointers') - for d in jsonData['fieldRvas']: - DefineFieldWithValue(d) - +def process_json(jsonData, status): # Function boundaries - print('Processing function boundaries') functionAddresses = jsonData['functionAddresses'] functionAddresses.sort() count = len(functionAddresses) + + status.update_step('Processing function boundaries', count) for i in range(count): - addrStart = int(functionAddresses[i],0) - if addrStart == 0: + start = from_hex(functionAddresses[i]) + if start == 0: + status.update_progress() continue - addrNext = None - if i != count -1: - addrNext = int(functionAddresses[i+1],0) - MakeFunction(addrStart,None,addrNext) + + end = from_hex(functionAddresses[i + 1]) if i + 1 != count else None + + make_function(start, end) + status.update_progress() + + # Method definitions + status.update_step('Processing method definitions', len(jsonData['methodDefinitions'])) + for d in jsonData['methodDefinitions']: + define_il_method(d) + status.update_progress() + + # Constructed generic methods + status.update_step('Processing constructed generic methods', len(jsonData['constructedGenericMethods'])) + for d in jsonData['constructedGenericMethods']: + define_il_method(d) + status.update_progress() + + # Custom attributes generators + status.update_step('Processing custom attributes generators', len(jsonData['customAttributesGenerators'])) + for d in jsonData['customAttributesGenerators']: + define_cpp_function(d) + status.update_progress() + + # Method.Invoke thunks + status.update_step('Processing Method.Invoke thunks', len(jsonData['methodInvokers'])) + for d in jsonData['methodInvokers']: + define_cpp_function(d) + status.update_progress() + + # String literals for version >= 19 + if 'virtualAddress' in jsonData['stringLiterals'][0]: + status.update_step('Processing string literals (V19+)', len(jsonData['stringLiterals'])) + for d in jsonData['stringLiterals']: + define_string(d) + status.update_progress() + + # String literals for version < 19 + else: + status.update_step('Processing string literals (pre-V19)') + litDecl = 'enum StringLiteralIndex {\n' + for d in jsonData['stringLiterals']: + litDecl += " " + d['name'] + ",\n" + litDecl += '};\n' + define_code(litDecl) + + # Il2CppClass (TypeInfo) pointers + status.update_step('Processing Il2CppClass (TypeInfo) pointers', len(jsonData['typeInfoPointers'])) + for d in jsonData['typeInfoPointers']: + define_field_from_json(d) + status.update_progress() + + # Il2CppType (TypeRef) pointers + status.update_step('Processing Il2CppType (TypeRef) pointers', len(jsonData['typeRefPointers'])) + for d in jsonData['typeRefPointers']: + define_field(d['virtualAddress'], d['name'], r'struct Il2CppType *', d['dotNetType']) + status.update_progress() + + # MethodInfo pointers + status.update_step('Processing MethodInfo pointers', len(jsonData['methodInfoPointers'])) + for d in jsonData['methodInfoPointers']: + define_il_method_info(d) + status.update_progress() + + # FieldInfo pointers, add the contents as a comment + status.update_step('Processing FieldInfo pointers', len(jsonData['fields'])) + for d in jsonData['fields']: + define_field_with_value(d) + status.update_progress() + + # FieldRva pointers, add the contents as a comment + status.update_step('Processing FieldRva pointers', len(jsonData['fieldRvas'])) + for d in jsonData['fieldRvas']: + define_field_with_value(d) + status.update_progress() # IL2CPP type metadata - print('Processing IL2CPP type metadata') + status.update_step('Processing IL2CPP type metadata', len(jsonData['typeMetadata'])) for d in jsonData['typeMetadata']: - DefineField(d['virtualAddress'], d['name'], d['type']) + define_field(d['virtualAddress'], d['name'], d['type']) # IL2CPP function metadata - print('Processing IL2CPP function metadata') + status.update_step('Processing IL2CPP function metadata', len(jsonData['functionMetadata'])) for d in jsonData['functionMetadata']: - DefineCppFunction(d) + define_cpp_function(d) # IL2CPP array metadata - print('Processing IL2CPP array metadata') + status.update_step('Processing IL2CPP array metadata', len(jsonData['arrayMetadata'])) for d in jsonData['arrayMetadata']: - DefineArray(d) + define_array(d) # IL2CPP API functions - print('Processing IL2CPP API functions') + status.update_step('Processing IL2CPP API functions', len(jsonData['apis'])) for d in jsonData['apis']: - DefineCppFunction(d) + define_cpp_function(d) # Entry point -print('Generated script file by Il2CppInspector - http://www.djkaty.com - https://github.com/djkaty') -CustomInitializer() +print('Generated script file by Il2CppInspectorRedux - https://github.com/LukeFZ (Original Il2CppInspector by http://www.djkaty.com - https://github.com/djkaty)') +status = StatusHandler() +status.initialize() -with open(os.path.join(GetScriptDirectory(), "%JSON_METADATA_RELATIVE_PATH%"), "r") as jsonFile: - jsonData = json.load(jsonFile)['addressMap'] - ProcessJSON(jsonData) +try: + status.update_step("Running script prologue") + script_prologue(status) -print('Script execution complete.') + with open(os.path.join(get_script_directory(), "%JSON_METADATA_RELATIVE_PATH%"), "r") as jsonFile: + status.update_step("Loading JSON metadata") + jsonData = json.load(jsonFile)['addressMap'] + process_json(jsonData, status) + + status.update_step("Running script epilogue") + script_epilogue(status) + + status.update_step('Script execution complete.') +except RuntimeError: pass +finally: status.close() diff --git a/Il2CppInspector.Common/Outputs/ScriptResources/shared-preamble.py b/Il2CppInspector.Common/Outputs/ScriptResources/shared-preamble.py index 9a2a4b6..dba3b85 100644 --- a/Il2CppInspector.Common/Outputs/ScriptResources/shared-preamble.py +++ b/Il2CppInspector.Common/Outputs/ScriptResources/shared-preamble.py @@ -1,6 +1,13 @@ -# Generated script file by Il2CppInspector - http://www.djkaty.com - https://github.com/djkaty +# Generated script file by Il2CppInspectorRedux - https://github.com/LukeFZ (Original Il2CppInspector by http://www.djkaty.com - https://github.com/djkaty) # Target Unity version: %TARGET_UNITY_VERSION% import json import os import sys + +class BaseStatusHandler: + def initialize(self): pass + def update_step(self, name, max_items = 0): print(name) + def update_progress(self, progress = 1): pass + def was_cancelled(self): return False + def close(self): pass