diff --git a/cleo4opcodes.cpp b/cleo4opcodes.cpp index cdea255..838beb8 100644 --- a/cleo4opcodes.cpp +++ b/cleo4opcodes.cpp @@ -158,6 +158,27 @@ CLEO_Fn(GET_OBJECT_POINTER) cleo->GetPointerToScriptVar(handle)->i = GetObjectFromRef(ref); } +CLEO_Fn(SET_CURRENT_DIRECTORY) +{ + const char* path; + char buf[MAX_STR_LEN]; + if(IsParamString(handle)) + { + path = CLEO_ReadStringEx(handle, buf, sizeof(buf)); + } + else + { + int idx = cleo->ReadParam(handle)->i; + switch(idx) + { + default: path = DIR_GAME; break; + case 1: path = DIR_USER; break; + case 2: path = DIR_SCRIPT; break; + } + } + GetAddonInfo(handle).workDir = path; +} + CLEO_Fn(OPEN_FILE) { char filename[MAX_STR_LEN], mode[10]; @@ -1513,9 +1534,8 @@ void Init4Opcodes() SET_TO(curCheatCar_VC, cleo->GetMainLibrarySymbol("curCheatCar")); } - // Those are WIDGET opcodes on Mobile (thanks WarDrum, lol) - //CLEO_RegisterOpcode(0x0A8C, WRITE_MEMORY); // - //CLEO_RegisterOpcode(0x0A8D, READ_MEMORY); // + //CLEO_RegisterOpcode(0x0A8C, WRITE_MEMORY); // WIDGET opcode on Mobile (thanks WarDrum, lol) + //CLEO_RegisterOpcode(0x0A8D, READ_MEMORY); // WIDGET opcode on Mobile (thanks WarDrum, lol) CLEO_RegisterOpcode(0x0A8E, INT_ADD); // 0A8E=3,%3d% = %1d% + %2d% ; int CLEO_RegisterOpcode(0x0A8F, INT_SUB); // 0A8F=3,%3d% = %1d% - %2d% ; int CLEO_RegisterOpcode(0x0A90, INT_MUL); // 0A90=3,%3d% = %1d% * %2d% ; int @@ -1527,7 +1547,7 @@ void Init4Opcodes() CLEO_RegisterOpcode(0x0A96, GET_PED_POINTER); // 0A96=2,%2d% = actor %1d% struct CLEO_RegisterOpcode(0x0A97, GET_VEHICLE_POINTER); // 0A97=2,%2d% = car %1d% struct CLEO_RegisterOpcode(0x0A98, GET_OBJECT_POINTER); // 0A98=2,%2d% = object %1d% struct - //CLEO_RegisterOpcode(0x0A99, SET_CURRENT_DIRECTORY); // + CLEO_RegisterOpcode(0x0A99, SET_CURRENT_DIRECTORY); // 0A99=1,set_current_directory %1b:userdir/rootdir% CLEO_RegisterOpcode(0x0A9A, OPEN_FILE); // 0A9A=3,%3d% = openfile %1d% mode %2d% // IF and SET CLEO_RegisterOpcode(0x0A9B, CLOSE_FILE); // 0A9B=1,closefile %1d% CLEO_RegisterOpcode(0x0A9C, GET_FILE_SIZE); // 0A9C=2,%2d% = file %1d% size diff --git a/cleoaddon.h b/cleoaddon.h index 963e86b..3e80c94 100644 --- a/cleoaddon.h +++ b/cleoaddon.h @@ -8,11 +8,21 @@ struct ScriptAddonInfo { + ScriptAddonInfo() + { + workDir.clear(); + scmFuncId = 0; + isCustom = false; + debugMode = false; + enableThreadSaving = false; + } + + std::string workDir; uint16_t scmFuncId : 10; // [0-1024] - 2^10 uint16_t isCustom : 1; // [0-1] uint16_t debugMode : 1; // [0-1] - uint16_t pad : 4; -}; // max is 16 bytes (uint16_t) + uint16_t enableThreadSaving : 1; // [0-1] +}; struct cleo_addon_ifs_t diff --git a/cleohelpers.h b/cleohelpers.h index e78972e..bdb68f2 100644 --- a/cleohelpers.h +++ b/cleohelpers.h @@ -680,9 +680,19 @@ inline bool IsCLEORelatedGXTKey(char* gxtLabel) return false; // uh-nuh } +extern uint16_t FreeScriptAddonInfoId; +extern ScriptAddonInfo ScriptAddonInfosStorage[0x400]; +inline uint16_t AssignAddonInfo(void* handle) +{ + uint16_t id = FreeScriptAddonInfoId++; + *(uint16_t*)((uintptr_t)handle + ValueForGame(0x26, 0x2E, 0x3A, 0, 0)) = id; + return id; +} inline ScriptAddonInfo& GetAddonInfo(void* handle) { - return *(ScriptAddonInfo*)((uintptr_t)handle + ValueForGame(0x26, 0x2E, 0x3A, 0, 0)); + uint16_t id = *(uint16_t*)((uintptr_t)handle + ValueForGame(0x26, 0x2E, 0x3A, 0, 0)); + if(!id) id = AssignAddonInfo(handle); + return ScriptAddonInfosStorage[id]; } inline uint16_t GetScmFunc(void* handle) { @@ -906,7 +916,7 @@ inline bool IsParamString(void* handle, bool checkIfPointer = false) void* probMem = (void*)cleo->ReadParam(handle)->i; GetPC(handle) = backupPC; - + if(IsAlloced(probMem)) return true; } return false; } @@ -927,10 +937,20 @@ static const char DIR_SCRIPT[] = "."; // current script directory static const char DIR_CLEO[] = "cleo:"; // game\cleo directory static const char DIR_MODULES[] = "modules:"; // game\cleo\modules directory -inline const char* GetWorkDir() +inline const char* GetFilesDir() { return aml->GetAndroidDataPath(); } +inline std::string& GetWorkDir(void* handle) +{ + return GetAddonInfo(handle).workDir; +} +inline const char* GetScriptWorkDir(void* handle) +{ + std::string& workDir = GetWorkDir(handle); + if(GetAddonInfo(handle).isCustom && !workDir.empty()) return workDir.c_str(); + return GetFilesDir(); +} inline const char* GetUserDirectory() { return aml->GetDataPath(); @@ -969,7 +989,7 @@ inline std::string ResolvePath(void* handle, const char* path, const char* custo if(customWorkDir != NULL) fsPath = ResolvePath(handle, customWorkDir) / fsPath; else - fsPath = GetWorkDir() / fsPath; + fsPath = GetScriptWorkDir(handle) / fsPath; } return std::filesystem::weakly_canonical(fsPath).string(); } @@ -982,7 +1002,7 @@ inline std::string ResolvePath(void* handle, const char* path, const char* custo if(handle && GetAddonInfo(handle).isCustom) resolved = GetCleoDir(); else { - resolved = GetWorkDir(); + resolved = GetFilesDir(); resolved /= "data"; resolved /= "script"; } diff --git a/main.cpp b/main.cpp index c03f25e..7e0d608 100644 --- a/main.cpp +++ b/main.cpp @@ -16,6 +16,8 @@ cleo_ifs_t* cleo = nullptr; #include "cleoaddon.h" cleo_addon_ifs_t cleo_addon_ifs; +uint16_t FreeScriptAddonInfoId = 1; // 0 is "not assigned" (used for dumbo scripts without that info) +ScriptAddonInfo ScriptAddonInfosStorage[0x400]; // SAUtils #include "isautils.h" @@ -162,7 +164,11 @@ DECL_HOOKv(CLEO_StartScripts) if(storageItem != 0 && *(int*)(storageItem + 24) == -1) { void* handle = *(void**)(storageItem + 28); - if(handle != NULL) GetAddonInfo(handle).isCustom = true; + if(handle != NULL) + { + AssignAddonInfo(handle); + GetAddonInfo(handle).isCustom = true; + } } } } @@ -184,7 +190,11 @@ DECL_HOOKb(CLEO_OnOpcodeCall, void *storageItem, uint16_t opcode) if(storageItem && *(int*)(storageItem + 24) != -1 && *(int*)(storageItem + 24) == *ScriptParams) { void* handle = *(void**)(storageItem + 28); - if(handle != NULL) GetAddonInfo(handle).isCustom = true; + if(handle != NULL) + { + AssignAddonInfo(handle); + GetAddonInfo(handle).isCustom = true; + } return ret; } }