Skip to content

Commit

Permalink
add(mach-o), feat(gnustl), chore(cocos2d): Support Mac and iOS. Move …
Browse files Browse the repository at this point in the history
…all STL header includes to seperate file and rework gnustl stuff. Update cocos2d headers.
  • Loading branch information
SpaghettDev committed Aug 18, 2024
1 parent dc8860c commit 3bcd7b8
Show file tree
Hide file tree
Showing 12 changed files with 1,471 additions and 1,301 deletions.
9 changes: 4 additions & 5 deletions BromaIDA.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION = "5.6.0"
VERSION = "5.7.0"
__AUTHOR__ = "SpaghettDev"

PLUGIN_NAME = "BromaIDA"
Expand Down Expand Up @@ -26,11 +26,10 @@ def bida_main():
import_export_prompt = popup(
"Import", "Export", "",
"Import or Export Broma file?\n"
"(Please make sure Extras.bro is in the same directory)"
)

if import_export_prompt == ASKBTN_BTN1:
filePath = ask_file(False, "GeometryDash.bro", "bro")
filePath: str = ask_file(False, "GeometryDash.bro", "bro")

if filePath is None or (filePath and not filePath.endswith(".bro")):
popup("Ok", "Ok", None, "Please select a valid file!")
Expand Down Expand Up @@ -101,15 +100,15 @@ class BromaIDAPlugin(ida_plugin_t):
def init(self):
"""Ran on plugin load"""
self._register_action()
ida_msg(f"{self.wanted_name} v{VERSION} initialized\n")
ida_msg(f"{PLUGIN_NAME} v{VERSION} initialized\n")

return PLUGIN_KEEP

def term(self):
"""Ran on plugin unload"""
self._unregister_action()

ida_msg(f"{self.wanted_name} v{VERSION} unloaded\n")
ida_msg(f"{PLUGIN_NAME} v{VERSION} unloaded\n")

