Merge branch 'main' of https://github.com/geode-sdk/sdk into main

This commit is contained in:
HJfod 2022-06-08 12:21:15 +03:00
commit 4e5fd56024
78 changed files with 1147 additions and 1108 deletions

52
.github/workflows/buildcodegen.yml vendored Normal file
View file

@ -0,0 +1,52 @@
name: Build Codegen
on:
workflow_dispatch:
push:
branches:
- '**' # every branch
- '!no-build-**' # unless marked as no-build
jobs:
build:
strategy:
fail-fast: false
matrix:
config:
- name: "Windows Codegen"
extra_flags: '-DGEODE_TARGET_PLATFORM=Win32'
- name: "macOS Codegen"
extra_flags: '-DGEODE_TARGET_PLATFORM=MacOS'
- name: "iOS Codegen"
extra_flags: '-DGEODE_TARGET_PLATFORM=iOS'
name: ${{ matrix.config.name }}
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./codegen
steps:
- uses: actions/checkout@v2
- name: Configure CMake for Codegen
run: |
cmake -B ./build ${{ matrix.config.extra_flags }} -DGEODE_BINDING_PATH=${{ github.workspace }}/bindings
- name: Build for Codegen
run: |
cd build
cmake --build . --config Release
- name: Move to output folder
run: |
pwd
ls ./build/codegen
mkdir ./out
mv ./build/codegen/*.hpp ./out
ls ./out
- name: Upload Artifacts
uses: actions/upload-artifact@v2
with:
name: ${{ matrix.config.name }} Files
path: ${{ github.workspace }}/codegen/out

23
.gitignore vendored
View file

@ -27,27 +27,14 @@
# Macos be like
**/.DS_Store
# Camila likes leaving sublime stuff in the repo so yeah
# Cache files for Sublime Text
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache
**/*.tmlanguage.cache
**/*.tmPreferences.cache
**/*.stTheme.cache
# Workspace files are user-specific
*.sublime-workspace
# I need to find a way to automatically remove this
Source/Geode/pkg/uber-apk-signer.jar
**/*.sublime-workspace
**/*.sublime-project
# Ignore build folders
**/build
# Ignore old files
scripts/
Scratch/
# Ignore data stuff
Source/Geode/gen/data/todo/
Source/Geode/gen/data/Backup/
JesusChristGen.cpp

View file

@ -46,12 +46,11 @@ function(setup_geode_mod)
endif()
if (${GEODE_DO_CODEGEN})
add_definitions(-DGEODE_EXPORTING_CODEGEN)
# only 1 codegen dir
get_property(GEODE_CODEGEN_DIR GLOBAL PROPERTY GEODE_CODEGEN_DIR)
if (NOT GEODE_CODEGEN_DIR)
set(GEODE_CODEGEN_BUILD 1)
set(GEODE_BINDING_PATH ${GEODE_SDK_PATH}/bindings)
set_property(GLOBAL PROPERTY GEODE_CODEGEN_DIR ${CMAKE_CURRENT_BINARY_DIR}/codegen)
get_property(GEODE_CODEGEN_DIR GLOBAL PROPERTY GEODE_CODEGEN_DIR)
endif()
@ -60,12 +59,15 @@ function(setup_geode_mod)
set_source_files_properties(${GEODE_CODEGEN_DIR}/GeneratedSource.cpp PROPERTIES GENERATED 1)
target_sources(${PROJECT_NAME} PRIVATE ${GEODE_CODEGEN_DIR}/GeneratedSource.cpp)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_BINARY_DIR})
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
#target_link_libraries(${PROJECT_NAME} fmt)
if (DEFINED GEODE_CODEGEN_BUILD)
add_subdirectory(${GEODE_SDK_PATH}/codegen ${GEODE_CODEGEN_DIR})
add_dependencies(${PROJECT_NAME} CodegenRun)
endif()
target_compile_definitions(${PROJECT_NAME} PUBLIC -DGEODE_BUILDING_CODEGEN)
endif()
target_compile_definitions(${PROJECT_NAME} PUBLIC -DPROJECT_NAME=${PROJECT_NAME} -DEXPORT_${PROJECT_NAME}=1)

View file

