mirror of
https://github.com/geode-sdk/geode.git
synced 2025-04-24 05:14:40 -04:00
Merge branch 'main' of https://github.com/geode-sdk/geode into main
This commit is contained in:
commit
049ff650e4
6 changed files with 105 additions and 57 deletions
|
@ -130,7 +130,7 @@ target_include_directories(${PROJECT_NAME} INTERFACE
|
|||
)
|
||||
target_link_directories(${PROJECT_NAME} INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/loader/include/link)
|
||||
|
||||
CPMAddPackage("gh:geode-sdk/json#85be630")
|
||||
CPMAddPackage("gh:geode-sdk/json#2b76460")
|
||||
CPMAddPackage("gh:fmtlib/fmt#9.1.0")
|
||||
CPMAddPackage("gh:gulrak/filesystem#3e5b930")
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// clang-format off
|
||||
|
||||
class cocos2d::CCActionTween {
|
||||
static cocos2d::CCActionTween* create(float, char const*, float, float) = mac 0x447590;
|
||||
}
|
||||
|
@ -495,11 +497,11 @@ class cocos2d::CCNode {
|
|||
virtual auto addChild(cocos2d::CCNode*, int, int) = mac 0x1232a0, ios 0x15e4e4;
|
||||
virtual auto addComponent(cocos2d::CCComponent*) = mac 0x124a40, ios 0x15f6a4;
|
||||
virtual auto cleanup() = mac 0x123100, ios 0x15e3a4;
|
||||
virtual auto convertToNodeSpace(cocos2d::CCPoint const&) = mac 0x124750, ios 0x15f55c;
|
||||
virtual auto convertToWorldSpace(cocos2d::CCPoint const&) = mac 0x124790;
|
||||
auto convertToNodeSpace(cocos2d::CCPoint const&) = mac 0x124750, ios 0x15f55c;
|
||||
auto convertToWorldSpace(cocos2d::CCPoint const&) = mac 0x124790;
|
||||
static cocos2d::CCNode* create() = mac 0x1230a0;
|
||||
virtual auto draw() = mac 0x123840, ios 0x15e974;
|
||||
virtual auto getActionByTag(int) = mac 0x123ee0;
|
||||
auto getActionByTag(int) = mac 0x123ee0;
|
||||
virtual auto getActionManager() = mac 0x123e50, ios 0x15ef54;
|
||||
virtual auto getAnchorPoint() = mac 0x122d80, ios 0x15e090;
|
||||
virtual auto getAnchorPointInPoints() = mac 0x122d70, ios 0x15e088;
|
||||
|
@ -543,7 +545,7 @@ class cocos2d::CCNode {
|
|||
virtual auto onExit() = mac 0x123ca0, ios 0x15edb0;
|
||||
virtual auto onExitTransitionDidStart() = mac 0x123c00, ios 0x15ed18;
|
||||
virtual auto parentToNodeTransform() = mac 0x1245d0, ios 0x15f410;
|
||||
virtual auto pauseSchedulerAndActions() = mac 0x123d60;
|
||||
auto pauseSchedulerAndActions() = mac 0x123d60;
|
||||
virtual auto registerScriptHandler(int) = mac 0x123d90, ios 0x15ee94;
|
||||
virtual auto removeAllChildren() = mac 0x123600, ios 0x15e788;
|
||||
virtual auto removeAllChildrenWithCleanup(bool) = mac 0x123620, ios 0x15e798;
|
||||
|
@ -558,11 +560,11 @@ class cocos2d::CCNode {
|
|||
virtual auto removeFromParentAndCleanup(bool) = mac 0x123410, ios 0x15e5f8;
|
||||
virtual auto removeMeAndCleanup() = mac 0x123440, ios 0x15e620;
|
||||
virtual auto reorderChild(cocos2d::CCNode*, int) = mac 0x123760, ios 0x15e87c;
|
||||
virtual auto resumeSchedulerAndActions() = mac 0x123b60;
|
||||
virtual auto runAction(cocos2d::CCAction*) = mac 0x123e60;
|
||||
virtual auto schedule(cocos2d::SEL_SCHEDULE) = mac 0x1240b0;
|
||||
virtual auto schedule(cocos2d::SEL_SCHEDULE, float) = mac 0x124120;
|
||||
virtual auto scheduleUpdate() = mac 0x123f80;
|
||||
auto resumeSchedulerAndActions() = mac 0x123b60;
|
||||
auto runAction(cocos2d::CCAction*) = mac 0x123e60;
|
||||
auto schedule(cocos2d::SEL_SCHEDULE) = mac 0x1240b0;
|
||||
auto schedule(cocos2d::SEL_SCHEDULE, float) = mac 0x124120;
|
||||
auto scheduleUpdate() = mac 0x123f80;
|
||||
virtual auto setActionManager(cocos2d::CCActionManager*) = mac 0x123e00, ios 0x15ef04;
|
||||
virtual auto setAnchorPoint(cocos2d::CCPoint const&) = mac 0x122d90, ios 0x15e098;
|
||||
virtual auto setContentSize(cocos2d::CCSize const&) = mac 0x122e50, ios 0x15e158;
|
||||
|
@ -591,12 +593,12 @@ class cocos2d::CCNode {
|
|||
virtual auto setVisible(bool) = mac 0x122d60, ios 0x15e080;
|
||||
virtual auto setZOrder(int) = mac 0x1229a0, ios 0x15dd84;
|
||||
virtual auto sortAllChildren() = mac 0x1237b0, ios 0x15e8d4;
|
||||
virtual auto stopActionByTag(int) = mac 0x123ec0;
|
||||
virtual auto stopAllActions() = mac 0x123190;
|
||||
auto stopActionByTag(int) = mac 0x123ec0;
|
||||
auto stopAllActions() = mac 0x123190;
|
||||
virtual auto unregisterScriptHandler() = mac 0x123dc0, ios 0x15eec4;
|
||||
virtual auto unschedule(cocos2d::SEL_SCHEDULE) = mac 0x124180;
|
||||
virtual auto unscheduleAllSelectors() = mac 0x1231b0;
|
||||
virtual auto unscheduleUpdate() = mac 0x124060;
|
||||
auto unschedule(cocos2d::SEL_SCHEDULE) = mac 0x124180;
|
||||
auto unscheduleAllSelectors() = mac 0x1231b0;
|
||||
auto unscheduleUpdate() = mac 0x124060;
|
||||
virtual auto update(float) = mac 0x1241a0, ios 0x15f124;
|
||||
virtual auto updateTransform() = mac 0x1249d0, ios 0x15f648;
|
||||
virtual auto updateTweenAction(float, char const*) = mac 0x1249c0, ios 0x15f644;
|
||||
|
@ -1047,3 +1049,5 @@ class cocos2d {
|
|||
// int getIntegerForKey(char const*) = mac 0xc1610;
|
||||
// void setIntegerForKey(char const*, int) = mac 0xc26b0;
|
||||
// }
|
||||
|
||||
// clang-format on
|
|
@ -27,10 +27,12 @@ if (GEODE_TARGET_PLATFORM STREQUAL "iOS")
|
|||
elseif (GEODE_TARGET_PLATFORM STREQUAL "MacOS")
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
SYSTEM_NAME MacOS
|
||||
OSX_DEPLOYMENT_TARGET 10.9
|
||||
APPLE_SILICON_PROCESSOR x86_64
|
||||
)
|
||||
|
||||
# only exists as a global property
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.14)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} INTERFACE curl "-framework Cocoa")
|
||||
target_compile_options(${PROJECT_NAME} INTERFACE -fms-extensions #[[-Wno-deprecated]] -Wno-ignored-attributes -Os #[[-flto]] #[[-fvisibility=internal]])
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ Result<tulip::hook::HandlerMetadata> geode::modifier::handlerMetadataForAddress(
|
|||
char const* declare_metadata = R"GEN(
|
||||
{{
|
||||
using FunctionType = {return}(*)({class_name}{const}*{parameter_comma}{parameter_types});
|
||||
ret[{address}] = +[](){{
|
||||
ret[modifier::address<{index}>()] = +[](){{
|
||||
return tulip::hook::HandlerMetadata{{
|
||||
.m_convention = geode::hook::createConvention(tulip::hook::TulipConvention::{convention}),
|
||||
.m_abstract = tulip::hook::AbstractFunction::from(FunctionType(nullptr)),
|
||||
|
@ -42,7 +42,7 @@ Result<tulip::hook::HandlerMetadata> geode::modifier::handlerMetadataForAddress(
|
|||
char const* declare_metadata_static = R"GEN(
|
||||
{{
|
||||
using FunctionType = {return}(*)({parameter_types});
|
||||
ret[{address}] = +[](){{
|
||||
ret[modifier::address<{index}>()] = +[](){{
|
||||
return tulip::hook::HandlerMetadata{{
|
||||
.m_convention = geode::hook::createConvention(tulip::hook::TulipConvention::{convention}),
|
||||
.m_abstract = tulip::hook::AbstractFunction::from(FunctionType(nullptr)),
|
||||
|
@ -54,7 +54,7 @@ Result<tulip::hook::HandlerMetadata> geode::modifier::handlerMetadataForAddress(
|
|||
char const* declare_metadata_structor = R"GEN(
|
||||
{{
|
||||
using FunctionType = void(*)({class_name}*{parameter_comma}{parameter_types});
|
||||
ret[{address}] = +[](){{
|
||||
ret[modifier::address<{index}>()] = +[](){{
|
||||
return tulip::hook::HandlerMetadata{{
|
||||
.m_convention = geode::hook::createConvention(tulip::hook::TulipConvention::{convention}),
|
||||
.m_abstract = tulip::hook::AbstractFunction::from(FunctionType(nullptr)),
|
||||
|
@ -170,7 +170,8 @@ std::string generateAddressHeader(Root& root) {
|
|||
fmt::arg("parameters", codegen::getParameters(fn->beginning)),
|
||||
fmt::arg("parameter_types", codegen::getParameterTypes(fn->beginning)),
|
||||
fmt::arg("arguments", codegen::getParameterNames(fn->beginning)),
|
||||
fmt::arg("parameter_comma", str_if(", ", !fn->beginning.args.empty()))
|
||||
fmt::arg("parameter_comma", str_if(", ", !fn->beginning.args.empty())),
|
||||
fmt::arg("index", field.field_id)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,6 +112,7 @@ class GeodeNodeMetadata;
|
|||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <variant>
|
||||
|
||||
namespace tulip::hook {
|
||||
|
@ -133,6 +134,11 @@ namespace geode {
|
|||
|
||||
Result<tulip::hook::HandlerMetadata, std::string> handlerMetadataForAddress(uintptr_t address);
|
||||
}
|
||||
|
||||
namespace addresser {
|
||||
template <class Class>
|
||||
Class* friendCreate(typename std::void_t<decltype(static_cast<Class* (*)()>(&Class::create))>*);
|
||||
}
|
||||
}
|
||||
|
||||
#define GEODE_FRIEND_MODIFY \
|
||||
|
@ -142,7 +148,10 @@ namespace geode {
|
|||
template <uint32_t> \
|
||||
friend uintptr_t geode::modifier::address(); \
|
||||
friend geode::Result<tulip::hook::HandlerMetadata, std::string> \
|
||||
geode::modifier::handlerMetadataForAddress(uintptr_t address);
|
||||
geode::modifier::handlerMetadataForAddress(uintptr_t address); \
|
||||
template <class Class> \
|
||||
friend Class* geode::addresser:: \
|
||||
friendCreate(typename std::void_t<decltype(static_cast<Class* (*)()>(&Class::create))>*);
|
||||
|
||||
#define GEODE_ADD(...) __VA_ARGS__
|
||||
|
||||
|
@ -161,9 +170,9 @@ namespace geode {
|
|||
@param varType : the type of variable.
|
||||
@param varName : variable name.
|
||||
@param funName : "get + funName" is the name of the getter.
|
||||
@warning : The getter is a public virtual function, you should rewrite it first.
|
||||
The variables and methods declared after CC_PROPERTY_READONLY are all public.
|
||||
If you need protected or private, please declare.
|
||||
@warning : The getter is a public virtual function, you should rewrite
|
||||
it first. The variables and methods declared after CC_PROPERTY_READONLY
|
||||
are all public. If you need protected or private, please declare.
|
||||
*/
|
||||
#define CC_PROPERTY_READONLY(varType, varName, funName) \
|
||||
\
|
||||
|
@ -182,14 +191,16 @@ public: \
|
|||
virtual const varType& get##funName(void);
|
||||
|
||||
/** CC_PROPERTY is used to declare a protected variable.
|
||||
We can use getter to read the variable, and use the setter to change the variable.
|
||||
We can use getter to read the variable, and use the setter to change
|
||||
the variable.
|
||||
@param varType : the type of variable.
|
||||
@param varName : variable name.
|
||||
@param funName : "get + funName" is the name of the getter.
|
||||
"set + funName" is the name of the setter.
|
||||
@warning : The getter and setter are public virtual functions, you should rewrite them first.
|
||||
The variables and methods declared after CC_PROPERTY are all public.
|
||||
If you need protected or private, please declare.
|
||||
@warning : The getter and setter are public virtual functions, you
|
||||
should rewrite them first. The variables and methods declared after
|
||||
CC_PROPERTY are all public. If you need protected or private, please
|
||||
declare.
|
||||
*/
|
||||
#define CC_PROPERTY(varType, varName, funName) \
|
||||
\
|
||||
|
@ -219,8 +230,8 @@ public: \
|
|||
@param varName : variable name.
|
||||
@param funName : "get + funName" is the name of the getter.
|
||||
@warning : The getter is a public inline function.
|
||||
The variables and methods declared after CC_SYNTHESIZE_READONLY are all public.
|
||||
If you need protected or private, please declare.
|
||||
The variables and methods declared after CC_SYNTHESIZE_READONLY are all
|
||||
public. If you need protected or private, please declare.
|
||||
*/
|
||||
#define CC_SYNTHESIZE_READONLY(varType, varName, funName) \
|
||||
\
|
||||
|
@ -412,11 +423,11 @@ public: \
|
|||
#if defined(__GNUC__) && (__GNUC__ >= 4)
|
||||
#define CC_FORMAT_PRINTF(formatPos, argPos) \
|
||||
__attribute__((__format__(printf, formatPos, argPos)))
|
||||
/** CC_FORMAT_PRINTF
|
||||
* Visual Studio 2019 has __has_attribute,
|
||||
* but __has_attribute(format) is undefined,
|
||||
* leaving CC_FORMAT_PRINTF undefined by default.
|
||||
*/
|
||||
/** CC_FORMAT_PRINTF
|
||||
* Visual Studio 2019 has __has_attribute,
|
||||
* but __has_attribute(format) is undefined,
|
||||
* leaving CC_FORMAT_PRINTF undefined by default.
|
||||
*/
|
||||
#elif defined(__has_attribute)
|
||||
#if __has_attribute(format)
|
||||
#define CC_FORMAT_PRINTF(formatPos, argPos) \
|
||||
|
|
|
@ -4,13 +4,15 @@
|
|||
* Adapted from https://gist.github.com/altalk23/29b97969e9f0624f783b673f6c1cd279
|
||||
*/
|
||||
|
||||
#include "../utils/casts.hpp"
|
||||
#include "casts.hpp"
|
||||
|
||||
#include <Geode/DefaultInclude.hpp>
|
||||
#include <cocos-ext.h>
|
||||
#include <cstdlib>
|
||||
#include <stddef.h>
|
||||
#include <type_traits>
|
||||
#include "../utils/casts.hpp"
|
||||
#include <concepts>
|
||||
|
||||
namespace geode::addresser {
|
||||
|
||||
|
@ -26,6 +28,18 @@ namespace geode::addresser {
|
|||
template <typename T, typename F>
|
||||
inline F rthunkAdjust(T func, F self);
|
||||
|
||||
template <class Class>
|
||||
Class* friendCreate(typename std::void_t<decltype(static_cast<Class* (*)()>(&Class::create))>*) {
|
||||
auto ret = Class::create();
|
||||
ret->retain();
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <class Class>
|
||||
concept HasCreate = requires() {
|
||||
{ friendCreate<Class>(nullptr) } -> std::same_as<Class*>;
|
||||
};
|
||||
|
||||
class GEODE_DLL Addresser final {
|
||||
template <char C>
|
||||
struct SingleInheritance {
|
||||
|
@ -62,6 +76,38 @@ namespace geode::addresser {
|
|||
return thunk;
|
||||
}
|
||||
|
||||
// I gave up
|
||||
template <HasCreate Class>
|
||||
static Class* generateInstance(Class*) {
|
||||
return friendCreate<Class>(nullptr);
|
||||
}
|
||||
|
||||
// I extra gave up
|
||||
static cocos2d::extension::CCScrollView* generateInstance(cocos2d::extension::CCScrollView*) {
|
||||
return cocos2d::extension::CCScrollView::create({0.0f, 0.0f}, cocos2d::CCLayer::create());
|
||||
}
|
||||
|
||||
template <class Class>
|
||||
static Class* generateInstance(Class*) {
|
||||
// Create a random memory block with the size of Class
|
||||
// Assign a pointer to that block and cast it to type Class*
|
||||
uint8_t dum[sizeof(Class)]{};
|
||||
auto ptr = reinterpret_cast<Class*>(dum);
|
||||
// Now you have a object of Class that actually isn't an object of Class and is just a
|
||||
// random memory But C++ doesn't know that of course So now you can copy an object
|
||||
// that wasn't there in the first place
|
||||
// ((oh also get the offsets of the virtual tables))
|
||||
auto ins = new Class(*ptr);
|
||||
// this is how the first human was made
|
||||
return ins;
|
||||
}
|
||||
|
||||
template <class Class>
|
||||
static Class* cachedInstance() {
|
||||
static auto ret = generateInstance<Class>(nullptr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialized functionss
|
||||
*/
|
||||
|
@ -71,19 +117,9 @@ namespace geode::addresser {
|
|||
) {
|
||||
using geode::cast::reference_cast;
|
||||
|
||||
// Create a random memory block with the size of T
|
||||
// Assign a pointer to that block and cast it to type T*
|
||||
uint8_t dum[sizeof(T)] {};
|
||||
auto ptr = reinterpret_cast<T*>(dum);
|
||||
// Now you have a object of T that actually isn't an object of T and is just a random
|
||||
// memory But C++ doesn't know that of course So now you can copy an object that wasn't
|
||||
// there in the first place
|
||||
// ((oh also get the offsets of the virtual tables))
|
||||
auto ins = new T(*ptr);
|
||||
// this is how the first human was made
|
||||
|
||||
auto index = indexOf(func);
|
||||
auto thunk = thunkOf(func);
|
||||
auto ins = cachedInstance<T>();
|
||||
|
||||
// log::debug("[[" + utils::intToHex((void*)ins) + " + " + utils::intToHex(thunk) + "] +
|
||||
// " + utils::intToHex(index) + "]");
|
||||
|
@ -93,8 +129,7 @@ namespace geode::addresser {
|
|||
// );
|
||||
|
||||
// [[this + thunk] + offset] is the f we want
|
||||
auto address =
|
||||
*(intptr_t*)(*(intptr_t*)(reference_cast<intptr_t>(ins) + thunk) + index);
|
||||
auto address = *(intptr_t*)(*(intptr_t*)(reference_cast<intptr_t>(ins) + thunk) + index);
|
||||
|
||||
#ifdef GEODE_IS_WINDOWS
|
||||
// check if first instruction is a jmp, i.e. if the func is a thunk
|
||||
|
@ -106,18 +141,13 @@ namespace geode::addresser {
|
|||
}
|
||||
#endif
|
||||
|
||||
// And we delete the new instance because we are good girls
|
||||
// and we don't leak memories
|
||||
operator delete(ins);
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
template <typename R, typename T, typename... Ps>
|
||||
static intptr_t addressOfVirtual(
|
||||
R (T::*func)(Ps...) const,
|
||||
typename std::enable_if_t<std::is_copy_constructible_v<T> && !std::is_abstract_v<T>>* =
|
||||
0
|
||||
typename std::enable_if_t<std::is_copy_constructible_v<T> && !std::is_abstract_v<T>>* = 0
|
||||
) {
|
||||
return addressOfVirtual(reinterpret_cast<R (T::*)(Ps...)>(func));
|
||||
}
|
||||
|
@ -199,7 +229,7 @@ namespace geode::addresser {
|
|||
|
||||
template <typename T, typename F>
|
||||
inline F thunkAdjust(T func, F self) {
|
||||
// do NOT delete the line below.
|
||||
// do NOT delete the line below.
|
||||
// doing so breaks thunk adjusting on windows.
|
||||
// why? bruh idk
|
||||
auto _ = *geode::cast::template union_cast<ptrdiff_t*>(&func);
|
||||
|
@ -208,7 +238,7 @@ namespace geode::addresser {
|
|||
|
||||
template <typename T, typename F>
|
||||
inline F rthunkAdjust(T func, F self) {
|
||||
// do NOT delete the line below.
|
||||
// do NOT delete the line below.
|
||||
// doing so breaks thunk adjusting on windows.
|
||||
// why? bruh idk
|
||||
auto _ = *geode::cast::template union_cast<ptrdiff_t*>(&func);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue