diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 1c220f58..262e178a 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -51,7 +51,6 @@ jobs:
@REM copy files
copy source\cleo_config.ini .output\Release\cleo\.cleo_config.ini
copy cleo_plugins\.output\*.cleo .output\Release\cleo\cleo_plugins
- copy cleo_plugins\.output\*.cleo5 .output\Release\cleo\cleo_plugins
copy cleo_plugins\.output\*.ini .output\Release\cleo\cleo_plugins
copy cleo_plugins\Audio\bass\bass.dll .output\Release\bass.dll
xcopy /E /I tests\ .output\cleo
diff --git a/README.md b/README.md
index 52f5bb5f..cae11b92 100644
--- a/README.md
+++ b/README.md
@@ -8,15 +8,18 @@ CLEO requires an 'ASI Loader' installed to run which is provided with the releas
No additional files are replaced, however the following files and folders are added:
- cleo\ (CLEO script directory)
-- cleo\cleo_plugins\DebugUtils.cleo (script debug utilities plugin)
-- cleo\cleo_plugins\FileSystemOperations.cleo (file system plugin)
-- cleo\cleo_plugins\IniFiles.cleo (INI config plugin)
-- cleo\cleo_plugins\IntOperations.cleo (INT operations plugin)
+- cleo\cleo_plugins\SA.Audio.cleo (audio playback utilities powered by BASS.dll library)
+- cleo\cleo_plugins\SA.DebugUtils.cleo (script debugging utilities plugin)
+- cleo\cleo_plugins\SA.FileSystemOperations.cleo (disk drive files related operations plugin)
+- cleo\cleo_plugins\SA.IniFiles.cleo (.ini config files handling plugin)
+- cleo\cleo_plugins\SA.IntOperations.cleo (additional math operations plugin)
+- cleo\cleo_plugins\SA.MemoryOperations (memory and .dll libraries utilities plugin)
- cleo\cleo_saves\ (CLEO save directory)
- cleo\cleo_text\ (CLEO text directory)
- cleo.asi (core library)
- bass.dll (audio engine library)
-- vorbisHooked.dll (Silent's ASI Loader)
+- vorbisFile.dll (Silent's ASI Loader)
+- vorbisHooked.dll (original vorbisFile.dll file)
All plugins are optional, however they may be required by various CLEO scripts.
diff --git a/cleo_plugins/DebugUtils/DebugUtils.vcxproj b/cleo_plugins/DebugUtils/DebugUtils.vcxproj
index 838cf9e1..536eb3b5 100644
--- a/cleo_plugins/DebugUtils/DebugUtils.vcxproj
+++ b/cleo_plugins/DebugUtils/DebugUtils.vcxproj
@@ -44,14 +44,14 @@
$(SolutionDir).output\
$(ProjectDir).obj\$(Configuration)\
- DebugUtils
- .cleo5
+ SA.DebugUtils
+ .cleo
$(SolutionDir).output\
$(ProjectDir).obj\$(Configuration)\
- DebugUtils
- .cleo5
+ SA.DebugUtils
+ .cleo
$(GTA_SA_DIR)\gta_sa.exe
@@ -132,7 +132,7 @@ xcopy /Y "$(OutDir)$(TargetName).*" "$(GTA_SA_DIR)\cleo\cleo_plugins\"
-
+
diff --git a/cleo_plugins/DebugUtils/DebugUtils.vcxproj.filters b/cleo_plugins/DebugUtils/DebugUtils.vcxproj.filters
index 533d3aa0..b06f5016 100644
--- a/cleo_plugins/DebugUtils/DebugUtils.vcxproj.filters
+++ b/cleo_plugins/DebugUtils/DebugUtils.vcxproj.filters
@@ -34,6 +34,6 @@
-
+
\ No newline at end of file
diff --git a/cleo_plugins/DebugUtils/DebugUtils.ini b/cleo_plugins/DebugUtils/SA.DebugUtils.ini
similarity index 100%
rename from cleo_plugins/DebugUtils/DebugUtils.ini
rename to cleo_plugins/DebugUtils/SA.DebugUtils.ini
diff --git a/cleo_plugins/FileSystemOperations/FileSystemOperations.vcxproj b/cleo_plugins/FileSystemOperations/FileSystemOperations.vcxproj
index 5129493b..742cef3a 100644
--- a/cleo_plugins/FileSystemOperations/FileSystemOperations.vcxproj
+++ b/cleo_plugins/FileSystemOperations/FileSystemOperations.vcxproj
@@ -44,14 +44,14 @@
$(SolutionDir).output\
$(ProjectDir).obj\$(Configuration)\
- FileSystemOperations
- .cleo5
+ SA.FileSystemOperations
+ .cleo
$(SolutionDir).output\
$(ProjectDir).obj\$(Configuration)\
- FileSystemOperations
- .cleo5
+ SA.FileSystemOperations
+ .cleo
$(GTA_SA_DIR)\gta_sa.exe
@@ -83,7 +83,9 @@
taskkill /IM gta_sa.exe /F /FI "STATUS eq RUNNING"
-xcopy /Y "$(OutDir)$(TargetName).*" "$(GTA_SA_DIR)\cleo\cleo_plugins\"
+if defined GTA_SA_DIR (
+ xcopy /Y "$(OutDir)$(TargetName).*" "$(GTA_SA_DIR)\cleo\cleo_plugins\"
+)
@@ -106,7 +108,9 @@ xcopy /Y "$(OutDir)$(TargetName).*" "$(GTA_SA_DIR)\cleo\cleo_plugins\"
taskkill /IM gta_sa.exe /F /FI "STATUS eq RUNNING"
-xcopy /Y "$(OutDir)$(TargetName).*" "$(GTA_SA_DIR)\cleo\cleo_plugins\"
+if defined GTA_SA_DIR (
+ xcopy /Y "$(OutDir)$(TargetName).*" "$(GTA_SA_DIR)\cleo\cleo_plugins\"
+)
diff --git a/cleo_plugins/IniFiles/IniFiles.cpp b/cleo_plugins/IniFiles/IniFiles.cpp
index 2daff3dd..0064d1e6 100644
--- a/cleo_plugins/IniFiles/IniFiles.cpp
+++ b/cleo_plugins/IniFiles/IniFiles.cpp
@@ -1,5 +1,6 @@
#include
#include "CLEO.h"
+#include "CLEO_Utils.h"
#include
using namespace CLEO;
@@ -28,27 +29,24 @@ class IniFiles
}
}
+ // resused globals to cut down allocations
+ static char section[128];
+ static char key[128];
+
static OpcodeResult WINAPI Script_InifileGetInt(CScriptThread* thread)
/****************************************************************
Opcode Format
0AF0=4,%4d% = get_int_from_ini_file %1s% section %2s% key %3s%
****************************************************************/
{
- char path[MAX_PATH];
- char sectionName[100];
- char key[100];
- int result;
-
- CLEO_ReadStringPointerOpcodeParam(thread, path, sizeof(path));
- CLEO_ReadStringPointerOpcodeParam(thread, sectionName, sizeof(sectionName));
- CLEO_ReadStringPointerOpcodeParam(thread, key, sizeof(key));
-
- CLEO_ResolvePath(thread, path, sizeof(path)); // convert to absolute path
+ auto path = OPCODE_READ_PARAM_FILEPATH();
+ OPCODE_READ_PARAM_STRING_BUFF(section, sizeof(section));
+ OPCODE_READ_PARAM_STRING_BUFF(key, sizeof(key));
- result = GetPrivateProfileInt(sectionName, key, 0x80000000, path);
- CLEO_SetIntOpcodeParam(thread, result);
- CLEO_SetThreadCondResult(thread, result != 0x80000000);
+ auto result = GetPrivateProfileInt(section, key, 0x80000000, path);
+ OPCODE_WRITE_PARAM_INT(result);
+ OPCODE_CONDITION_RESULT(result != 0x80000000);
return OR_CONTINUE;
}
@@ -58,23 +56,16 @@ class IniFiles
0AF1=4,write_int %1d% to_ini_file %2s% section %3s% key %4s%
****************************************************************/
{
- char path[MAX_PATH];
- char sectionName[100];
- char key[100];
- DWORD value;
- char strValue[100];
- BOOL result;
+ auto value = OPCODE_READ_PARAM_INT();
+ auto path = OPCODE_READ_PARAM_FILEPATH();
+ OPCODE_READ_PARAM_STRING_BUFF(section, sizeof(section));
+ OPCODE_READ_PARAM_STRING_BUFF(key, sizeof(key));
- value = CLEO_GetIntOpcodeParam(thread);
- CLEO_ReadStringPointerOpcodeParam(thread, path, sizeof(path));
- CLEO_ReadStringPointerOpcodeParam(thread, sectionName, sizeof(sectionName));
- CLEO_ReadStringPointerOpcodeParam(thread, key, sizeof(key));
-
- CLEO_ResolvePath(thread, path, sizeof(path)); // convert to absolute path
-
- result = WritePrivateProfileString(sectionName, key, _itoa(value, strValue, 10), path);
- CLEO_SetThreadCondResult(thread, result);
+ char strValue[32];
+ _itoa(value, strValue, 10);
+ auto result = WritePrivateProfileString(section, key, strValue, path);
+ OPCODE_CONDITION_RESULT(result);
return OR_CONTINUE;
}
@@ -84,30 +75,23 @@ class IniFiles
0AF2=4,%4d% = get_float_from_ini_file %1s% section %2s% key %3s%
****************************************************************/
{
- char path[MAX_PATH];
- char sectionName[100];
- char key[100];
- float value = 0.0f;
- char strValue[100];
- BOOL result;
-
- CLEO_ReadStringPointerOpcodeParam(thread, path, sizeof(path));
- CLEO_ReadStringPointerOpcodeParam(thread, sectionName, sizeof(sectionName));
- CLEO_ReadStringPointerOpcodeParam(thread, key, sizeof(key));
+ auto path = OPCODE_READ_PARAM_FILEPATH();
+ OPCODE_READ_PARAM_STRING_BUFF(section, sizeof(section));
+ OPCODE_READ_PARAM_STRING_BUFF(key, sizeof(key));
- CLEO_ResolvePath(thread, path, sizeof(path)); // convert to absolute path
-
- result = GetPrivateProfileString(sectionName, key, NULL, strValue, sizeof(strValue), path);
+ auto value = 0.0f;
+ char strValue[32];
+ auto result = GetPrivateProfileString(section, key, NULL, strValue, sizeof(strValue), path);
if (result)
{
value = (float)atof(strValue);
- CLEO_SetFloatOpcodeParam(thread, value);
+ OPCODE_WRITE_PARAM_FLOAT(value);
}
else
- CLEO_SkipOpcodeParams(thread, 1);
-
- CLEO_SetThreadCondResult(thread, result);
-
+ {
+ OPCODE_SKIP_PARAMS(1);
+ }
+ OPCODE_CONDITION_RESULT(result);
return OR_CONTINUE;
}
@@ -117,25 +101,16 @@ class IniFiles
0AF3=4,write_float %1d% to_ini_file %2s% section %3s% key %4s%
****************************************************************/
{
- char path[MAX_PATH];
- char sectionName[100];
- char key[100];
- float value;
- char strValue[100];
- BOOL result;
-
- value = CLEO_GetFloatOpcodeParam(thread);
- CLEO_ReadStringPointerOpcodeParam(thread, path, sizeof(path));
- CLEO_ReadStringPointerOpcodeParam(thread, sectionName, sizeof(sectionName));
- CLEO_ReadStringPointerOpcodeParam(thread, key, sizeof(key));
-
- CLEO_ResolvePath(thread, path, sizeof(path)); // convert to absolute path
+ auto value = OPCODE_READ_PARAM_FLOAT();
+ auto path = OPCODE_READ_PARAM_FILEPATH();
+ OPCODE_READ_PARAM_STRING_BUFF(section, sizeof(section));
+ OPCODE_READ_PARAM_STRING_BUFF(key, sizeof(key));
+ char strValue[32];
sprintf(strValue, "%g", value);
+ auto result = WritePrivateProfileString(section, key, strValue, path);
- result = WritePrivateProfileString(sectionName, key, strValue, path);
- CLEO_SetThreadCondResult(thread, result);
-
+ OPCODE_CONDITION_RESULT(result);
return OR_CONTINUE;
}
@@ -145,40 +120,21 @@ class IniFiles
0AF4=4,%4d% = read_string_from_ini_file %1s% section %2s% key %3s%
****************************************************************/
{
- char path[MAX_PATH];
- char sectionName[100];
- char key[100];
- char strValue[100];
- char *strptr;
- BOOL result;
-
- CLEO_ReadStringPointerOpcodeParam(thread, path, sizeof(path));
- CLEO_ReadStringPointerOpcodeParam(thread, sectionName, sizeof(sectionName));
- CLEO_ReadStringPointerOpcodeParam(thread, key, sizeof(key));
+ auto path = OPCODE_READ_PARAM_FILEPATH();
+ OPCODE_READ_PARAM_STRING_BUFF(section, sizeof(section));
+ OPCODE_READ_PARAM_STRING_BUFF(key, sizeof(key));
- CLEO_ResolvePath(thread, path, sizeof(path)); // convert to absolute path
-
- result = GetPrivateProfileString(sectionName, key, NULL, strValue, sizeof(strValue), path);
+ char strValue[MAX_STR_LEN];
+ auto result = GetPrivateProfileString(section, key, NULL, strValue, sizeof(strValue), path);
if (result)
{
- switch (CLEO_GetOperandType(thread))
- {
- case DT_VAR_STRING:
- case DT_LVAR_STRING:
- case DT_VAR_TEXTLABEL:
- case DT_LVAR_TEXTLABEL:
- CLEO_WriteStringOpcodeParam(thread, strValue);
- break;
- default:
- strptr = (char *)CLEO_GetIntOpcodeParam(thread);
- strcpy(strptr, strValue);
- }
+ OPCODE_WRITE_PARAM_STRING(strValue);
}
else
- CLEO_SkipOpcodeParams(thread, 1);
-
- CLEO_SetThreadCondResult(thread, result);
-
+ {
+ OPCODE_SKIP_PARAMS(1);
+ }
+ OPCODE_CONDITION_RESULT(result);
return OR_CONTINUE;
}
@@ -188,23 +144,17 @@ class IniFiles
0AF5=4,write_string %1s% to_ini_file %2s% section %3s% key %4s%
****************************************************************/
{
- char path[MAX_PATH];
- char sectionName[100];
- char key[100];
- char strValue[100];
- BOOL result;
-
- CLEO_ReadStringPointerOpcodeParam(thread, strValue, sizeof(strValue));
- CLEO_ReadStringPointerOpcodeParam(thread, path, sizeof(path));
- CLEO_ReadStringPointerOpcodeParam(thread, sectionName, sizeof(sectionName));
- CLEO_ReadStringPointerOpcodeParam(thread, key, sizeof(key));
+ char strValue[MAX_STR_LEN]; OPCODE_READ_PARAM_STRING_BUFF(strValue, sizeof(strValue));
+ auto path = OPCODE_READ_PARAM_FILEPATH();
+ OPCODE_READ_PARAM_STRING_BUFF(section, sizeof(section));
+ OPCODE_READ_PARAM_STRING_BUFF(key, sizeof(key));
- CLEO_ResolvePath(thread, path, sizeof(path)); // convert to absolute path
-
- result = WritePrivateProfileString(sectionName, key, strValue, path);
-
- CLEO_SetThreadCondResult(thread, result);
+ auto result = WritePrivateProfileString(section, key, strValue, path);
+ OPCODE_CONDITION_RESULT(result);
return OR_CONTINUE;
}
} iniFiles;
+
+char IniFiles::section[128];
+char IniFiles::key[128];
diff --git a/cleo_plugins/IniFiles/IniFiles.vcxproj b/cleo_plugins/IniFiles/IniFiles.vcxproj
index 32eb6071..295783ac 100644
--- a/cleo_plugins/IniFiles/IniFiles.vcxproj
+++ b/cleo_plugins/IniFiles/IniFiles.vcxproj
@@ -44,14 +44,14 @@
$(SolutionDir).output\
$(ProjectDir).obj\$(Configuration)\
- IniFiles
- .cleo5
+ SA.IniFiles
+ .cleo
$(SolutionDir).output\
$(ProjectDir).obj\$(Configuration)\
- IniFiles
- .cleo5
+ SA.IniFiles
+ .cleo
$(GTA_SA_DIR)\gta_sa.exe
diff --git a/cleo_plugins/IntOperations/IntOperations.vcxproj b/cleo_plugins/IntOperations/IntOperations.vcxproj
index 3d0b82a1..83dd2abd 100644
--- a/cleo_plugins/IntOperations/IntOperations.vcxproj
+++ b/cleo_plugins/IntOperations/IntOperations.vcxproj
@@ -44,14 +44,14 @@
$(SolutionDir).output\
$(ProjectDir).obj\$(Configuration)\
- IntOperations
- .cleo5
+ SA.IntOperations
+ .cleo
$(SolutionDir).output\
$(ProjectDir).obj\$(Configuration)\
- IntOperations
- .cleo5
+ SA.IntOperations
+ .cleo
$(GTA_SA_DIR)\gta_sa.exe
diff --git a/cleo_plugins/MemoryOperations/MemoryOperations.vcxproj b/cleo_plugins/MemoryOperations/MemoryOperations.vcxproj
index 3a5b08dc..bb8086a3 100644
--- a/cleo_plugins/MemoryOperations/MemoryOperations.vcxproj
+++ b/cleo_plugins/MemoryOperations/MemoryOperations.vcxproj
@@ -45,14 +45,14 @@
$(SolutionDir).output\
$(ProjectDir).obj\$(Configuration)\
- MemoryOperations
- .cleo5
+ SA.MemoryOperations
+ .cleo
$(SolutionDir).output\
$(ProjectDir).obj\$(Configuration)\
- MemoryOperations
- .cleo5
+ SA.MemoryOperations
+ .cleo
$(GTA_SA_DIR)\gta_sa.exe
@@ -84,7 +84,9 @@
taskkill /IM gta_sa.exe /F /FI "STATUS eq RUNNING"
-xcopy /Y "$(OutDir)$(TargetName).*" "$(GTA_SA_DIR)\cleo\cleo_plugins\"
+if defined GTA_SA_DIR (
+ xcopy /Y "$(OutDir)$(TargetName).*" "$(GTA_SA_DIR)\cleo\cleo_plugins\"
+)
@@ -107,7 +109,9 @@ xcopy /Y "$(OutDir)$(TargetName).*" "$(GTA_SA_DIR)\cleo\cleo_plugins\"
taskkill /IM gta_sa.exe /F /FI "STATUS eq RUNNING"
-xcopy /Y "$(OutDir)$(TargetName).*" "$(GTA_SA_DIR)\cleo\cleo_plugins\"
+if defined GTA_SA_DIR (
+ xcopy /Y "$(OutDir)$(TargetName).*" "$(GTA_SA_DIR)\cleo\cleo_plugins\"
+)
diff --git a/source/CCustomOpcodeSystem.cpp b/source/CCustomOpcodeSystem.cpp
index 04b3fb53..10430374 100644
--- a/source/CCustomOpcodeSystem.cpp
+++ b/source/CCustomOpcodeSystem.cpp
@@ -209,7 +209,7 @@ namespace CLEO
CCustomOpcodeSystem::CCustomOpcodeSystem()
{
- // register CLEO opcodes
+ TRACE("Initializing CLEO core opcodes...");
CLEO_RegisterOpcode(0x0A92, opcode_0A92);
CLEO_RegisterOpcode(0x0A93, opcode_0A93);
CLEO_RegisterOpcode(0x0A94, opcode_0A94);
@@ -2018,7 +2018,7 @@ extern "C"
return texture;
}
- CLEO::HSTREAM WINAPI CLEO_GetInternalAudioStream(CLEO::CRunningScript* thread, DWORD stream) // arg CAudioStream *
+ DWORD WINAPI CLEO_GetInternalAudioStream(CLEO::CRunningScript* thread, DWORD stream) // arg CAudioStream *
{
return stream; // CAudioStream::streamInternal offset is 0
}
diff --git a/source/CPluginSystem.h b/source/CPluginSystem.h
index e807953f..58341806 100644
--- a/source/CPluginSystem.h
+++ b/source/CPluginSystem.h
@@ -17,39 +17,55 @@ namespace CLEO
CPluginSystem()
{
std::set loaded;
- auto LoadPluginsDir = [&](std::string path, std::string extension)
- {
+ auto LoadPluginsDir = [&](std::string path, std::string prefix, std::string extension)
+ {
+ std::set> filesWithPrefix;
+ std::set> filesWithoutPrefix;
+
FilesWalk(path.c_str(), extension.c_str(), [&](const char* fullPath, const char* filename)
{
std::string name = filename;
name.resize(name.length() - extension.length()); // cut off file type
std::transform(name.begin(), name.end(), name.begin(), [](unsigned char c) { return std::tolower(c); });
- if (loaded.find(name) == loaded.end())
+ if (_strnicmp(name.c_str(), prefix.c_str(), prefix.length()) == 0)
{
- TRACE("Loading plugin '%s'", fullPath);
- HMODULE hlib = LoadLibrary(fullPath);
- if (!hlib)
- {
- LOG_WARNING(0, "Error loading plugin '%s'", fullPath);
- }
- else
- {
- loaded.insert(name);
- plugins.push_back(hlib);
- }
+ filesWithPrefix.insert({ fullPath, name.c_str() + prefix.length() });
}
else
{
- LOG_WARNING(0, "Plugin `%s` already loaded. Skipping '%s'", name.c_str(), fullPath);
+ filesWithoutPrefix.insert({ fullPath, name });
}
});
+
+ auto loadLib = [&](const char* fullPath, const char* name)
+ {
+ if (loaded.find(name) != loaded.end())
+ {
+ LOG_WARNING(0, "Plugin `%s` already loaded. Skipping '%s'", fullPath, name);
+ return;
+ }
+
+ TRACE("Loading plugin '%s'", fullPath);
+ HMODULE hlib = LoadLibrary(fullPath);
+ if (!hlib)
+ {
+ LOG_WARNING(0, "Error loading plugin '%s'", fullPath);
+ return;
+ }
+
+ loaded.insert(name);
+ plugins.push_back(hlib);
+ };
+
+ // load with prefix first
+ for (const auto& entry : filesWithPrefix) loadLib(entry.first.c_str(), entry.second.c_str());
+ for (const auto& entry : filesWithoutPrefix) loadLib(entry.first.c_str(), entry.second.c_str());
};
TRACE("Loading plugins...");
- LoadPluginsDir(FS::path(Filepath_Cleo).append("cleo_plugins").string(), ".cleo5"); // CLEO5 plugins
- LoadPluginsDir(FS::path(Filepath_Cleo).append("cleo_plugins").string(), ".cleo"); // legacy plugins
- LoadPluginsDir(Filepath_Cleo.c_str(), ".cleo"); // legacy plugins location
+ LoadPluginsDir(FS::path(Filepath_Cleo).append("cleo_plugins").string(), "SA.", ".cleo"); // prioritize with prefix
+ LoadPluginsDir(Filepath_Cleo.c_str(), "SA.", ".cleo"); // legacy plugins location
}
~CPluginSystem()
diff --git a/source/CleoBase.cpp b/source/CleoBase.cpp
index c872d51d..9a010cf0 100644
--- a/source/CleoBase.cpp
+++ b/source/CleoBase.cpp
@@ -116,11 +116,10 @@ namespace CLEO
if (m_bStarted) return; // already started
m_bStarted = true;
- FS::create_directory(Filepath_Cleo);
- FS::create_directory(FS::path(Filepath_Cleo).append("cleo_modules"));
- FS::create_directory(FS::path(Filepath_Cleo).append("cleo_plugins"));
- FS::create_directory(FS::path(Filepath_Cleo).append("cleo_saves"));
- FS::create_directory(FS::path(Filepath_Cleo).append("cleo_text"));
+ FS::create_directory(FS::path(Filepath_Root).append("cleo"));
+ FS::create_directory(FS::path(Filepath_Root).append("cleo\\cleo_modules"));
+ FS::create_directory(FS::path(Filepath_Root).append("cleo\\cleo_plugins"));
+ FS::create_directory(FS::path(Filepath_Root).append("cleo\\cleo_saves"));
CodeInjector.OpenReadWriteAccess(); // must do this earlier to ensure plugins write access on init
GameMenu.Inject(CodeInjector);