@ -132,6 +132,7 @@ class cocos2d::CCDirector {
}
class cocos2d::CCDrawNode {
CCDrawNode() = mac 0x378b40;
auto clear() = mac 0x379e80;
static cocos2d::CCDrawNode* create() = mac 0x378d00;
auto drawPolygon(cocos2d::CCPoint*, unsigned int, cocos2d::_ccColor4F const&, float, cocos2d::_ccColor4F const&) = mac 0x3797f0;
@ -613,6 +614,10 @@ class cocos2d::CCRotateBy {
static cocos2d::CCRotateBy* create(float, float) = mac 0x1f4c50;
}
class cocos2d::CCRotateTo {
static cocos2d::CCRotateTo* create(float, float) = mac 0x1f47b0;
}
class cocos2d::CCScaleTo {
static cocos2d::CCScaleTo* create(float, float) = mac 0x1f6ff0;
static cocos2d::CCScaleTo* create(float, float, float) = mac 0x1f70f0;
@ -725,6 +730,7 @@ class cocos2d::CCSpriteBatchNode {
class cocos2d::CCSpriteFrame {
static auto createWithTexture(cocos2d::CCTexture2D*, cocos2d::CCRect const&, bool, cocos2d::CCPoint const&, cocos2d::CCSize const&) = mac 0x1ac7f0;
static auto createWithTexture(cocos2d::CCTexture2D*, cocos2d::CCRect const&) = mac 0x1ac5c0;
auto getTexture() = mac 0x1ad250;
}
class cocos2d::CCSpriteFrameCache {
@ -782,12 +788,14 @@ class cocos2d::CCTexture2D {
auto setTexParameters(cocos2d::_ccTexParams*) = mac 0x247980;
}
class cocos2d::CCTextFieldDelegate {
class cocos2d::CCTextFieldTTF {
static auto textFieldWithPlaceHolder(char const*, char const*, float) = mac 0x126220;
}
class cocos2d::CCTextureCache {
auto addImage(char const*, bool) = mac 0x358120, ios 0xa8388;
auto textureForKey(char const*) = mac 0x359050;
static cocos2d::CCTextureCache* sharedTextureCache() = mac 0x356e00, ios 0xa81ec;
}
@ -807,10 +815,14 @@ class cocos2d::CCTouch {
}
class cocos2d::CCTouchDispatcher {
auto addTargetedDelegate(cocos2d::CCTouchDelegate*, int, bool) = mac 0x281180;
auto addStandardDelegate(cocos2d::CCTouchDelegate*, int) = mac 0x281060;
auto removeDelegate(cocos2d::CCTouchDelegate*) = mac 0x2813b0;
auto decrementForcePrio(int) = mac 0x280f70, ios 0xcc280;
auto incrementForcePrio(int) = mac 0x280f60, ios 0xcc268;
void touches(cocos2d::CCSet*, cocos2d::CCEvent*, unsigned int) = mac 0x281a60;
void removeDelegate(cocos2d::CCTouchDelegate* delegate);
}
class cocos2d::CCTouchHandler {

View file

@ -34,12 +34,12 @@ class AchievementNotifier : cocos2d::CCNode {
AchievementBar* m_currentAchievement;
}
class AchievementsLayer {
void customSetup() = mac 0x1bdea0, win 0x0, ios 0x0;
class AchievementsLayer : GJDropDownLayer {
void customSetup() = mac 0x1bdea0, win 0x3c2f0, ios 0x0;
void loadPage(int) = mac 0x1be190, win 0x3c600, ios 0x0;
}
class AnimatedGameObject {
class AnimatedGameObject : GameObject, AnimatedSpriteDelegate, SpritePartDelegate {
void playAnimation(int) = mac 0xc93d0, win 0x0, ios 0x0;
void updateChildSpriteColor(cocos2d::_ccColor3B) = mac 0xc8450, win 0x0, ios 0x0;
}
@ -63,10 +63,14 @@ class AppDelegate : cocos2d::CCApplication {
virtual void applicationDidEnterBackground() = mac 0x3aabe0, win 0x3cf40, ios 0x0;
virtual void applicationWillEnterForeground() = mac 0x3aac80, win 0x3d130, ios 0x0;
virtual void applicationWillBecomeActive() = mac 0x3aab30, win 0x3ce90, ios 0x0;
virtual void applicationWillResignActive() = mac 0x3aab50, win 0x3d3e0, ios 0x0;
virtual void applicationWillResignActive() = mac 0x3aab50, win 0x3cf20, ios 0x0;
virtual void trySaveGame() = mac 0x3aaf10, win 0x3d5e0, ios 0x1a28f0;
virtual void willSwitchToScene(cocos2d::CCScene*) = mac 0x3aaf40, win 0x3d690, ios 0x0;
static AppDelegate* get() = mac 0x3aab10, win 0x0, ios 0x0;
bool musicTest() = mac 0x0, win 0x3d580, ios 0x0;
void pauseGame() = mac 0x0, win 0x3d3e0, ios 0x0;
void resumeSound() = mac 0x0, win 0x3d4d0, ios 0x0;
void setupGLView() = mac 0x0, win 0x3c950, ios 0x0;
cocos2d::CCScene* m_runningScene;
}
@ -74,7 +78,7 @@ class AppDelegate : cocos2d::CCApplication {
class ArtistCell : TableViewCell {
void draw() = mac 0x11c980, win 0x0, ios 0x0;
virtual bool init() = mac 0x11c7c0, win 0x0, ios 0x0;
void loadFromObject(SongInfoObject*) = mac 0x1118b0, win 0x0, ios 0x0;
void loadFromObject(SongInfoObject*) = mac 0x1118b0, win 0x5ede0, ios 0x0;
void onNewgrounds(cocos2d::CCObject*) = mac 0x11c7e0, win 0x0, ios 0x0;
void updateBGColor(int) = mac 0x110460, win 0x5c6b0, ios 0x0;
@ -452,7 +456,7 @@ class CCSpritePlus : cocos2d::CCSprite {
class CCTextInputNode : cocos2d::CCLayer, cocos2d::CCIMEDelegate, cocos2d::CCTextFieldDelegate {
inline CCTextInputNode() : cocos2d::CCLayer(), cocos2d::CCIMEDelegate(), cocos2d::CCTextFieldDelegate(), m_caption(), m_allowedChars() {
m_unknown0 = nullptr;
m_numberInput = false;
m_unknown1 = 0;
m_selected = false;
m_unknown2 = false;
@ -529,6 +533,7 @@ class CCTextInputNode : cocos2d::CCLayer, cocos2d::CCIMEDelegate, cocos2d::CCTex
void refreshLabel() = mac 0x5d730, win 0x21330, ios 0xe2af4;
void updateLabel(gd::string) = mac 0x5d4a0, win 0x0, ios 0x0;
void updateBlinkLabel() = mac 0x5d920;
virtual void registerWithTouchDispatcher() = mac 0x5eec0, win 0x220e0, ios 0x0;
virtual void visit() = mac 0x5d380, win 0x21000, ios 0x0;
virtual bool ccTouchBegan(cocos2d::CCTouch*, cocos2d::CCEvent*) = mac 0x5ec80, win 0x21f20, ios 0x0;
@ -543,7 +548,7 @@ class CCTextInputNode : cocos2d::CCLayer, cocos2d::CCIMEDelegate, cocos2d::CCTex
virtual bool onTextFieldAttachWithIME(cocos2d::CCTextFieldTTF*) = mac 0x5e2c0, win 0x21b10, ios 0x0;
virtual bool onTextFieldDetachWithIME(cocos2d::CCTextFieldTTF*) = mac 0x5e610, win 0x21d60, ios 0x0;
void* m_unknown0;
bool m_numberInput;
gd::string m_caption;
int m_unknown1;
bool m_selected;
@ -569,7 +574,7 @@ class ChallengesPage {
}
class CheckpointObject : cocos2d::CCNode {
static CheckpointObject* create() = mac 0x7e7d0, win 0x0, ios 0x0;
static CheckpointObject* create() = mac 0x7e7d0, win 0x20DDD0, ios 0x0;
void getObject() = mac 0x7ef50, win 0x0, ios 0x0;
GameObject* m_gameObject;
@ -1251,9 +1256,13 @@ class EffectGameObject : GameObject {
}
static EffectGameObject* create(const char*) = mac 0xc9790, win 0x253c30, ios 0x0;
bool init(char const*) = win 0x253CD0;
void getTargetColorIndex() = mac 0xca1f0, win 0x0, ios 0x0;
virtual void triggerObject(GJBaseGameLayer*) = mac 0xc9870, win 0x253d60, ios 0x0;
gd::string getSaveString() = mac 0x0, win 0x257560, ios 0x0;
void updateSpecialColor() = win 0x254980;
void spawnXPosition() = win 0x254A00;
void triggerActivated(float) = win 0x254A30;
int targetGroup = mac 0x4F8, win 0x0, android 0x0;
bool activateGroup = mac 0x578, win 0x0, android 0x0;
@ -1321,7 +1330,7 @@ class EffectGameObject : GameObject {
bool m_dynamicBlock;
int m_targetItemID;
int m_pickupMode;
PAD = mac 0x0, win 0x24, android 0x0;
PAD = mac 0x24, win 0x24, android 0x0;
}
class EndLevelLayer {
@ -1524,7 +1533,7 @@ class GJBaseGameLayer : cocos2d::CCLayer, TriggerEffectDelegate {
void objectIntersectsCircle(GameObject*, GameObject*) = mac 0xb66e0, win 0x0, ios 0x0;
void objectTriggered(EffectGameObject*) = mac 0xb71b0, win 0x0, ios 0x0;
void optimizeMoveGroups() = mac 0xb96c0, win 0x0, ios 0x0;
void parentForZLayer(int, bool, int) = mac 0xb55d0, win 0x0, ios 0x0;
cocos2d::CCNode* parentForZLayer(int, bool, int) = mac 0xb55d0, win 0x0, ios 0x0;
void playerTouchedRing(PlayerObject*, GameObject*) = mac 0xb69e0, win 0x0, ios 0x0;
void processColorObject(EffectGameObject*, int, cocos2d::CCDictionary*, float, GJEffectManager*) = mac 0xb5a90, win 0x0, ios 0x0;
void processFollowActions() = mac 0xb8fd0, win 0x0, ios 0x0;
@ -1661,8 +1670,8 @@ class GJBaseGameLayer : cocos2d::CCLayer, TriggerEffectDelegate {
int m_unk2AC;
bool m_activeDualTouch;
int m_attemptClickCount;
int m_currentSection;
int m_oldSection;
int m_lastVisibleSection;
int m_firstVisibleSection;
bool m_objectsAreDisabled;
bool m_blending;
PAD = mac 0x16, win 0x8, android 0x0;
@ -2841,11 +2850,11 @@ class GameObject : CCSpritePlus {
virtual void triggerObject(GJBaseGameLayer*) = mac 0x2fa8f0, win 0x0, ios 0x0;
virtual void activateObject() = mac 0x2faf60, win 0xEF0E0, ios 0x0;
virtual void deactivateObject(bool) = mac 0x2fb8f0, win 0xd19b0, ios 0x0;
virtual cocos2d::CCRect* getObjectRect() = mac 0x3352b0, win 0xe4a40, ios 0x0;
virtual cocos2d::CCRect* getObjectRect(float, float) = mac 0x3352d0, win 0xe4a70, ios 0x0;
virtual cocos2d::CCRect* getObjectRect2(float, float) = mac 0x3354e0, win 0xe4b90, ios 0x0;
virtual cocos2d::CCRect* getObjectTextureRect() = mac 0x3355b0, win 0xe4c40, ios 0x0;
virtual void getRealPosition() = mac 0x335750, win 0xe4d90, ios 0x0;
virtual cocos2d::CCRect const& getObjectRect() = mac 0x3352b0, win 0xe4a40, ios 0x0;
virtual cocos2d::CCRect getObjectRect(float, float) = mac 0x3352d0, win 0xe4a70, ios 0x0;
virtual cocos2d::CCRect getObjectRect2(float, float) = mac 0x3354e0, win 0xe4b90, ios 0x0;
virtual cocos2d::CCRect const& getObjectTextureRect() = mac 0x3355b0, win 0xe4c40, ios 0x0;
virtual cocos2d::CCPoint getRealPosition() = mac 0x335750, win 0xe4d90, ios 0x0;
virtual void setStartPos(cocos2d::CCPoint) = mac 0x2fa520, win 0xd1390, ios 0x0;
virtual void updateStartValues() = mac 0x2fa800, win 0xd1610, ios 0x0;
virtual void customObjectSetup() = mac 0xdc1a0, win 0x0, ios 0x0;
@ -2873,10 +2882,11 @@ class GameObject : CCSpritePlus {
virtual void setOrientedRectDirty(bool) = mac 0xdc200, win 0x0, ios 0x0;
virtual GameObjectType getType() const = mac 0xdc210, win 0x989e0, ios 0x0;
virtual void setType(GameObjectType) = mac 0xdc220, win 0x989f0, ios 0x0;
virtual void getStartPos() const = mac 0xdc230, win 0x98a00, ios 0x0;
virtual cocos2d::CCPoint const& getStartPos() const = mac 0xdc230, win 0x98a00, ios 0x0;
void activatedByPlayer(GameObject*) = mac 0x342a20, win 0x0, ios 0x0;
void addColorSprite() = mac 0x2f7fe0, win 0x0, ios 0x0;
void addColorSpriteToParent(bool) = mac 0x2fb470, win 0x0, ios 0x0;
void addGlow() = mac 0x2f5c10, win 0x0, ios 0x0;
void addToTempOffset(float, float) = mac 0x335700, win 0x0, ios 0x0;
void calculateOrientedBox() = mac 0x342b20, win 0x0, ios 0x0;
void canChangeCustomColor() = mac 0x342db0, win 0x0, ios 0x0;
@ -2958,9 +2968,10 @@ class GameObject : CCSpritePlus {
//GJSpriteColor* m_secondaryColourMode;
//bool m_col1;
//bool m_col2;
float m_unknown27c;
float m_unknown280;
float m_unknown284;
int m_baseColorID; //0x27c on macos
int m_detailColorID;
bool m_baseColorHSVModified;
bool m_detailColorHSVModified;
cocos2d::CCPoint m_startPosOffset;
float m_rotateOffset;
bool m_tintTrigger;
@ -3075,18 +3086,25 @@ class GameObject : CCSpritePlus {
bool m_unknownLayerRelated;
float m_multiScaleMultiplier;
bool m_isGroupParent;
short* m_groups;
inline using GroupArrayType = short*;
// it is a short array with size 10 but pointer to arrays are weird
GroupArrayType m_groups;
short m_groupCount;
PAD = mac 0x22, win 0x12, android 0x0;
GroupArrayType m_pulseGroups;
short m_pulseGroupCount; // mac 0x470
GroupArrayType m_alphaGroups;
short m_alphaGroupCount; // mac 0x480
int m_editorLayer;
int m_editorLayer2;
int m_unk414;
PAD = mac 0xc, win 0xc, android 0x0;
cocos2d::CCPoint m_firstPosition;
PAD = mac 0x1c, win 0x1c, android 0x0;
PAD = mac 0x15, win 0x0, android 0x0;
bool m_isTriggerable;
PAD = mac 0x7, win 0x7, android 0x0;
bool m_highDetail;
ColorActionSprite* m_colorActionSprite1;
ColorActionSprite* m_colorActionSprite2;
ColorActionSprite* m_colorActionSpriteBase;
ColorActionSprite* m_colorActionSpriteDetail;
GJEffectManager* m_effectManager;
PAD = mac 0x10, win 0x10, android 0x0;
}
@ -3105,7 +3123,7 @@ class GameSoundManager : cocos2d::CCNode {
void getMeteringValue() = mac 0x362db0, win 0x0, ios 0x0;
void playBackgroundMusic(gd::string, bool, bool) = mac 0x362070, win 0x0, ios 0x0;
void playEffect(gd::string, float, float, float) = mac 0x3623d0, win 0x25450, ios 0x0;
void stopBackgroundMusic() = mac 0x362130, win 0x0, ios 0x0;
void stopBackgroundMusic() = mac 0x362130, win 0x253A0, ios 0x0;
~GameSoundManager() = mac 0x362c00, win 0x0, ios 0x0;
static GameSoundManager* sharedManager() = mac 0x3610f0, win 0x24800, ios 0x0;
@ -3412,6 +3430,8 @@ class LevelEditorLayer : GJBaseGameLayer, LevelSettingsDelegate {
void objectMoved(GameObject*) = mac 0x999f0, win 0x0, ios 0x0;
void objectsInRect(cocos2d::CCRect, bool) = mac 0x95e60, win 0x0, ios 0x0;
void onPlaytest() = mac 0xa06b0, win 0x0, ios 0x0;
void onResumePlaytest() = mac 0xa15e0;
void onPausePlaytest() = mac 0xa1570;
void onStopPlaytest() = mac 0xa1780, win 0x0, ios 0x0;
void pasteAttributeState(GameObject* obj, cocos2d::CCArray* objs) = mac 0x0, win 0x16b740, ios 0x0;
void playMusic() = mac 0xa13c0, win 0x0, ios 0x0;
@ -3486,6 +3506,7 @@ class LevelEditorLayer : GJBaseGameLayer, LevelSettingsDelegate {
class LevelInfoLayer : cocos2d::CCLayer, LevelDownloadDelegate, LevelUpdateDelegate, RateLevelDelegate, LikeItemDelegate, FLAlertLayerProtocol, LevelDeleteDelegate, NumberInputDelegate, SetIDPopupDelegate {
static LevelInfoLayer* create(GJGameLevel* level) = mac 0x15f290, win 0x175d50, ios 0x0;
bool init(GJGameLevel* level) = mac 0x0, win 0x175DF0, ios 0x0;
void onGarage(cocos2d::CCObject* pSender) = mac 0x0, win 0x177c10, ios 0x0;
void onViewProfile(cocos2d::CCObject* pSender) = mac 0x0, win 0x17ac90, ios 0x0;
void onLevelInfo(cocos2d::CCObject* pSender) = mac 0x0, win 0x17acf0, ios 0x0;
@ -3688,8 +3709,10 @@ class MoreSearchLayer : FLAlertLayer {
class MoreOptionsLayer {
static MoreOptionsLayer* create() = mac 0x0, win 0x1de850, ios 0x0;
void addToggle(const char* name, const char* key, const char* info) = mac 0x0, win 0x1df6b0, ios 0x0;
void onKeybindings(cocos2d::CCObject* pSender) = mac 0x0, win 0x749d0, ios 0x0;
bool init() = mac 0x43f470;
void addToggle(const char* name, const char* key, const char* info) = mac 0x440430, win 0x1df6b0, ios 0x0;
void onKeybindings(cocos2d::CCObject* sender) = mac 0x0, win 0x749d0, ios 0x0;
void onToggle(cocos2d::CCObject* sender) = mac 0x441370;
}
class MoreVideoOptionsLayer : FLAlertLayer {
@ -3823,7 +3846,8 @@ class PauseLayer : CCBlockLayer {
void createToggleButton(cocos2d::SEL_MenuHandler callback, bool on, cocos2d::CCMenu* menu, gd::string caption, cocos2d::CCPoint pos) = mac 0x0, win 0x1e5570, ios 0x0;
virtual void customSetup() = mac 0x0, win 0x1e4620, ios 0x0;
void onRestart(cocos2d::CCObject* sender) = mac 0x0, win 0x1e6040, ios 0x0;
void keyDown(cocos2d::enumKeyCodes) = mac 0x20cc80;
bool m_unknown;
bool m_unknown2;
}
@ -3863,7 +3887,7 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, DialogDelegate {
void colorObject(int, cocos2d::_ccColor3B) = mac 0x77810, win 0x0, ios 0x0;
void commitJumps() = mac 0x737e0, win 0x0, ios 0x0;
static PlayLayer* create(GJGameLevel*) = mac 0x6b590, win 0x1fb6d0, ios 0x0;
void createCheckpoint() = mac 0x7e470, win 0x20b050, ios 0x0;
CheckpointObject* createCheckpoint() = mac 0x7e470, win 0x20b050, ios 0x0;
void createObjectsFromSetup(gd::string) = mac 0x6d130, win 0x0, ios 0x0;
void createParticle(int, char const*, int, cocos2d::tCCPositionType) = mac 0x76800, win 0x0, ios 0x0;
void currencyWillExit(CurrencyRewardLayer*) = mac 0x7e070, win 0x0, ios 0x0;
@ -3954,7 +3978,7 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, DialogDelegate {
void spawnParticle(char const*, int, cocos2d::tCCPositionType, cocos2d::CCPoint) = mac 0x76330, win 0x0, ios 0x0;
void spawnPlayer2() = mac 0x7d170, win 0x0, ios 0x0;
void startGame() = mac 0x726b0, win 0x0, ios 0x0;
void startMusic() = mac 0x72910, win 0x0, ios 0x0;
void startMusic() = mac 0x72910, win 0x20C8F0, ios 0x0;
void startRecording() = mac 0x7fec0, win 0x0, ios 0x0;
void startRecordingDelayed() = mac 0x7fed0, win 0x0, ios 0x0;
void stopCameraShake() = mac 0x75900, win 0x0, ios 0x0;
@ -4003,7 +4027,7 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, DialogDelegate {
int m_dontSaveRand;
int m_dontSaveSeed;
int unknown4d8;
bool unknown4dc;
bool m_debugPauseOff;
bool m_shouldSmoothCamera;
float unused_4e0;
cocos2d::CCObject* unknown4e8;
@ -4012,7 +4036,7 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, DialogDelegate {
float m_somegroup4f8;
float m_groundRestriction;
float m_ceilRestriction;
bool unknown504;
bool m_fullReset;
bool unknown505;
float unknown508;
float unknown50c;
@ -4021,7 +4045,7 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, DialogDelegate {
float unknown518;
//PAD = mac 0x19, win 0x19, android 0x0;
StartPosObject* m_startPos;
CheckpointObject* unk330;
CheckpointObject* m_startPosCheckpoint;
EndPortalObject* m_endPortal;
cocos2d::CCArray* m_checkpoints;
cocos2d::CCArray* unk33C;
@ -4043,7 +4067,7 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, DialogDelegate {
bool unk36A;
bool unk36B;
cocos2d::CCArray* m_screenRingObjects;
cocos2d::CCParticleSystemQuad* unk370;
cocos2d::CCParticleSystemQuad* m_particleSystem;
cocos2d::CCDictionary* m_pickedUpItems;
cocos2d::CCArray* m_circleWaves;
cocos2d::CCArray* unk37C;
@ -4052,10 +4076,7 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, DialogDelegate {
float unknown5c4;
GJGroundLayer* m_bottomGround;
GJGroundLayer* m_topGround;
// this is literaly garbage data
PAD = mac 0x8, win 0x8, android 0x0;
double m_completelyUninitializedData;
bool m_isDead;
bool m_startCameraAtCorner;
bool m_cameraYLocked;
@ -4063,7 +4084,7 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, DialogDelegate {
bool unknown5e4;
int m_ballFrameSeed;
float unknown5ec;
float unknown5f0;
float m_lockGroundToCamera;
float unknown5f4;
float m_levelLength;
float m_realLevelLength;
@ -4113,14 +4134,14 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, DialogDelegate {
float m_mirrorTransition;
UILayer* m_UILayer;
GJGameLevel* m_level;
cocos2d::CCPoint m_cameraPos;
cocos2d::CCPoint m_cameraPosition;
bool m_isTestMode;
bool m_isPracticeMode;
bool unk496;
bool unk497;
cocos2d::CCArray* unk498;
bool unk49C;
cocos2d::CCPoint unk4A0;
cocos2d::CCPoint m_playerStartPosition;
int m_currentAttempt;
int m_jumpCount;
bool unk4B0;
@ -4132,28 +4153,28 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, DialogDelegate {
bool unk4BF;
int m_lastDeathPercent;
bool unk4C4;
PAD = mac 0x0, win 0xb, android 0x0;
PAD = mac 0xb, win 0xb, android 0x0;
bool unk4D0;
bool unk4D1;
cocos2d::CCArray* unk4D4;
cocos2d::CCDictionary* unk4D8;
PAD = mac 0x0, win 0x4, android 0x0;
double unk4E0;
double unk4E8;
PAD = mac 0x0, win 0xc, android 0x0;
float unk4FC;
int unk500;
PAD = mac 0x0, win 0x4, android 0x0;
double m_inlineCalculatedKickTime;
double m_accumulatedKickDeltaTime;
double m_unusedKickDouble;
bool m_shouldTryToKick;
float m_kickCheckDeltaSnapshot;
int m_accumulatedKickCounter;
PAD = mac 0x4, win 0x4, android 0x0;
double unk508;
PAD = mac 0x0, win 0x8, android 0x0;
PAD = mac 0x8, win 0x8, android 0x0;
double unk518;
double unk520;
PAD = mac 0x0, win 0x4, android 0x0;
PAD = mac 0x4, win 0x4, android 0x0;
bool m_hasGlitter;
bool m_isBgEffectOff;
bool unk52F;
GameObject* unk530;
bool unk534;
GameObject* m_antiCheatObject;
bool m_antiCheatPassed;
bool unk535;
bool m_disableGravityEffect;
}
@ -4193,7 +4214,7 @@ class PlayerObject : GameObject, AnimatedSpriteDelegate {
virtual void setFlipX(bool) = mac 0x22e720, win 0x1fa690, ios 0x0;
virtual void setFlipY(bool) = mac 0x22e7b0, win 0x1fa740, ios 0x0;
virtual void resetObject() = mac 0x223170, win 0x1eecd0, ios 0x0;
virtual void getRealPosition() = mac 0x22d5f0, win 0x1f7e20, ios 0x0;
virtual cocos2d::CCPoint getRealPosition() = mac 0x22d5f0, win 0x1f7e20, ios 0x0;
virtual void getOrientedBox() = mac 0x22dee0, win 0x1f95d0, ios 0x0;
virtual void animationFinished(char const*) = mac 0x22e9d0, win 0x0, ios 0x0;
void activateStreak() = mac 0x21aef0, win 0x1f9080, ios 0x0;
@ -4203,9 +4224,9 @@ class PlayerObject : GameObject, AnimatedSpriteDelegate {
void bumpPlayer(float, int) = mac 0x22d890, win 0x0, ios 0x0;
void buttonDown(PlayerButton) = mac 0x22b7e0, win 0x0, ios 0x0;
void checkSnapJumpToObject(GameObject*) = mac 0x2217f0, win 0x0, ios 0x0;
void collidedWithObject(float, GameObject*) = mac 0x21d880, win 0x0, ios 0x0;
void collidedWithObject(float, GameObject*, cocos2d::CCRect) = mac 0x21f0b0, win 0x0, ios 0x0;
void collidedWithSlope(float, GameObject*, bool) = mac 0x21d8d0, win 0x0, ios 0x0;
bool collidedWithObject(float, GameObject*) = mac 0x21d880, win 0x0, ios 0x0;
bool collidedWithObject(float, GameObject*, cocos2d::CCRect) = mac 0x21f0b0, win 0x0, ios 0x0;
bool collidedWithSlope(float, GameObject*, bool) = mac 0x21d8d0, win 0x0, ios 0x0;
void convertToClosestRotation(float) = mac 0x21c860, win 0x0, ios 0x0;
void copyAttributes(PlayerObject*) = mac 0x22dc70, win 0x0, ios 0x0;
static PlayerObject* create(int, int, cocos2d::CCLayer*) = mac 0x217260, win 0x0, ios 0x0;
@ -4375,6 +4396,7 @@ class PlayerObject : GameObject, AnimatedSpriteDelegate {
bool m_isHidden;
int m_hasGhostTrail;
GhostTrailEffect* m_ghostTrail;
void* m_unknown;
cocos2d::CCSprite* m_iconSprite;
cocos2d::CCSprite* m_iconSpriteSecondary;
cocos2d::CCSprite* m_iconSpriteWhitener;
@ -4384,13 +4406,12 @@ class PlayerObject : GameObject, AnimatedSpriteDelegate {
cocos2d::CCSprite* m_unk500;
cocos2d::CCSprite* m_vehicleSpriteWhitener;
cocos2d::CCSprite* m_vehicleGlow;
cocos2d::CCSprite* m_unk50C;
cocos2d::CCMotionStreak* m_regularTrail;
HardStreak* m_waveTrail;
double m_xAccel;
double m_jumpAccel;
double m_gravity;
PAD = mac 0x10, win 0x08, android 0x0;
double m_unknown20;
bool m_unk538;
bool m_unk539;
bool m_unk53A;
@ -4399,16 +4420,16 @@ class PlayerObject : GameObject, AnimatedSpriteDelegate {
bool m_unk53D;
bool m_unk53E;
bool m_unk53F;
PAD = mac 0x0, win 0x10, android 0x0;
PAD = mac 0x10, win 0x10;
double m_lastJumpTime;
double m_unk558;
PAD = mac 0x0, win 0x24, android 0x0;
float m_unk584;
PAD = mac 0x0, win 0x14, android 0x0;
PAD = mac 0x24, win 0x24;
float m_decelerationRate;
PAD = mac 0x14, win 0x14;
GameObject* m_unk59C;
PAD = mac 0x0, win 0x8, android 0x0;
GJRobotSprite* m_robot;
GJSpiderSprite* m_spider;
PAD = mac 0x10, win 0x8;
GJRobotSprite* m_robotSprite;
GJSpiderSprite* m_spiderSprite;
bool m_unk5B0;
cocos2d::CCParticleSystemQuad* m_unk5B4;
cocos2d::CCParticleSystemQuad* m_unk5B8;
@ -4417,17 +4438,17 @@ class PlayerObject : GameObject, AnimatedSpriteDelegate {
cocos2d::CCParticleSystemQuad* m_unk5C4;
cocos2d::CCParticleSystemQuad* m_unk5C8;
cocos2d::CCParticleSystemQuad* m_unk5CC;
PAD = mac 0x0, win 0x4, android 0x0;
PAD = mac 0x8, win 0x4, android 0x0;
cocos2d::CCParticleSystemQuad* m_unk5D4;
cocos2d::CCParticleSystemQuad* m_unk5D8;
PAD = mac 0x0, win 0x20, android 0x0;
PAD = mac 0x20, win 0x20, android 0x0;
// int m_streakID;
// float m_wellIdk;
// PAD = mac 0x0, win 0x10, android 0x0;
bool m_unk5FC;
bool m_unk5FD;
bool m_unk5FE;
PAD = mac 0x0, win 0x11, android 0x0;
PAD = mac 0x11, win 0x11, android 0x0;
bool m_unk610;
bool m_isHolding;
bool m_hasJustHeld;
@ -4462,7 +4483,9 @@ class PlayerObject : GameObject, AnimatedSpriteDelegate {
cocos2d::CCArray* m_touchingRings;
GameObject* m_lastActivatedPortal;
bool m_unk674;
PAD = mac 0x0, win 0x4, android 0x0;
bool m_unk675;
cocos2d::ccColor3B m_playerColor1;
cocos2d::ccColor3B m_playerColor2;
cocos2d::CCPoint m_position;
bool m_unk684;
bool m_unk685;
@ -4510,6 +4533,21 @@ class RetryLevelLayer {
static RetryLevelLayer* create() = mac 0x28dd60, win 0x0, ios 0x0;
}
class RingObject : EffectGameObject {
bool create(char const*) = mac 0x0, win 0x252220, ios 0x0;
bool init(char const*) = mac 0x0, win 0x2522E0, ios 0x0;
void spawnCircle() = win 0x2523A0;
virtual void setRotation(float) = win 0x252640;
virtual void setScale(float) = win 0x252580;
virtual void resetObject() = win 0x252560;
virtual void customObjectSetup(gd::map<gd::string, gd::string>&) = win 0x2526A0;
virtual void getSaveString() = win 0x2527F0;
virtual void powerOnObject() = win 0x252360;
virtual void powerOffObject();
virtual void setRScale(float) = win 0x2525D0;
virtual void triggerActivated(float) = win 0x252350;
}
class ScrollingLayer : cocos2d::CCLayerColor {
static ScrollingLayer* create(cocos2d::CCSize, cocos2d::CCPoint, float) = mac 0x41a900, win 0x0, ios 0x0;
}
@ -4809,7 +4847,13 @@ class SpawnTriggerAction : cocos2d::CCNode {
int m_uuid;
}
class StartPosObject {}
class SpritePartDelegate {}
class StartPosObject : EffectGameObject {
static StartPosObject* create() = mac 0xda7c0;
LevelSettingsObject* m_levelSettings;
}
class StatsCell {
void updateBGColor(unsigned int index) = mac 0x0, win 0x59cf0, ios 0x0;
@ -4906,15 +4950,7 @@ class TextArea : cocos2d::CCSprite {
virtual void draw() = mac 0x19f890, win 0x0, ios 0x0;
virtual void setOpacity(unsigned char) = mac 0x19f760, win 0x0, ios 0x0;
bool init(gd::string str, char const* font, float width, float height, cocos2d::CCPoint anchor, float scale, bool disableColor) = mac 0x19ec70, win 0x33370, ios 0x92444;
static TextArea* create(gd::string const& str, char const* font, float width, float height, cocos2d::CCPoint const& anchor, float scale, bool disableColor) {
auto ret = new TextArea();
if (ret->init(str, font, width, height, anchor, scale, disableColor)) {
ret->autorelease();
return ret;
}
CC_SAFE_DELETE(ret);
return nullptr;
}
static TextArea* create(gd::string str, char const* font, float width, float height, cocos2d::CCPoint const& anchor, float scale, bool disableColor) = mac 0x19eb40, win 0x33270;
void colorAllCharactersTo(cocos2d::ccColor3B color) = mac 0x0, win 0x33830, ios 0x0;
void setString(gd::string str) = mac 0x19eda0, win 0x33480, ios 0x0;

View file

@ -1,7 +1,7 @@
add_definitions(-DANDROID)
add_definitions(-DCC_TARGET_OS_ANDROID)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fms-extensions -Xlinker --no-demangle -Wno-deprecated -m32 ")
target_compile_options(${PROJECT_NAME} -fms-extensions -Xlinker --no-demangle -Wno-deprecated -m32)
target_link_libraries(${PROJECT_NAME} log android EGL GLESv2)

View file

@ -1,9 +1,10 @@
add_definitions(-DCC_TARGET_OS_MAC)
set(CMAKE_SYSTEM_NAME MacOS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fms-extensions -Wno-deprecated -Wno-ignored-attributes -O2 -Os -fdata-sections -ffunction-sections")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -dead_strip")
target_compile_options(${PROJECT_NAME} PUBLIC -fms-extensions -Wno-deprecated -Wno-ignored-attributes -Os -flto -fvisibility=internal)
set(CMAKE_OSX_ARCHITECTURES x86_64)
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9) # did i tell im lazy
include_directories(
${GEODE_SDK_PATH}/include/cocos/cocos2dx/platform/mac
@ -37,4 +38,4 @@ endmacro()
# TARGET ${PROJECT_NAME} POST_BUILD
# COMMAND strip -x $<TARGET_FILE:${PROJECT_NAME}>
# VERBATIM USES_TERMINAL
# )
# )

View file

@ -24,6 +24,7 @@ link_prebuilts(${PROJECT_NAME})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/out)
set(CMAKE_SIZEOF_VOID_P 4)
set(CMAKE_SYSTEM_PROCESSOR "i686")
if(MSVC)
set(CMAKE_GENERATOR_PLATFORM x86)
endif()

View file

@ -13,9 +13,8 @@ if (NOT DEFINED GEODE_IOS_SDK)
endif()
set(CMAKE_SYSTEM_NAME iOS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fms-extensions -Wno-deprecated -fdata-sections -ffunction-sections")
set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -fms-extensions -Wno-deprecated -fdata-sections -ffunction-sections")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -dead_strip -arch arm64")
target_compile_options(${PROJECT_NAME} PUBLIC -fms-extensions -Wno-deprecated -Wno-ignored-attributes -Os -flto -fvisibility=internal)
target_link_options(${PROJECT_NAME} PUBLIC -arch arm64)
set(CMAKE_OSX_ARCHITECTURES arm64)
set(CMAKE_OSX_SYSROOT ${GEODE_IOS_SDK})

View file

@ -127,7 +127,7 @@ struct ClassDefinition {
depends.push_back(sclass);
}
// intentional
// else cacerr("Duplicate superclass %s for class %s\n", sclass.c_str(), name.c_str());
// else codegenerr("Duplicate superclass %s for class %s\n", sclass.c_str(), name.c_str());
}
template<typename T>

View file

@ -2,9 +2,9 @@
#include <stdio.h>
/*template <typename ...Args>
void cacerr(Args... stuff) {
void codegenerr(Args... stuff) {
printf(stuff...); // to be changed later
}*/
#define cacerr(...) { fprintf(stderr, __VA_ARGS__); abort(); }
// change later pls
#define codegenerr(...) { fprintf(stderr, __VA_ARGS__); abort(); }
// change later pls

View file

@ -73,7 +73,7 @@ inline Token parseIdent(stringstream& stream) {
stream.get();
} while (stream);
cacerr("Unexpected EOF\n");
codegenerr("Unexpected EOF\n");
}
inline void parseString(stringstream& stream, string& slice, char start) {
@ -215,7 +215,7 @@ inline void parsePreproc(stringstream& stream) {
}
if (stream.get() != '<') {
cacerr("Invalid include\n");
codegenerr("Invalid include\n");
}
stringstream a;
while (stream.peek() != '>') {
@ -229,7 +229,7 @@ inline void parsePreproc(stringstream& stream) {
if (!fptr) {
cout << fname << endl;
cacerr("Could not include file %s\n", fname.c_str());
codegenerr("Could not include file %s\n", fname.c_str());
}
fclose(fptr);
@ -241,7 +241,7 @@ inline void parsePreproc(stringstream& stream) {
//slice = stream.str();
//cout << stream.str().erase(0, stream.tellp()) << endl;
} else {
cacerr("Invalid preprocessor token %s\n", slice.c_str());
codegenerr("Invalid preprocessor token %s\n", slice.c_str());
}
}
@ -308,7 +308,7 @@ inline vector<Token> lexStream(stringstream& stream) {
std::istringstream ss(slice);
ss >> std::setbase(16) >> tn;
if (ss.fail()) {
cacerr("Invalid hex %s", slice.c_str());
codegenerr("Invalid hex %s", slice.c_str());
}
}
@ -411,7 +411,7 @@ inline vector<Token> lexStream(stringstream& stream) {
}
}
} else {
cacerr("Invalid token \"%s\"", slice.c_str());
codegenerr("Invalid token \"%s\"", slice.c_str());
}
break;
case '\'':
@ -424,7 +424,7 @@ inline vector<Token> lexStream(stringstream& stream) {
break;
default:
std::streamoff pos = stream.tellg();
cacerr("Invalid token \"%s\"", slice.c_str());
codegenerr("Invalid token \"%s\"", slice.c_str());
}
t.slice = slice;

View file

@ -11,7 +11,7 @@ using Tokens = queue<Token>;
inline Token next(Tokens& tokens) {
if (tokens.size() == 0) {
cacerr("Unexpected EOF while parsing\n");
codegenerr("Unexpected EOF while parsing\n");
}
Token p = tokens.front();
// epic debugger
@ -22,7 +22,7 @@ inline Token next(Tokens& tokens) {
inline Token peek(Tokens& tokens) {
if (tokens.size() == 0) {
cacerr("Unexpected EOF while parsing\n");
codegenerr("Unexpected EOF while parsing\n");
}
Token p = tokens.front();
return p;
@ -32,7 +32,7 @@ inline Token next_expect(Tokens& tokens, TokenType type, string tname) {
auto t = next(tokens);
if (t.type == type)
return t;
cacerr("Expected %s, found %s (next tokens %s)\n", tname.c_str(), t.slice.c_str(), next(tokens).slice.c_str());
codegenerr("Expected %s, found %s (next tokens %s)\n", tname.c_str(), t.slice.c_str(), next(tokens).slice.c_str());
}
inline bool next_if_type(TokenType type, Tokens& tokens) {
@ -80,7 +80,7 @@ inline string parseQualifiedName(Tokens& tokens) {
qual += t.slice;
} while ((t.type == kQualifier && peek(tokens).type == kIdent) || (t.type == kIdent && peek(tokens).type == kQualifier));
if (qual.size() == 0)
cacerr("Expected identifier, found %s\n", next(tokens).slice.c_str());
codegenerr("Expected identifier, found %s\n", next(tokens).slice.c_str());
return qual;
}
@ -109,7 +109,7 @@ inline string parseAttribute(Tokens& tokens) { // if attributes are expanded we
return docs;
} else {
// we can add more later
cacerr("Invalid attribute %s\n", attrib_name.c_str());
codegenerr("Invalid attribute %s\n", attrib_name.c_str());
return "";
}
}
@ -145,7 +145,7 @@ inline void parseFunction(ClassDefinition& c, Function myFunction, Tokens& token
} else if (!next_if_type(kEqual, tokens)) {
for (int k = 0; k < 4; ++k) {
if (k == 3)
cacerr("Maximum of 3 binds allowed\n");
codegenerr("Maximum of 3 binds allowed\n");
auto t = peek(tokens);
if (t.type == kComma)
@ -155,19 +155,19 @@ inline void parseFunction(ClassDefinition& c, Function myFunction, Tokens& token
auto platform = t.slice;
t = next(tokens);
if (t.slice == "0x0") t.slice = "";
if (t.type != kAddress) cacerr("Expected address, found %s\n", t.slice.c_str());
if (t.type != kAddress) codegenerr("Expected address, found %s\n", t.slice.c_str());
if (platform == "mac") myFunction.binds[kMacFunction] = t.slice;
else if (platform == "win") myFunction.binds[kWindowsFunction] = t.slice;
else if (platform == "ios") myFunction.binds[kIosFunction] = t.slice;
else cacerr("Unknown identifier, found %s\n", t.slice.c_str());
else codegenerr("Unknown identifier, found %s\n", t.slice.c_str());
} else
cacerr("Expected platform identifier, found %s\n", t.slice.c_str());
codegenerr("Expected platform identifier, found %s\n", t.slice.c_str());
t = next(tokens);
if (t.type == kSemi)
break;
if (t.type != kComma)
cacerr("Expected comma, found %s.\n", t.slice.c_str());
codegenerr("Expected comma, found %s.\n", t.slice.c_str());
}
} else next_expect(tokens, kSemi, ";");
// myFunction.parent_class = &c;
@ -176,7 +176,7 @@ inline void parseFunction(ClassDefinition& c, Function myFunction, Tokens& token
}
inline void parseMember(ClassDefinition& c, string type, string varName, Tokens& tokens) {
//cacerr("not implemented yet!!!\n");
//codegenerr("not implemented yet!!!\n");
Member myMember;
myMember.type = type;
@ -187,7 +187,7 @@ inline void parseMember(ClassDefinition& c, string type, string varName, Tokens&
if (!next_if_type(kBrackL, tokens)) {
auto num_maybe = next_expect(tokens, kIdent, "number").slice;
if (num_maybe.find_first_not_of("0123456789") != string::npos) {
cacerr("Expected number, found %s\n", num_maybe.c_str());
codegenerr("Expected number, found %s\n", num_maybe.c_str());
}
myMember.count = static_cast<size_t>(strtoll(num_maybe.c_str(), NULL, 10));
@ -200,7 +200,7 @@ inline void parseMember(ClassDefinition& c, string type, string varName, Tokens&
myMember.member_type = MemberType::kHardcode;
for (int k = 0; k < 5; ++k) {
if (k == 4)
cacerr("Maximum of 4 hardcodes allowed\n");
codegenerr("Maximum of 4 hardcodes allowed\n");
auto t = next(tokens);
if (t.type == kComma)
@ -209,23 +209,23 @@ inline void parseMember(ClassDefinition& c, string type, string varName, Tokens&
auto platform = t.slice;
t = next(tokens);
if (t.slice == "0x0") t.slice = "";
if (t.type != kAddress) cacerr("Expected address, found %s\n", t.slice.c_str());
if (t.type != kAddress) codegenerr("Expected address, found %s\n", t.slice.c_str());
if (platform == "mac") myMember.hardcodes[kMacMember] = t.slice;
else if (platform == "win") myMember.hardcodes[kWindowsMember] = t.slice;
else if (platform == "ios") myMember.hardcodes[kIosMember] = t.slice;
else if (platform == "android") myMember.hardcodes[kAndroidMember] = t.slice;
else cacerr("Unknown identifier, found %s\n", t.slice.c_str());
else codegenerr("Unknown identifier, found %s\n", t.slice.c_str());
}
else if (t.type == kAddress)
myMember.hardcodes[k] = t.slice;
else
cacerr("Expected platform identifier, found %s\n", t.slice.c_str());
codegenerr("Expected platform identifier, found %s\n", t.slice.c_str());
t = next(tokens);
if (t.type == kSemi)
break;
if (t.type != kComma)
cacerr("Expected comma, found %s.\n", t.slice.c_str());
codegenerr("Expected comma, found %s.\n", t.slice.c_str());
}
} else {
myMember.member_type = MemberType::kDefault;
@ -288,9 +288,9 @@ inline void parseField(ClassDefinition& c, Tokens& tokens) {
}
if (return_name.empty())
cacerr("Expected identifier, found %s\n", next(tokens).slice.c_str());
codegenerr("Expected identifier, found %s\n", next(tokens).slice.c_str());
if (return_name.back().type != kIdent)
cacerr("Expected identifier, found %s\n", return_name.back().slice.c_str());
codegenerr("Expected identifier, found %s\n", return_name.back().slice.c_str());
string varName = return_name.back().slice;
return_name.pop_back();
@ -333,9 +333,9 @@ inline void parseField(ClassDefinition& c, Tokens& tokens) {
}
if (fn_type == kVirtualFunction)
cacerr("Unexpected virtual keyword\n")
codegenerr("Unexpected virtual keyword\n")
if (fn_type == kStaticFunction)
cacerr("Unexpected static keyword\n")
codegenerr("Unexpected static keyword\n")
return parseMember(c, return_type, varName, tokens);
}
@ -393,6 +393,6 @@ inline Root parseTokens(vector<Token> ts) {
parseClass(root, tokens);
}
//cacerr("s %d\n", tokens.size());
//codegenerr("s %d\n", tokens.size());
return root;
}

View file

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(Codegen LANGUAGES C CXX)
project(CodegenRun LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 17)
@ -8,43 +8,49 @@ if (NOT DEFINED GEODE_HOST_ARM AND APPLE)
set(CMAKE_OSX_SYSROOT )
endif()
message(STATUS "Building Codegen")
add_subdirectory(fmt)
set(GEODE_CG_FIRST "")
file(GLOB SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp
)
macro(add_gen project file)
add_executable(${project}Gen ${project}Gen.cpp)
file(GLOB HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/Broma/src/*.hpp
${CMAKE_CURRENT_SOURCE_DIR}/fmt/include/*.h
)
target_link_libraries(${project}Gen PUBLIC fmt)
target_include_directories(${project}Gen PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/Broma/src
${CMAKE_CURRENT_SOURCE_DIR}/fmt/include
${CMAKE_CURRENT_SOURCE_DIR}/
)
add_executable(Codegen ${SOURCES})
target_link_libraries(Codegen PRIVATE fmt)
target_include_directories(Codegen PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/Broma/src
${CMAKE_CURRENT_SOURCE_DIR}/fmt/include
${CMAKE_CURRENT_SOURCE_DIR}/src
)
target_precompile_headers(Codegen PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/Shared.hpp
)
if ("${GEODE_CG_FIRST}" STREQUAL "")
target_precompile_headers(${project}Gen PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/SharedGen.hpp")
set(GEODE_CG_FIRST ${project}Gen)
else()
target_precompile_headers(${project}Gen REUSE_FROM ${GEODE_CG_FIRST})
endif()
# set(GEODE_TARGET_PLATFORM MacOS)
add_custom_target(${project}Run
COMMAND ${project}Gen ${GEODE_TARGET_PLATFORM} "${GEODE_SDK_PATH}/bindings" "${GEODE_CODEGEN_DIR}/${file}"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Run ${project}Gen"
)
add_dependencies(${CMAKE_PROJECT_NAME} ${project}Run)
endmacro()
# set(GEODE_BINDING_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../bindings)
# set(GEODE_CODEGEN_DIR ${CMAKE_CURRENT_BINARY_DIR}/codegen)
# message(${GEODE_BINDING_PATH})
add_gen(Source GeneratedSource.cpp)
add_gen(Header GeneratedHeader.hpp)
# add_gen(Tidy Tidy.bro) # run manually
add_gen(Wrapper GeneratedWrapper.hpp)
add_gen(Modify GeneratedModify.hpp)
add_gen(Type GeneratedType.hpp)
add_gen(Address GeneratedAddress.hpp)
# add_gen(JesusChrist DynamicTypes.cpp)
if (NOT DEFINED GEODE_TARGET_PLATFORM)
message(FATAL_ERROR "GEODE_TARGET_PLATFORM is not defined")
endif()
if (NOT DEFINED GEODE_BINDING_PATH)
message(FATAL_ERROR "GEODE_BINDING_PATH is not defined")
endif()
if (NOT DEFINED GEODE_CODEGEN_DIR)
set(GEODE_CODEGEN_DIR ${CMAKE_CURRENT_BINARY_DIR}/codegen)
message("Using current binary dir for GEODE_CODEGEN_DIR, which is ${CMAKE_CURRENT_BINARY_DIR}/codegen")
endif()
add_custom_target(CodegenRun ALL
COMMAND Codegen ${GEODE_TARGET_PLATFORM} ${GEODE_BINDING_PATH} ${GEODE_CODEGEN_DIR}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Run Codegen"
)
add_dependencies(CodegenRun Codegen)

View file

@ -1,53 +0,0 @@
#include <SharedGen.hpp>
#include <set>
namespace format_strings {
char const* declare_member_type = R"RAW(
template <class, class, class, class = void>
struct {function_name} {{
constexpr static inline bool value = false;
}};
template <class Derived, class Base, class Ret, class ...Parameters>
struct {function_name}<Derived, Base, Ret(Parameters...), std::void_t<
decltype(substitute<Ret, Base, Derived, Parameters...>(&Base::{function_name})),
decltype(substitute<Ret, Base, Derived, Parameters...>(&Derived::{function_name}))
>> {{
private:
using base_type = decltype(substitute<Ret, Base, Derived, Parameters...>(&Base::{function_name}));
using derived_type = decltype(substitute<Ret, Base, Derived, Parameters...>(&Derived::{function_name}));
public:
constexpr static inline bool value =
function_uuid<(derived_type)&Derived::{function_name}>::value !=
function_uuid<(base_type)&Base::{function_name}>::value;
}};
)RAW";
}
using std::set;
int main(int argc, char** argv) {
string output("");
Root root = CacShare::init(argc, argv);
set<string> used;
for (auto& [name, c] : root.classes) {
for (auto& f : c.functions) {
switch (f.function_type) {
case kConstructor: [[fallthrough]];
case kDestructor: continue;
default: break;
}
if (used.find(f.name) != used.end()) continue;
output += fmt::format(format_strings::declare_member_type,
fmt::arg("function_name", f.name)
);
used.insert(f.name);
}
}
CacShare::writeFile(output);
}

View file

@ -1,159 +0,0 @@
#include <SharedGen.hpp>
#include <iostream>
namespace format_strings {
// requires: class_name
char const* interface_start = R"CAC(
template<template <auto, typename> class D = BlankBase, typename UUID = void>
struct ${class_name} : {raw_class_name}, ModifierBase {{
${class_name}(const ${class_name}& c) : {class_name}(c) {{}}
${class_name}() : ${class_name}(*this) {{}}
~${class_name}() {{
cocos2d::CCDestructor::lock(this) = true;
}}
GEODE_NOINLINE static inline auto& getAdditionalFields() {{
static std::unordered_map<uintptr_t, container_t<>*> ret;
return ret;
}}
GEODE_NOINLINE static inline auto& getOriginalDestructor() {{
static uintptr_t ret;
return ret;
}}
static void fieldCleanup(uintptr_t self) {{
const uintptr_t begin = self + sizeof(${class_name});
const uintptr_t end = self + sizeof(D<0, UUID>);
for (uintptr_t i = begin; i < end; i += sizeof(uintptr_t)) {{
if (getAdditionalFields().find(i) != getAdditionalFields().end()) {{
delete getAdditionalFields().at(i);
getAdditionalFields().erase(i);
}}
}}
reinterpret_cast<void(*)(uintptr_t)>(getOriginalDestructor())(self);
}}
)CAC";
char const* declare_structor = R"CAC(
GEODE_DUPABLE void {function_name}({raw_args}) {{
reinterpret_cast<void(*)(decltype(this){arg_types})>(addresser::address{global_index})(this{parameters});
}})CAC";
char const* apply_start = R"CAC(
static bool _apply() {
)CAC";
// requires: index, class_name, arg_types, function_name, raw_arg_types, non_virtual
char const* apply_function_member = R"CAC(
using baseType{global_index} = temp_name_find_better::ret{global_index}({class_name}::*)({raw_arg_types}) {const};
constexpr auto baseAddress{global_index} = (baseType{global_index})(&{class_name}::{function_name});
using derivedType{global_index} = temp_name_find_better::ret{global_index}(D<baseAddress{global_index}, UUID>::*)({raw_arg_types}) {const};
GEODE_VIRTUAL_CONSTEXPR auto derivedAddress{global_index} = (derivedType{global_index})(&D<baseAddress{global_index}, UUID>::{function_name});
if (baseAddress{global_index} != derivedAddress{global_index}) {{
Interface::get()->logInfo("Adding hook at function {class_name}::{function_name}", Severity::Debug);
Interface::get()->addHook("{class_name}::{function_name}", (void*)addresser::address{global_index}(), (void*)addresser::get{non_virtual}Virtual(derivedAddress{global_index}));
}}
)CAC";
char const* apply_function_structor = R"CAC(
using baseType{global_index} = temp_name_find_better::ret{global_index}(${class_name}::*)({raw_arg_types}) {const};
constexpr auto baseAddress{global_index} = (baseType{global_index})(&${class_name}::{function_name});
using derivedType{global_index} = temp_name_find_better::ret{global_index}(D<baseAddress{global_index}, UUID>::*)({raw_arg_types}) {const};
GEODE_VIRTUAL_CONSTEXPR auto derivedAddress{global_index} = (derivedType{global_index})(&D<baseAddress{global_index}, UUID>::{function_name});
if (baseAddress{global_index} != derivedAddress{global_index}) {{
Interface::get()->logInfo("Adding hook at function {class_name}::{function_name}", Severity::Debug);
Interface::get()->addHook("{class_name}::{function_name}", (void*)addresser::address{global_index}(), (void*)addresser::get{non_virtual}Virtual(derivedAddress{global_index}));
}}
)CAC";
char const* apply_function_static = R"CAC(
using baseType{global_index} = temp_name_find_better::ret{global_index}(*)({raw_arg_types});
constexpr auto baseAddress{global_index} = (baseType{global_index})(&{class_name}::{function_name});
using derivedType{global_index} = temp_name_find_better::ret{global_index}(*)({raw_arg_types});
GEODE_VIRTUAL_CONSTEXPR auto derivedAddress{global_index} = (derivedType{global_index})(&D<baseAddress{global_index}, UUID>::{function_name});
if (baseAddress{global_index} != derivedAddress{global_index}) {{
Interface::get()->logInfo("Adding hook at function {class_name}::{function_name}", Severity::Debug);
Interface::get()->addHook("{class_name}::{function_name}", (void*)temp_name_find_better::address{global_index}(), (void*)addresser::getNonVirtual(derivedAddress{global_index}));
}}
)CAC";
char const* apply_end = R"CAC(
return true;
}
)CAC";
}
int main(int argc, char** argv) {
auto root = CacShare::init(argc, argv);
string output;
for (auto& [name, c] : root.classes) {
string unqualifiedName = CacShare::toUnqualified(name);
output += fmt::format(format_strings::interface_start, fmt::arg("class_name", unqualifiedName), fmt::arg("raw_class_name", name));
for (auto& f : c.functions) {
if (!CacShare::functionDefined(f))
continue; // Function not supported for this platform, skip it
string name;
switch (f.function_type) {
case kDestructor:
name = "destructor";
case kConstructor:
if (name != "destructor") name = "constructor";
output += fmt::format(format_strings::declare_structor,
fmt::arg("arg_types", CacShare::formatArgTypes(f.args)),
fmt::arg("raw_arg_types", CacShare::formatRawArgTypes(f.args)),
fmt::arg("class_name", unqualifiedName),
fmt::arg("const", f.is_const ? "const " : ""),
fmt::arg("convention", CacShare::getConvention(f)),
fmt::arg("function_name",name),
fmt::arg("global_index",f.hash()),
fmt::arg("parameters", CacShare::formatParameters(f.args.size())),
fmt::arg("raw_args", CacShare::formatRawArgs(f.args)),
fmt::arg("raw_parameters", CacShare::formatRawParameters(f.args.size()))
);
default:
break;
}
}
output += format_strings::apply_start;
for (auto& f : c.functions) {
if (!CacShare::functionDefined(f))
continue; // Function not supported for this platform, skip it
char const* used_format;
string name = f.name;
switch (f.function_type) {
case kStaticFunction:
used_format = format_strings::apply_function_static;
break;
case kDestructor:
name = "destructor";
case kConstructor:
if (name != "destructor") name = "constructor";
used_format = format_strings::apply_function_structor;
break;
default:
used_format = format_strings::apply_function_member;
break;
}
output += fmt::format(used_format,
fmt::arg("global_index",f.hash()),
fmt::arg("class_name", unqualifiedName),
fmt::arg("arg_types", CacShare::formatArgTypes(f.args)),
fmt::arg("function_name", name),
fmt::arg("raw_arg_types", CacShare::formatRawArgTypes(f.args)),
fmt::arg("non_virtual", f.function_type == kVirtualFunction ? "" : "Non"),
fmt::arg("const", f.is_const ? "const " : "")
);
}
output += format_strings::apply_end;
output += "};\n";
}
// fmt::print("{}", output);
CacShare::writeFile(output);
}

View file

@ -1,175 +0,0 @@
#pragma once
#include <broma.hpp>
#include <array>
#include <fmt/format.h>
#include <fmt/ranges.h>
#include <fstream>
using std::istreambuf_iterator;
#ifdef _MSC_VER
#pragma warning(disable: 4996)
#endif
#if _WIN32
#include <direct.h>
#else
#include <unistd.h>
#endif
struct CacShare {
inline static Platform platform;
inline static string writePath;
static Root init(int argc, char** argv) {
if (argc < 4)
cacerr("Invalid number of parameters (expected 3 found %d)", argc-1);
char const* p = argv[1];
if (strcmp(p, "Win32") == 0)
platform = kWindows;
else if (strcmp(p, "MacOS") == 0)
platform = kMac;
else if (strcmp(p, "iOS") == 0)
platform = kIos;
else if (strcmp(p, "Android") == 0)
platform = kAndroid;
else
cacerr("Invalid platform %s\n", p);
chdir(argv[2]);
stringstream s;
s << "#include <Entry.bro>";
writePath = argv[3];
return parseTokens(lexStream(s));
}
// new funcs start here
static void editArguments(Function& f) {
for (size_t i = 0; i < f.argnames.size(); ++i) {
if (f.argnames[i] == "") {
f.argnames[i] = fmt::format("p{}", i);
}
}
}
static string getBind(Function const& f) {
return f.binds[CacShare::platform];
}
static string getIndex(Function const& f) {
return fmt::format("{}", f.global_index);
}
static string getClassName(Function const& f) {
return f.parent_class->name;
}
static string getFunctionName(Function const& f) {
return f.name;
}
static string getConst(Function const& f) {
return f.is_const ? "const" : "";
}
static string getConstWhitespace(Function const& f) {
return f.is_const ? " " : "";
}
static string getParameters(Function const& f) { // int p0, float p1
vector<string> parameters;
for (size_t i = 0; i < f.args.size(); ++i) {
parameters.push_back(fmt::format("{} {}", f.args[i], f.argnames[i])); // p0, myFloat
}
return fmt::format("{}", fmt::join(parameters, ", "));
}
static string getParameterTypes(Function const& f) { //int, float
return fmt::format("{}", fmt::join(f.args, ", "));
}
static string getArguments(Function const& f) { // p0, p1
return fmt::format("{}", fmt::join(f.argnames, ", "));
}
static string getParameterComma(Function const& f) { // int p0, float p1
return f.args.size() > 0 ? ", " : "";
}
static string getParameterTypeComma(Function const& f) { //int, float
return f.args.size() > 0 ? ", " : "";
}
static string getArgumentComma(Function const& f) { // p0, p1
return f.argnames.size() > 0 ? ", " : "";
}
static string getConvention(Function const& f) {
if (CacShare::platform != kWindows) return "DefaultConv";
switch (f.function_type) {
case kConstructor: [[fallthrough]];
case kDestructor: [[fallthrough]];
case kRegularFunction:
if (isFunctionDefined(f)) return "x86::Thiscall";
return "x86::Membercall";
case kVirtualFunction:
return "x86::Thiscall";
case kStaticFunction:
if (isFunctionDefined(f)) return "x86::Cdecl";
return "x86::Optcall";
}
return "x86::Membercall";
}
// defined : we have a symbol that is usable
static bool isFunctionDefined(Function const& f) {
// basically this is true for
// fmod for all platforms
// cocos for windows
// all funcs without stl parameter for android
// destructors for no platforms
if (f.function_type == kDestructor) return false;
if (f.function_type == kConstructor) return false;
if (f.parent_class->name.rfind("fmod::", 0) == 0) return true;
if (f.parent_class->name.rfind("cocos2d::", 0) == 0 && platform == kWindows) return true;
if (getParameterTypes(f).find("gd::", 0) != string::npos && platform == kAndroid) return false;
if (platform == kAndroid) return true;
return false;
}
// definable : we can define it and hook it
static bool isFunctionDefinable(Function const& f) {
// basically this is true for
// all funcs that we have the offset for
// all funcs with stl parameter for android
if (getParameterTypes(f).find("gd::", 0) != string::npos && platform == kAndroid) return true;
if (getBind(f) != "") return true;
return false;
}
// and end here
static void writeFile(string& output) {
ifstream readfile;
readfile >> std::noskipws;
readfile.open(writePath);
string data((istreambuf_iterator<char>(readfile)), istreambuf_iterator<char>());
readfile.close();
if (data != output) {
ofstream writefile;
writefile.open(writePath);
writefile << output;
writefile.close();
}
}
};
#ifdef _MSC_VER
#pragma warning(default: 4996)
#endif

View file

@ -1,67 +0,0 @@
#include <SharedGen.hpp>
#include <set>
namespace format_strings {
char const* declare_member_type = R"RAW(
template <template <class, class...> class, class, class, class, class = void>
struct {function_name} {{
private:
static void wrapper(...) {{}}
public:
constexpr static inline auto value = &wrapper;
}};
template <template <class, class...> class Conv, class Derived, class Base, class Ret, class ...Parameters>
struct {function_name}<Conv, Derived, Base, Ret(Parameters...), std::enable_if_t<
std::is_member_function_pointer_v<decltype(substitute<Ret, Base, Derived, Parameters...>(&Derived::{function_name}))>
>> {{
private:
static Ret wrapper(Derived* self, Parameters... ps) {{
return self->Derived::{function_name}(ps...);
}}
public:
using MyConv = Conv<Ret, Derived*, Parameters...>;
constexpr static inline auto value = MyConv::template get_wrapper<&wrapper>();
}};
template <template <class, class...> class Conv, class Derived, class Base, class Ret, class ...Parameters>
struct {function_name}<Conv, Derived, Base, Ret(Parameters...), std::enable_if_t<
is_function_pointer_v<decltype(substitute<Ret, Base, Derived, Parameters...>(&Derived::{function_name}))>
>> {{
private:
static Ret wrapper(Parameters... ps) {{
return Derived::{function_name}(ps...);
}}
public:
using MyConv = Conv<Ret, Parameters...>;
constexpr static inline auto value = MyConv::template get_wrapper<&wrapper>();
}};
)RAW";
}
using std::set;
int main(int argc, char** argv) {
string output("");
Root root = CacShare::init(argc, argv);
set<string> used;
for (auto& [name, c] : root.classes) {
for (auto& f : c.functions) {
switch (f.function_type) {
case kConstructor: [[fallthrough]];
case kDestructor: continue;
default: break;
}
if (used.find(f.name) != used.end()) continue;
output += fmt::format(format_strings::declare_member_type,
fmt::arg("function_name", f.name)
);
used.insert(f.name);
}
}
CacShare::writeFile(output);
}

View file

@ -1,6 +1,6 @@
#include <SharedGen.hpp>
#include "Shared.hpp"
namespace format_strings {
namespace { namespace format_strings {
char const* declare_address = R"GEN(
GEODE_NOINLINE GEODE_HIDDEN inline static uintptr_t address{index}() {{
@ -9,10 +9,10 @@ GEODE_NOINLINE GEODE_HIDDEN inline static uintptr_t address{index}() {{
}}
)GEN";
}
}}
static string getAddress(Function const& f) {
if (CacShare::isFunctionDefined(f)) {
if (codegen::isFunctionDefined(f)) {
string format;
if (f.function_type == kVirtualFunction)
format = "addresser::getVirtual((types::member{})(&{}::{}))";
@ -20,23 +20,22 @@ static string getAddress(Function const& f) {
format = "addresser::getNonVirtual((types::member{})(&{}::{}))";
return fmt::format(format, f.global_index, f.parent_class->name, f.name);
}
else return "base::get() + " + f.binds[CacShare::platform];
else return "base::get() + " + f.binds[codegen::platform];
}
int main(int argc, char** argv) {
std::string generateAddressHeader(Root const& root) {
string output("");
Root root = CacShare::init(argc, argv);
for (auto& [name, c] : root.classes) {
for (auto& f : c.functions) {
if (!CacShare::isFunctionDefinable(f) && !CacShare::isFunctionDefined(f))
if (!codegen::isFunctionDefinable(f) && !codegen::isFunctionDefined(f))
continue; // Function not supported, skip
output += fmt::format(format_strings::declare_address,
output += fmt::format(::format_strings::declare_address,
fmt::arg("address", getAddress(f)),
fmt::arg("index", CacShare::getIndex(f))
fmt::arg("index", codegen::getIndex(f))
);
}
}
CacShare::writeFile(output);
return output;
}

View file

@ -1,19 +1,19 @@
#include <SharedGen.hpp>
#include "Shared.hpp"
#include <iostream>
#include <set>
using std::set;
namespace format_strings {
namespace { namespace format_strings {
char const* class_predeclare = "class {class_name};\n";
// requires: base_classes, class_name
char const* class_start = R"GEN(
class {class_name}{base_classes} {{
class GEODE_CODEGEN_DLL {class_name}{base_classes} {{
public:
)GEN";
char const* function_definition = R"GEN(
{docs}GEODE_CODEGEN_DLL {static}{virtual}{return_type} {function_name}({parameters}){const_whitespace}{const};
{docs}{static}{virtual}{return_type} {function_name}({parameters}){const_whitespace}{const};
)GEN";
char const* error_definition = R"GEN(
@ -24,7 +24,7 @@ public:
)GEN";
char const* structor_definition = R"GEN(
GEODE_CODEGEN_DLL {function_name}({parameters});)GEN";
{function_name}({parameters});)GEN";
// requires: type, member_name, array
char const* member_definition = R"GEN(
@ -42,9 +42,9 @@ public:
char const* class_end = R"GEN(
};
)GEN";
}
}}
void sortClass(Root& r, ClassDefinition* c, set<ClassDefinition*>& looked, vector<ClassDefinition*>& ordered) {
void sortClass(Root const& r, ClassDefinition const* c, set<ClassDefinition const*>& looked, vector<ClassDefinition const*>& ordered) {
if (c->name.find("DS_Dictionary") != string::npos) return;
if (c->name.find("cocos2d") != string::npos) return; // cocos headers exist already
if (looked.find(c) == looked.end()) {
@ -52,11 +52,11 @@ void sortClass(Root& r, ClassDefinition* c, set<ClassDefinition*>& looked, vecto
for (string j : c->depends) {
if (j.find("cocos2d") != string::npos) continue;
if (r.classes.count(c->name) == 0) {
cacerr("Expected class definition for %s\n", c->name.c_str());
codegenerr("Expected class definition for %s\n", c->name.c_str());
}
else {
if (r.classes.find(j) == r.classes.end()) {
cacerr("Create class definition for %s\n", j.c_str());
codegenerr("Create class definition for %s\n", j.c_str());
}
else sortClass(r, &r.classes.at(j), looked, ordered);
}
@ -65,12 +65,11 @@ void sortClass(Root& r, ClassDefinition* c, set<ClassDefinition*>& looked, vecto
}
}
int main(int argc, char** argv) {
set<ClassDefinition*> looked;
vector<ClassDefinition*> ordered;
std::string generateGDHeader(Root const& root) {
set<ClassDefinition const*> looked;
vector<ClassDefinition const*> ordered;
string output = "#pragma once\n#include <gdstdlib.hpp>\n#include <cocos2d.h>\n";
Root root = CacShare::init(argc, argv);
for (auto& [name, c] : root.classes) {
sortClass(root, &c, looked, ordered);
@ -78,7 +77,7 @@ int main(int argc, char** argv) {
for (auto& cp : ordered) {
if (cp->name != "") {
output += fmt::format(format_strings::class_predeclare,
output += fmt::format(::format_strings::class_predeclare,
fmt::arg("class_name", cp->name)
);
}
@ -95,7 +94,7 @@ int main(int argc, char** argv) {
string bases = cd.superclasses.size() > 0 ? fmt::format(" : {}", fmt::join(base_strings, ", ")) : "";
output += fmt::format(format_strings::class_start,
output += fmt::format(::format_strings::class_start,
fmt::arg("class_name", cd.name),
fmt::arg("base_classes", bases)
);
@ -105,36 +104,35 @@ int main(int argc, char** argv) {
}
for (auto f : cd.functions) {
CacShare::editArguments(f);
char const* used_format;
switch (f.function_type) {
case kDestructor:
case kConstructor:
used_format = format_strings::structor_definition;
used_format = ::format_strings::structor_definition;
break;
default:
used_format = format_strings::function_definition;
used_format = ::format_strings::function_definition;
break;
}
if (f.binds[CacShare::platform].size() == 0 && !f.is_defined) {
if (f.binds[codegen::platform].size() == 0 && !f.is_defined) {
//continue;
// ok new idea
if (f.function_type == kDestructor || f.function_type == kConstructor)
continue;
used_format = format_strings::error_definition;
used_format = ::format_strings::error_definition;
}
output += fmt::format(used_format,
fmt::arg("virtual", f.function_type == kVirtualFunction ? "virtual " : ""),
fmt::arg("static", f.function_type == kStaticFunction ? "static " : ""),
fmt::arg("class_name", CacShare::getClassName(f)),
fmt::arg("const", CacShare::getConst(f)),
fmt::arg("const_whitespace", CacShare::getConstWhitespace(f)),
fmt::arg("function_name", CacShare::getFunctionName(f)),
fmt::arg("index", CacShare::getIndex(f)),
fmt::arg("parameters", CacShare::getParameters(f)),
fmt::arg("class_name", codegen::getClassName(f)),
fmt::arg("const", codegen::getConst(f)),
fmt::arg("const_whitespace", codegen::getConstWhitespace(f)),
fmt::arg("function_name", codegen::getFunctionName(f)),
fmt::arg("index", codegen::getIndex(f)),
fmt::arg("parameters", codegen::getParameters(f)),
fmt::arg("return_type", f.return_type),
fmt::arg("docs", f.docs)
);
@ -142,7 +140,7 @@ int main(int argc, char** argv) {
for (auto m : cd.members) {
string hardcode;
switch (CacShare::platform) {
switch (codegen::platform) {
case kIos:
hardcode = m.hardcodes[kIosMember];
break;
@ -162,14 +160,14 @@ int main(int argc, char** argv) {
char const* used_format;
switch (m.member_type) {
case kDefault:
used_format = format_strings::member_definition;
used_format = ::format_strings::member_definition;
break;
case kHardcode:
used_format = format_strings::hardcode_definition;
used_format = ::format_strings::hardcode_definition;
break;
case kPad:
used_format = format_strings::pad_definition;
if (hardcode.size() == 0) used_format = format_strings::unimplemented_definition;
used_format = ::format_strings::pad_definition;
if (hardcode.size() == 0) used_format = ::format_strings::unimplemented_definition;
break;
}
@ -184,10 +182,10 @@ int main(int argc, char** argv) {
}
// if (hasClass)
output += format_strings::class_end;
output += ::format_strings::class_end;
// queued.pop_front();
}
CacShare::writeFile(output);
return output;
}

60
codegen/src/Main.cpp Normal file
View file

@ -0,0 +1,60 @@
#include "Shared.hpp"
#include "../../include/utils/fs/filesystem.hpp" // bruh
using namespace codegen;
void writeFile(ghc::filesystem::path const& writePath, std::string const& output) {
std::ifstream readfile;
readfile >> std::noskipws;
readfile.open(writePath);
std::string data((std::istreambuf_iterator<char>(readfile)), std::istreambuf_iterator<char>());
readfile.close();
if (data != output) {
std::ofstream writefile;
writefile.open(writePath);
writefile << output;
writefile.close();
}
}
int main(int argc, char** argv) {
if (argc != 4) codegenerr("Invalid number of parameters (expected 3 found %d)", argc-1);
std::string p = argv[1];
if (p == "Win32") codegen::platform = kWindows;
else if (p == "MacOS") codegen::platform = kMac;
else if (p == "iOS") codegen::platform = kIos;
else if (p == "Android") codegen::platform = kAndroid;
else codegenerr("Invalid platform %s\n", p.c_str());
chdir(argv[2]);
std::stringstream stream;
stream << "#include <Entry.bro>";
ghc::filesystem::path writeDir = argv[3];
ghc::filesystem::create_directories(writeDir);
auto fileWithDir = [writeDir](char const* file) {
return writeDir / file;
};
Root root = parseTokens(lexStream(stream));
/* add missing parameter names */
for (auto& [name, c] : root.classes) {
for (auto& f : c.functions) {
for (size_t i = 0; i < f.argnames.size(); ++i) {
if (f.argnames[i] == "") {
f.argnames[i] = fmt::format("p{}", i);
}
}
}
}
writeFile(fileWithDir("GeneratedAddress.hpp"), generateAddressHeader(root));
writeFile(fileWithDir("GeneratedModify.hpp"), generateModifyHeader(root)); // pretty much obsolete with a custom compiler
writeFile(fileWithDir("GeneratedWrapper.hpp"), generateWrapperHeader(root)); // pretty much obsolete with a custom compiler
writeFile(fileWithDir("GeneratedType.hpp"), generateTypeHeader(root)); // pretty much obsolete with a custom compiler
writeFile(fileWithDir("GeneratedHeader.hpp"), generateGDHeader(root));
writeFile(fileWithDir("GeneratedSource.cpp"), generateGDSource(root));
}

View file

@ -1,7 +1,7 @@
#include <SharedGen.hpp>
#include "Shared.hpp"
#include <iostream>
namespace format_strings {
namespace { namespace format_strings {
// requires: class_name
char const* modify_start = R"GEN(
template<class Derived>
@ -20,42 +20,41 @@ struct Modify<Derived, {class_name}> : ModifyBase<Modify<Derived, {class_name}>>
}
};
)GEN";
}
}}
int main(int argc, char** argv) {
auto root = CacShare::init(argc, argv);
std::string generateModifyHeader(Root const& root) {
string output;
for (auto& [name, c] : root.classes) {
if (name == "" || name == "cocos2d")
continue;
output += fmt::format(format_strings::modify_start,
output += fmt::format(::format_strings::modify_start,
fmt::arg("class_name", name)
);
for (auto& f : c.functions) {
if (!CacShare::isFunctionDefinable(f) && !CacShare::isFunctionDefined(f))
if (!codegen::isFunctionDefinable(f) && !codegen::isFunctionDefined(f))
continue; // Function not supported for this platform, skip it
string function_name = CacShare::getFunctionName(f);
string function_name = codegen::getFunctionName(f);
switch (f.function_type) {
case kConstructor: function_name = "constructor";
case kDestructor: function_name = "destructor";
default: break;
}
output += fmt::format(format_strings::apply_function,
fmt::arg("index", CacShare::getIndex(f)),
fmt::arg("class_name", CacShare::getClassName(f)),
output += fmt::format(::format_strings::apply_function,
fmt::arg("index", codegen::getIndex(f)),
fmt::arg("class_name", codegen::getClassName(f)),
fmt::arg("function_name", function_name),
fmt::arg("function_convention", CacShare::getConvention(f))
fmt::arg("function_convention", codegen::getConvention(f))
);
}
output += format_strings::modify_end;
output += ::format_strings::modify_end;
}
// fmt::print("{}", output);
CacShare::writeFile(output);
return output;
}

126
codegen/src/Shared.hpp Normal file
View file

@ -0,0 +1,126 @@
#pragma once
#include <broma.hpp>
#include <array>
#include <fmt/format.h>
#include <fmt/ranges.h>
#include <fstream>
using std::istreambuf_iterator;
#ifdef _MSC_VER
#pragma warning(disable: 4996)
#endif
#if _WIN32
#include <direct.h>
#else
#include <unistd.h>
#endif
std::string generateAddressHeader(Root const& root);
std::string generateModifyHeader(Root const& root);
std::string generateWrapperHeader(Root const& root);
std::string generateTypeHeader(Root const& root);
std::string generateGDHeader(Root const& root);
std::string generateGDSource(Root const& root);
std::string generateTidyHeader(Root const& root);
namespace codegen {
inline Platform platform;
inline std::string getBind(Function const& f) {
return f.binds[codegen::platform];
}
inline std::string getIndex(Function const& f) {
return fmt::format("{}", f.global_index);
}
inline std::string getClassName(Function const& f) {
return f.parent_class->name;
}
inline std::string getFunctionName(Function const& f) {
return f.name;
}
inline std::string getConst(Function const& f) {
return f.is_const ? "const" : "";
}
inline std::string getConstWhitespace(Function const& f) {
return f.is_const ? " " : "";
}
inline std::string getParameters(Function const& f) { // int p0, float p1
std::vector<std::string> parameters;
for (size_t i = 0; i < f.args.size(); ++i) {
parameters.push_back(fmt::format("{} {}", f.args[i], f.argnames[i])); // p0, myFloat
}
return fmt::format("{}", fmt::join(parameters, ", "));
}
inline std::string getParameterTypes(Function const& f) { //int, float
return fmt::format("{}", fmt::join(f.args, ", "));
}
inline std::string getArguments(Function const& f) { // p0, p1
return fmt::format("{}", fmt::join(f.argnames, ", "));
}
inline std::string getParameterComma(Function const& f) { // int p0, float p1
return f.args.size() > 0 ? ", " : "";
}
inline std::string getParameterTypeComma(Function const& f) { //int, float
return f.args.size() > 0 ? ", " : "";
}
inline std::string getArgumentComma(Function const& f) { // p0, p1
return f.argnames.size() > 0 ? ", " : "";
}
// defined : we have a symbol that is usable
inline bool isFunctionDefined(Function const& f) {
// basically this is true for
// fmod for all platforms
// cocos for windows
// all funcs without stl parameter for android
// destructors for no platforms
if (f.function_type == kDestructor) return false;
if (f.function_type == kConstructor) return false;
if (f.parent_class->name.rfind("fmod::", 0) == 0) return true;
if (f.parent_class->name.rfind("cocos2d::", 0) == 0 && codegen::platform == kWindows) return true;
if (getParameterTypes(f).find("gd::", 0) != string::npos && codegen::platform == kAndroid) return false;
if (codegen::platform == kAndroid) return true;
return false;
}
// definable : we can define it and hook it
inline bool isFunctionDefinable(Function const& f) {
// basically this is true for
// all funcs that we have the offset for
// all funcs with stl parameter for android
if (getParameterTypes(f).find("gd::", 0) != string::npos && codegen::platform == kAndroid) return true;
if (getBind(f) != "") return true;
return false;
}
inline std::string getConvention(Function const& f) {
if (codegen::platform != kWindows) return "DefaultConv";
switch (f.function_type) {
case kConstructor: [[fallthrough]];
case kDestructor: [[fallthrough]];
case kRegularFunction:
if (isFunctionDefined(f)) return "x86::Thiscall";
return "x86::Membercall";
case kVirtualFunction:
return "x86::Thiscall";
case kStaticFunction:
if (isFunctionDefined(f)) return "x86::Cdecl";
return "x86::Optcall";
}
return "x86::Membercall";
}
}

View file

@ -1,6 +1,6 @@
#include <SharedGen.hpp>
#include "Shared.hpp"
namespace format_strings {
namespace { namespace format_strings {
char const* source_start = R"CAC(
#include <codegen-base/HeaderBase.hpp>
#include <utils/addresser.hpp>
@ -57,71 +57,68 @@ types::ret{index} {class_name}::{function_name}({parameters}){const_whitespace}{
char const* ool_function_definition = R"GEN(
{return} {class_name}::{function_name}({parameters}){const_whitespace}{const} {definition}
)GEN";
}
}}
int main(int argc, char** argv) {
std::string generateGDSource(Root const& root) {
vector<ClassDefinition*> in_order;
string output(format_strings::source_start);
Root root = CacShare::init(argc, argv);
string output(::format_strings::source_start);
for (auto& [name, c] : root.classes) {
for (auto& f : c.functions) {
CacShare::editArguments(f);
for (auto& f : c.functions) {
if (f.is_defined) {
output += fmt::format(format_strings::ool_function_definition,
fmt::arg("function_name", CacShare::getFunctionName(f)),
fmt::arg("const", CacShare::getConst(f)),
fmt::arg("const_whitespace", CacShare::getConstWhitespace(f)),
fmt::arg("class_name", CacShare::getClassName(f)),
fmt::arg("parameters", CacShare::getParameters(f)),
fmt::arg("index", CacShare::getIndex(f)),
output += fmt::format(::format_strings::ool_function_definition,
fmt::arg("function_name", codegen::getFunctionName(f)),
fmt::arg("const", codegen::getConst(f)),
fmt::arg("const_whitespace", codegen::getConstWhitespace(f)),
fmt::arg("class_name", codegen::getClassName(f)),
fmt::arg("parameters", codegen::getParameters(f)),
fmt::arg("index", codegen::getIndex(f)),
fmt::arg("definition", f.definition),
fmt::arg("return", f.return_type)
);
continue;
}
if (f.binds[CacShare::platform].size() == 0) continue; // Function not implemented, skip
if (!codegen::isFunctionDefinable(f)) continue; // Function not implemented, skip
char const* used_declare_format;
switch (f.function_type) {
case kVirtualFunction:
used_declare_format = format_strings::declare_virtual;
used_declare_format = ::format_strings::declare_virtual;
break;
case kRegularFunction:
used_declare_format = format_strings::declare_member;
used_declare_format = ::format_strings::declare_member;
break;
case kStaticFunction:
used_declare_format = format_strings::declare_static;
used_declare_format = ::format_strings::declare_static;
break;
case kDestructor:
used_declare_format = format_strings::declare_destructor;
used_declare_format = ::format_strings::declare_destructor;
break;
case kConstructor:
used_declare_format = format_strings::declare_constructor;
used_declare_format = ::format_strings::declare_constructor;
break;
}
// cout << "dsffdssd" << endl;
output += fmt::format(used_declare_format,
fmt::arg("class_name", CacShare::getClassName(f)),
fmt::arg("const", CacShare::getConst(f)),
fmt::arg("const_whitespace", CacShare::getConstWhitespace(f)),
fmt::arg("convention", CacShare::getConvention(f)),
fmt::arg("function_name", CacShare::getFunctionName(f)),
fmt::arg("index", CacShare::getIndex(f)),
fmt::arg("parameters", CacShare::getParameters(f)),
fmt::arg("parameter_types", CacShare::getParameterTypes(f)),
fmt::arg("arguments", CacShare::getArguments(f)),
fmt::arg("parameter_comma", CacShare::getParameterComma(f)),
fmt::arg("parameter_type_comma", CacShare::getParameterTypeComma(f)),
fmt::arg("argument_comma", CacShare::getArgumentComma(f))
fmt::arg("class_name", codegen::getClassName(f)),
fmt::arg("const", codegen::getConst(f)),
fmt::arg("const_whitespace", codegen::getConstWhitespace(f)),
fmt::arg("convention", codegen::getConvention(f)),
fmt::arg("function_name", codegen::getFunctionName(f)),
fmt::arg("index", codegen::getIndex(f)),
fmt::arg("parameters", codegen::getParameters(f)),
fmt::arg("parameter_types", codegen::getParameterTypes(f)),
fmt::arg("arguments", codegen::getArguments(f)),
fmt::arg("parameter_comma", codegen::getParameterComma(f)),
fmt::arg("parameter_type_comma", codegen::getParameterTypeComma(f)),
fmt::arg("argument_comma", codegen::getArgumentComma(f))
);
}
if (CacShare::platform == kMac || CacShare::platform == kIos) {
if (codegen::platform == kMac || codegen::platform == kIos) {
for (auto& i : c.inlines) {
if (c.name.find("cocos2d") == string::npos) continue; // cocos inlines
output += i.inlined + "\n";
@ -129,5 +126,5 @@ int main(int argc, char** argv) {
}
}
CacShare::writeFile(output);
return output;
}

View file

@ -1,21 +1,21 @@
#include <SharedGen.hpp>
#include "Shared.hpp"
#include <iostream>
#include <set>
using std::set;
namespace format_strings {
namespace { namespace format_strings {
// requires: base_classes, class_name
char const* class_start = "class {class_name}{base_classes} {{\n";
char const* class_start = "class {class_name}{colon}{base_classes} {{\n";
char const* function_address_definition = " = mac {mac_address}, win {win_address}, ios {ios_address}";
char const* address_definition = " = {address}";
// requires: static, virtual, return_type, function_name, raw_parameters, const
char const* function_definition = "\t{static}{virtual}{return_type} {function_name}({raw_params}){const}{address};\n";
char const* function_definition = "\t{static}{virtual}{return_type} {function_name}({parameters}){const_whitespace}{const}{address};\n";
char const* outofline_definition = "\t{static}{virtual}{return_type} {function_name}({raw_params}){const} {definition}\n";
char const* outofline_definition = "\t{static}{virtual}{return_type} {function_name}({parameters}){const_whitespace}{const} {definition}\n";
char const* structor_definition = "\t{function_name}({raw_params}){address};\n";
char const* structor_definition = "\t{function_name}({parameters}){address};\n";
char const* member_address_definition = " = mac {mac_address}, win {win_address}, android {android_address}";
@ -29,11 +29,10 @@ namespace format_strings {
char const* inline_definition = "\tinline{inline}\n";
char const* class_end = "}\n";
}
}}
int main(int argc, char** argv) {
std::string generateTidyHeader(Root const& root) {
string output("");
Root root = CacShare::init(argc, argv);
vector<ClassDefinition> sorted_classes;
for (auto& [name, cd] : root.classes) {
sorted_classes.push_back(cd);
@ -45,15 +44,16 @@ int main(int argc, char** argv) {
});
for (auto& cd : sorted_classes) {
output += fmt::format(format_strings::class_start,
output += fmt::format(::format_strings::class_start,
fmt::arg("class_name", cd.name),
fmt::arg("base_classes", CacShare::formatBases(cd.superclasses))
fmt::arg("colon", cd.superclasses.size() ? " : " : ""),
fmt::arg("base_classes", fmt::join(cd.superclasses, ", "))
);
bool inlinePad = false;
for (auto i : cd.inlines) {
inlinePad = true;
output += fmt::format(format_strings::inline_definition,
output += fmt::format(::format_strings::inline_definition,
fmt::arg("inline", i.inlined)
);
}
@ -63,13 +63,14 @@ int main(int argc, char** argv) {
for (auto f : cd.functions) {
if (!f.is_defined) continue;
outoflinePad = true;
output += fmt::format(format_strings::outofline_definition,
output += fmt::format(::format_strings::outofline_definition,
fmt::arg("virtual", f.function_type == kVirtualFunction ? "virtual " : ""),
fmt::arg("static", f.function_type == kStaticFunction ? "static " : ""),
fmt::arg("return_type", CacShare::getReturn(f)),
fmt::arg("function_name", f.name),
fmt::arg("raw_params", CacShare::formatRawArgs(f.args, f.argnames)),
fmt::arg("const", f.is_const ? " const" : ""),
fmt::arg("return_type", f.return_type),
fmt::arg("function_name", codegen::getFunctionName(f)),
fmt::arg("parameters", codegen::getParameters(f)),
fmt::arg("const", codegen::getConst(f)),
fmt::arg("const_whitespace", codegen::getConstWhitespace(f)),
fmt::arg("definition", f.definition)
);
}
@ -83,24 +84,28 @@ int main(int argc, char** argv) {
switch (f.function_type) {
case kDestructor:
case kConstructor:
used_format = format_strings::structor_definition;
used_format = ::format_strings::structor_definition;
break;
default:
used_format = format_strings::function_definition;
used_format = ::format_strings::function_definition;
break;
}
auto address = fmt::format(format_strings::function_address_definition,
fmt::arg("mac_address", f.binds[kMac].size() ? f.binds[kMac] : "0x0"),
fmt::arg("win_address", f.binds[kWindows].size() ? f.binds[kWindows] : "0x0"),
fmt::arg("ios_address", f.binds[kIos].size() ? f.binds[kIos] : "0x0")
);
string address;
if (f.binds[kMac].size() || f.binds[kWindows].size() || f.binds[kIos].size()) {
vector<string> addresses;
if (f.binds[kMac].size()) addresses.push_back("mac " + f.binds[kMac]);
if (f.binds[kWindows].size()) addresses.push_back("win " + f.binds[kWindows]);
if (f.binds[kIos].size()) addresses.push_back("ios " + f.binds[kIos]);
address = fmt::format(" = {}", fmt::join(addresses, ", "));
}
output += fmt::format(used_format,
fmt::arg("virtual", f.function_type == kVirtualFunction ? "virtual " : ""),
fmt::arg("static", f.function_type == kStaticFunction ? "static " : ""),
fmt::arg("return_type", f.return_type),
fmt::arg("function_name", f.name),
fmt::arg("raw_params", CacShare::formatRawArgs(f.args, f.argnames)),
fmt::arg("const", f.is_const ? " const" : ""),
fmt::arg("function_name", codegen::getFunctionName(f)),
fmt::arg("parameters", codegen::getParameters(f)),
fmt::arg("const", codegen::getConst(f)),
fmt::arg("const_whitespace", codegen::getConstWhitespace(f)),
fmt::arg("address", address)
);
}
@ -112,35 +117,40 @@ int main(int argc, char** argv) {
char const* used_format;
switch (m.member_type) {
case kDefault:
used_format = format_strings::member_definition;
used_format = ::format_strings::member_definition;
break;
case kHardcode:
used_format = format_strings::hardcode_definition;
used_format = ::format_strings::hardcode_definition;
break;
case kPad:
used_format = format_strings::pad_definition;
used_format = ::format_strings::pad_definition;
break;
}
auto address = fmt::format(format_strings::member_address_definition,
fmt::arg("mac_address", m.hardcodes[kMacMember].size() ? m.hardcodes[kMacMember] : "0x0"),
fmt::arg("win_address", m.hardcodes[kWindowsMember].size() ? m.hardcodes[kWindowsMember] : "0x0"),
fmt::arg("android_address", m.hardcodes[kAndroidMember].size() ? m.hardcodes[kAndroidMember] : "0x0")
);
string address;
if (m.hardcodes[kMacMember].size() || m.hardcodes[kWindowsMember].size() || m.hardcodes[kAndroidMember].size()) {
vector<string> addresses;
if (m.hardcodes[kMacMember].size()) addresses.push_back("mac " + m.hardcodes[kMacMember]);
if (m.hardcodes[kWindowsMember].size()) addresses.push_back("win " + m.hardcodes[kWindowsMember]);
if (m.hardcodes[kAndroidMember].size()) addresses.push_back("android " + m.hardcodes[kAndroidMember]);
address = fmt::format(" = {}", fmt::join(addresses, ", "));
}
string array = m.count > 0 ? fmt::format("[{}]", m.count) : "";
output += fmt::format(used_format,
fmt::arg("type", m.type),
fmt::arg("member_name", m.name.substr(m.member_type == kHardcode ? 2 : 0, m.name.size())),
fmt::arg("member_name", m.name),
fmt::arg("address", address),
fmt::arg("array", CacShare::getArray(m.count)) //why is this not tied to member
fmt::arg("array", array) //why is this not tied to member
);
}
if (memberPad) output += "\n";
output = output.substr(0, output.size()-1);
output += format_strings::class_end;
output += ::format_strings::class_end;
output += "\n";
// queued.pop_front();
}
CacShare::writeFile(output);
return output;
}

View file

@ -1,7 +1,7 @@
#include <SharedGen.hpp>
#include "Shared.hpp"
#include <set>
namespace format_strings {
namespace { namespace format_strings {
char const* declare_member_type = R"GEN(
using ret{index} = {return};
@ -27,7 +27,7 @@ using meta{index} = ret{index}({const}{const_whitespace}{class_name}*{parameter_
using member{index} = func{index};
)GEN";
}
}}
using std::set;
@ -55,39 +55,38 @@ static string getReturn(Function const& f) {
else return f.return_type;
}
int main(int argc, char** argv) {
std::string generateTypeHeader(Root const& root) {
string output("");
Root root = CacShare::init(argc, argv);
for (auto& [name, c] : root.classes) {
for (auto& f : c.functions) {
if (!CacShare::isFunctionDefinable(f) && !CacShare::isFunctionDefined(f))
if (!codegen::isFunctionDefinable(f) && !codegen::isFunctionDefined(f))
continue; // Function not supported, skip
char const* used_format;
switch (f.function_type) {
case kVirtualFunction:
case kRegularFunction:
used_format = format_strings::declare_member_type;
used_format = ::format_strings::declare_member_type;
break;
case kStaticFunction:
used_format = format_strings::declare_static_type;
used_format = ::format_strings::declare_static_type;
break;
case kDestructor:
case kConstructor:
used_format = format_strings::declare_structor_type;
used_format = ::format_strings::declare_structor_type;
break;
}
output += fmt::format(used_format,
fmt::arg("parameter_types", CacShare::getParameterTypes(f)),
fmt::arg("parameter_type_comma", CacShare::getParameterTypeComma(f)),
fmt::arg("class_name", CacShare::getClassName(f)),
fmt::arg("const", CacShare::getConst(f)),
fmt::arg("const_whitespace", CacShare::getConstWhitespace(f)),
fmt::arg("index", CacShare::getIndex(f)),
fmt::arg("parameter_types", codegen::getParameterTypes(f)),
fmt::arg("parameter_type_comma", codegen::getParameterTypeComma(f)),
fmt::arg("class_name", codegen::getClassName(f)),
fmt::arg("const", codegen::getConst(f)),
fmt::arg("const_whitespace", codegen::getConstWhitespace(f)),
fmt::arg("index", codegen::getIndex(f)),
fmt::arg("return", getReturn(f))
);
}
}
CacShare::writeFile(output);
}
return output;
}

View file

@ -1,17 +1,16 @@
#include <SharedGen.hpp>
#include "Shared.hpp"
#include <set>
namespace format_strings {
namespace { namespace format_strings {
char const* declare_member_type = R"GEN(
GEODE_WRAPPER_FOR_IDENTIFIER({function_name}) )GEN";
}
}}
using std::set;
int main(int argc, char** argv) {
std::string generateWrapperHeader(Root const& root) {
string output("");
Root root = CacShare::init(argc, argv);
set<string> used;
for (auto& [name, c] : root.classes) {
@ -22,12 +21,12 @@ int main(int argc, char** argv) {
default: break;
}
if (used.find(f.name) != used.end()) continue;
output += fmt::format(format_strings::declare_member_type,
fmt::arg("function_name", CacShare::getFunctionName(f))
output += fmt::format(::format_strings::declare_member_type,
fmt::arg("function_name", codegen::getFunctionName(f))
);
used.insert(f.name);
}
}
CacShare::writeFile(output);
return output;
}

View file

@ -1,10 +1,11 @@
#include "c++stl/gdstdlib.hpp"
#include "utils/include.hpp"
#include "codegen-base/InterfaceBase.hpp"
#include "syntax/Modify.hpp"
#include "syntax/Field.hpp"
#include "syntax/InternalMacros.hpp"
#include "utils/include.hpp"
#include "loader/GeodeLoader.hpp"
#include "loader/Dispatcher.hpp"
#include "loader/API.hpp"
using namespace geode::modifier;

View file

@ -18,7 +18,7 @@ namespace gd {
int m_refcount;
};
class string {
class GEODE_DLL string {
public:
string();
string(char const* ok);
@ -188,7 +188,7 @@ namespace gd {
}
template <typename K, typename V>
class map {
class GEODE_DLL map {
protected:
std::less<K> compare;
_rb_tree_base m_header;
@ -278,7 +278,7 @@ namespace gd {
};
template <typename T>
class vector {
class GEODE_DLL vector {
public:
operator std::vector<T>() {
std::vector<T> out;
@ -433,7 +433,7 @@ namespace gd {
#elif defined(GEODE_IS_IOS)
namespace gd {
class string {
class GEODE_DLL string {
public:
string() {}
string(char const* ok) : m_internal(ok) {}
@ -454,7 +454,7 @@ namespace gd {
};
template <typename T>
class vector {
class GEODE_DLL vector {
public:
operator std::vector<T>() {
return m_internal;
@ -479,7 +479,7 @@ namespace gd {
};
template <typename K, typename V>
class map {
class GEODE_DLL map {
protected:
std::map<K, V> m_internal;
public:
@ -498,4 +498,4 @@ namespace gd {
}
#else
namespace gd = std;
#endif
#endif

View file

@ -150,17 +150,69 @@ public:
virtual void setString(const char *label);
virtual const char* getString(void);
CCTextAlignment getHorizontalAlignment();
void setHorizontalAlignment(CCTextAlignment alignment);
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();
void setVerticalAlignment(CCVerticalTextAlignment verticalAlignment);
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();
void setDimensions(const CCSize &dim);
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();
void setFontSize(float fontSize);
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);

View file

@ -235,8 +235,8 @@ protected:
/** weak reference to the CCSpriteBatchNode that renders the CCSprite */
CC_PROPERTY(CCParticleBatchNode*, m_pBatchNode, BatchNode);
// index of system in batch node array
CC_SYNTHESIZE(unsigned int, m_uAtlasIndex, AtlasIndex);
// RobTop removed this
///CC_SYNTHESIZE(unsigned int, m_uAtlasIndex, AtlasIndex);
//true if scaled or rotated
bool m_bTransformSystemDirty;

View file

@ -115,19 +115,6 @@ namespace geode {
#define GEODE_FRIEND_MODIFY GEODE_ADD(friend struct geode::modify; friend struct geode::modifier::addresses; friend struct geode::modifier::types; friend struct geode::temp_name_find_better;)
#define GEODE_ADD(...) __VA_ARGS__
/**
* For CCDestructor
*/
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
#ifdef GEODE_EXPORTING
#define GEODE_CC_DLL __declspec(dllexport)
#else
#define GEODE_CC_DLL __declspec(dllimport)
#endif
#else
#define GEODE_CC_DLL __attribute__((visibility("default")))
#endif
#ifdef __cplusplus
#define NS_CC_BEGIN namespace cocos2d {
#define NS_CC_END }

View file

@ -31,7 +31,7 @@
#define CC_ZIP_DLL __declspec(dllimport)
#endif
#else
#define CC_ZIP_DLL
#define CC_ZIP_DLL __attribute__((visibility("default")))
#endif
#if (!defined(_WIN32)) && (!defined(WIN32))

View file

@ -13,7 +13,7 @@
#define CC_ZIP_DLL __declspec(dllimport)
#endif
#else
#define CC_ZIP_DLL
#define CC_ZIP_DLL __attribute__((visibility("default")))
#endif
#endif

View file

@ -140,7 +140,7 @@ public:
// properties
//////////////////////////////////////////////////////////////////////////
CC_SYNTHESIZE(CCTextFieldDelegate *, m_pDelegate, Delegate);
CC_SYNTHESIZE_NV(CCTextFieldDelegate *, m_pDelegate, Delegate);
CC_SYNTHESIZE_READONLY(int, m_nCharCount, CharCount);
virtual const ccColor3B& getColorSpaceHolder();
virtual void setColorSpaceHolder(const ccColor3B& color);

View file

@ -36,7 +36,7 @@
NS_CC_EXT_BEGIN
class CCInvocation;
class CC_DLL CCInvocation;
/**
* @addtogroup GUI
@ -85,7 +85,7 @@ typedef unsigned int CCControlState;
*
* To use the CCControl you have to subclass it.
*/
class CCControl : public CCLayerRGBA
class CC_DLL CCControl : public CCLayerRGBA
{
/** The current control state constant. */
RT_REMOVE(

View file

@ -50,7 +50,7 @@ NS_CC_EXT_BEGIN
*/
/** @class CCControlButton Button control for Cocos2D. */
class CCControlButton : public CCControl
class CC_DLL CCControlButton : public CCControl
{
public:
CCControlButton();

View file

@ -48,7 +48,7 @@ NS_CC_EXT_BEGIN
* @{
*/
class CCControlColourPicker : public CCControl
class CC_DLL CCControlColourPicker : public CCControl
{
GEODE_FRIEND_MODIFY

View file

@ -45,7 +45,7 @@ NS_CC_EXT_BEGIN
* @{
*/
class CCControlHuePicker : public CCControl
class CC_DLL CCControlHuePicker : public CCControl
{
//maunally put in the setters
CC_SYNTHESIZE_READONLY(float, m_hue, Hue);

View file

@ -39,7 +39,7 @@ NS_CC_EXT_BEGIN
*/
/** @class CCControlPotentiometer Potentiometer control for Cocos2D. */
class CCControlPotentiometer : public CCControl
class CC_DLL CCControlPotentiometer : public CCControl
{
public:
CCControlPotentiometer();

View file

@ -45,7 +45,7 @@ NS_CC_EXT_BEGIN
* @{
*/
class CCControlSaturationBrightnessPicker : public CCControl
class CC_DLL CCControlSaturationBrightnessPicker : public CCControl
{
/** Contains the receiver¡¯s current saturation value. */
CC_SYNTHESIZE_READONLY(float, m_saturation, Saturation);

View file

@ -42,7 +42,7 @@ NS_CC_EXT_BEGIN
* @{
*/
class CCControlSlider: public CCControl
class CC_DLL CCControlSlider: public CCControl
{
//maunally put in the setters
/** Contains the receiver¡¯s current value. */

View file

@ -46,7 +46,7 @@ typedef enum
kCCControlStepperPartNone,
} CCControlStepperPart;
class CCControlStepper : public CCControl
class CC_DLL CCControlStepper : public CCControl
{
public:
CCControlStepper();

View file

@ -36,7 +36,7 @@ namespace cocos2d { class CCLabelTTF; }
NS_CC_EXT_BEGIN
class CCControlSwitchSprite;
class CC_DLL CCControlSwitchSprite;
/**
* @addtogroup GUI
@ -46,7 +46,7 @@ class CCControlSwitchSprite;
*/
/** @class CCControlSwitch Switch control for Cocos2D. */
class CCControlSwitch : public CCControl
class CC_DLL CCControlSwitch : public CCControl
{
public:
CCControlSwitch();

View file

@ -65,14 +65,14 @@ typedef struct
* @js NA
* @lua NA
**/
class CCColor3bObject : public CCObject
class CC_DLL CCColor3bObject : public CCObject
{
public:
ccColor3B value;
CCColor3bObject(ccColor3B s_value):value(s_value){}
};
class CCControlUtils
class CC_DLL CCControlUtils
{
public:
static CCSprite* addSpriteToTargetWithPosAndAnchor(const char* spriteName, CCNode * target, CCPoint pos, CCPoint anchor);

View file

@ -52,7 +52,7 @@ typedef void (CCObject::*SEL_CCControlHandler)(CCObject*, CCControlEvent);
* @js NA
* @lua NA
*/
class CCInvocation : public CCObject
class CC_DLL CCInvocation : public CCObject
{
CC_SYNTHESIZE_READONLY(SEL_CCControlHandler, m_action, Action);
CC_SYNTHESIZE_READONLY(CCObject*, m_target, Target);

View file

@ -50,7 +50,7 @@ NS_CC_EXT_BEGIN
*
* @see http://yannickloriot.com/library/ios/cccontrolextension/Classes/CCScale9Sprite.html
*/
class CCScale9Sprite : public CCNodeRGBA
class CC_DLL CCScale9Sprite : public CCNodeRGBA
{
public:
CCScale9Sprite();

View file

@ -124,14 +124,14 @@ enum EditBoxInputFlag
};
class CCEditBox;
class CCEditBoxImpl;
class CC_DLL CCEditBox;
class CC_DLL CCEditBoxImpl;
/**
* @js NA
* @lua NA
*/
class CCEditBoxDelegate
class CC_DLL CCEditBoxDelegate
{
public:
virtual ~CCEditBoxDelegate() {};
@ -171,7 +171,7 @@ public:
*
*/
class CCEditBox
class CC_DLL CCEditBox
: public CCControlButton
, public CCIMEDelegate
{

View file

@ -33,7 +33,7 @@
NS_CC_EXT_BEGIN
class CCEditBoxImpl
class CC_DLL CCEditBoxImpl
{
public:
CCEditBoxImpl(CCEditBox* pEditBox) : m_pDelegate(NULL),m_pEditBox(pEditBox) {}

View file

@ -35,9 +35,9 @@
NS_CC_EXT_BEGIN
class CCEditBox;
class CC_DLL CCEditBox;
class CCEditBoxImplAndroid : public CCEditBoxImpl
class CC_DLL CCEditBoxImplAndroid : public CCEditBoxImpl
{
public:
CCEditBoxImplAndroid(CCEditBox* pEditText);

View file

@ -66,12 +66,12 @@
NS_CC_EXT_BEGIN
class CCEditBox;
class CC_DLL CCEditBox;
/**
* @js NA
* @lua NA
*/
class CCEditBoxImplIOS : public CCEditBoxImpl
class CC_DLL CCEditBoxImplIOS : public CCEditBoxImpl
{
public:
CCEditBoxImplIOS(CCEditBox* pEditText);

View file

@ -65,12 +65,12 @@
NS_CC_EXT_BEGIN
class CCEditBox;
class CC_DLL CCEditBox;
/**
* @js NA
* @lua NA
*/
class CCEditBoxImplMac : public CCEditBoxImpl
class CC_DLL CCEditBoxImplMac : public CCEditBoxImpl
{
public:
CCEditBoxImplMac(CCEditBox* pEditText);

View file

@ -36,12 +36,12 @@
NS_CC_EXT_BEGIN
class CCEditBox;
class CC_DLL CCEditBox;
/**
* @js NA
* @lua NA
*/
class CCEditBoxImplTizen : public CCEditBoxImpl
class CC_DLL CCEditBoxImplTizen : public CCEditBoxImpl
{
public:
CCEditBoxImplTizen(CCEditBox* pEditText);

View file

@ -35,12 +35,12 @@
NS_CC_EXT_BEGIN
class CCEditBox;
class CC_DLL CCEditBox;
/**
* @js NA
* @lua NA
*/
class CCEditBoxImplWin : public CCEditBoxImpl
class CC_DLL CCEditBoxImplWin : public CCEditBoxImpl
{
public:
CCEditBoxImplWin(CCEditBox* pEditText);

View file

@ -29,9 +29,9 @@ THE SOFTWARE.
NS_CC_EXT_BEGIN
class CCEditBox;
class CC_DLL CCEditBox;
class CCEditBoxImplWp8 : public CCEditBoxImpl
class CC_DLL CCEditBoxImplWp8 : public CCEditBoxImpl
{
public:
CCEditBoxImplWp8(CCEditBox* pEditText);

View file

@ -43,12 +43,12 @@ typedef enum {
kCCScrollViewDirectionBoth
} CCScrollViewDirection;
class CCScrollView;
class CC_DLL CCScrollView;
/**
* @js NA
* @lua NA
*/
class CCScrollViewDelegate
class CC_DLL CCScrollViewDelegate
{
public:
virtual ~CCScrollViewDelegate() {}
@ -62,7 +62,7 @@ public:
* It provides scroll view functionalities to cocos2d projects natively.
* @lua NA
*/
class CCScrollView : public CCLayer
class CC_DLL CCScrollView : public CCLayer
{
public:
/**

View file

@ -34,7 +34,7 @@ NS_CC_EXT_BEGIN
* @js NA
* @lua NA
*/
class CCSortableObject
class CC_DLL CCSortableObject
{
public:
virtual ~CCSortableObject() {}
@ -45,7 +45,7 @@ public:
* @js NA
* @lua NA
*/
class CCArrayForObjectSorting : public CCArray
class CC_DLL CCArrayForObjectSorting : public CCArray
{
public:
CCArrayForObjectSorting() : CCArray() {}

View file

@ -34,8 +34,8 @@
NS_CC_EXT_BEGIN
class CCTableView;
class CCArrayForObjectSorting;
class CC_DLL CCTableView;
class CC_DLL CCArrayForObjectSorting;
typedef enum {
kCCTableViewFillTopDown,
@ -47,7 +47,7 @@ typedef enum {
* @js NA
* @lua NA
*/
class CCTableViewDelegate : public CCScrollViewDelegate
class CC_DLL CCTableViewDelegate : public CCScrollViewDelegate
{
public:
/**
@ -91,7 +91,7 @@ public:
* Data source that governs table backend data.
* @lua NA
*/
class CCTableViewDataSource
class CC_DLL CCTableViewDataSource
{
public:
virtual ~CCTableViewDataSource() {}
@ -137,7 +137,7 @@ public:
* this is a very basic, minimal implementation to bring UITableView-like component into cocos2d world.
* @lua NA
*/
class CCTableView : public CCScrollView, public CCScrollViewDelegate
class CC_DLL CCTableView : public CCScrollView, public CCScrollViewDelegate
{
public:
/**

View file

@ -35,7 +35,7 @@ NS_CC_EXT_BEGIN
* Abstract class for SWTableView cell node
* @lua NA
*/
class CCTableViewCell: public CCNode, public CCSortableObject
class CC_DLL CCTableViewCell: public CCNode, public CCSortableObject
{
public:
CCTableViewCell() {}

View file

@ -45,7 +45,7 @@ NS_CC_EXT_BEGIN
* @js NA
* @lua NA
*/
class CCHttpClient : public CCObject
class CC_DLL CCHttpClient : public CCObject
{
public:
/** Return the shared instance **/

View file

@ -30,8 +30,8 @@
NS_CC_EXT_BEGIN
class CCHttpClient;
class CCHttpResponse;
class CC_DLL CCHttpClient;
class CC_DLL CCHttpResponse;
typedef void (CCObject::*SEL_HttpResponse)(CCHttpClient* client, CCHttpResponse* response);
#define httpresponse_selector(_SELECTOR) (cocos2d::extension::SEL_HttpResponse)(&_SELECTOR)
@ -43,7 +43,7 @@ typedef void (CCObject::*SEL_HttpResponse)(CCHttpClient* client, CCHttpResponse*
@lua NA
*/
class CCHttpRequest : public CCObject
class CC_DLL CCHttpRequest : public CCObject
{
public:
/** Use this enum type as param in setReqeustType(param) */

View file

@ -38,7 +38,7 @@ NS_CC_EXT_BEGIN
@js NA
@lua NA
*/
class CCHttpResponse : public CCObject
class CC_DLL CCHttpResponse : public CCObject
{
public:
/** Constructor, it's used by CCHttpClient internal, users don't need to create HttpResponse manually

View file

@ -44,7 +44,7 @@ NS_CC_EXT_BEGIN
@lua NA
*/
class CCPhysicsDebugNode : public CCDrawNode
class CC_DLL CCPhysicsDebugNode : public CCDrawNode
{
protected:
cpSpace *m_pSpacePtr;

View file

@ -48,7 +48,7 @@ NS_CC_EXT_BEGIN
* @js NA
* @lua NA
*/
class CCPhysicsSprite : public CCSprite
class CC_DLL CCPhysicsSprite : public CCSprite
{
protected:
bool m_bIgnoreBodyRotation;

View file

@ -34,7 +34,7 @@ namespace cocos2d { namespace extension {
/**
Draws a skeleton.
*/
class CCSkeleton: public cocos2d::CCNodeRGBA, public cocos2d::CCBlendProtocol {
class CC_DLL CCSkeleton: public cocos2d::CCNodeRGBA, public cocos2d::CCBlendProtocol {
public:
Skeleton* skeleton;
Bone* rootBone;

View file

@ -35,7 +35,7 @@ namespace cocos2d { namespace extension {
/**
Draws an animated skeleton, providing a simple API for applying one or more animations and queuing animations to be played later.
*/
class CCSkeletonAnimation: public CCSkeleton {
class CC_DLL CCSkeletonAnimation: public CCSkeleton {
public:
gd::vector<AnimationState*> states;

View file

@ -1,6 +1,6 @@
#pragma once
#include "platform/platform.hpp"
#include "../platform/platform.hpp"
// Because C++ doesn't like using a
// namespace that doesn't exist
@ -76,3 +76,83 @@ _61,_62,_63,N,...) N
19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
9, 8, 7, 6, 5, 4, 3, 2, 1, 0
#define GEODE_NEST1(macro, begin) \
macro(GEODE_CONCAT(begin, 0)), \
macro(GEODE_CONCAT(begin, 1)), \
macro(GEODE_CONCAT(begin, 2)), \
macro(GEODE_CONCAT(begin, 3)), \
macro(GEODE_CONCAT(begin, 4)), \
macro(GEODE_CONCAT(begin, 5)), \
macro(GEODE_CONCAT(begin, 6)), \
macro(GEODE_CONCAT(begin, 7)), \
macro(GEODE_CONCAT(begin, 8)), \
macro(GEODE_CONCAT(begin, 9)), \
macro(GEODE_CONCAT(begin, a)), \
macro(GEODE_CONCAT(begin, b)), \
macro(GEODE_CONCAT(begin, c)), \
macro(GEODE_CONCAT(begin, d)), \
macro(GEODE_CONCAT(begin, e)), \
macro(GEODE_CONCAT(begin, f))
#define GEODE_NEST2(macro, begin) \
GEODE_NEST1(macro, GEODE_CONCAT(begin, 0)), \
GEODE_NEST1(macro, GEODE_CONCAT(begin, 1)), \
GEODE_NEST1(macro, GEODE_CONCAT(begin, 2)), \
GEODE_NEST1(macro, GEODE_CONCAT(begin, 3)), \
GEODE_NEST1(macro, GEODE_CONCAT(begin, 4)), \
GEODE_NEST1(macro, GEODE_CONCAT(begin, 5)), \
GEODE_NEST1(macro, GEODE_CONCAT(begin, 6)), \
GEODE_NEST1(macro, GEODE_CONCAT(begin, 7)), \
GEODE_NEST1(macro, GEODE_CONCAT(begin, 8)), \
GEODE_NEST1(macro, GEODE_CONCAT(begin, 9)), \
GEODE_NEST1(macro, GEODE_CONCAT(begin, a)), \
GEODE_NEST1(macro, GEODE_CONCAT(begin, b)), \
GEODE_NEST1(macro, GEODE_CONCAT(begin, c)), \
GEODE_NEST1(macro, GEODE_CONCAT(begin, d)), \
GEODE_NEST1(macro, GEODE_CONCAT(begin, e)), \
GEODE_NEST1(macro, GEODE_CONCAT(begin, f))
#define GEODE_NEST3(macro, begin) \
GEODE_NEST2(macro, GEODE_CONCAT(begin, 0)), \
GEODE_NEST2(macro, GEODE_CONCAT(begin, 1)), \
GEODE_NEST2(macro, GEODE_CONCAT(begin, 2)), \
GEODE_NEST2(macro, GEODE_CONCAT(begin, 3)), \
GEODE_NEST2(macro, GEODE_CONCAT(begin, 4)), \
GEODE_NEST2(macro, GEODE_CONCAT(begin, 5)), \
GEODE_NEST2(macro, GEODE_CONCAT(begin, 6)), \
GEODE_NEST2(macro, GEODE_CONCAT(begin, 7)), \
GEODE_NEST2(macro, GEODE_CONCAT(begin, 8)), \
GEODE_NEST2(macro, GEODE_CONCAT(begin, 9)), \
GEODE_NEST2(macro, GEODE_CONCAT(begin, a)), \
GEODE_NEST2(macro, GEODE_CONCAT(begin, b)), \
GEODE_NEST2(macro, GEODE_CONCAT(begin, c)), \
GEODE_NEST2(macro, GEODE_CONCAT(begin, d)), \
GEODE_NEST2(macro, GEODE_CONCAT(begin, e)), \
GEODE_NEST2(macro, GEODE_CONCAT(begin, f))
#define GEODE_NEST4(macro, begin) \
GEODE_NEST3(macro, GEODE_CONCAT(begin, 0)), \
GEODE_NEST3(macro, GEODE_CONCAT(begin, 1)), \
GEODE_NEST3(macro, GEODE_CONCAT(begin, 2)), \
GEODE_NEST3(macro, GEODE_CONCAT(begin, 3)), \
GEODE_NEST3(macro, GEODE_CONCAT(begin, 4)), \
GEODE_NEST3(macro, GEODE_CONCAT(begin, 5)), \
GEODE_NEST3(macro, GEODE_CONCAT(begin, 6)), \
GEODE_NEST3(macro, GEODE_CONCAT(begin, 7)), \
GEODE_NEST3(macro, GEODE_CONCAT(begin, 8)), \
GEODE_NEST3(macro, GEODE_CONCAT(begin, 9)), \
GEODE_NEST3(macro, GEODE_CONCAT(begin, a)), \
GEODE_NEST3(macro, GEODE_CONCAT(begin, b)), \
GEODE_NEST3(macro, GEODE_CONCAT(begin, c)), \
GEODE_NEST3(macro, GEODE_CONCAT(begin, d)), \
GEODE_NEST3(macro, GEODE_CONCAT(begin, e)), \
GEODE_NEST3(macro, GEODE_CONCAT(begin, f))
#define GEODE_ENUM_OFFSETS_DEFINE(hex) GEODE_CONCAT($, hex)
#define GEODE_ENUM_OFFSETS_SET() GEODE_NEST4(GEODE_ENUM_OFFSETS_DEFINE, 0x)
enum class PrinterOffsets {
GEODE_ENUM_OFFSETS_SET()
};

View file

@ -0,0 +1,92 @@
#pragma once
#include "../codegen-base/Macros.hpp"
#include "Mod.hpp"
#include <functional>
#include <string>
#include <vector>
namespace geode {
class Dispatcher;
struct dispatch_handle {
void* handle;
dispatch_handle() = delete;
dispatch_handle(dispatch_handle const& d) : handle(d.handle) {}
template <typename T>
std::function<T> into() {
return *reinterpret_cast<std::function<T>*>(this->handle);
}
template <typename R, typename ...Args>
R call(Args... args) {
return this->into<std::function<R(Args...)>>()(args...);
}
bool operator<(dispatch_handle const& b) const {
return handle < b.handle;
}
bool operator==(dispatch_handle const& b) const {
return handle == b.handle;
}
private:
dispatch_handle(void* h) : handle(h) {}
template <typename T>
static dispatch_handle from(std::function<T> f) {
return dispatch_handle(reinterpret_cast<void*>(new std::function<T>(f)));
}
friend class Dispatcher;
};
class GEODE_DLL Dispatcher {
protected:
std::map<dispatch_handle, std::pair<std::string, Mod*>> m_dispatchMap;
std::map<std::string, std::vector<dispatch_handle>> m_selectorMap;
// 2 maps for lookup speed
std::vector<dispatch_handle> getFunctions_(std::string const& a);
void addFunction_(Mod* m, std::string const& a, dispatch_handle u);
std::vector<dispatch_handle> allFunctions_();
Dispatcher() {}
public:
static Dispatcher* get();
template <typename T>
std::vector<std::function<T>> getFunctions(std::string const& a) {
return geode::vector_utils::map(getFunctions_(a), [this](dispatch_handle fn) {
return fn.into<T>();
});
}
template <typename T>
std::function<T> getFunction(std::string const& a) {
return getFunctions_(a).back().into<T>();
}
template <typename T>
dispatch_handle addFunction(std::string const& a, std::function<T> f) {
dispatch_handle hdl = dispatch_handle::from(f);
addFunction_(Mod::get(), a, hdl);
return hdl;
}
template <typename T>
std::vector<dispatch_handle> allFunctions() {
return geode::vector_utils::map(allFunctions_(), [this](dispatch_handle fn) {
return fn.into<T>();
});
}
void removeFunction(dispatch_handle u);
std::pair<std::string, Mod*> getFunctionInfo(dispatch_handle u);
};
}

View file

@ -1,148 +0,0 @@
#pragma once
#include <string>
#include <typeinfo>
#include <memory>
#include <exception>
#include <map>
#include <Macros.hpp>
#include <any>
#include <variant>
#ifndef GEODE_DLL
#define GEODE_DLL
#endif
namespace geode {
class EventCenter;
class Mod;
template <typename T = std::monostate>
struct EventInfo {
std::string selector;
inline EventInfo(std::string sel) : selector(sel) {}
inline EventInfo() {}
};
template <typename T = std::monostate>
struct ConstEventInfo {
char const* selector;
inline constexpr ConstEventInfo(char const* sel) : selector(sel) {}
inline constexpr ConstEventInfo() {}
inline operator EventInfo<T>() {
return EventInfo<T>(selector);
}
};
template <typename T = std::monostate>
class Event {
protected:
EventInfo<T> m_info;
T m_object;
Mod* m_sender;
public:
inline T const& object() const {
return m_object;
}
inline std::string const& selector() const { return m_info.selector; }
inline Mod* sender() const { return m_sender; }
inline Event(EventInfo<T> inf, T obj, Mod* sender) :
m_info(inf),
m_object(obj),
m_sender(sender) {}
inline Event(std::string sel, T obj, Mod* sender) : Event(EventInfo<T>(sel), obj, sender) {}
inline Event(std::string sel, Mod* sender) : Event(sel, T(), sender) {}
inline Event(EventInfo<T> inf, Mod* sender) : Event(inf, T(), sender) {}
// Event(std::string sel) : Event(sel, Interface::get()->mod()) {}
inline Event(Event&& a) : m_info(a.m_info), m_sender(a.m_sender), m_object(std::move(a.m_object)) {}
inline operator T() { return m_object; }
friend class EventCenter;
};
template <typename T = std::monostate>
struct Observer {
EventInfo<T> m_info;
Mod* m_mod;
std::function<void(Event<T> const&)> m_callback;
template <typename U = std::monostate>
inline Observer<U>* into() {
return reinterpret_cast<Observer<U>*>(this);
}
};
class GEODE_DLL EventCenter {
public:
std::map<Mod*, std::map<std::string, std::vector<Observer<std::monostate>*>>> m_observers;
static EventCenter* shared;
public:
EventCenter();
static EventCenter* get();
template <typename T>
void send(Event<T> n, Mod* m) {
for (auto& obs : m_observers[m][n.selector()]) {
obs->template into<T>()->m_callback(n);
}
}
template <typename T>
void broadcast(Event<T> n) {
for (auto& [k, v] : m_observers) {
for (auto& obs : v[n.selector()]) {
obs->template into<T>()->m_callback(n);
}
}
}
template <typename T = std::monostate>
Observer<std::monostate>* registerObserver(Mod* m, EventInfo<T> info, std::function<void(Event<T> const&)> cb) {
Observer<T>* ob = new Observer<T>;
ob->m_info = info;
ob->m_callback = cb;
ob->m_mod = m;
m_observers[m][info.selector].push_back(ob->into());
return ob->into();
}
template <typename T = std::monostate>
Observer<std::monostate>* registerObserver(Mod* m, std::string sel, std::function<void(Event<T> const&)> cb) {
return registerObserver(m, EventInfo<T>(sel), cb);
}
template <typename T = std::monostate>
inline Observer<std::monostate>* registerObserver(std::string sel, std::function<void(Event<T> const&)> cb);
template <typename T = std::monostate>
inline Observer<std::monostate>* registerObserver(EventInfo<T> info, std::function<void(Event<T> const&)> cb);
void unregisterObserver(Observer<std::monostate>* ob);
std::vector<Observer<std::monostate>*> getObservers(std::string selector, Mod* m);
};
}
#define _$observe3(sel, T, data, ctr) \
void $_observer##ctr(geode::Event<T> const&); \
static auto $_throw##ctr = (([](){ \
geode::Interface::get()->scheduleOnLoad(+[](Mod* m) { \
geode::EventCenter::get()->registerObserver<T>( \
m, sel, $_observer##ctr \
); \
}); \
})(), 0); \
void $_observer##ctr(geode::Event<T> const& data)
#define _$observe1(sel, ctr) _$observe3(sel, std::monostate, , ctr)
#define $observe(...) GEODE_INVOKE(GEODE_CONCAT(_$observe, GEODE_NUMBER_OF_ARGS(__VA_ARGS__)), __VA_ARGS__, __COUNTER__)

View file

@ -59,15 +59,9 @@ namespace geode {
using loadfn_t = void(*)(Mod*);
struct ScheduledExport {
std::string m_selector;
std::variant<unknownmemfn_t, unknownfn_t> m_func;
};
Mod* m_mod = nullptr;
std::vector<ScheduledHook> m_scheduledHooks;
std::vector<ScheduledLog> m_scheduledLogs;
std::vector<ScheduledExport> m_scheduledExports;
std::vector<loadfn_t> m_scheduledFunctions;
public:
@ -115,6 +109,9 @@ namespace geode {
*/
template<auto Detour, template <class, class...> class Convention>
Result<Hook*> addHook(std::string const& displayName, void* address) {
if (this->m_mod) {
return this->m_mod->addHook<Detour, Convention>(displayName, address);
}
this->m_scheduledHooks.push_back({ displayName, address, &Mod::addHook<Detour, Convention> });
return Ok<Hook*>(nullptr);
}
@ -132,19 +129,19 @@ namespace geode {
GEODE_DLL void scheduleOnLoad(loadfn_t fn);
protected:
GEODE_DLL void exportAPIFunctionInternal(std::string const& selector, unknownmemfn_t fn);
GEODE_DLL void exportAPIFunctionInternal(std::string const& selector, unknownfn_t fn);
// GEODE_DLL void exportAPIFunctionInternal(std::string const& selector, unknownmemfn_t fn);
// GEODE_DLL void exportAPIFunctionInternal(std::string const& selector, unknownfn_t fn);
public:
template <typename T>
inline void exportAPIFunction(std::string const& selector, T ptr) {
if constexpr (std::is_member_function_pointer_v<decltype(ptr)>) {
exportAPIFunctionInternal(selector, cast::reference_cast<unknownmemfn_t>(ptr));
}
else {
exportAPIFunctionInternal(selector, reinterpret_cast<unknownfn_t>(ptr));
}
}
// template <typename T>
// inline void exportAPIFunction(std::string const& selector, T ptr) {
// if constexpr (std::is_member_function_pointer_v<decltype(ptr)>) {
// exportAPIFunctionInternal(selector, cast::reference_cast<unknownmemfn_t>(ptr));
// }
// else {
// exportAPIFunctionInternal(selector, reinterpret_cast<unknownfn_t>(ptr));
// }
// }
friend Mod* Mod::get<void>();
};
@ -157,17 +154,6 @@ namespace geode {
inline Log Log::get() {
return Mod::get()->log();
}
template <typename T>
inline Observer<std::monostate>* EventCenter::registerObserver(std::string sel, std::function<void(Event<T> const&)> cb) {
return registerObserver(Mod::get(), EventInfo<T>(sel), cb);
}
template <typename T>
inline Observer<std::monostate>* EventCenter::registerObserver(EventInfo<T> info, std::function<void(Event<T> const&)> cb) {
return registerObserver(Mod::get(), info, cb);
}
}
inline const char* operator"" _spr(const char* str, size_t) {

View file

@ -3,7 +3,6 @@
#include <Macros.hpp>
#include "Types.hpp"
#include "Hook.hpp"
#include "Event.hpp"
#include "../utils/types.hpp"
#include "../utils/Result.hpp"
#include "../utils/VersionInfo.hpp"
@ -161,10 +160,11 @@ namespace geode {
DataStore(Mod* m, nlohmann::json& j) : m_mod(m), m_store(j) {}
friend class Mod;
public:
public:
~DataStore();
nlohmann::json& operator[](std::string const&);
DataStore& operator=(nlohmann::json&);
bool contains(std::string const&);
operator nlohmann::json();
};
@ -335,37 +335,6 @@ namespace geode {
Severity severity
);
/**
* Exports an internal function. You can use this
* for mod interoperability.
* @param selector mod-specific string identifier
* for your function
* @param ptr pointer to your exported function
*/
template <typename T>
void exportAPIFunction(std::string const& selector, T ptr) {
EventCenter::get()->registerObserver<T*>(this, selector, [ptr](Event<T*> const& n) {
//*reinterpret_cast<T*>(n.object<void*>()) = ptr;
*n.object() = ptr;
});
}
/**
* Imports an internal function. You can use this
* for mod interoperability.
* @param selector Mod-specific string identifier
* for your function
* @param source Mod that the API function originates
* from
* @returns Pointer to the external function
*/
template <typename T>
T importAPIFunction(std::string const& selector, Mod* source) {
T out;
EventCenter::get()->send(Event(selector, &out, nullptr), source);
return out;
}
/**
* Get all hooks owned by this Mod
* @returns Vector of hooks

View file

@ -79,9 +79,13 @@ namespace std {
#endif
#ifdef GEODE_EXPORTING_CODEGEN
#define GEODE_CODEGEN_DLL __declspec(dllexport)
#define GEODE_CODEGEN_DLL __declspec(dllexport)
#else
#define GEODE_CODEGEN_DLL __declspec(dllimport)
#ifndef GEODE_BUILDING_CODEGEN
#define GEODE_CODEGEN_DLL __declspec(dllimport)
#else
#define GEODE_CODEGEN_DLL
#endif
#endif
#define GEODE_API extern "C" __declspec(dllexport)
@ -153,7 +157,7 @@ namespace std {
#ifdef GEODE_EXPORTING_CODEGEN
#define GEODE_CODEGEN_DLL __attribute__((visibility("default")))
#else
#define GEODE_CODEGEN_DLL
#define GEODE_CODEGEN_DLL
#endif
#define GEODE_API extern "C" __attribute__((visibility("default")))

View file

@ -1,5 +1,11 @@
#pragma once
#include "Traits.hpp"
#include "../platform/platform.hpp"
#ifdef GEODE_IS_WINDOWS
// for the manual virtualprotect
#include <memoryapi.h>
#endif
namespace geode::modifier {
template<typename T = void*>
@ -77,20 +83,25 @@ namespace geode::modifier {
return ret;
}
using DestructorType = void(GEODE_WINDOWS(__thiscall)*)(void* GEODE_WINDOWS(, bool));
template <typename T>
GEODE_NOINLINE inline auto& getOriginalDestructor() {
static void(*ret)(void*);
static DestructorType ret;
return ret;
}
template <typename T>
GEODE_NOINLINE inline void fieldCleanup(T* self) {{
for (auto& [mem, cont] : getAdditionalContainers<T>()[self]) {
delete cont;
}
getAdditionalContainers<T>().erase(self);
getOriginalDestructor<T>()(self);
}}
// this is beautiful
struct FieldCleanupHook {
template <typename T>
static GEODE_NOINLINE inline void GEODE_WINDOWS(__thiscall) fieldCleanup(T* self GEODE_WINDOWS(, bool arg)) {{
for (auto& [mem, cont] : getAdditionalContainers<T>()[self]) {
delete cont;
}
getAdditionalContainers<T>().erase(self);
getOriginalDestructor<T>()(self GEODE_WINDOWS(, arg));
}}
};
template <typename T, typename A>
GEODE_NOINLINE T& operator->*(A* self, field<T>& member) {
@ -102,10 +113,16 @@ namespace geode::modifier {
// on first use
if (destructor == nullptr) {
// takes the third element because all cocos classes have the destructor at third.
auto& vtableDestructor = 2[*(uintptr_t**)self]; // i love this
destructor = reinterpret_cast<void(*)(void*)>(vtableDestructor);
vtableDestructor = (uintptr_t)&fieldCleanup<A>;
// classes inheriting CCObject always have their destructor(s) as the 2nd (and 3rd on itanium) element in the vtable
// choose 3rd elemnt (the second destructor) on itanium platforms because the first one gets inlined often
static constexpr size_t index = GEODE_WINDOWS(1) GEODE_MACOS(2) GEODE_IOS(2) GEODE_ANDROID(2);
auto& vtableDestructor = index[*reinterpret_cast<uintptr_t**>(self)]; // i love this
destructor = reinterpret_cast<DestructorType>(vtableDestructor);
#ifdef GEODE_IS_WINDOWS
DWORD old;
VirtualProtect(reinterpret_cast<void*>(&vtableDestructor), sizeof(void*), PAGE_EXECUTE_READWRITE, &old);
#endif
vtableDestructor = reinterpret_cast<uintptr_t>(&FieldCleanupHook::fieldCleanup<A>);
}
if (containers[self].size() == 0) {
void* obj = new A();

View file

@ -57,7 +57,7 @@ template <> struct GEODE_HIDDEN _##derived<derived##ID> \
#define $modify(...) GEODE_INVOKE(GEODE_CONCAT(GEODE_CRTP, GEODE_NUMBER_OF_ARGS(__VA_ARGS__)), __VA_ARGS__)
#define $(...) $modify(__VA_ARGS__)
#define GEODE_ONLY_FIELD(type, field) private: field<type> field; public:
#define GEODE_ONLY_FIELD(type, field_, default_) private: field<type> field_ = default_; public:
#define GEODE_INTERNAL_FIELD(type, field, name) inline type& name() { return this->*field; }
#define GEODE_EXTERNAL_FIELD(type, field, name) static inline type& name##From(void* self) { return reinterpret_cast<decltype(this)>(self)->*field; }
#define GEODE_FIELD(type, field, name) GEODE_ONLY_FIELD(type, field) GEODE_INTERNAL_FIELD(type, field, name) GEODE_EXTERNAL_FIELD(type, field, name)
//#define GEODE_EXTERNAL_FIELD(type, field, name) static inline type& name##From(void* self) { return reinterpret_cast<decltype(this)>(self)->*field; }
#define GEODE_FIELD(type, field, name, default_) GEODE_ONLY_FIELD(type, field, default_) GEODE_INTERNAL_FIELD(type, field, name) //GEODE_EXTERNAL_FIELD(type, field, name)

View file

@ -2,6 +2,7 @@
#include <Macros.hpp>
#include <string_view>
#include "types.hpp"
namespace geode {
/**
@ -142,7 +143,7 @@ namespace geode {
template <class E = std::string>
struct Err {
const E _value;
Err(const E value) : _value(value) {}
Err(const TypeIdentityType<E> value) : _value(value) {}
template <class T>
operator Result<T, E>() const {
return Result<T, E>::err(_value);

View file

@ -81,4 +81,164 @@ namespace geode::cocos {
* }
*/
GEODE_DLL bool fileExistsInSearchPaths(const char* filename);
template <typename T>
struct GEODE_DLL CCArrayIterator {
public:
CCArrayIterator(T* p) : m_ptr(p) {}
T* m_ptr;
T& operator*() { return *m_ptr; }
T* operator->() { return m_ptr; }
auto& operator++() {
++m_ptr;
return *this;
}
friend bool operator== (const CCArrayIterator<T>& a, const CCArrayIterator<T>& b) { return a.m_ptr == b.m_ptr; };
friend bool operator!= (const CCArrayIterator<T>& a, const CCArrayIterator<T>& b) { return a.m_ptr != b.m_ptr; };
};
template <typename T>
class CCArrayExt {
protected:
cocos2d::CCArray* m_arr;
public:
CCArrayExt() : m_arr(cocos2d::CCArray::create()) {
m_arr->retain();
}
CCArrayExt(cocos2d::CCArray* arr) : m_arr(arr) {
m_arr->retain();
}
CCArrayExt(CCArrayExt const& a) : m_arr(a.m_arr) {
m_arr->retain();
}
CCArrayExt(CCArrayExt&& a) : m_arr(a.m_arr) {
a.m_arr = nullptr;
}
~CCArrayExt() {
if (m_arr)
m_arr->release();
}
auto begin() {
return CCArrayIterator<T*>(reinterpret_cast<T*>(m_arr->data->arr));
}
auto end() {
return CCArrayIterator<T*>(reinterpret_cast<T*>(m_arr->data->arr) + m_arr->count());
}
auto size() const {
return m_arr->count();
}
T operator[](size_t index) {
return reinterpret_cast<T>(m_arr->objectAtIndex(index));
}
void push_back(T item) {
m_arr->addObject(item);
}
T pop_back() {
T ret = m_arr->lastObject();
m_arr->removeLastObject();
return ret;
}
cocos2d::CCArray* inner() {
return m_arr;
}
};
template <typename K, typename T>
struct CCDictIterator {
public:
CCDictIterator(cocos2d::CCDictElement* p) : m_ptr(p) {}
cocos2d::CCDictElement* m_ptr;
std::pair<K, T> operator*() {
if constexpr (std::is_same<K, std::string>::value) {
return { m_ptr->getStrKey(), reinterpret_cast<T>(m_ptr->getObject()) };
} else {
return { m_ptr->getIntKey(), reinterpret_cast<T>(m_ptr->getObject()) };
}
}
auto& operator++() {
m_ptr = reinterpret_cast<decltype(m_ptr)>(m_ptr->hh.next);
return *this;
}
friend bool operator== (const CCDictIterator<K, T>& a, const CCDictIterator<K, T>& b) { return a.m_ptr == b.m_ptr; };
friend bool operator!= (const CCDictIterator<K, T>& a, const CCDictIterator<K, T>& b) { return a.m_ptr != b.m_ptr; };
bool operator!= (int b) { return m_ptr != nullptr; }
};
template <typename K, typename T>
struct CCDictEntry {
K m_key;
cocos2d::CCDictionary* m_dict;
CCDictEntry(K key, cocos2d::CCDictionary* dict) : m_key(key), m_dict(dict) {}
T operator->() {
return reinterpret_cast<T>(m_dict->objectForKey(m_key));
}
operator T() {
return reinterpret_cast<T>(m_dict->objectForKey(m_key));
}
CCDictEntry& operator=(T f) {
m_dict->setObject(f, m_key);
return *this;
}
};
template <typename K, typename T>
struct CCDictionaryExt {
protected:
cocos2d::CCDictionary* m_dict;
public:
CCDictionaryExt() : m_dict(cocos2d::CCDictionary::create()) {
m_dict->retain();
}
CCDictionaryExt(cocos2d::CCDictionary* dict) : m_dict(dict) {
m_dict->retain();
}
CCDictionaryExt(CCDictionaryExt const& d) : m_dict(d.m_dict) {
m_dict->retain();
}
CCDictionaryExt(CCDictionaryExt&& d) : m_dict(d.m_dict) {
d.m_dict = nullptr;
}
~CCDictionaryExt() {
if (m_dict)
m_dict->release();
}
CCDictionaryExt const& operator=(cocos2d::CCDictionary* d) {
m_dict->release();
m_dict = d;
m_dict->retain();
}
auto begin() {
return CCDictIterator<K, T*>(m_dict->m_pElements);
}
// do not use this
auto end() {
return nullptr;
}
size_t size() { return m_dict->count(); }
auto operator[](K key) {
auto ret = reinterpret_cast<T*>(m_dict->objectForKey(key));
if (!ret)
m_dict->setObject(cocos2d::CCNode::create(), key);
return CCDictEntry<K, T*>(key, m_dict);
}
size_t count(K key) {
return m_dict->allKeys(key)->count();
}
};
}

View file

@ -1,5 +1,6 @@
#pragma once
#include "json.hpp"
#include "VersionInfo.hpp"
#include "Result.hpp"
#include "types.hpp"
@ -10,4 +11,4 @@
#include "ext.hpp"
#include "convert.hpp"
#include "cocos.hpp"
#include "operators.hpp"
#include "operators.hpp"

View file

@ -5,6 +5,14 @@
namespace geode {
using byte_array = std::vector<uint8_t>;
template<class T>
struct TypeIdentity {
using type = T;
};
template<class T>
using TypeIdentityType = typename TypeIdentity<T>::type;
#ifndef GEODE_NO_CRINGE
using unknown_t = uintptr_t;