Skip to content

Commit

Permalink
I think it works...
Browse files Browse the repository at this point in the history
  • Loading branch information
AndroidModLoader committed Sep 11, 2021
1 parent e589f32 commit 95f9679
Show file tree
Hide file tree
Showing 15 changed files with 9,154 additions and 0 deletions.
10 changes: 10 additions & 0 deletions Android.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_CPP_EXTENSION := .cpp .cc
LOCAL_MODULE := CLEOMod
LOCAL_SRC_FILES := main.cpp mod/logger.cpp mod/config.cpp libcleo.cpp
LOCAL_CFLAGS += -O2 -mfloat-abi=softfp -DNDEBUG -std=c++17
LOCAL_C_INCLUDES += ./include
LOCAL_LDLIBS += -llog
include $(BUILD_SHARED_LIBRARY)
3 changes: 3 additions & 0 deletions Application.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
APP_STL := c++_static
APP_ABI := armeabi-v7a
APP_OPTIM := release
13 changes: 13 additions & 0 deletions build.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
$NDKPath = Get-Content $PSScriptRoot/NDKPath.txt
Write-Output "NDK located at: $NDKPath"

$buildScript = "$NDKPath/build/ndk-build"
if (-not ($PSVersionTable.PSEdition -eq "Core")) {
$buildScript += ".cmd"
}

Write-Output "[BUILD] Starting NDK..."
& $buildScript NDK_PROJECT_PATH=$PSScriptRoot APP_BUILD_SCRIPT=$PSScriptRoot/Android.mk NDK_APPLICATION_MK=$PSScriptRoot/Application.mk NDK_DEBUG=0
Write-Output "[BUILD] Done!"

Exit $LASTEXITCODE
66 changes: 66 additions & 0 deletions isautils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#include <stdint.h>

typedef void (*OnSettingChangedFn)(int nOldValue, int nNewValue);
typedef const char* (*OnSettingDrawedFn)(int nNewValue);

enum eTypeOfSettings : unsigned char
{
Controller = 0,
Game = 1,
Display = 2,
Audio = 3,
Language = 4,
};

class ISAUtils
{
public:
/* Functions below added in 1.0.0.0 */

/** Get an address of Fastman Limit Adjuster if included
*
* \return Address of a FLA library
*/
virtual uintptr_t IsFLALoaded() = 0;

// switchesArray is an array of items of clickable item (isSlider = false)
#if __cplusplus >= 201300 // Do not create errors on C++11 and lower :P
[[deprecated("Use AddClickableItem or AddSliderItem")]]
#endif
virtual int AddSettingsItem(eTypeOfSettings typeOf, const char* name, int initVal = 0, int minVal = 0, int maxVal = 0, OnSettingChangedFn fnOnValueChange = nullptr, bool isSlider = false, void* switchesArray = nullptr) = 0;

/** Get a value of setting (returned by AddClickableItem or AddSliderItem)
*
* \param settingId Numeric ID of setting (0-200 for example)
* \return Value of that setting
*/
virtual int ValueOfSettingsItem(int settingId) = 0;

/* Functions below added in 1.1.0.0 */

/** Adds clickable text button in menu settings
*
* \param typeOf In which setting option that item should be added
* \param name Obviously a displayed name
* \param initVal Initial value (def: 0)
* \param minVal Minimum value (def: 0)
* \param maxVal Maximum value (def: 0)
* \param switchesArray An array that includes names of options
* \param fnOnValueChange A function that will be called on value being saved (def: null)
* \return Setting ID
*/
virtual int AddClickableItem(eTypeOfSettings typeOf, const char* name, int initVal = 0, int minVal = 0, int maxVal = 0, const char** switchesArray = nullptr, OnSettingChangedFn fnOnValueChange = nullptr) = 0;

/** Adds a slider in menu settings
*
* \param typeOf In which setting option that item should be added
* \param name Obviously a displayed name
* \param initVal Initial value (def: 0)
* \param minVal Minimum value (def: 0)
* \param maxVal Maximum value (def: 0)
* \param fnOnValueChange A function that will be called on value being saved (def: null)
* \param fnOnValueDraw A function that will control a text of a slider (def: null)
* \return Setting ID
*/
virtual int AddSliderItem(eTypeOfSettings typeOf, const char* name, int initVal = 0, int minVal = 0, int maxVal = 0, OnSettingChangedFn fnOnValueChange = nullptr, OnSettingDrawedFn fnOnValueDraw = nullptr) = 0;
};
8,349 changes: 8,349 additions & 0 deletions libcleo.cpp