def run(self, arg):
"""Ran on "File -> Script File" (shocker) (broken for me :D)"""
Expand Down
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,17 @@ Parses a Broma file and exports the bindings into a Broma file/imports the bindi
To import types, you must have IDAClang and the headers for the target platform. Currently only tested with Windows and Android.
1. Open the target binary in IDA
2. In the top bar, select Options > Compiler, Source Parser: Clang. And in Include Directories, replace with the location of the header files
1. For MSVC (Windows binary)
1. Set the Include Directories to `C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.40.33807\include`
2. For GCC (Android binary)
1. For Windows binary
1. Get MSVC Headers by installing MSVC using [Visual Studio Installer](https://visualstudio.microsoft.com/downloads)
2. Set the Include Directories to `C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.40.33807\include`
2. For Android binaries (Android 64 and 32 bit)
1. First get gcc-arm-none-linux-gnueabihf (i did so by using scoop; `scoop install extras/gcc-arm-none-linux-gnueabihf`)
2. Then, in the Include Directories, set it to `C:\Users\YOUR_NAME\scoop\apps\gcc-arm-none-linux-gnueabihf\current\arm-none-linux-gnueabihf\include\c++\13.3.1;C:\Users\YOUR_NAME\scoop\apps\gcc-arm-none-linux-gnueabihf\current\arm-none-linux-gnueabihf\include\c++\13.3.1\arm-none-linux-gnueabihf;C:\Users\YOUR_NAME\scoop\apps\gcc-arm-none-linux-gnueabihf\current\arm-none-linux-gnueabihf\libc\usr\include;C:\Users\YOUR_NAME\scoop\apps\gcc-arm-none-linux-gnueabihf\current\lib\gcc\arm-none-linux-gnueabihf\13.3.1\include` (be sure to replace YOUR_NAME with your windows username)
3. Or use MSVC headers, i think it works fine?
3. For GCC (MacOS and iOS), i have no clue
3. Or use MSVC headers, but be sure to click "Yes" when prompted to use Custom GNU STL!
3. For MacOS (Intel and M1 Mac) and iOS binaries
1. First get gcc (i did so by using scoop; `scoop install gcc`)
2. Then, in the Include Directories, set it to `C:\Users\YOUR_NAME\scoop\apps\gcc\current\include\c++\13.2.0;C:\Users\YOUR_NAME\scoop\apps\gcc\current\include\c++\13.2.0\x86_64-w64-mingw32;C:\Users\YOUR_NAME\scoop\apps\gcc\current\x86_64-w64-mingw32\include` (be sure to replace YOUR_NAME with your windows username)
3. Or use MSVC headers, but again, be sure to click "Yes" when prompted to use Custom GNU STL.
3. Click on OK

Start the script and when prompted to import types, click yes, then the types will automatically be imported for you.
Expand Down
109 changes: 55 additions & 54 deletions broma_ida/broma/codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@
class BromaCodegen:
"""Codegen for Broma"""

FILE_HEADER = f"""// Generated by BromaIDA, do not modify
FILE_HEADER = """// Generated by BromaIDA, do not modify
#include <array>
#define BROMAIDA_PLATFORM_MACRO_NAME
#define BROMAIDA_USE_CUSTOM_GNUSTL_MACRO
#define BROMAIDA_USE_CUSTOM_GNUSTL {BROMAIDA_USE_CUSTOM_GNUSTL_VALUE}
// platform shorthands
#define BROMAIDA_IS_PLATFORM_MACHO {BROMAIDA_IS_PLATFORM_MACHO_VALUE}
#define BROMAIDA_IS_PLATFORM_ANDROID {BROMAIDA_IS_PLATFORM_ANDROID_VALUE}
#define STR_CONCAT_WRAPPER(a, b) a ## b
#define STR_CONCAT(a, b) STR_CONCAT_WRAPPER(a, b)
Expand All @@ -25,15 +28,13 @@ class BromaCodegen:
_use_custom_gnustl: bool = True
_broma_path: Path

_added_classes: set[str] = set()

def __init__(
self,
platform: BROMA_PLATFORMS,
use_custom_gnustl: bool,
broma_classes: dict[str, Class],
path: Path,
broma_path: Path,
broma_path: Path
):
self._target_platform = platform
self._use_custom_gnustl = use_custom_gnustl
Expand All @@ -50,53 +51,46 @@ def write(self):
Args:
path (Path)
"""
macro_val = lambda b: "1" if b else "0"

with open(
self._path / "codegen" / f"{self._target_platform}.hpp",
"w",
buffering=10 * 1024 * 1024,
) as f:
f.write(
self.FILE_HEADER.replace(
"BROMAIDA_PLATFORM_MACRO_NAME",
self._get_bromaida_platform_macro(),
).replace(
"BROMAIDA_USE_CUSTOM_GNUSTL_MACRO",
"BROMAIDA_USE_CUSTOM_GNUSTL"
if self._use_custom_gnustl
else "BROMAIDA_DONT_USE_CUSTOM_GNUSTL",
)
self.FILE_HEADER.format_map({
"BROMAIDA_PLATFORM_MACRO_NAME":
self._get_bromaida_platform_macro(),
"BROMAIDA_USE_CUSTOM_GNUSTL_VALUE":
macro_val(self._use_custom_gnustl),
"BROMAIDA_IS_PLATFORM_MACHO_VALUE":
macro_val(self._target_platform in ["imac", "m1", "ios"]),
"BROMAIDA_IS_PLATFORM_ANDROID_VALUE":
macro_val(
self._target_platform in ["android32", "android64"]
)
})
)

with open(self._path / "enums.hpp") as enums:
f.write("// enums.hpp\n")
f.writelines(enums.readlines())
f.write("\n\n")

if self._target_platform.startswith("android"):
with open(self._path / "gnustl.hpp") as gnustl:
f.write("// gnustl.hpp\n")
f.writelines(gnustl.readlines())
f.write("\n\n")
else:
f.write("// standard headers\n")
for header in (
"string",
"vector",
"map",
"unordered_map",
"set",
"unordered_set",
):
f.write(f"#include <{header}>\n")
f.write("\n")
with open(self._path / "stl_includes.hpp") as stl_includes:
f.write("// stl_includes.hpp\n")
f.writelines(stl_includes.readlines())
f.write("\n\n")

with open(self._path / "stl_types.hpp") as stl_types:
f.write("// stl_types.hpp\n")
f.writelines(self._filter_relative_includes(stl_types.readlines()))
f.write("\n\n")

with open(self._path / "cocos2d.hpp") as cocos:
f.write("// cocos2d.hpp\n")
for line in cocos.readlines():
if line.startswith('#include "'):
line = f"// {line}"

f.write(line)
f.writelines(self._filter_relative_includes(cocos.readlines()))
f.write("\n\n")

with open(self._path / "fmod.hpp") as fmod:
Expand Down Expand Up @@ -140,10 +134,10 @@ def write(self):
f.flush()

f.write("// extras\n")
for name, broma_class in (
for _, broma_class in (
Root(str(self._broma_path / "Extras.bro"))
.classesAsDict()
.items()
.classesAsDict()
.items()
):
f.write(
ClassBuilder(self._target_platform, broma_class).get_str()
Expand All @@ -153,12 +147,10 @@ def write(self):
f.flush()

f.write("// delegates and non-polymorphic classes\n")
for name, broma_class in self._classes.items():
for _, broma_class in self._classes.items():
if len(broma_class.superclasses) != 0:
continue

self._added_classes.add(name)

f.write(
ClassBuilder(self._target_platform, broma_class).get_str()
)
Expand All @@ -167,23 +159,15 @@ def write(self):
f.flush()

f.write("// classes\n")
for name, broma_class in self._classes.items():
if name in self._added_classes:
for _, broma_class in self._classes.items():
if len(broma_class.superclasses) == 0:
continue

f.write(
ClassBuilder(self._target_platform, broma_class).get_str()
)
f.write("\n")

with open(self._path / "stl_types.hpp") as stl_types:
f.write("// stl_types.hpp\n")
for line in stl_types.readlines():
if line.startswith('#include "'):
line = f"// {line}"

f.write(line)

def _get_bromaida_platform_macro(self) -> str:
"""Gets the BromaIDA platform macro name (shocker)"""
plat_to_macro_suffix: dict[BROMA_PLATFORMS, str] = {
Expand All @@ -192,7 +176,24 @@ def _get_bromaida_platform_macro(self) -> str:
"m1": "M1_MACOS",
"ios": "IOS",
"android32": "ANDROID32",
"android64": "ANDROID64",
"android64": "ANDROID64"
}

return f"""BROMAIDA_PLATFORM_{plat_to_macro_suffix[self._target_platform]}"""
return f"""BROMAIDA_PLATFORM_{
plat_to_macro_suffix[self._target_platform]
}"""

def _filter_relative_includes(self, lines: list[str]) -> list[str]:
"""Comments out relative includes from a list of lines
Args:
lines (list[str])
Returns:
list[str]
"""
for i, e in enumerate(lines):
if e.startswith('#include "'):
lines[i] = f"// {lines[i]}"

return lines
42 changes: 22 additions & 20 deletions broma_ida/broma/importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def from_pybroma_args(args: dict[str, Type]) -> list[ArgType]:
@staticmethod
def verify_type(t: Optional[ida_tinfo_t]) -> bool:
if t is None:
return True
return False

if t.get_size() == 0xFFFFFFFFFFFFFFFF or t.is_forward_decl():
return True
Expand All @@ -145,26 +145,26 @@ def verify_types(platform: BROMA_PLATFORMS) -> bool:
popup(
"Ok", "Ok", None,
"Mismatch in STL types! "
"Function types will not be changed! "
"Classes will not be imported!\n"
"To fix this, go to the local types window "
"and delete all Cocos and GD types "
"and delete all Cocos and GD types\n"
"(as well as holy_shit struct)"
)
return False

if not all([
if any([
BIUtils.verify_type(BIUtils.get_type_info(t))
for t in (
"cocos2d::CCObject", "cocos2d::CCImage",
"cocos2d::CCObject", "cocos2d::CCNode", "cocos2d::CCImage",
"cocos2d::CCApplication", "cocos2d::CCDirector"
)
]):
popup(
"Ok", "Ok", None,
"Mismatch in cocos2d types! "
"Function types will not be changed! "
"Classes will not be imported!\n"
"To fix this, go to the local types window "
"and delete all Cocos and GD types "
"and delete all Cocos and GD types\n"
"(as well as holy_shit struct)"
)
return False
Expand All @@ -181,12 +181,11 @@ def get_holy_shit_struct_size(platform: BROMA_PLATFORMS) -> int:
Returns:
int: size in bytes
"""
# TODO: yea wth update this!!
plat_to_hss_size: dict[BROMA_PLATFORMS, int] = {
"win": 0x808,
"imac": 0x1, # need them headers
"m1": 0x1,
"ios": 0x1, # this probably will never exist
"imac": 0x6A0,
"m1": 0x6A0,
"ios": 0x6A0,
"android32": 0x490,
"android64": 0x920
}
Expand All @@ -206,9 +205,11 @@ def get_parser_argv(platform: BROMA_PLATFORMS) -> str:
"win": "-x c++ -target x86_64-pc-win32",
"imac": "-x c++ -target x86_64-apple-darwin",
"m1": "-x c++ -target arm64-apple-darwin",
"ios": "", # idfk
"android32": "-x c++ -target armv7-none-linux-androideabi -mfloat-abi=hard",
"android64": "-x c++ -target aarch64-none-linux-android -mfloat-abi=hard"
"ios": "-x c++ -target arm64-apple-darwin",
"android32":
"-x c++ -target armv7-none-linux-androideabi -mfloat-abi=hard",
"android64":
"-x c++ -target aarch64-none-linux-android -mfloat-abi=hard"
}

return plat_to_parser_argv[platform]
Expand Down Expand Up @@ -424,14 +425,15 @@ def _codegen_classes(self, classes: dict[str, Class]) -> bool:
)
return False

use_custom_gnustl = True
if self._target_platform.startswith("android"):
use_custom_gnustl = False
if self._target_platform != "win":
if popup(
"Yes", "No", None,
"Use custom GNU STL? "
"(Recommended if you're not using genuine android GCC headers)"
) == ASKBTN_BTN2:
use_custom_gnustl = False
"Use custom GNU STL?\n"
"(Chose No ONLY if you're using genuine GCC headers)",
1
) == ASKBTN_BTN1:
use_custom_gnustl = True

BromaCodegen(
self._target_platform,
Expand Down
Loading

0 comments on commit 3bcd7b8

Please sign in to comment.