diff --git a/BromaIDA.py b/BromaIDA.py index 4b2bd03..941a184 100644 --- a/BromaIDA.py +++ b/BromaIDA.py @@ -14,7 +14,6 @@ from idautils import Names from broma_ida.pybroma_installer import install_pybroma -install_pybroma() from broma_ida.utils import ( popup, stop, get_platform, get_platform_printable @@ -60,6 +59,13 @@ def bida_main(): ) elif import_export_prompt == ASKBTN_BTN2: + popup( + "Ok", "Ok", None, + "Exporter is currently broken! " + "Don't rely on it exporting correctly...\n" + "But hey, I won't judge." + ) + platform = get_platform() # for_saving is not True because we need to read the file first @@ -98,7 +104,7 @@ def init(self): """Ran on plugin load""" self._register_action() - if install_pybroma() != 0: + if not install_pybroma(): popup( "Ok", "Ok", None, "Couldn't install PyBroma! " diff --git a/broma_ida/broma/argtype.py b/broma_ida/broma/argtype.py index e9331f8..2397cc7 100644 --- a/broma_ida/broma/argtype.py +++ b/broma_ida/broma/argtype.py @@ -52,7 +52,9 @@ def _expand_stl_type(self, t: str) -> str: if "std::" not in t: return t - if t == "std::string": + if sub( + "(?: )?const(?: )?", "", t + ).removesuffix("&").removesuffix("*") == "std::string": return t if t.startswith("std::vector"): @@ -237,7 +239,7 @@ def _expand_stl_type(self, t: str) -> str: "{}", contained.group(1) )) - raise BaseException(f"[!] Couldn't expand STL type: {t}") + raise BaseException(f"[!] Couldn't expand STL type: '{t}'") def __init__(self, btype: Union[BaseArgType, BaseShortArgType]): if btype.get("reg"): diff --git a/broma_ida/broma/binding.py b/broma_ida/broma/binding.py index e12063e..8ec7f8c 100644 --- a/broma_ida/broma/binding.py +++ b/broma_ida/broma/binding.py @@ -2,7 +2,6 @@ from ida_name import is_visible_cp -from broma_ida.broma.constants import BROMA_CALLING_CONVENTIONS from broma_ida.broma.argtype import ArgType, RetType @@ -16,7 +15,6 @@ class BaseBindingType(TypedDict): return_type: RetType parameters: list[ArgType] - calling_convention: BROMA_CALLING_CONVENTIONS is_virtual: bool is_static: bool @@ -32,7 +30,6 @@ class BaseShortBindingTypeWithMD(BaseShortBindingType): """Base binding type (shorter, with metadata about the function)""" return_type: RetType parameters: list[ArgType] - calling_convention: BROMA_CALLING_CONVENTIONS is_virtual: bool is_static: bool @@ -93,8 +90,6 @@ def __init__( "name": "", "type": "", "reg": "" }), "parameters": binding.get("parameters") or [], - "calling_convention": - binding.get("calling_convention") or "default", "is_virtual": binding.get("is_virtual") or False, "is_static": binding.get("is_static") or False }) @@ -138,13 +133,6 @@ def __getitem__(self, key: Literal["parameters"]) -> list[ArgType]: def __getitem__(self, key: Literal["return_type"]) -> RetType: ... - @overload - def __getitem__( - self, - key: Literal["calling_convention"] - ) -> BROMA_CALLING_CONVENTIONS: - ... - def __getitem__(self, key): return self.binding.__getitem__(key) @@ -155,7 +143,6 @@ def __str__(self) -> str: return f"""{"virtual " if self.binding["is_virtual"] else ""}""" \ f"""{"static " if self.binding["is_static"] else ""}""" \ f"""{self.binding["return_type"]["type"]} """ \ - f"""__{self.binding["calling_convention"]} """ \ f"""{self.binding["class_name"]}::{self.binding["name"]}""" \ f"""({", ".join([ str(arg) for arg in self.binding["parameters"] diff --git a/broma_ida/broma/codegen.py b/broma_ida/broma/codegen.py index 1d4fd36..a25825b 100644 --- a/broma_ida/broma/codegen.py +++ b/broma_ida/broma/codegen.py @@ -89,6 +89,14 @@ def write(self): f.write("using TodoReturn = void; // :troll:\n") f.write("\n") + f.flush() + + f.write("// class fwddec\n") + f.writelines([f"class {c};\n" for c in self._classes.keys()]) + f.write("\n") + + f.flush() + f.write("// extras\n") for name, broma_class in Root( str(self._broma_path / "Extras.bro") @@ -98,10 +106,6 @@ def write(self): ) f.write("\n") - f.write("// class fwddec\n") - f.writelines([f"class {c};\n" for c in self._classes.keys()]) - f.write("\n") - f.flush() f.write("// delegates and non-polymorphic classes\n") diff --git a/broma_ida/broma/constants.py b/broma_ida/broma/constants.py index f5706d6..eabb4fd 100644 --- a/broma_ida/broma/constants.py +++ b/broma_ida/broma/constants.py @@ -1,7 +1,6 @@ from typing import Literal -# no android32 nor android64 because they have symbols -BROMA_PLATFORMS = Literal["win", "mac", "ios"] +BROMA_PLATFORMS = Literal["win", "imac", "m1", "ios"] BROMA_CALLING_CONVENTIONS = Literal[ "default", "thiscall", diff --git a/broma_ida/broma/importer.py b/broma_ida/broma/importer.py index d7b140a..22f4a67 100644 --- a/broma_ida/broma/importer.py +++ b/broma_ida/broma/importer.py @@ -1,5 +1,5 @@ from io import TextIOWrapper -from typing import cast, Optional, Union, Literal +from typing import cast, Optional from idaapi import get_imagebase from idc import ( @@ -16,25 +16,18 @@ ) from ida_nalt import get_tinfo -from functools import cmp_to_key from re import sub from pathlib import Path from pybroma import Root, FunctionBindField, Type, Class -from broma_ida.broma.constants import ( - BROMA_PLATFORMS, BROMA_CALLING_CONVENTIONS, - CALLING_CONVENTIONS, CPP_TYPE_QUALIFIERS, - CPP_TYPE_SPECIFIERS, CPP_DATA_TYPES, - CPP_PRIMITIVES, DATA_TYPE_TO_SIZE -) +from broma_ida.broma.constants import BROMA_PLATFORMS from broma_ida.broma.binding import Binding from broma_ida.broma.argtype import ArgType, RetType from broma_ida.broma.codegen import BromaCodegen from broma_ida.utils import ( get_platform_printable, get_short_info, rename_func, popup, stop, - are_args_primitive, is_primitive_type, get_ida_plugin_path ) @@ -53,26 +46,6 @@ class BIUtils: """BromaImporter utilities""" - @staticmethod - def _get_biggest_type(types: list[str]) -> str: - """_summary_ - - Args: - types (list[str]): _description_ - - Returns: - str: _description_ - """ - biggest_type = "" - last_biggest_size = 0 - - for t in types: - if last_biggest_size < DATA_TYPE_TO_SIZE[t]: - biggest_type = t - last_biggest_size = DATA_TYPE_TO_SIZE[t] - - return biggest_type - @staticmethod def get_function_info(ida_ea: int) -> Optional[ida_func_type_data_t]: """_summary_ @@ -141,241 +114,27 @@ def from_pybroma_args(args: dict[str, Type]) -> list[ArgType]: ] @staticmethod - def simplify_type(t: str) -> str: - """_summary_ - - Args: - t (str): _description_ - - Returns: - str: _description_ - """ - ret = "" - - is_pointer = t.endswith("*") - is_ref = t.endswith("&") - t_no_pref = t.rstrip("*").rstrip("&") if is_pointer or is_ref else t - - if len(t.split(" ")) == 1 and t_no_pref in CPP_TYPE_SPECIFIERS: - if is_pointer: - t = "int*" - elif is_ref: - t = "int&" - else: - t = "int" - - ret = sub( - "|".join([ - rf"(? int: - """_summary_ - - Args: - a (ArgType): _description_ - b (ArgType): _description_ - - Returns: - int: _description_ - """ - a_is_composite = BIUtils.simplify_type(a["type"]) not in CPP_PRIMITIVES - b_is_composite = BIUtils.simplify_type(b["type"]) not in CPP_PRIMITIVES - - if a_is_composite and b_is_composite: - return 0 - - if a_is_composite: - return 1 - - if b_is_composite: - return -1 - - return 0 - - @staticmethod - def init_types() -> bool: - """_summary_""" - if not g_has_idaclang: - return False - - stl_struct = BIUtils.get_type_info("holy_shit") - if stl_struct and stl_struct.get_size() == 0x40C: + def verify_type(t: Optional[ida_tinfo_t]) -> bool: + if t is None: return True - plugin_path = get_ida_plugin_path() - - if plugin_path is None: - print("[!] Plugin path wasn't able to be found!") - popup( - "Ok", "Ok", None, - "Couldn't find plugin path. Please open a GitHub issue." - ) - return False - - types_path = plugin_path / "broma_ida" / "types" - - if set_parser_argv("clang", "-x c++ -target i386-pc-win32") != 0: - print("[!] Clang potentially not found!") - popup( - "Ok", "Ok", None, - "IDAClang is needed to import types!" - ) - return False - - popup( - "Ok", "Ok", None, - "Importing STL Types...\n" - "This will probably freeze IDA for a couple of seconds.\n" - "So don't close the plugin/IDA!\n" - "(This will only happen once, unless new STL types " - "are found in Broma)" - ) - - # sorry... - enum_file = "" - file = "" - - with open(types_path / "enums.hpp", "r") as f: - enum_file = "".join(f.readlines()) - - with open(types_path / "stl_types.hpp", "r") as f: - file = "".join(f.readlines()).replace( - """#include "enums.hpp\"""", enum_file - ) - - if parse_decls_for_srclang(SRCLANG_CPP, None, file, False) != 0: - print( - "[!] Some errors have occurred! " - "If something breaks please make a " - "bug report in the GitHub repository" - ) - - def verify_type(t: Optional[ida_tinfo_t]) -> bool: - if t is None: - return True - - if t.get_size() == 0xFFFFFFFFFFFFFFFF: - return True - - return False - - if any([ - verify_type(BIUtils.get_type_info(t)) - for t in ( - "cocos2d::CCObject", "cocos2d::CCImage", - "cocos2d::CCApplication" - ) - ]): - popup( - "Ok", "Ok", None, - "Importing cocos2d Types...\n" - "This will probably freeze IDA for a couple of seconds, " - "if not minutes.\n" - "So don't close the plugin/IDA!\n" - "(This will only happen once, unless new cocos2d types " - "are found in Broma)" - ) - - if parse_decls_for_srclang( - SRCLANG_CPP, None, - types_path / "cocos2d.hpp", False - ) != 0: - print( - "[!] Some errors have occurred! " - "If something breaks please make a " - "bug report in the GitHub repository" - ) + if t.get_size() == 0xFFFFFFFFFFFFFFFF: + return True - return True + return False class BromaImporter: """Broma importer of all time using PyBroma now!""" _target_platform: BROMA_PLATFORMS _file_path: str - _has_types: bool + _has_types: bool = False bindings: list[Binding] = [] # { 0xaddr: [Binding, Binding, ...] } duplicates: dict[int, list[Binding]] = {} # Signature specific functions below - def _reorder_args( - self, - binding: Binding - ) -> list[ArgType]: - """Reorders a function's arguments (membercall and optcall shenanigans) - - Args: - binding (Binding): The binding. - - Returns: - list[BType]: Reordered arguments - """ - reordered_args: list[ArgType] = sorted( - binding["parameters"], - key=cmp_to_key(BIUtils.args_comparator) - ) - - xmm_reg = 0 - for i in range(len(reordered_args)): - arg = reordered_args[i] - - if i < 4 and arg["type"] in ["float", "double"]: - reordered_args[i]["reg"] = f"xmm{xmm_reg}" - xmm_reg += 1 - else: - if i == 0 and arg["type"] in CPP_PRIMITIVES: - reordered_args[i]["reg"] = "ecx" - elif binding["calling_convention"] == "optcall" and i == 1 \ - and arg["type"] in CPP_PRIMITIVES: - reordered_args[i]["reg"] = "edx" - else: - # not defined yet type or sm???? - # if type.isNotDefinedYet(): - # ... - - # is manual stack fixing needed? - ... - - return reordered_args - - def _fix_return_type(self, binding: Binding): - """_summary_ - - Args: - binding (Binding): _description_ - """ - if binding["return_type"] == "TodoReturn": - ida_func_info = BIUtils.get_function_info( - get_imagebase() + binding["address"] - ) - binding["return_type"] = RetType({ - "name": "", - "type": ida_func_info.rettype if ida_func_info - else "void" - }) - - return - - if BIUtils.simplify_type(binding["return_type"]["type"]) in \ - ["float", "double"]: - binding["name"] += "@" - else: - if binding["return_type"] != "void": - binding["name"] += "@" - def _has_mismatch( self, function: ida_func_type_data_t, @@ -394,55 +153,6 @@ def _has_mismatch( # TODO: impl return True - def _get_calling_convention( - self, - function: FunctionBindField - ) -> BROMA_CALLING_CONVENTIONS: - """Ya - - Args: - function (FunctionBindField): The function got hennessy. - - Returns: - BROMA_CALLING_CONVENTIONS - """ - if self._target_platform != "win": - return "default" - - if function.prototype.is_virtual or function.prototype.is_callback: - return "thiscall" - - if function.prototype.is_static: - return "optcall" - - if function.binds.__getattribute__(self._target_platform) != -1: - return "thiscall" - - return "membercall" - - def _get_ida_calling_convention( - self, - convention: BROMA_CALLING_CONVENTIONS - ) -> Union[CALLING_CONVENTIONS, Literal[""]]: - """Gets the real calling convention for a given - Broma calling convention. - - Args: - convention (BROMA_CALLING_CONVENTIONS): The Broma - calling convention. - - Returns: - CALLING_CONVENTIONS: The real one. - """ - if convention == "default": - return "" # let IDA handle it :D - - if convention == "thiscall" or convention == "membercall": - return "__thiscall" - - if convention == "optcall": - return "__fastcall" - def _get_ida_args_str( self, binding: Binding @@ -457,8 +167,7 @@ def _get_ida_args_str( """ this_arg_or_empty: str = "" - if self._get_ida_calling_convention(binding["calling_convention"]) == \ - "__thiscall": + if not binding["is_static"]: this_arg_or_empty += f"""{binding["class_name"]}* this""" if len(binding["parameters"]) > 0: this_arg_or_empty += ", " @@ -479,40 +188,12 @@ def _get_function_signature( Returns: str: The C++ function signature """ - # incase return type register was fixed, update the name - binding.update() - return \ f"""{"static " if binding["is_static"] else ""}""" \ f"""{"virtual " if binding["is_virtual"] else ""}""" \ f"""{binding["return_type"]["type"]} """ \ - f"""{ - self._get_ida_calling_convention(binding["calling_convention"]) - } """ \ f"""{binding["ida_qualified_name"]}""" \ f"""({self._get_ida_args_str(binding)});""" - - def _fix_function(self, binding: Binding): - """_summary_ - - Args: - binding (Binding): _description_ - """ - should_reorder_args = ( - binding["calling_convention"] == "membercall" or - binding["calling_convention"] == "optcall" - ) and any([ - ( - BIUtils.simplify_type(arg["type"]) not in CPP_PRIMITIVES or - BIUtils.simplify_type(arg["type"]) in ["float", "double"] - ) - for arg in binding["parameters"] - ]) - - if should_reorder_args: - binding["parameters"] = self._reorder_args(binding) - - self._fix_return_type(binding) # End of signature specific functions def _codegen_classes(self, classes: dict[str, Class]) -> bool: @@ -540,7 +221,7 @@ def _codegen_classes(self, classes: dict[str, Class]) -> bool: self._target_platform, classes, plugin_path / "broma_ida" / "types", - Path("".join(Path(self._file_path).parts[:-1])) + Path("/".join(Path(self._file_path).parts[:-1])) ).write() return True @@ -551,7 +232,6 @@ def __init__(self, platform: BROMA_PLATFORMS): Args: platform (BROMA_PLATFORMS): The target platform """ - self._has_types = BIUtils.init_types() self._reset() self._target_platform = platform @@ -571,15 +251,53 @@ def parse_file_stream(self, file: TextIOWrapper): if g_has_idaclang and popup( "Yes", "No", None, "Import classes from Broma?" - ) == 1: + ) == ASKBTN_BTN1: if self._codegen_classes(root.classesAsDict()): + if self._target_platform == "win": + set_parser_argv("clang", "-x c++ -target x86_64-pc-win32") + # TODO: handle other platforms + + popup( + "Ok", "Ok", None, + "Importing Types...\n" + "This will probably freeze IDA for a couple of " + "seconds, if not minutes.\n" + "So don't close the plugin/IDA!\n" + "(This will only happen once, unless new " + "types are found in Broma)" + ) + parse_decls_for_srclang( SRCLANG_CPP, None, - get_ida_plugin_path() / "broma_ida" / "types" / "codegen.hpp", # type: ignore + ( + get_ida_plugin_path() / "broma_ida" / "types" / "codegen.hpp" # type: ignore + ).as_posix(), True ) + self._has_types = True + else: + holy_shit_struct = BIUtils.get_type_info("holy_shit") + + if holy_shit_struct: + self._has_types = holy_shit_struct.get_size() == 0x808 + + if any([ + BIUtils.verify_type(BIUtils.get_type_info(t)) + for t in ( + "cocos2d::CCObject", "cocos2d::CCImage", + "cocos2d::CCApplication", "cocos2d::CCDirector" + ) + ]): + self._has_types = False + + popup( + "Ok", "Ok", None, + "Mismatch in cocos2d types! " + "Function types will not be changed!" + ) + for class_name, broma_class in root.classesAsDict().items(): for field in broma_class.fields: function_field = field.getAsFunctionBindField() @@ -591,7 +309,7 @@ def parse_file_stream(self, file: TextIOWrapper): self._target_platform ) - if function_address == -1: + if function_address == -1 or function_address == -2: continue function = function_field.prototype @@ -640,8 +358,6 @@ def parse_file_stream(self, file: TextIOWrapper): "type": function.ret.name }), "parameters": BIUtils.from_pybroma_args(function.args), - "calling_convention": - self._get_calling_convention(function_field), "is_virtual": function.is_virtual, "is_static": function.is_static })) @@ -656,8 +372,6 @@ def parse_file_stream(self, file: TextIOWrapper): "type": function.ret.name }), "parameters": BIUtils.from_pybroma_args(function.args), - "calling_convention": - self._get_calling_convention(function_field), "is_virtual": function.is_virtual, "is_static": function.is_static })) @@ -697,18 +411,13 @@ def import_into_idb(self): ) continue - # are_args_primitive(binding["parameters"]) and if self._has_types and \ - is_primitive_type(binding["return_type"]["type"]) and \ - self._has_mismatch( - cast( - ida_func_type_data_t, - BIUtils.get_function_info(ida_ea) + self._has_mismatch(cast( + ida_func_type_data_t, + BIUtils.get_function_info(ida_ea) ), binding - ): - self._fix_function(binding) - # SetType(ida_ea, self._get_function_signature(binding)) - print(self._get_function_signature(binding)) + ): + SetType(ida_ea, self._get_function_signature(binding)) if ida_name.startswith("sub_"): rename_func( @@ -767,7 +476,8 @@ def import_into_idb(self): f"{hex(addr)} already has a comment! Would you like to " "overwrite it with merge information or keep the current " "comment?\n" - "(You will be prompted with this again if you rerun the " + "(You will be prompted with this again if you keep the " + "current comment and rerun the " "script and there are merged functions!)" ) == ASKBTN_BTN1: set_func_cmt( diff --git a/broma_ida/class_builder/class_builder.py b/broma_ida/class_builder/class_builder.py index d62a997..561db87 100644 --- a/broma_ida/class_builder/class_builder.py +++ b/broma_ida/class_builder/class_builder.py @@ -1,8 +1,6 @@ from pybroma import Class -# from broma_ida.broma.constants import BROMA_PLATFORMS -from typing import Literal -BROMA_PLATFORMS = Literal["win", "mac", "ios"] +from broma_ida.broma.constants import BROMA_PLATFORMS class ClassBuilder: @@ -25,8 +23,7 @@ def _import_class(self): has_left_functions: bool = False for field in self._broma_class.fields: - func_field = field.getAsFunctionBindField() or \ - field.getAsOutOfLineField() + func_field = field.getAsFunctionBindField() member_field = field.getAsMemberField() pad_field = field.getAsPadField() @@ -42,13 +39,6 @@ def _import_class(self): for n, a in function.args.items()]) });\n""" - # if BIUtils.simplify_type(function.ret.name) not in CPP_PRIMITIVES and \ - # BIUtils.get_type_info(function.ret.name) is None: - # ret_type = function.ret.name[:-1] \ - # if function.ret.name.endswith("*") or \ - # function.ret.name.endswith("&") \ - # else function.ret.name - has_left_functions = True elif member_field is not None: diff --git a/broma_ida/pybroma_installer.py b/broma_ida/pybroma_installer.py index 94a9ca1..0c040d2 100644 --- a/broma_ida/pybroma_installer.py +++ b/broma_ida/pybroma_installer.py @@ -7,12 +7,12 @@ g_has_pybroma: bool = False -def install_pybroma() -> int: +def install_pybroma() -> bool: """Installs PyBroma if not already installed. Not in utils to avoid cyclic dependencies.""" global g_has_pybroma if g_has_pybroma: - return 0 + return False try: si = STARTUPINFO() @@ -28,27 +28,29 @@ def install_pybroma() -> int: print("[+] BromaIDA: PyBroma found") - return ret + return True except CalledProcessError: try: - print("[!] BromaIDA: PyBroma not installed! Installing...") + # print("[!] BromaIDA: PyBroma not installed! Installing...") - si = STARTUPINFO() - si.dwFlags |= STARTF_USESHOWWINDOW - ret = call([ - "python", "-m", "pip", "install", - "https://github.com/CallocGD/PyBroma/archive/refs/heads/main.zip" - ], startupinfo=si, stdout=DEVNULL, stderr=STDOUT) + # si = STARTUPINFO() + # si.dwFlags |= STARTF_USESHOWWINDOW + # ret = call([ + # "python", "-m", "pip", "install", + # "https://github.com/CallocGD/PyBroma/archive/refs/heads/main.zip" + # ], startupinfo=si, stdout=DEVNULL, stderr=STDOUT) - if ret != 0: - raise CalledProcessError(ret, "") + # if ret != 0: + # raise CalledProcessError(ret, "") - g_has_pybroma = True + # g_has_pybroma = True - print("[+] BromaIDA: PyBroma successfully installed") + # print("[+] BromaIDA: PyBroma successfully installed") - return ret + # return ret + print("[!] BromaIDA: PyBroma not installed! Please install it!") + return False except CalledProcessError: print("[!] BromaIDA: Couldn't install PyBroma!") - return 1 + return False diff --git a/broma_ida/types/cocos2d.hpp b/broma_ida/types/cocos2d.hpp index fdbd9a7..2f8ccd9 100644 --- a/broma_ida/types/cocos2d.hpp +++ b/broma_ida/types/cocos2d.hpp @@ -425,6 +425,97 @@ namespace cocos2d namespace cocos2d { + // not in cocos2d, blame geode + // 2.2 additions + struct ParticleStruct + { + int TotalParticles; + float Duration; + float Life; + float LifeVar; + int EmissionRate; + int Angle; + int AngleVar; + int Speed; + int SpeedVar; + int PosVarX; + int PosVarY; + int GravityX; + int GravityY; + int RadialAccel; + int RadialAccelVar; + int TangentialAccel; + int TangentialAccelVar; + + int StartSize; + int StartSizeVar; + int StartSpin; + int StartSpinVar; + float StartColorR; + float StartColorVarR; + float StartColorG; + float StartColorVarG; + float StartColorB; + float StartColorVarB; + float StartColorA; + float StartColorVarA; + + int EndSize; + int EndSizeVar; + int EndSpin; + int EndSpinVar; + float EndColorR; + float EndColorVarR; + float EndColorG; + float EndColorVarG; + float EndColorB; + float EndColorVarB; + float EndColorA; + float EndColorVarA; + + float FadeInTime; + float FadeInTimeVar; + float FadeOutTime; + float FadeOutTimeVar; + + int StartRadius; + int StartRadiusVar; + int EndRadius; + int EndRadiusVar; + int RotatePerSecond; + int RotatePerSecondVar; + + int EmitterMode; + int PositionType; + bool isBlendAdditive; + bool startSpinEqualToEndSpin; + bool rotationIsDir; + bool dynamicRotationIsDir; + int customParticleIdx; + bool uniformColorMode; + + float frictionPos; + float frictionPosVar; + + float respawn; + float respawnVar; + + bool orderSensitive; + bool startSizeEqualToEndSize; + bool startRadiusEqualToEndRadius; + + bool startRGBVarSync; + bool endRGBVarSync; + + float frictionSize; + float frictionSizeVar; + + float frictionRot; + float frictionRotVar; + + std::string sFrame; + }; + // enums enum class CCObjectType { PlayLayer = 5, @@ -998,6 +1089,37 @@ namespace cocos2d ccTouchMax = 4, }; + enum ResolutionPolicy + { + // The entire application is visible in the specified area without trying to preserve the original aspect ratio. + // Distortion can occur, and the application may appear stretched or compressed. + kResolutionExactFit, + // The entire application fills the specified area, without distortion but possibly with some cropping, + // while maintaining the original aspect ratio of the application. + kResolutionNoBorder, + // The entire application is visible in the specified area without distortion while maintaining the original + // aspect ratio of the application. Borders can appear on two sides of the application. + kResolutionShowAll, + // The application takes the height of the design resolution size and modifies the width of the internal + // canvas so that it fits the aspect ratio of the device + // no distortion will occur however you must make sure your application works on different + // aspect ratios + kResolutionFixedHeight, + // The application takes the width of the design resolution size and modifies the height of the internal + // canvas so that it fits the aspect ratio of the device + // no distortion will occur however you must make sure your application works on different + // aspect ratios + kResolutionFixedWidth, + + kResolutionUnKnown, + }; + + typedef enum { + // the back key clicked msg + kTypeBackClicked = 1, + kTypeMenuClicked, + } ccKeypadMSGType; + struct cc_timeval { @@ -1054,6 +1176,28 @@ namespace cocos2d float duration; // the soft keyboard animation duration } CCIMEKeyboardNotificationInfo; + typedef struct GLFWvidmode + { + /*! The width, in screen coordinates, of the video mode. + */ + int width; + /*! The height, in screen coordinates, of the video mode. + */ + int height; + /*! The bit depth of the red channel of the video mode. + */ + int redBits; + /*! The bit depth of the green channel of the video mode. + */ + int greenBits; + /*! The bit depth of the blue channel of the video mode. + */ + int blueBits; + /*! The refresh rate, in Hz, of the video mode. + */ + int refreshRate; + } GLFWvidmode; + struct ccTouchHandlerHelperData { // we only use the type // void (StandardTouchDelegate::*touchesSel)(CCSet*, CCEvent*); @@ -1061,11 +1205,6 @@ namespace cocos2d int m_type; }; - // 2.2 additions - struct ParticleStruct { - - }; - // CCObject class CCObject; @@ -1095,6 +1234,9 @@ namespace cocos2d typedef void (CCObject::*SEL_EventHandler)(CCEvent*); typedef int (CCObject::*SEL_Compare)(CCObject*); + typedef long long (*CUSTOM_WND_PROC)(unsigned int message, unsigned long long wParam, long long lParam, int* pProcessed); + + class CCCopying { public: @@ -4236,169 +4378,971 @@ namespace cocos2d }; - // CCTextFieldTTF - class CCLabelTTF : public CCSprite, public CCLabelProtocol + // CCTouchDispatcher + class CCTouchHandler : public CCObject { public: - CCLabelTTF(); - virtual ~CCLabelTTF(); - const char* description(); + inline CCTouchHandler() = default; + virtual ~CCTouchHandler(void); - static CCLabelTTF * create(const char *string, const char *fontName, float fontSize); + CCTouchDelegate* getDelegate(); + void setDelegate(CCTouchDelegate *pDelegate); - static CCLabelTTF * create(const char *string, const char *fontName, float fontSize, - const CCSize& dimensions, CCTextAlignment hAlignment); + int getPriority(void); + void setPriority(int nPriority); - static CCLabelTTF * create(const char *string, const char *fontName, float fontSize, - const CCSize& dimensions, CCTextAlignment hAlignment, - CCVerticalTextAlignment vAlignment); + int getEnabledSelectors(void); + void setEnalbedSelectors(int nValue); - static CCLabelTTF * createWithFontDefinition(const char *string, ccFontDefinition &textDefinition); - - bool initWithString(const char *string, const char *fontName, float fontSize); - - bool initWithString(const char *string, const char *fontName, float fontSize, - const CCSize& dimensions, CCTextAlignment hAlignment); + virtual bool initWithDelegate(CCTouchDelegate *pDelegate, int nPriority); - bool initWithString(const char *string, const char *fontName, float fontSize, - const CCSize& dimensions, CCTextAlignment hAlignment, - CCVerticalTextAlignment vAlignment); - - bool initWithStringAndTextDefinition(const char *string, ccFontDefinition &textDefinition); - - void setTextDefinition(ccFontDefinition *theDefinition); - - ccFontDefinition * getTextDefinition(); - - - - void enableShadow(const CCSize &shadowOffset, float shadowOpacity, float shadowBlur, bool mustUpdateTexture = true); - - void disableShadow(bool mustUpdateTexture = true); - - void enableStroke(const ccColor3B &strokeColor, float strokeSize, bool mustUpdateTexture = true); - - void disableStroke(bool mustUpdateTexture = true); - - void setFontFillColor(const ccColor3B &tintColor, bool mustUpdateTexture = true); + public: + static CCTouchHandler* handlerWithDelegate(CCTouchDelegate *pDelegate, int nPriority); + public: + CCTouchDelegate *m_pDelegate; + int m_nPriority; + int m_nEnabledSelectors; + }; - bool init(); + class EGLTouchDelegate + { + public: + virtual void touchesBegan(CCSet* touches, CCEvent* pEvent) = 0; + virtual void touchesMoved(CCSet* touches, CCEvent* pEvent) = 0; + virtual void touchesEnded(CCSet* touches, CCEvent* pEvent) = 0; + virtual void touchesCancelled(CCSet* touches, CCEvent* pEvent) = 0; + virtual ~EGLTouchDelegate() {} + }; - static CCLabelTTF * create(); + class CCTouchDispatcher : public CCObject, public EGLTouchDelegate + { + public: + ~CCTouchDispatcher(); + bool init(void); + CCTouchDispatcher() + : m_pTargetedHandlers(NULL) + , m_pStandardHandlers(NULL) + , m_pHandlersToAdd(NULL) + , m_pHandlersToRemove(NULL) + {} - virtual void setString(const char *label); - virtual const char* getString(void); - - CCTextAlignment getHorizontalAlignment() { - return m_hAlignment; - } - void setHorizontalAlignment(CCTextAlignment alignment) { - if (alignment != m_hAlignment) - { - m_hAlignment = alignment; - - // Force update - if (std::string(m_string).size() > 0) - { - this->updateTexture(); - } - } - } - - CCVerticalTextAlignment getVerticalAlignment() { - return m_vAlignment; - } - void setVerticalAlignment(CCVerticalTextAlignment verticalAlignment) { - if (verticalAlignment != m_vAlignment) - { - m_vAlignment = verticalAlignment; - - // Force update - if (std::string(m_string).size() > 0) - { - this->updateTexture(); - } - } - } - - CCSize getDimensions() { - return m_tDimensions; - } - void setDimensions(const CCSize &dim) { - if (dim.width != m_tDimensions.width || dim.height != m_tDimensions.height) - { - m_tDimensions = dim; - - // Force update - if (std::string(m_string).size() > 0) - { - this->updateTexture(); - } - } - } - - float getFontSize() { - return m_fFontSize; - } - void setFontSize(float fontSize) { - if (m_fFontSize != fontSize) - { - m_fFontSize = fontSize; - - // Force update - if (std::string(m_string).size() > 0) - { - this->updateTexture(); - } - } - } - - const char* getFontName(); - void setFontName(const char *fontName); + public: + bool isDispatchEvents(void); + void setDispatchEvents(bool bDispatchEvents); + + void addStandardDelegate(CCTouchDelegate *pDelegate, int nPriority); + + void addTargetedDelegate(CCTouchDelegate *pDelegate, int nPriority, bool bSwallowsTouches); + + void removeDelegate(CCTouchDelegate *pDelegate); + + void removeAllDelegates(void); + + void setPriority(int nPriority, CCTouchDelegate *pDelegate); + void touches(CCSet *pTouches, CCEvent *pEvent, unsigned int uIndex); + virtual void touchesBegan(CCSet* touches, CCEvent* pEvent); + virtual void touchesMoved(CCSet* touches, CCEvent* pEvent); + virtual void touchesEnded(CCSet* touches, CCEvent* pEvent); + virtual void touchesCancelled(CCSet* touches, CCEvent* pEvent); + + public: + CCTouchHandler* findHandler(CCTouchDelegate *pDelegate); + + void addPrioTargetedDelegate(cocos2d::CCTouchDelegate*, int, bool); + bool isUsingForcePrio(); + void registerForcePrio(cocos2d::CCObject*, int); + void unregisterForcePrio(cocos2d::CCObject*); private: - bool updateTexture(); + RT_ADD( + void incrementForcePrio(int priority); + void decrementForcePrio(int priority); + ) protected: - void _updateWithTextDefinition(ccFontDefinition & textDefinition, bool mustUpdateTexture = true); - ccFontDefinition _prepareTextDefinition(bool adjustForResolution = false); + void forceRemoveDelegate(CCTouchDelegate *pDelegate); + void forceAddHandler(CCTouchHandler *pHandler, CCArray* pArray); + void forceRemoveAllDelegates(void); + void rearrangeHandlers(CCArray* pArray); + CCTouchHandler* findHandler(CCArray* pArray, CCTouchDelegate *pDelegate); - CCSize m_tDimensions; - CCTextAlignment m_hAlignment; - CCVerticalTextAlignment m_vAlignment; - std::string * m_pFontName; - float m_fFontSize; - std::string m_string; + public: + CCArray* m_pTargetedHandlers; + CCArray* m_pStandardHandlers; - bool m_shadowEnabled; - CCSize m_shadowOffset; - float m_shadowOpacity; - float m_shadowBlur; + bool m_bLocked; + bool m_bToAdd; + bool m_bToRemove; + CCArray* m_pHandlersToAdd; + struct _ccCArray *m_pHandlersToRemove; + bool m_bToQuit; + bool m_bDispatchEvents; + // 4, 1 for each type of event + struct ccTouchHandlerHelperData m_sHandlerHelperData[ccTouchMax]; - bool m_strokeEnabled; - ccColor3B m_strokeColor; - float m_strokeSize; + protected: + // 2.2 changes - ccColor3B m_textFillColor; + CC_SYNTHESIZE_NV(int, m_forcePrio, ForcePrio); + void* m_unknown; + CC_SYNTHESIZE_NV(int, m_targetPrio, TargetPrio); }; - // is this really pimpl? - class CCIMEDelegate; - class CCIMEDispatcher + // CCDirector + class TypeInfo { public: - ~CCIMEDispatcher(); + virtual long getClassTypeInfo() = 0; + }; - static CCIMEDispatcher* sharedDispatcher(); + static inline unsigned int getHashCodeByString(const char *key) + { + unsigned int len = strlen(key); + const char *end=key+len; + unsigned int hash; - // /** - // @brief Releases all CCIMEDelegates from the shared dispatcher. - // */ - // static void purgeSharedDispatcher(); + for (hash = 0; key < end; key++) + { + hash *= 16777619; + hash ^= (unsigned int) (unsigned char) toupper(*key); + } + return (hash); + } - void dispatchInsertText(const char * pText, int nLen, cocos2d::enumKeyCodes); + class CCEGLViewProtocol + { + public: + CCEGLViewProtocol(); + virtual ~CCEGLViewProtocol(); + + virtual void end() {} + virtual bool isOpenGLReady() { return false; } + virtual void swapBuffers() {} + virtual void setIMEKeyboardState(bool bOpen) {} + virtual const CCSize& getFrameSize() const; + virtual void setFrameSize(float width, float height); + virtual CCSize getVisibleSize() const; + virtual CCPoint getVisibleOrigin() const; + virtual void setDesignResolutionSize(float width, float height, ResolutionPolicy resolutionPolicy); + virtual const CCSize& getDesignResolutionSize() const; + virtual void setTouchDelegate(EGLTouchDelegate * pDelegate); + virtual void setViewPortInPoints(float x , float y , float w , float h); + virtual void setScissorInPoints(float x , float y , float w , float h); + virtual bool isScissorEnabled(); + virtual CCRect getScissorRect(); + virtual void setViewName(const char* pszViewName); + const char* getViewName(); + virtual void handleTouchesBegin(int num, int ids[], float xs[], float ys[]); + virtual void handleTouchesMove(int num, int ids[], float xs[], float ys[]); + virtual void handleTouchesEnd(int num, int ids[], float xs[], float ys[]); + virtual void handleTouchesCancel(int num, int ids[], float xs[], float ys[]); + const CCRect& getViewPortRect() const; + float getScaleX() const; + float getScaleY() const; + virtual void pollInputEvents(); + void updateDesignResolutionSize(); + + private: + void getSetOfTouchesEndOrCancel(CCSet& set, int num, int ids[], float xs[], float ys[]); + + protected: + EGLTouchDelegate* m_pDelegate; + + // real screen size + CCSize m_obScreenSize; + // resolution size, it is the size appropriate for the app resources. + CCSize m_obDesignResolutionSize; + // the view port size + CCRect m_obViewPortRect; + // the view name + char m_szViewName[50]; + + float m_fScaleX; + float m_fScaleY; + ResolutionPolicy m_eResolutionPolicy; + }; + + class CCEGLView : public CCEGLViewProtocol RT_ADD(, public CCObject) + { + protected: + RT_ADD( virtual ~CCEGLView(); ) + public: + CCEGLView(); + + RT_REMOVE( virtual ~CCEGLView(); ) + + virtual bool isOpenGLReady(); + virtual void end(); + virtual void swapBuffers(); + virtual void setFrameSize(float width, float height); + RT_REMOVE( virtual void setEditorFrameSize(float width, float height,HWND hWnd); ) + virtual void setIMEKeyboardState(bool bOpen); + void updateWindow(int width, int height); + void pollEvents(void); + + void setMenuResource(const wchar_t* menu); + void setWndProc(CUSTOM_WND_PROC proc); + + protected: + RT_REMOVE( virtual bool Create(); ) + void setupWindow(cocos2d::CCRect rect); + RT_ADD(bool initGlew();) + + public: + RT_REMOVE(bool initGL();) + RT_REMOVE(void destroyGL();) + + RT_REMOVE( virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); ) + + void setHWnd(void* hWnd); + // win32 platform function + RT_REMOVE( void* getHWnd(); ) + RT_REMOVE( virtual void resize(int width, int height); ) + RT_ADD( void resizeWindow(int width, int height); ) + + void setFrameZoomFactor(float fZoomFactor); + float getFrameZoomFactor(); + RT_REMOVE( virtual void centerWindow(); ) + RT_ADD( void centerWindow(); ) + RT_ADD( bool windowShouldClose(); ) + + RT_ADD( void showCursor(bool state); ) + + typedef void (*LPFN_ACCELEROMETER_KEYHOOK)( unsigned int message, unsigned long long wParam, long long lParam ); + void setAccelerometerKeyHook( LPFN_ACCELEROMETER_KEYHOOK lpfnAccelerometerKeyHook ); + + virtual void setViewPortInPoints(float x , float y , float w , float h); + virtual void setScissorInPoints(float x , float y , float w , float h); + + static CCEGLView* sharedOpenGLView(); + + static CCEGLView* create(const std::string&); + + static cocos2d::CCEGLView* createWithFullScreen(std::string const&, bool); + static cocos2d::CCEGLView* createWithFullScreen(std::string const&, bool, GLFWvidmode const&, void*); + static cocos2d::CCEGLView* createWithRect(std::string const&, cocos2d::CCRect, float); + + void toggleFullScreen(bool fullscreen, bool borderless); + + void* getWindow(void) const; + + CCSize getDisplaySize(); + + void capture(); + void checkErrorGL(char const*); + + void enableRetina(bool); + + bool getCursorLocked() const; + bool getGameplayActive() const; + bool getIsBorderless() const; + bool getIsFullscreen() const; + int getRetinaFactor() const; + bool getShouldHideCursor() const; + void iconify(); + + bool initWithFullScreen(std::string const&, bool); + bool initWithFullscreen(std::string const&, bool, GLFWvidmode const&, void*); + bool initWithRect(std::string const&, cocos2d::CCRect, float); + + bool isRetinaEnabled() const; + + void onGLFWWindowCloseFunCallback(void*); + void releaseCapture(); + void showMessage(std::string); + + void toggleGameplayActive(bool); + void toggleLockCursor(bool); + void updateDesignSize(int, int); + void updateFrameSize(); + + protected: + static CCEGLView* s_pEglView; + bool m_bCaptured; + RT_REMOVE( + HWND m_hWnd; + HDC m_hDC; + HGLRC m_hRC; + LPFN_ACCELEROMETER_KEYHOOK m_lpfnAccelerometerKeyHook; + ) + bool m_bSupportTouch; + RT_ADD( + bool m_bInRetinaMonitor; + bool m_bRetinaEnabled; + int m_nRetinaFactor; + bool m_bCursorHidden; + ) + RT_REMOVE( + LPCWSTR m_menu; + CUSTOM_WND_PROC m_wndproc; + ) + float m_fFrameZoomFactor; + RT_ADD( + void* m_pMainWindow; + void* m_pPrimaryMonitor; + ) + public: + RT_ADD( + CC_SYNTHESIZE_NV(CCSize, m_obWindowedSize, WindowedSize); + ) + + RT_ADD( + float m_fMouseX; + float m_fMouseY; + bool m_bIsFullscreen; + bool m_bIsBorderless; + bool m_bShouldHideCursor; + bool m_bCursorLocked; + bool m_bShouldCallGLFinish; + ) + + protected: + RT_ADD( + void onGLFWCharCallback(void* window, unsigned int entered); + void onGLFWCursorEnterFunCallback(void* window, int entered); + void onGLFWDeviceChangeFunCallback(void* window); + void onGLFWError(int code, const char* description); + void onGLFWframebuffersize(void* window, int width, int height); + void onGLFWMouseMoveCallBack(void* window, double x, double y); + void onGLFWMouseCallBack(void* window, int button, int action, int mods); + void onGLFWKeyCallback(void* window, int key, int scancode, int action, int mods); + void onGLFWMouseScrollCallback(void* window, double xoffset, double yoffset); + void onGLFWWindowIconifyFunCallback(void* window, int iconified); + void onGLFWWindowPosCallback(void* window, int x, int y); + void onGLFWWindowSizeFunCallback(void* window, int width, int height); + ) + }; + + class CCDirectorDelegate + { + public: + virtual void updateProjection(void) = 0; + }; + + class CCKeypadDispatcher : public CCObject + { + public: + CCKeypadDispatcher(); + ~CCKeypadDispatcher(); + + void addDelegate(CCKeypadDelegate* pDelegate); + void removeDelegate(CCKeypadDelegate* pDelegate); + + void forceAddDelegate(CCKeypadDelegate* pDelegate); + void forceRemoveDelegate(CCKeypadDelegate* pDelegate); + + bool dispatchKeypadMSG(ccKeypadMSGType nMsgType); + + protected: + CCArray* m_pDelegates; + bool m_bLocked; + bool m_bToAdd; + bool m_bToRemove; + + struct _ccCArray *m_pHandlersToAdd; + struct _ccCArray *m_pHandlersToRemove; + }; + + RT_ADD( + class CCKeyboardDispatcher : public CCObject + { + public: + CCKeyboardDispatcher(); + virtual ~CCKeyboardDispatcher(); + + void addDelegate(CCKeyboardDelegate* pDelegate); + void removeDelegate(CCKeyboardDelegate* pDelegate); + + void forceAddDelegate(CCKeyboardDelegate* pDelegate); + void forceRemoveDelegate(CCKeyboardDelegate* pDelegate); + + static enumKeyCodes convertKeyCode(enumKeyCodes key); + + bool dispatchKeyboardMSG(enumKeyCodes key, bool isKeyDown, bool isKeyRepeat); + + inline bool getAltKeyPressed() const { + return m_bAltPressed; + } + inline bool getCommandKeyPressed() const { + return m_bCommandPressed; + } + inline bool getControlKeyPressed() const { + return m_bControlPressed; + } + inline bool getShiftKeyPressed() const { + return m_bShiftPressed; + } + + const char* keyToString(enumKeyCodes key); + + void updateModifierKeys(bool shft, bool ctrl, bool alt, bool cmd); + + inline bool getBlockRepeat() const { + return m_bBlockRepeat; + } + + inline void setBlockRepeat(bool blockRepeat) { + this->m_bBlockRepeat = blockRepeat; + } + + protected: + CCArray* m_pDelegates; // 0x34 + bool m_bUnknown38; // 0x38 + bool m_bUnknown39; // 0x39 + bool m_bUnknown3a; // 0x3a + ccCArray* m_pUnknown3c; // 0x3c + ccCArray* m_pUnknown40; // 0x40 + bool m_bShiftPressed; // 0x44 + bool m_bControlPressed; // 0x45 + bool m_bAltPressed; // 0x46 + bool m_bCommandPressed; // 0x47 + bool m_bBlockRepeat; // 0x48 + + // ~~there's more here, check the initializer~~ no there's not?? + }; + + class CCMouseDispatcher : public CCObject + { + public: + CCMouseDispatcher(); + virtual ~CCMouseDispatcher(); + + void addDelegate(CCMouseDelegate* pDelegate); + void removeDelegate(CCMouseDelegate* pDelegate); + + void forceAddDelegate(CCMouseDelegate* pDelegate); + void forceRemoveDelegate(CCMouseDelegate* pDelegate); + + bool dispatchScrollMSG(float x, float y); + + protected: + CCArray* m_pMouseHandlers; + bool m_bLocked; + bool m_bToAdd; + bool m_bToRemove; + ccCArray* m_pHandlersToAdd; + ccCArray* m_pHandlersToRemove; + }; +) + + class CCAccelerometer + { + public: + CCAccelerometer(); + ~CCAccelerometer(); + + void setDelegate(CCAccelerometerDelegate* pDelegate); + void setAccelerometerInterval(float interval); + void update( double x,double y,double z,double timestamp ); + private: + CCAcceleration m_obAccelerationValue; + CCAccelerometerDelegate* m_pAccelDelegate; + }; + + class CCTextureAtlas; + class CCAtlasNode : public CCNodeRGBA, public CCTextureProtocol + { + protected: + unsigned int m_uItemsPerRow; + unsigned int m_uItemsPerColumn; + + unsigned int m_uItemWidth; + unsigned int m_uItemHeight; + + ccColor3B m_tColorUnmodified; + + CC_PROPERTY(CCTextureAtlas*, m_pTextureAtlas, TextureAtlas); + + bool m_bIsOpacityModifyRGB; + + CC_PROPERTY(ccBlendFunc, m_tBlendFunc, BlendFunc); + + CC_PROPERTY(unsigned int, m_uQuadsToDraw, QuadsToDraw); + GLint m_nUniformColor; + bool m_bIgnoreContentScaleFactor; + + public: + CCAtlasNode(); + virtual ~CCAtlasNode(); + + static CCAtlasNode * create(const char* tile,unsigned int tileWidth, unsigned int tileHeight, + unsigned int itemsToRender); + + bool initWithTileFile(const char* tile, unsigned int tileWidth, unsigned int tileHeight, unsigned int itemsToRender); + + bool initWithTexture(CCTexture2D* texture, unsigned int tileWidth, unsigned int tileHeight, unsigned int itemsToRender); + + virtual void updateAtlasValues(); + + virtual void draw(void); + + // CC Texture protocol + virtual CCTexture2D* getTexture(void); + + virtual void setTexture(CCTexture2D *texture); + + virtual bool isOpacityModifyRGB(); + virtual void setOpacityModifyRGB(bool isOpacityModifyRGB); + virtual const ccColor3B& getColor(void); + virtual void setColor(const ccColor3B& color); + virtual void setOpacity(GLubyte opacity); + + private : + void calculateMaxItems(); + void updateBlendFunc(); + void updateOpacityModifyRGB(); + + friend class CCDirector; + void setIgnoreContentScaleFactor(bool bIgnoreContentScaleFactor); + }; + + class CCLabelAtlas : public CCAtlasNode, public CCLabelProtocol + { + public: + CCLabelAtlas() + : m_sString("") + {} + virtual ~CCLabelAtlas() + { + m_sString = ""; + } + + static CCLabelAtlas * create(const char *string, const char *charMapFile, unsigned int itemWidth, unsigned int itemHeight, unsigned int startCharMap); + + static CCLabelAtlas* create(const char *string, const char *fntFile); + + bool initWithString(const char *string, const char *charMapFile, unsigned int itemWidth, unsigned int itemHeight, unsigned int startCharMap); + + bool initWithString(const char *string, const char *fntFile); + + bool initWithString(const char* string, CCTexture2D* texture, unsigned int itemWidth, unsigned int itemHeight, unsigned int startCharMap); + + virtual void updateAtlasValues(); + virtual void setString(const char *label); + virtual const char* getString(void); + + #if CC_LABELATLAS_DEBUG_DRAW + virtual void draw(); + #endif + + protected: + // string to render + std::string m_sString; + // the first char in the charmap + unsigned int m_uMapStartChar; + }; + + class CCDirector : public CCObject, public TypeInfo + { + public: + CCDirector(void); + virtual ~CCDirector(void); + virtual bool init(void); + + virtual long getClassTypeInfo() { + // static const long id = cocos2d::getHashCodeByString(typeid(cocos2d::CCDirector).name()); + static const long id = 0; + return id; + } + + inline CCScene* getRunningScene(void) { return m_pRunningScene; } + + inline double getAnimationInterval(void) { return m_dAnimationInterval; } + virtual void setAnimationInterval(double dValue) {} + + inline bool isDisplayStats(void) { return m_bDisplayStats; } + inline void setDisplayStats(bool bDisplayStats) { m_bDisplayStats = bDisplayStats; } + + inline float getSecondsPerFrame() { return m_fSecondsPerFrame; } + + inline CCEGLView* getOpenGLView(void) { return m_pobOpenGLView; } + void setOpenGLView(CCEGLView *pobOpenGLView); + + inline bool isNextDeltaTimeZero(void) { return m_bNextDeltaTimeZero; } + void setNextDeltaTimeZero(bool bNextDeltaTimeZero); + + inline bool isPaused(void) { return m_bPaused; } + + inline unsigned int getTotalFrames(void) { return m_uTotalFrames; } + + inline ccDirectorProjection getProjection(void) { return m_eProjection; } + void setProjection(ccDirectorProjection kProjection); + void reshapeProjection(const CCSize& newWindowSize); + + void setViewport(); + + inline bool isSendCleanupToScene(void) { return m_bSendCleanupToScene; } + + CCNode* getNotificationNode(); + void setNotificationNode(CCNode *node); + + CCDirectorDelegate* getDelegate() const; + void setDelegate(CCDirectorDelegate* pDelegate); + + // window size + CCSize getWinSize(void); + CCSize getWinSizeInPixels(void); + CCSize getVisibleSize(); + CCPoint getVisibleOrigin(); + + CCPoint convertToGL(const CCPoint& obPoint); + + CCPoint convertToUI(const CCPoint& obPoint); + + float getZEye(void); + + // Scene Management + + void runWithScene(CCScene *pScene); + + RT_REMOVE( void pushScene(CCScene *pScene); ) + RT_ADD( bool pushScene(CCScene *pScene); ) + + void popScene(void); + void popToRootScene(void); + void popToSceneStackLevel(int level); + + RT_REMOVE( void replaceScene(CCScene *pScene); ) + RT_ADD( bool replaceScene(CCScene *pScene); ) + + void end(void); + void pause(void); + void resume(void); + + protected: + virtual void stopAnimation(void) {} + virtual void startAnimation(void) {} + + public: + void drawScene(void); + + // Memory Helper + + void purgeCachedData(void); + void setDefaultValues(void); + + // OpenGL Helper + void setGLDefaultValues(void); + void setAlphaBlending(bool bOn); + void setDepthTest(bool bOn); + + protected: + virtual void mainLoop(void) {} + + public: + void setContentScaleFactor(float scaleFactor); + inline float getContentScaleFactor(void) { return m_fContentScaleFactor; } + + RT_ADD( + public: + void checkSceneReference(void); + + CCScene* getNextScene(void); + int levelForSceneInStack(CCScene*); + bool popSceneWithTransition(float, PopTransition); + void popToSceneInStack(CCScene*); + int sceneCount(void); + void willSwitchToScene(CCScene*); + + void removeStatsLabel(void); + + void resetSmoothFixCounter(void); + void setDeltaTime(float); + + void setupScreenScale(CCSize, CCSize, TextureQuality); + void updateContentScale(TextureQuality); + void updateScreenScale(CCSize); + + void applySmoothFix(); + void showFPSLabel(); + void toggleShowFPS(bool, std::string, cocos2d::CCPoint); + protected: + void createStatsLabel(); + + protected: + CC_SYNTHESIZE_READONLY_NV(float, m_fScreenScaleFactor, ScreenScaleFactor); + CC_SYNTHESIZE_READONLY_NV(float, m_fScreenScaleFactorMax, ScreenScaleFactorMax); + CC_SYNTHESIZE_READONLY_NV(float, m_fScreenScaleFactorW, ScreenScaleFactorW); + CC_SYNTHESIZE_READONLY_NV(float, m_fScreenScaleFactorH, ScreenScaleFactorH); + CC_SYNTHESIZE_READONLY_NV(float, m_fScreenTop, ScreenTop); + CC_SYNTHESIZE_READONLY_NV_NC(float, m_fScreenBottom, ScreenBottom); + CC_SYNTHESIZE_READONLY_NV_NC(float, m_fScreenLeft, ScreenLeft); + CC_SYNTHESIZE_READONLY_NV(float, m_fScreenRight, ScreenRight); + CC_SYNTHESIZE_NV(CCScene*, m_pSceneReference, SceneReference); + ) + + public: + CC_PROPERTY(CCScheduler*, m_pScheduler, Scheduler); + CC_PROPERTY(CCActionManager*, m_pActionManager, ActionManager); + CC_PROPERTY(CCTouchDispatcher*, m_pTouchDispatcher, TouchDispatcher); + CC_PROPERTY(CCKeypadDispatcher*, m_pKeypadDispatcher, KeypadDispatcher); + RT_ADD( + CC_PROPERTY(CCKeyboardDispatcher*, m_pKeyboardDispatcher, KeyboardDispatcher); + + CC_PROPERTY(CCMouseDispatcher*, m_pMouseDispatcher, MouseDispatcher); + ) + CC_PROPERTY(CCAccelerometer*, m_pAccelerometer, Accelerometer); + CC_PROPERTY_READONLY(float, m_fDeltaTime, DeltaTime); + + RT_ADD( + CC_SYNTHESIZE_NV(float, m_fActualDeltaTime, ActualDeltaTime); + ) + + public: + static CCDirector* sharedDirector(void); + + protected: + void purgeDirector(); + RT_ADD( + CC_SYNTHESIZE_READONLY_NV(bool, m_bIsTransitioning, IsTransitioning); // if in a CCTransitionScene + + CC_SYNTHESIZE_NV(bool, m_bSmoothFix, SmoothFix); // if smooth fix is on + CC_SYNTHESIZE_NV(bool, m_bSmoothFixCheck, SmoothFixCheck); // not exactly sure what this is, but the name says something ig + CC_SYNTHESIZE_NV(bool, m_bForceSmoothFix, ForceSmoothFix); // if "force smooth fix" is on or not + CC_SYNTHESIZE_READONLY_NV(int, m_nSmoothFixCounter, SmoothFixCounter); // not sure about this one either + ) + + bool m_bPurgeDirecotorInNextLoop; // this flag will be set to true in end() + + protected: + void setNextScene(void); + + void showStats(); + RT_REMOVE(void createStatsLabel();) + void calculateMPF(); + void getFPSImageData(unsigned char** datapointer, unsigned int* length); + + void calculateDeltaTime(); + public: + CCEGLView *m_pobOpenGLView; + + double m_dAnimationInterval; + double m_dOldAnimationInterval; + + bool m_bLandscape; + + bool m_bDisplayStats; + + float m_fFpsAccumDt; + + float m_fAccumDt; + float m_fFrameRate; + + CCLabelAtlas *m_pFPSLabel; + CCLabelAtlas *m_pSPFLabel; + CCLabelAtlas *m_pDrawsLabel; + + bool m_bPaused; + + unsigned int m_uTotalFrames; + unsigned int m_uFrames; + float m_fSecondsPerFrame; + + CCScene *m_pRunningScene; + + CCScene *m_pNextScene; + + bool m_bSendCleanupToScene; + + CCArray* m_pobScenesStack; + + struct cc_timeval *m_pLastUpdate; + + bool m_bNextDeltaTimeZero; + + ccDirectorProjection m_eProjection; + + CCSize m_obWinSizeInPoints; + + float m_fContentScaleFactor; + + char *m_pszFPS; + + CCNode *m_pNotificationNode; + + CCDirectorDelegate *m_pProjectionDelegate; + + RT_ADD( + CC_SYNTHESIZE(CCSceneDelegate*, m_pAppDelegate, SceneDelegate); + bool m_bDisplayFPS; + CCLabelBMFont* m_pFPSNode; + CCSize m_obScaleFactor; + CCSize m_obResolutionInPixels; + CC_SYNTHESIZE_READONLY_NV(TextureQuality, m_eTextureQuality, LoadedTextureQuality); + CC_SYNTHESIZE_NV(bool, m_bDontCallWillSwitch, DontCallWillSwitch); + void* m_unknownPtr2; + void* m_unknownPtr3; + ) + + friend class CCEGLViewProtocol; + }; + + + // CCTextFieldTTF + class CCLabelTTF : public CCSprite, public CCLabelProtocol + { + public: + CCLabelTTF(); + virtual ~CCLabelTTF(); + const char* description(); + + static CCLabelTTF * create(const char *string, const char *fontName, float fontSize); + + static CCLabelTTF * create(const char *string, const char *fontName, float fontSize, + const CCSize& dimensions, CCTextAlignment hAlignment); + + static CCLabelTTF * create(const char *string, const char *fontName, float fontSize, + const CCSize& dimensions, CCTextAlignment hAlignment, + CCVerticalTextAlignment vAlignment); + + static CCLabelTTF * createWithFontDefinition(const char *string, ccFontDefinition &textDefinition); + + bool initWithString(const char *string, const char *fontName, float fontSize); + + bool initWithString(const char *string, const char *fontName, float fontSize, + const CCSize& dimensions, CCTextAlignment hAlignment); + + bool initWithString(const char *string, const char *fontName, float fontSize, + const CCSize& dimensions, CCTextAlignment hAlignment, + CCVerticalTextAlignment vAlignment); + + bool initWithStringAndTextDefinition(const char *string, ccFontDefinition &textDefinition); + + void setTextDefinition(ccFontDefinition *theDefinition); + + ccFontDefinition * getTextDefinition(); + + + + void enableShadow(const CCSize &shadowOffset, float shadowOpacity, float shadowBlur, bool mustUpdateTexture = true); + + void disableShadow(bool mustUpdateTexture = true); + + void enableStroke(const ccColor3B &strokeColor, float strokeSize, bool mustUpdateTexture = true); + + void disableStroke(bool mustUpdateTexture = true); + + void setFontFillColor(const ccColor3B &tintColor, bool mustUpdateTexture = true); + + + bool init(); + + static CCLabelTTF * create(); + + virtual void setString(const char *label); + virtual const char* getString(void); + + CCTextAlignment getHorizontalAlignment() { + return m_hAlignment; + } + void setHorizontalAlignment(CCTextAlignment alignment) { + if (alignment != m_hAlignment) + { + m_hAlignment = alignment; + + // Force update + if (std::string(m_string).size() > 0) + { + this->updateTexture(); + } + } + } + + CCVerticalTextAlignment getVerticalAlignment() { + return m_vAlignment; + } + void setVerticalAlignment(CCVerticalTextAlignment verticalAlignment) { + if (verticalAlignment != m_vAlignment) + { + m_vAlignment = verticalAlignment; + + // Force update + if (std::string(m_string).size() > 0) + { + this->updateTexture(); + } + } + } + + CCSize getDimensions() { + return m_tDimensions; + } + void setDimensions(const CCSize &dim) { + if (dim.width != m_tDimensions.width || dim.height != m_tDimensions.height) + { + m_tDimensions = dim; + + // Force update + if (std::string(m_string).size() > 0) + { + this->updateTexture(); + } + } + } + + float getFontSize() { + return m_fFontSize; + } + void setFontSize(float fontSize) { + if (m_fFontSize != fontSize) + { + m_fFontSize = fontSize; + + // Force update + if (std::string(m_string).size() > 0) + { + this->updateTexture(); + } + } + } + + const char* getFontName(); + void setFontName(const char *fontName); + + private: + bool updateTexture(); + + protected: + void _updateWithTextDefinition(ccFontDefinition & textDefinition, bool mustUpdateTexture = true); + ccFontDefinition _prepareTextDefinition(bool adjustForResolution = false); + + CCSize m_tDimensions; + CCTextAlignment m_hAlignment; + CCVerticalTextAlignment m_vAlignment; + std::string * m_pFontName; + float m_fFontSize; + std::string m_string; + + bool m_shadowEnabled; + CCSize m_shadowOffset; + float m_shadowOpacity; + float m_shadowBlur; + + + bool m_strokeEnabled; + ccColor3B m_strokeColor; + float m_strokeSize; + + ccColor3B m_textFillColor; + }; + + // is this really pimpl? + class CCIMEDelegate; + class CCIMEDispatcher + { + public: + ~CCIMEDispatcher(); + + static CCIMEDispatcher* sharedDispatcher(); + + // /** + // @brief Releases all CCIMEDelegates from the shared dispatcher. + // */ + // static void purgeSharedDispatcher(); + + void dispatchInsertText(const char * pText, int nLen, cocos2d::enumKeyCodes); void dispatchDeleteBackward(); @@ -4577,6 +5521,8 @@ namespace cocos2d private: class LengthStack; LengthStack * m_pLens; + public: + int m_uCursorPos; }; @@ -4684,119 +5630,6 @@ namespace cocos2d }; - // CCTouchDispatcher - class CCTouchHandler : public CCObject - { - public: - inline CCTouchHandler() = default; - virtual ~CCTouchHandler(void); - - CCTouchDelegate* getDelegate(); - void setDelegate(CCTouchDelegate *pDelegate); - - int getPriority(void); - void setPriority(int nPriority); - - int getEnabledSelectors(void); - void setEnalbedSelectors(int nValue); - - virtual bool initWithDelegate(CCTouchDelegate *pDelegate, int nPriority); - - public: - static CCTouchHandler* handlerWithDelegate(CCTouchDelegate *pDelegate, int nPriority); - - public: - CCTouchDelegate *m_pDelegate; - int m_nPriority; - int m_nEnabledSelectors; - }; - - class EGLTouchDelegate - { - public: - virtual void touchesBegan(CCSet* touches, CCEvent* pEvent) = 0; - virtual void touchesMoved(CCSet* touches, CCEvent* pEvent) = 0; - virtual void touchesEnded(CCSet* touches, CCEvent* pEvent) = 0; - virtual void touchesCancelled(CCSet* touches, CCEvent* pEvent) = 0; - virtual ~EGLTouchDelegate() {} - }; - - class CCTouchDispatcher : public CCObject, public EGLTouchDelegate - { - public: - ~CCTouchDispatcher(); - bool init(void); - CCTouchDispatcher() - : m_pTargetedHandlers(NULL) - , m_pStandardHandlers(NULL) - , m_pHandlersToAdd(NULL) - , m_pHandlersToRemove(NULL) - {} - - public: - bool isDispatchEvents(void); - void setDispatchEvents(bool bDispatchEvents); - - void addStandardDelegate(CCTouchDelegate *pDelegate, int nPriority); - - void addTargetedDelegate(CCTouchDelegate *pDelegate, int nPriority, bool bSwallowsTouches); - - void removeDelegate(CCTouchDelegate *pDelegate); - - void removeAllDelegates(void); - - void setPriority(int nPriority, CCTouchDelegate *pDelegate); - void touches(CCSet *pTouches, CCEvent *pEvent, unsigned int uIndex); - virtual void touchesBegan(CCSet* touches, CCEvent* pEvent); - virtual void touchesMoved(CCSet* touches, CCEvent* pEvent); - virtual void touchesEnded(CCSet* touches, CCEvent* pEvent); - virtual void touchesCancelled(CCSet* touches, CCEvent* pEvent); - - public: - CCTouchHandler* findHandler(CCTouchDelegate *pDelegate); - - void addPrioTargetedDelegate(cocos2d::CCTouchDelegate*, int, bool); - bool isUsingForcePrio(); - void registerForcePrio(cocos2d::CCObject*, int); - void unregisterForcePrio(cocos2d::CCObject*); - - private: - RT_ADD( - void incrementForcePrio(int priority); - void decrementForcePrio(int priority); - ) - - protected: - void forceRemoveDelegate(CCTouchDelegate *pDelegate); - void forceAddHandler(CCTouchHandler *pHandler, CCArray* pArray); - void forceRemoveAllDelegates(void); - void rearrangeHandlers(CCArray* pArray); - CCTouchHandler* findHandler(CCArray* pArray, CCTouchDelegate *pDelegate); - - public: - CCArray* m_pTargetedHandlers; - CCArray* m_pStandardHandlers; - - bool m_bLocked; - bool m_bToAdd; - bool m_bToRemove; - CCArray* m_pHandlersToAdd; - struct _ccCArray *m_pHandlersToRemove; - bool m_bToQuit; - bool m_bDispatchEvents; - - // 4, 1 for each type of event - struct ccTouchHandlerHelperData m_sHandlerHelperData[ccTouchMax]; - - protected: - // 2.2 changes - - CC_SYNTHESIZE_NV(int, m_forcePrio, ForcePrio); - void* m_unknown; - CC_SYNTHESIZE_NV(int, m_targetPrio, TargetPrio); - }; - - // extension namespace extension { diff --git a/broma_ida/types/enums.hpp b/broma_ida/types/enums.hpp index 74aeff3..de4b742 100644 --- a/broma_ida/types/enums.hpp +++ b/broma_ida/types/enums.hpp @@ -208,6 +208,7 @@ enum class GJSongError { DownloadSongFailed = 1, DownloadSFXFailed = 2 }; +enum class GJSongType {}; //probs normal and ncs enum class LikeItemType { Unknown = 0, Level = 1, @@ -455,6 +456,8 @@ enum class ObjectScaleType { enum class CommentType { Level = 0, Account = 1, + FriendRequest = 2, + ListDescription = 4, }; enum class BoomListType { @@ -643,6 +646,7 @@ enum class EasingType { }; enum class GJDifficulty { + NA = -1, Auto = 0, Easy = 1, Normal = 2, @@ -710,7 +714,67 @@ enum class LevelLeaderboardType { }; enum class GJHttpType { - + UploadLevel = 0x1, + GetOnlineLevels = 0x2, + GetMapPacks = 0x3, + DownloadLevel = 0x4, + UpdateLevel = 0x5, + RateStars = 0x6, + DeleteServerLevel = 0x7, + SetLevelStars = 0x8, + SetLevelFeatured = 0x9, + UpdateUserScore = 0xA, + GetLeaderboardScores = 0xB, + GetLevelComments = 0xC, + UploadComment = 0xD, + DeleteComment = 0xE, + LikeItem = 0xF, + RestoreItems = 0x10, + SubmitUserInfo = 0x11, + ReportLevel = 0x12, + GetSongInfo = 0x13, + BackupAccount = 0x14, + SyncAccount = 0x15, + RegisterAccount = 0x16, + LoginAccount = 0x17, + UpdateDescription = 0x18, + GetAccountComments = 0x19, + UpdateAccountSettings = 0x1A, + GetGJUserInfo = 0x1B, + GetFriendRequests = 0x1C, + UploadFriendRequest = 0x1D, + DeleteFriendRequest = 0x1E, + AcceptFriendRequest = 0x1F, + ReadFriendRequest = 0x20, + RemoveFriend = 0x21, + BlockUser = 0x22, + UnblockUser = 0x23, + GetUserList = 0x24, + GetUserMessages = 0x25, + DownloadUserMessage = 0x26, + DeleteUserMessages = 0x27, + UploadUserMessage = 0x28, + GetUsers = 0x29, + BanUser = 0x2A, + RequestUserAccess = 0x2B, + GetLevelSaveData = 0x2C, + SuggestLevelStars = 0x2D, + GetGJRewards = 0x2E, + GetGJChallenges = 0x2F, + GetGJDailyLevelState = 0x30, + Unknown49 = 0x31, + RateDemon = 0x32, + GetLevelLeaderboard = 0x33, + GetGauntlets = 0x34, + GetTopArtists = 0x35, + GetAccountBackupURL = 0x36, + GetAccountSyncURL = 0x37, + + // Yet to be added by Robtop in 2.21 + // joinLobby = 0x39, + // ExitMPLobby = 0x3a, + + DeleteServerLevelList = 0x3e, }; enum class DialogChatPlacement { @@ -728,6 +792,11 @@ enum class DialogAnimationType { // a 5th type is defined which acts exactly the same as FromTop }; +enum class CircleMode { + Filled = 0, + Outline = 1, +}; + // Geode Additions diff --git a/broma_ida/utils.py b/broma_ida/utils.py index 0e3cd8b..41017b7 100644 --- a/broma_ida/utils.py +++ b/broma_ida/utils.py @@ -1,9 +1,8 @@ from typing import get_args, Union, NoReturn, Optional from idaapi import ( - get_imagebase, get_inf_structure, get_file_type_name, - BADADDR, SN_NOWARN, - f_PE, f_MACHO + get_imagebase, get_file_type_name, + BADADDR, SN_NOWARN ) from ida_kernwin import ask_buttons, ask_str, ASKBTN_BTN1 from ida_name import get_name_ea @@ -11,15 +10,10 @@ from sys import path as sys_path from os import path as os_path -from re import sub from pathlib import Path -from broma_ida.broma.constants import ( - BROMA_PLATFORMS, CPP_TYPE_QUALIFIERS, CPP_DATA_TYPES, - CPP_PRIMITIVES -) +from broma_ida.broma.constants import BROMA_PLATFORMS from broma_ida.broma.binding import Binding -from broma_ida.broma.argtype import ArgType g_platform: Optional[BROMA_PLATFORMS] = None @@ -121,27 +115,21 @@ def get_platform() -> Union[BROMA_PLATFORMS, NoReturn]: if g_platform is not None: return g_platform - structure_info = get_inf_structure() + structure_info = get_file_type_name() - if structure_info.filetype == f_PE: + if "PE" in structure_info: g_platform = "win" return "win" - - if structure_info.filetype == f_MACHO: - file_type_name = get_file_type_name() - - if file_type_name.endswith("ARM64"): - g_platform = "ios" - return "ios" - elif file_type_name.endswith("X86_64"): - g_platform = "mac" - return "mac" - - if g_platform == "": - platform = ask_str( - "win", 256, "Enter a platform (win, mac or ios)" - ) - g_platform = platform + elif structure_info.endswith("ARM64"): + g_platform = "m1" + return "m1" + elif structure_info.endswith("X86_64"): + g_platform = "imac" + return "imac" + + platform = ask_str( + "win", 256, "Enter a platform (win, imac (intel mac), m1 or ios)" + ) if platform not in get_args(BROMA_PLATFORMS): popup( @@ -152,6 +140,8 @@ def get_platform() -> Union[BROMA_PLATFORMS, NoReturn]: ) stop() + g_platform = platform + return platform @@ -167,70 +157,13 @@ def get_platform_printable(platform: BROMA_PLATFORMS) -> str: platform_to_printable = { "win": "Windows", "ios": "iOS", - "mac": "MacOS" # MacchewOS my beloved + "imac": "Intel MacOS", # MacchewOS my beloved + "m1": "M1 MacOS" } return platform_to_printable[platform] -def are_args_primitive(arguments: dict[str, ArgType]) -> bool: - """Checks if the arguments are all primitives because - importing structs isn't supported yet - TODO: start importing structs :D - - Args: - arguments (dict[str, str]) - - Returns: - bool: ya - """ - is_pointer_or_reference = \ - lambda p: p[-1] == "*" or p[-1] == "&" # noqa: E731 - remove_pointer_or_reference = \ - lambda p: p[:-1] if is_pointer_or_reference(p) else p # noqa: E731 - - if len(arguments) == 0: - return True - - arguments_str = { - name: t["type"] for name, t in arguments.items() - } - - for name, arg_type in arguments_str.items(): - arguments_str[name] = sub( - rf"""(?: )?unsigned(?!{ - "|".join([f" {x}" for x in CPP_DATA_TYPES]) - })""", - "unsigned int", - arg_type - ) - - for qualifier in CPP_TYPE_QUALIFIERS: - arguments_str[name] = sub( - rf"(?: )?{qualifier}(?: )?", - "", - arguments_str[name] - ) - - arguments_str[name] = remove_pointer_or_reference(arguments_str[name]) - - return all([ - arg_type in CPP_PRIMITIVES for _, arg_type in arguments_str.items() - ]) - - -def is_primitive_type(ret: str) -> bool: - """Is a type a C++ primitive - - Args: - ret (str): ya - - Returns: - bool: ya - """ - return ret in CPP_PRIMITIVES - - def get_ida_plugin_path() -> Optional[Path]: """_summary_