Large diffs are not rendered by default.

110 changes: 110 additions & 0 deletions main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#include <mod/amlmod.h>
#include <mod/logger.h>
#include <mod/config.h>

#include <stdlib.h>
#include <filesystem>
#include <fstream>
#include <stdint.h>
#include <dlfcn.h>

#include "isautils.h"
ISAUtils* sautils = nullptr;

#define sizeofA(__aVar) ((int)(sizeof(__aVar)/sizeof(__aVar[0])))

MYMODCFG(net.rusjj.cleolib, CLEO Library, 2.0.1, Alexander Blade & RusJJ)
BEGIN_DEPLIST()
ADD_DEPENDENCY_VER(net.rusjj.aml, 1.0.0.4)
END_DEPLIST()

std::string loadFrom;
void* pCLEO;
Dl_info pDLInfo;
uintptr_t pGTASA;

ConfigEntry* pCLEOLocation;
ConfigEntry* pCLEORedArrow;

extern unsigned char cleoData[100160];
const char* pLocations[] =
{
"CLEO 2.0.1",
"Old CLEO",
"Old CLEO (+cleo)",
};
const char* pYesNo[] =
{
"FEM_OFF",
"FEM_ON",
};
void OnLocationChanged(int oldVal, int newVal)
{
pCLEOLocation->SetInt(newVal);
cfg->Save();
}
void OnRedArrowChanged(int oldVal, int newVal)
{
pCLEORedArrow->SetBool(newVal != 0);
cfg->Save();
}

extern "C" void OnModLoad()
{
logger->SetTag("CLEO Mod");
pCLEOLocation = cfg->Bind("CLEO_Location", 0);
pCLEORedArrow = cfg->Bind("CLEO_RedArrow", true);

pGTASA = aml->GetLib("libGTASA.so");
loadFrom = aml->GetDataPath();
loadFrom += "/cleo_mod.so";

std::ofstream fs(loadFrom.data(), std::ios::out | std::ios::binary);
fs.write((const char*)cleoData, sizeof(cleoData));
fs.close();
pCLEO = dlopen(loadFrom.data(), RTLD_NOW);
if(pCLEO == nullptr)
{
OOPSIE:
logger->Error("Failed to load CLEO library!");
return;
}
auto libEntry = (void(*)())dlsym(pCLEO, "JNI_OnLoad");
if(libEntry == nullptr) goto OOPSIE;

dladdr((void*)libEntry, &pDLInfo);
setenv("EXTERNAL_STORAGE", std::filesystem::path(aml->GetConfigPath()).parent_path().parent_path().c_str(), 1);
if(pCLEOLocation->GetInt() == 1)
{
aml->Unprot((uintptr_t)pDLInfo.dli_fbase + 0x146A9, 11);
uintptr_t cleoDir = (uintptr_t)pDLInfo.dli_fbase + 0x146A9;
*(char*)(cleoDir + 3) = '\0';

aml->Unprot((uintptr_t)pDLInfo.dli_fbase + 0x14C2C, 16);
uintptr_t cleoLog = (uintptr_t)pDLInfo.dli_fbase + 0x14C2C;
*(char*)(cleoLog + 7) = '.';
*(char*)(cleoLog + 8) = 'l';
*(char*)(cleoLog + 9) = 'o';
*(char*)(cleoLog + 10) = 'g';
*(char*)(cleoLog + 11) = '\0';
}
else if(pCLEOLocation->GetInt() == 2)
{
aml->Unprot((uintptr_t)pDLInfo.dli_fbase + 0x146A9, 11);
uintptr_t cleoDir = (uintptr_t)pDLInfo.dli_fbase + 0x146A9;
*(char*)(cleoDir + 8) = '\0';
}

if(!pCLEORedArrow->GetBool())
aml->PlaceNOP((uintptr_t)pDLInfo.dli_fbase + 0xBD82, 2);

libEntry();
logger->Info("CLEO initialized!");

sautils = (ISAUtils*)GetInterface("SAUtils");
if(sautils)
{
sautils->AddClickableItem(Game, "CLEO Location", pCLEOLocation->GetInt(), 0, sizeofA(pLocations)-1, pLocations, OnLocationChanged);
sautils->AddClickableItem(Game, "CLEO Red Arrow", pCLEORedArrow->GetInt(), 0, sizeofA(pYesNo)-1, pYesNo, OnRedArrowChanged);
}
}
118 changes: 118 additions & 0 deletions mod/amlmod.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#ifndef _AMLMOD
#define _AMLMOD

#include "iaml.h"
#include <stdio.h>
#include <string>

#ifdef __clang__
#define TARGET_ARM __attribute__((target("no-thumb-mode")))
#define TARGET_THUMB __attribute__((target("thumb-mode")))
#endif

#ifdef __GNUC__
#define ASM_NAKED __attribute__((naked))
#else
#define ASM_NAKED __declspec(naked)
#endif

#define MYMOD(_guid, _name, _version, _author) \
static ModInfo modinfoLocal(#_guid, #_name, #_version, #_author); \
ModInfo* modinfo = &modinfoLocal; \
extern "C" ModInfo* __GetModInfo() { return modinfo; } \
IAML* aml = (IAML*)GetInterface("AMLInterface");

#define MYMODCFG(_guid, _name, _version, _author) \
static ModInfo modinfoLocal(#_guid, #_name, #_version, #_author); \
ModInfo* modinfo = &modinfoLocal; \
extern "C" ModInfo* __GetModInfo() { return modinfo; } \
IAML* aml = (IAML*)GetInterface("AMLInterface"); \
static Config cfgLocal(#_guid); \
Config* cfg = &cfgLocal;

#define NEEDGAME(_pkg_name) \
extern "C" const char* __INeedASpecificGame() {return #_pkg_name;}

#define MYMODDECL() \
extern ModInfo* modinfo; // Just in case if you need to use that somewhere else in your mod

/* Dependencies! */
#define BEGIN_DEPLIST() \
static ModInfoDependency g_listDependencies[] = {

#define ADD_DEPENDENCY(_guid) \
{#_guid, ""},

#define ADD_DEPENDENCY_VER(_guid, _version) \
{#_guid, #_version},

#define END_DEPLIST() \
{"", ""} }; \
extern "C" ModInfoDependency* __GetDepsList() { return &g_listDependencies[0]; }



struct ModInfoDependency
{
const char* szGUID;
const char* szVersion;
};

class ModInfo
{
public:
ModInfo(const char* szGUID, const char* szName, const char* szVersion, const char* szAuthor)
{
/* No buffer overflow! */
strncpy(this->szGUID, szGUID, sizeof(ModInfo::szGUID)); this->szGUID[sizeof(ModInfo::szGUID) - 1] = '\0';
strncpy(this->szName, szName, sizeof(ModInfo::szName)); this->szName[sizeof(ModInfo::szName) - 1] = '\0';
strncpy(this->szVersion, szVersion, sizeof(ModInfo::szVersion)); this->szVersion[sizeof(ModInfo::szVersion) - 1] = '\0';
strncpy(this->szAuthor, szAuthor, sizeof(ModInfo::szAuthor)); this->szAuthor[sizeof(ModInfo::szAuthor) - 1] = '\0';

/* GUID should be lowcase */
for(int i = 0; this->szGUID[i] != '\0'; ++i)
{
this->szGUID[i] = tolower((int)(this->szGUID[i]));
}

/* Parse version string */
if(sscanf(this->szVersion, "%hu.%hu.%hu.%hu", &major, &minor, &revision, &build) < 4)
{
if(sscanf(this->szVersion, "%hu.%hu.%hu", &major, &minor, &revision) < 3)
{
if(sscanf(this->szVersion, "%hu.%hu", &major, &minor) < 2)
{
major = (unsigned short)atoi(this->szVersion);
}
revision = 0;
}
build = 0;
}
}
inline const char* GUID() { return szGUID; }
inline const char* Name() { return szName; }
inline const char* VersionString() { return szVersion; }
inline const char* Author() { return szAuthor; }
inline unsigned short Major() { return major; }
inline unsigned short Minor() { return minor; }
inline unsigned short Revision() { return revision; }
inline unsigned short Build() { return build; }
inline uintptr_t Handle() { return handle; }
private:
char szGUID[48];
char szName[48];
char szVersion[24];
char szAuthor[48];
unsigned short major;
unsigned short minor;
unsigned short revision;
unsigned short build;
uintptr_t handle;
ModInfoDependency* dependencies;

friend class ModsList;
};

typedef ModInfo* (*GetModInfoFn)();

#endif // _AMLMOD
Loading

0 comments on commit 95f9679

Please sign in to comment.