diff --git a/src/android/android_main.cpp b/src/android/android_main.cpp
index 03b06beecf..e60ec49765 100644
--- a/src/android/android_main.cpp
+++ b/src/android/android_main.cpp
@@ -1,159 +1,236 @@
-#include
-
-#ifdef CONF_PLATFORM_ANDROID
-#include
-#include
+#include "android_main.h"
#include
#include
+#include
#include
+
#include
+
#include
#include
-extern "C" __attribute__((visibility("default"))) void InitAndroid();
-
-static int gs_AndroidStarted = false;
-
-void InitAndroid()
+static bool UnpackAsset(const char *pFilename)
{
- if(gs_AndroidStarted)
+ char aAssetFilename[IO_MAX_PATH_LENGTH];
+ str_copy(aAssetFilename, "asset_integrity_files/");
+ str_append(aAssetFilename, pFilename);
+
+ // This uses SDL_RWFromFile because it can read Android assets,
+ // which are files stored in the app's APK file. All data files
+ // are stored as assets and unpacked to the external storage.
+ SDL_RWops *pAssetFile = SDL_RWFromFile(aAssetFilename, "rb");
+ if(!pAssetFile)
{
- SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "DDNet", "The app was started, but not closed properly, this causes bugs. Please restart or manually delete this task.", SDL_GL_GetCurrentWindow());
- std::exit(0);
+ log_error("android", "Failed to open asset '%s' for reading", pFilename);
+ return false;
}
- gs_AndroidStarted = true;
+ const long int FileLength = SDL_RWsize(pAssetFile);
+ if(FileLength < 0)
+ {
+ SDL_RWclose(pAssetFile);
+ log_error("android", "Failed to determine length of asset '%s'", pFilename);
+ return false;
+ }
- // change current path to a writable directory
- const char *pPath = SDL_AndroidGetExternalStoragePath();
- chdir(pPath);
- dbg_msg("client", "changed path to %s", pPath);
+ char *pData = static_cast(malloc(FileLength));
+ const size_t ReadLength = SDL_RWread(pAssetFile, pData, 1, FileLength);
+ SDL_RWclose(pAssetFile);
- // copy integrity files
+ if(ReadLength != (size_t)FileLength)
{
- SDL_RWops *pF = SDL_RWFromFile("asset_integrity_files/integrity.txt", "rb");
- if(!pF)
- {
- SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "DDNet", "integrity.txt not found, consider reinstalling", SDL_GL_GetCurrentWindow());
- std::exit(0);
- }
+ free(pData);
+ log_error("android", "Failed to read asset '%s' (read %" PRIzu ", wanted %ld)", pFilename, ReadLength, FileLength);
+ return false;
+ }
+
+ IOHANDLE TargetFile = io_open(pFilename, IOFLAG_WRITE);
+ if(!TargetFile)
+ {
+ free(pData);
+ log_error("android", "Failed to open '%s' for writing", pFilename);
+ return false;
+ }
- long int length;
- SDL_RWseek(pF, 0, RW_SEEK_END);
- length = SDL_RWtell(pF);
- SDL_RWseek(pF, 0, RW_SEEK_SET);
+ const size_t WriteLength = io_write(TargetFile, pData, FileLength);
+ io_close(TargetFile);
+ free(pData);
+
+ if(WriteLength != (size_t)FileLength)
+ {
+ log_error("android", "Failed to write data to '%s' (wrote %" PRIzu ", wanted %ld)", pFilename, WriteLength, FileLength);
+ return false;
+ }
- char *pAl = (char *)malloc(length);
- SDL_RWread(pF, pAl, 1, length);
+ return true;
+}
- SDL_RWclose(pF);
+constexpr const char *INTEGRITY_INDEX = "integrity.txt";
+constexpr const char *INTEGRITY_INDEX_SAVE = "integrity_save.txt";
- mkdir("data", 0755);
+// The first line of each integrity file contains the combined hash for all files,
+// if the hashes match then we assume that the unpacked data folder is up-to-date.
+static bool EqualIntegrityFiles(const char *pAssetFilename, const char *pStorageFilename)
+{
+ IOHANDLE StorageFile = io_open(pStorageFilename, IOFLAG_READ);
+ if(!StorageFile)
+ {
+ return false;
+ }
- dbg_msg("integrity", "copying integrity.txt with size: %ld", length);
+ char aStorageMainSha256[SHA256_MAXSTRSIZE];
+ const size_t StorageReadLength = io_read(StorageFile, aStorageMainSha256, sizeof(aStorageMainSha256) - 1);
+ io_close(StorageFile);
+ if(StorageReadLength != sizeof(aStorageMainSha256) - 1)
+ {
+ return false;
+ }
+ aStorageMainSha256[sizeof(aStorageMainSha256) - 1] = '\0';
- IOHANDLE pIO = io_open("integrity.txt", IOFLAG_WRITE);
- io_write(pIO, pAl, length);
- io_close(pIO);
+ char aAssetFilename[IO_MAX_PATH_LENGTH];
+ str_copy(aAssetFilename, "asset_integrity_files/");
+ str_append(aAssetFilename, pAssetFilename);
- free(pAl);
+ SDL_RWops *pAssetFile = SDL_RWFromFile(aAssetFilename, "rb");
+ if(!pAssetFile)
+ {
+ return false;
}
- IOHANDLE pIO = io_open("integrity.txt", IOFLAG_READ);
- CLineReader LineReader;
- LineReader.Init(pIO);
- const char *pReadLine = NULL;
- std::vector vLines;
- while((pReadLine = LineReader.Get()))
+ char aAssetMainSha256[SHA256_MAXSTRSIZE];
+ const size_t AssetReadLength = SDL_RWread(pAssetFile, aAssetMainSha256, 1, sizeof(aAssetMainSha256) - 1);
+ SDL_RWclose(pAssetFile);
+ if(AssetReadLength != sizeof(aAssetMainSha256) - 1)
{
- vLines.push_back(pReadLine);
+ return false;
}
- io_close(pIO);
+ aAssetMainSha256[sizeof(aAssetMainSha256) - 1] = '\0';
+
+ return str_comp(aStorageMainSha256, aAssetMainSha256) == 0;
+}
+
+class CIntegrityFileLine
+{
+public:
+ char m_aFilename[IO_MAX_PATH_LENGTH];
+ SHA256_DIGEST m_Sha256;
+};
- // first line is the whole hash
- std::string AllAsOne;
- for(size_t i = 1; i < vLines.size(); ++i)
+static std::vector ReadIntegrityFile(const char *pFilename)
+{
+ CLineReader LineReader;
+ if(!LineReader.OpenFile(io_open(pFilename, IOFLAG_READ)))
{
- AllAsOne.append(vLines[i]);
- AllAsOne.append("\n");
+ return {};
}
- SHA256_DIGEST ShaAll;
- bool GotSHA = false;
+
+ std::vector vLines;
+ while(const char *pReadLine = LineReader.Get())
{
- IOHANDLE pIOR = io_open("integrity_save.txt", IOFLAG_READ);
- if(pIOR != NULL)
+ const char *pSpaceInLine = str_rchr(pReadLine, ' ');
+ CIntegrityFileLine Line;
+ char aSha256[SHA256_MAXSTRSIZE];
+ if(pSpaceInLine == nullptr)
{
- CLineReader LineReader;
- LineReader.Init(pIOR);
- const char *pLine = LineReader.Get();
- if(pLine != NULL)
+ if(!vLines.empty())
{
- sha256_from_str(&ShaAll, pLine);
- GotSHA = true;
+ // Only the first line is allowed to not contain a filename
+ log_error("android", "Failed to parse line %" PRIzu " of '%s': line does not contain space", vLines.size() + 1, pFilename);
+ return {};
}
+ Line.m_aFilename[0] = '\0';
+ str_copy(aSha256, pReadLine);
}
+ else
+ {
+ str_truncate(Line.m_aFilename, sizeof(Line.m_aFilename), pReadLine, pSpaceInLine - pReadLine);
+ str_copy(aSha256, pSpaceInLine + 1);
+ }
+ if(sha256_from_str(&Line.m_Sha256, aSha256) != 0)
+ {
+ log_error("android", "Failed to parse line %" PRIzu " of '%s': invalid SHA256 string", vLines.size() + 1, pFilename);
+ return {};
+ }
+ vLines.emplace_back(std::move(Line));
}
- SHA256_DIGEST ShaAllFile;
- sha256_from_str(&ShaAllFile, vLines[0].c_str());
+ return vLines;
+}
- // TODO: check files individually
- if(!GotSHA || ShaAllFile != ShaAll)
+const char *InitAndroid()
+{
+ // Change current working directory to our external storage location
+ const char *pPath = SDL_AndroidGetExternalStoragePath();
+ if(pPath == nullptr)
{
- // then the files
- for(size_t i = 1; i < vLines.size(); ++i)
- {
- std::string FileName, Hash;
- std::string::size_type n = 0;
- std::string::size_type c = 0;
- while((c = vLines[i].find(' ', n)) != std::string::npos)
- n = c + 1;
- FileName = vLines[i].substr(0, n - 1);
- Hash = vLines[i].substr(n + 1);
-
- std::string AssetFileName = std::string("asset_integrity_files/") + FileName;
- SDL_RWops *pF = SDL_RWFromFile(AssetFileName.c_str(), "rb");
-
- dbg_msg("Integrity", "Copying from assets: %s", FileName.c_str());
-
- std::string FileNamePath = FileName;
- std::string FileNamePathSub;
- c = 0;
- while((c = FileNamePath.find('/', c)) != std::string::npos)
- {
- FileNamePathSub = FileNamePath.substr(0, c);
- fs_makedir(FileNamePathSub.c_str());
- ++c;
- }
+ return "The external storage is not available.";
+ }
+ if(fs_chdir(pPath) != 0)
+ {
+ return "Failed to change current directory to external storage.";
+ }
+ log_info("android", "Changed current directory to '%s'", pPath);
+
+ if(fs_makedir("data") != 0 || fs_makedir("user") != 0)
+ {
+ return "Failed to create 'data' and 'user' directories in external storage.";
+ }
- long int length;
- SDL_RWseek(pF, 0, RW_SEEK_END);
- length = SDL_RWtell(pF);
- SDL_RWseek(pF, 0, RW_SEEK_SET);
+ if(EqualIntegrityFiles(INTEGRITY_INDEX, INTEGRITY_INDEX_SAVE))
+ {
+ return nullptr;
+ }
+
+ if(!UnpackAsset(INTEGRITY_INDEX))
+ {
+ return "Failed to unpack the integrity index file. Consider reinstalling the app.";
+ }
- char *pAl = (char *)malloc(length);
- SDL_RWread(pF, pAl, 1, length);
+ std::vector vIntegrityLines = ReadIntegrityFile(INTEGRITY_INDEX);
+ if(vIntegrityLines.empty())
+ {
+ return "Failed to load the integrity index file. Consider reinstalling the app.";
+ }
- SDL_RWclose(pF);
+ std::vector vIntegritySaveLines = ReadIntegrityFile(INTEGRITY_INDEX_SAVE);
- IOHANDLE pIO = io_open(FileName.c_str(), IOFLAG_WRITE);
- io_write(pIO, pAl, length);
- io_close(pIO);
+ // The remaining lines of each integrity file list all assets and their hashes
+ for(size_t i = 1; i < vIntegrityLines.size(); ++i)
+ {
+ const CIntegrityFileLine &IntegrityLine = vIntegrityLines[i];
- free(pAl);
+ // Check if the asset is unchanged from the last unpacking
+ const auto IntegritySaveLine = std::find_if(vIntegritySaveLines.begin(), vIntegritySaveLines.end(), [&](const CIntegrityFileLine &Line) {
+ return str_comp(Line.m_aFilename, IntegrityLine.m_aFilename) == 0;
+ });
+ if(IntegritySaveLine != vIntegritySaveLines.end() && IntegritySaveLine->m_Sha256 == IntegrityLine.m_Sha256)
+ {
+ continue;
}
- IOHANDLE pIOR = io_open("integrity_save.txt", IOFLAG_WRITE);
- if(pIOR != NULL)
+ if(fs_makedir_rec_for(IntegrityLine.m_aFilename) != 0 || !UnpackAsset(IntegrityLine.m_aFilename))
{
- char aFileSHA[SHA256_MAXSTRSIZE];
- sha256_str(ShaAllFile, aFileSHA, sizeof(aFileSHA));
- io_write(pIOR, aFileSHA, str_length(aFileSHA));
- io_close(pIOR);
+ return "Failed to unpack game assets, consider reinstalling the app.";
}
}
+
+ // The integrity file will be unpacked every time when launching,
+ // so we can simply rename it to update the saved integrity file.
+ if((fs_is_file(INTEGRITY_INDEX_SAVE) && fs_remove(INTEGRITY_INDEX_SAVE) != 0) || fs_rename(INTEGRITY_INDEX, INTEGRITY_INDEX_SAVE) != 0)
+ {
+ return "Failed to update the saved integrity index file.";
+ }
+
+ return nullptr;
}
-#endif
+// See NativeMain.java
+constexpr uint32_t COMMAND_USER = 0x8000;
+constexpr uint32_t COMMAND_RESTART_APP = COMMAND_USER + 1;
+
+void RestartAndroidApp()
+{
+ SDL_AndroidSendMessage(COMMAND_RESTART_APP, 0);
+}
diff --git a/src/android/android_main.h b/src/android/android_main.h
new file mode 100644
index 0000000000..c7e3a3e88d
--- /dev/null
+++ b/src/android/android_main.h
@@ -0,0 +1,31 @@
+#ifndef ANDROID_ANDROID_MAIN_H
+#define ANDROID_ANDROID_MAIN_H
+
+#include
+#if !defined(CONF_PLATFORM_ANDROID)
+#error "This header should only be included when compiling for Android"
+#endif
+
+/**
+ * Initializes the Android storage. Must be called on Android-systems
+ * before using any of the I/O and storage functions.
+ *
+ * This will change the current working directory to the app specific external
+ * storage location and unpack the assets from the APK file to the `data` folder.
+ * The folder `user` is created in the external storage to store the user data.
+ *
+ * Failure must be handled by exiting the app.
+ *
+ * @return `nullptr` on success, error message on failure.
+ */
+const char *InitAndroid();
+
+/**
+ * Sends an intent to the Android system to restart the app.
+ *
+ * This will restart the main activity in a new task. The current process
+ * must immediately terminate after this function is called.
+ */
+void RestartAndroidApp();
+
+#endif // ANDROID_ANDROID_MAIN_H
diff --git a/src/antibot/antibot_data.h b/src/antibot/antibot_data.h
index f65f626287..5751db6163 100644
--- a/src/antibot/antibot_data.h
+++ b/src/antibot/antibot_data.h
@@ -87,10 +87,10 @@ struct CAntibotData
int64_t m_Now;
int64_t m_Freq;
- void (*m_pfnKick)(int ClientID, const char *pMessage, void *pUser);
+ void (*m_pfnKick)(int ClientId, const char *pMessage, void *pUser);
void (*m_pfnLog)(const char *pMessage, void *pUser);
- void (*m_pfnReport)(int ClientID, const char *pMessage, void *pUser);
- void (*m_pfnSend)(int ClientID, const void *pData, int DataSize, int Flags, void *pUser);
+ void (*m_pfnReport)(int ClientId, const char *pMessage, void *pUser);
+ void (*m_pfnSend)(int ClientId, const void *pData, int DataSize, int Flags, void *pUser);
void (*m_pfnTeehistorian)(const void *pData, int DataSize, void *pUser);
void *m_pUser;
};
diff --git a/src/antibot/antibot_interface.h b/src/antibot/antibot_interface.h
index a982802c9e..e98e7cd636 100644
--- a/src/antibot/antibot_interface.h
+++ b/src/antibot/antibot_interface.h
@@ -17,23 +17,23 @@ ANTIBOTAPI void AntibotRoundEnd(void);
ANTIBOTAPI void AntibotUpdateData(void);
ANTIBOTAPI void AntibotDestroy(void);
ANTIBOTAPI void AntibotConsoleCommand(const char *pCommand);
-ANTIBOTAPI void AntibotOnPlayerInit(int ClientID);
-ANTIBOTAPI void AntibotOnPlayerDestroy(int ClientID);
-ANTIBOTAPI void AntibotOnSpawn(int ClientID);
-ANTIBOTAPI void AntibotOnHammerFireReloading(int ClientID);
-ANTIBOTAPI void AntibotOnHammerFire(int ClientID);
-ANTIBOTAPI void AntibotOnHammerHit(int ClientID, int TargetID);
-ANTIBOTAPI void AntibotOnDirectInput(int ClientID);
-ANTIBOTAPI void AntibotOnCharacterTick(int ClientID);
-ANTIBOTAPI void AntibotOnHookAttach(int ClientID, bool Player);
+ANTIBOTAPI void AntibotOnPlayerInit(int ClientId);
+ANTIBOTAPI void AntibotOnPlayerDestroy(int ClientId);
+ANTIBOTAPI void AntibotOnSpawn(int ClientId);
+ANTIBOTAPI void AntibotOnHammerFireReloading(int ClientId);
+ANTIBOTAPI void AntibotOnHammerFire(int ClientId);
+ANTIBOTAPI void AntibotOnHammerHit(int ClientId, int TargetId);
+ANTIBOTAPI void AntibotOnDirectInput(int ClientId);
+ANTIBOTAPI void AntibotOnCharacterTick(int ClientId);
+ANTIBOTAPI void AntibotOnHookAttach(int ClientId, bool Player);
ANTIBOTAPI void AntibotOnEngineTick(void);
-ANTIBOTAPI void AntibotOnEngineClientJoin(int ClientID, bool Sixup);
-ANTIBOTAPI void AntibotOnEngineClientDrop(int ClientID, const char *pReason);
+ANTIBOTAPI void AntibotOnEngineClientJoin(int ClientId, bool Sixup);
+ANTIBOTAPI void AntibotOnEngineClientDrop(int ClientId, const char *pReason);
// Returns true if the message shouldn't be processed by the server.
-ANTIBOTAPI bool AntibotOnEngineClientMessage(int ClientID, const void *pData, int Size, int Flags);
-ANTIBOTAPI bool AntibotOnEngineServerMessage(int ClientID, const void *pData, int Size, int Flags);
+ANTIBOTAPI bool AntibotOnEngineClientMessage(int ClientId, const void *pData, int Size, int Flags);
+ANTIBOTAPI bool AntibotOnEngineServerMessage(int ClientId, const void *pData, int Size, int Flags);
// Returns true if the server should simulate receiving a client message.
-ANTIBOTAPI bool AntibotOnEngineSimulateClientMessage(int *pClientID, void *pBuffer, int BufferSize, int *pOutSize, int *pFlags);
+ANTIBOTAPI bool AntibotOnEngineSimulateClientMessage(int *pClientId, void *pBuffer, int BufferSize, int *pOutSize, int *pFlags);
}
#endif // ANTIBOT_ANTIBOT_INTERFACE_H
diff --git a/src/antibot/antibot_null.cpp b/src/antibot/antibot_null.cpp
index 6a70c0387a..2db022c097 100644
--- a/src/antibot/antibot_null.cpp
+++ b/src/antibot/antibot_null.cpp
@@ -32,19 +32,19 @@ void AntibotConsoleCommand(const char *pCommand)
g_pData->m_pfnLog("unknown command", g_pData->m_pUser);
}
}
-void AntibotOnPlayerInit(int /*ClientID*/) {}
-void AntibotOnPlayerDestroy(int /*ClientID*/) {}
-void AntibotOnSpawn(int /*ClientID*/) {}
-void AntibotOnHammerFireReloading(int /*ClientID*/) {}
-void AntibotOnHammerFire(int /*ClientID*/) {}
-void AntibotOnHammerHit(int /*ClientID*/, int /*TargetID*/) {}
-void AntibotOnDirectInput(int /*ClientID*/) {}
-void AntibotOnCharacterTick(int /*ClientID*/) {}
-void AntibotOnHookAttach(int /*ClientID*/, bool /*Player*/) {}
+void AntibotOnPlayerInit(int /*ClientId*/) {}
+void AntibotOnPlayerDestroy(int /*ClientId*/) {}
+void AntibotOnSpawn(int /*ClientId*/) {}
+void AntibotOnHammerFireReloading(int /*ClientId*/) {}
+void AntibotOnHammerFire(int /*ClientId*/) {}
+void AntibotOnHammerHit(int /*ClientId*/, int /*TargetId*/) {}
+void AntibotOnDirectInput(int /*ClientId*/) {}
+void AntibotOnCharacterTick(int /*ClientId*/) {}
+void AntibotOnHookAttach(int /*ClientId*/, bool /*Player*/) {}
void AntibotOnEngineTick(void) {}
-void AntibotOnEngineClientJoin(int /*ClientID*/, bool /*Sixup*/) {}
-void AntibotOnEngineClientDrop(int /*ClientID*/, const char * /*pReason*/) {}
-bool AntibotOnEngineClientMessage(int /*ClientID*/, const void * /*pData*/, int /*Size*/, int /*Flags*/) { return false; }
-bool AntibotOnEngineServerMessage(int /*ClientID*/, const void * /*pData*/, int /*Size*/, int /*Flags*/) { return false; }
-bool AntibotOnEngineSimulateClientMessage(int * /*pClientID*/, void * /*pBuffer*/, int /*BufferSize*/, int * /*pOutSize*/, int * /*pFlags*/) { return false; }
+void AntibotOnEngineClientJoin(int /*ClientId*/, bool /*Sixup*/) {}
+void AntibotOnEngineClientDrop(int /*ClientId*/, const char * /*pReason*/) {}
+bool AntibotOnEngineClientMessage(int /*ClientId*/, const void * /*pData*/, int /*Size*/, int /*Flags*/) { return false; }
+bool AntibotOnEngineServerMessage(int /*ClientId*/, const void * /*pData*/, int /*Size*/, int /*Flags*/) { return false; }
+bool AntibotOnEngineSimulateClientMessage(int * /*pClientId*/, void * /*pBuffer*/, int /*BufferSize*/, int * /*pOutSize*/, int * /*pFlags*/) { return false; }
}
diff --git a/src/base/.clang-tidy b/src/base/.clang-tidy
new file mode 100644
index 0000000000..6d6f9e5d52
--- /dev/null
+++ b/src/base/.clang-tidy
@@ -0,0 +1 @@
+Checks: '-readability-identifier-naming'
diff --git a/src/base/Cargo.toml b/src/base/Cargo.toml
index 709a35c8e3..c72aa91b3a 100644
--- a/src/base/Cargo.toml
+++ b/src/base/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "ddnet-base"
version = "0.0.1"
-edition = "2018"
+edition = "2021"
publish = false
license = "Zlib"
diff --git a/src/base/color.h b/src/base/color.h
index 4e84645f43..0480183069 100644
--- a/src/base/color.h
+++ b/src/base/color.h
@@ -137,6 +137,16 @@ class color4_base
return col;
}
+ DerivedT Multiply(const DerivedT &Other) const
+ {
+ DerivedT Color(static_cast(*this));
+ Color.x *= Other.x;
+ Color.y *= Other.y;
+ Color.z *= Other.z;
+ Color.a *= Other.a;
+ return Color;
+ }
+
template
static UnpackT UnpackAlphaLast(unsigned Color, bool Alpha = true)
{
@@ -166,8 +176,9 @@ class ColorHSLA : public color4_base
ColorHSLA(){};
constexpr static const float DARKEST_LGT = 0.5f;
+ constexpr static const float DARKEST_LGT7 = 61.0f / 255.0f;
- ColorHSLA UnclampLighting(float Darkest = DARKEST_LGT) const
+ ColorHSLA UnclampLighting(float Darkest) const
{
ColorHSLA col = *this;
col.l = Darkest + col.l * (1.0f - Darkest);
diff --git a/src/base/detect.h b/src/base/detect.h
index 8bceed0861..28b9982cb7 100644
--- a/src/base/detect.h
+++ b/src/base/detect.h
@@ -163,19 +163,19 @@
#define CONF_ARCH_ARM 1
#define CONF_ARCH_STRING "arm"
#define CONF_ARCH_ENDIAN_BIG 1
-#endif
-
-#if defined(__ARMEL__)
+#elif defined(__ARMEL__)
#define CONF_ARCH_ARM 1
#define CONF_ARCH_STRING "arm"
#define CONF_ARCH_ENDIAN_LITTLE 1
-#endif
-
-#if defined(__aarch64__) || defined(__arm64__)
+#elif defined(__aarch64__) || defined(__arm64__) || defined(__ARM_ARCH_ISA_A64)
#define CONF_ARCH_ARM64 1
#define CONF_ARCH_STRING "arm64"
+#if defined(__ARM_BIG_ENDIAN)
+#define CONF_ARCH_ENDIAN_BIG 1
+#else
#define CONF_ARCH_ENDIAN_LITTLE 1
#endif
+#endif
#ifndef CONF_FAMILY_STRING
#define CONF_FAMILY_STRING "unknown"
diff --git a/src/base/log.cpp b/src/base/log.cpp
index b0b167c68f..989238007b 100644
--- a/src/base/log.cpp
+++ b/src/base/log.cpp
@@ -8,9 +8,8 @@
#include
#if defined(CONF_FAMILY_WINDOWS)
-#define WIN32_LEAN_AND_MEAN
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501 /* required for mingw to get getaddrinfo to work */
+#include
+#include
#include
#else
#include
@@ -49,7 +48,10 @@ void log_set_global_logger_default()
#else
logger = log_logger_stdout();
#endif
- log_set_global_logger(logger.release());
+ if(logger)
+ {
+ log_set_global_logger(logger.release());
+ }
}
ILogger *log_get_scope_logger()
@@ -233,19 +235,16 @@ class CLoggerAsync : public ILogger
return;
}
aio_lock(m_pAio);
- if(m_AnsiTruecolor)
+ if(m_AnsiTruecolor && pMessage->m_HaveColor)
{
// https://en.wikipedia.org/w/index.php?title=ANSI_escape_code&oldid=1077146479#24-bit
char aAnsi[32];
- if(pMessage->m_HaveColor)
- {
- str_format(aAnsi, sizeof(aAnsi),
- "\x1b[38;2;%d;%d;%dm",
- pMessage->m_Color.r,
- pMessage->m_Color.g,
- pMessage->m_Color.b);
- aio_write_unlocked(m_pAio, aAnsi, str_length(aAnsi));
- }
+ str_format(aAnsi, sizeof(aAnsi),
+ "\x1b[38;2;%d;%d;%dm",
+ pMessage->m_Color.r,
+ pMessage->m_Color.g,
+ pMessage->m_Color.b);
+ aio_write_unlocked(m_pAio, aAnsi, str_length(aAnsi));
}
aio_write_unlocked(m_pAio, pMessage->m_aLine, pMessage->m_LineLength);
if(m_AnsiTruecolor && pMessage->m_HaveColor)
@@ -317,14 +316,16 @@ static int color_hsv_to_windows_console_color(const ColorHSVA &Hsv)
class CWindowsConsoleLogger : public ILogger
{
HANDLE m_pConsole;
+ bool m_EnableColor;
int m_BackgroundColor;
int m_ForegroundColor;
CLock m_OutputLock;
bool m_Finished = false;
public:
- CWindowsConsoleLogger(HANDLE pConsole) :
- m_pConsole(pConsole)
+ CWindowsConsoleLogger(HANDLE pConsole, bool EnableColor) :
+ m_pConsole(pConsole),
+ m_EnableColor(EnableColor)
{
CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
if(GetConsoleScreenBufferInfo(pConsole, &ConsoleInfo))
@@ -344,15 +345,12 @@ class CWindowsConsoleLogger : public ILogger
{
return;
}
- const std::wstring WideMessage = windows_utf8_to_wide(pMessage->m_aLine) + L"\r\n";
+ const std::wstring WideMessage = windows_utf8_to_wide(pMessage->m_aLine);
int Color = m_BackgroundColor;
- if(pMessage->m_HaveColor)
+ if(m_EnableColor && pMessage->m_HaveColor)
{
- ColorRGBA Rgba(1.0, 1.0, 1.0, 1.0);
- Rgba.r = pMessage->m_Color.r / 255.0;
- Rgba.g = pMessage->m_Color.g / 255.0;
- Rgba.b = pMessage->m_Color.b / 255.0;
+ const ColorRGBA Rgba(pMessage->m_Color.r / 255.0f, pMessage->m_Color.g / 255.0f, pMessage->m_Color.b / 255.0f);
Color |= color_hsv_to_windows_console_color(color_cast(Rgba));
}
else
@@ -362,7 +360,8 @@ class CWindowsConsoleLogger : public ILogger
if(!m_Finished)
{
SetConsoleTextAttribute(m_pConsole, Color);
- WriteConsoleW(m_pConsole, WideMessage.c_str(), WideMessage.length(), NULL, NULL);
+ WriteConsoleW(m_pConsole, WideMessage.c_str(), WideMessage.length(), nullptr, nullptr);
+ WriteConsoleW(m_pConsole, L"\r\n", 2, nullptr, nullptr);
}
}
void GlobalFinish() override REQUIRES(!m_OutputLock)
@@ -373,28 +372,15 @@ class CWindowsConsoleLogger : public ILogger
m_Finished = true;
}
};
-class CWindowsFileLogger : public ILogger
-{
- HANDLE m_pFile;
- CLock m_OutputLock;
-public:
- CWindowsFileLogger(HANDLE pFile) :
- m_pFile(pFile)
- {
- }
- void Log(const CLogMessage *pMessage) override REQUIRES(!m_OutputLock)
- {
- if(m_Filter.Filters(pMessage))
- {
- return;
- }
- const CLockScope LockScope(m_OutputLock);
- DWORD Written; // we don't care about the value, but Windows 7 crashes if we pass NULL
- WriteFile(m_pFile, pMessage->m_aLine, pMessage->m_LineLength, &Written, NULL);
- WriteFile(m_pFile, "\r\n", 2, &Written, NULL);
- }
-};
+static IOHANDLE ConvertWindowsHandle(HANDLE pHandle, int OpenFlags)
+{
+ int FileDescriptor = _open_osfhandle(reinterpret_cast(pHandle), OpenFlags);
+ dbg_assert(FileDescriptor != -1, "_open_osfhandle failure");
+ IOHANDLE FileStream = _wfdopen(FileDescriptor, L"w");
+ dbg_assert(FileStream != nullptr, "_wfdopen failure");
+ return FileStream;
+}
#endif
std::unique_ptr log_logger_stdout()
@@ -402,18 +388,71 @@ std::unique_ptr log_logger_stdout()
#if !defined(CONF_FAMILY_WINDOWS)
// TODO: Only enable true color when COLORTERM contains "truecolor".
// https://github.com/termstandard/colors/tree/65bf0cd1ece7c15fa33a17c17528b02c99f1ae0b#checking-for-colorterm
- const bool colors = getenv("NO_COLOR") == nullptr && isatty(STDOUT_FILENO);
- return std::make_unique(io_stdout(), colors, false);
+ const bool Colors = getenv("NO_COLOR") == nullptr && isatty(STDOUT_FILENO);
+ return std::make_unique(io_stdout(), Colors, false);
#else
+ // If we currently have no stdout (console, file, pipe),
+ // try to attach to the console of the parent process.
if(GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) == FILE_TYPE_UNKNOWN)
+ {
AttachConsole(ATTACH_PARENT_PROCESS);
+ }
+
HANDLE pOutput = GetStdHandle(STD_OUTPUT_HANDLE);
- switch(GetFileType(pOutput))
+ if(pOutput == nullptr)
{
- case FILE_TYPE_CHAR: return std::make_unique(pOutput);
- case FILE_TYPE_PIPE: [[fallthrough]]; // writing to pipe works the same as writing to a file
- case FILE_TYPE_DISK: return std::make_unique(pOutput);
- default: return std::make_unique(io_stdout(), false, false);
+ // There is no console, file or pipe that we can output to.
+ return nullptr;
+ }
+ dbg_assert(pOutput != INVALID_HANDLE_VALUE, "GetStdHandle failure");
+
+ const DWORD OutputType = GetFileType(pOutput);
+ if(OutputType == FILE_TYPE_CHAR)
+ {
+ DWORD OldConsoleMode = 0;
+ if(!GetConsoleMode(pOutput, &OldConsoleMode))
+ {
+ // GetConsoleMode can fail with ERROR_INVALID_HANDLE when redirecting output to "nul",
+ // which is considered a character file but cannot be used as a console.
+ dbg_assert(GetLastError() == ERROR_INVALID_HANDLE, "GetConsoleMode failure");
+ return nullptr;
+ }
+
+ const bool Colors = _wgetenv(L"NO_COLOR") == nullptr;
+
+ // Try to enable virtual terminal processing in the Windows console.
+ // See https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
+ if(!SetConsoleMode(pOutput, OldConsoleMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN))
+ {
+ // Try to downgrade mode gracefully when failing to set both.
+ if(!SetConsoleMode(pOutput, OldConsoleMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING))
+ {
+ // Fallback to old, slower Windows logging API, when failing to enable virtual terminal processing.
+ return std::make_unique(pOutput, Colors);
+ }
+ }
+
+ // Virtual terminal processing was enabled successfully. We can
+ // use the async logger with ANSI escape codes for colors now.
+ // We need to set the output encoding to UTF-8 manually and
+ // convert the HANDLE to an IOHANDLE to use the async logger.
+ // We assume UTF-8 is available when virtual terminal processing is.
+ dbg_assert(SetConsoleOutputCP(CP_UTF8) != 0, "SetConsoleOutputCP failure");
+ return std::make_unique(ConvertWindowsHandle(pOutput, _O_TEXT), Colors, false);
+ }
+ else if(OutputType == FILE_TYPE_DISK || OutputType == FILE_TYPE_PIPE)
+ {
+ // Writing to a pipe works the same as writing to a file.
+ // We can use the async logger to write to files and pipes
+ // by converting the HANDLE to an IOHANDLE.
+ // For pipes there does not seem to be any way to determine
+ // whether the console supports ANSI escape codes.
+ return std::make_unique(ConvertWindowsHandle(pOutput, _O_APPEND), false, false);
+ }
+ else
+ {
+ dbg_assert(false, "GetFileType failure");
+ dbg_break();
}
#endif
}
@@ -444,6 +483,19 @@ std::unique_ptr log_logger_windows_debugger()
}
#endif
+class CLoggerNoOp : public ILogger
+{
+public:
+ void Log(const CLogMessage *pMessage) override
+ {
+ // no-op
+ }
+};
+std::unique_ptr log_logger_noop()
+{
+ return std::make_unique();
+}
+
void CFutureLogger::Set(std::shared_ptr pLogger)
{
const CLockScope LockScope(m_PendingLock);
diff --git a/src/base/logger.h b/src/base/logger.h
index cc6575b49a..b43d0468c0 100644
--- a/src/base/logger.h
+++ b/src/base/logger.h
@@ -210,6 +210,13 @@ std::unique_ptr log_logger_stdout();
*/
std::unique_ptr log_logger_windows_debugger();
+/**
+ * @ingroup Log
+ *
+ * Logger which discards all logs.
+ */
+std::unique_ptr log_logger_noop();
+
/**
* @ingroup Log
*
diff --git a/src/base/system.cpp b/src/base/system.cpp
index 4255afa228..f42341453c 100644
--- a/src/base/system.cpp
+++ b/src/base/system.cpp
@@ -9,7 +9,9 @@
#include
#include
#include
+#include // std::get_time
#include // std::size
+#include // std::istringstream
#include
#include "lock.h"
@@ -60,11 +62,6 @@
#endif
#elif defined(CONF_FAMILY_WINDOWS)
-#define WIN32_LEAN_AND_MEAN
-#undef _WIN32_WINNT
-// 0x0501 (Windows XP) is required for mingw to get getaddrinfo to work
-// 0x0600 (Windows Vista) is required to use RegGetValueW and RegDeleteTreeW
-#define _WIN32_WINNT 0x0600
#include
#include
#include
@@ -87,58 +84,6 @@
#include
#endif
-IOHANDLE io_stdin()
-{
- return stdin;
-}
-
-IOHANDLE io_stdout()
-{
- return stdout;
-}
-
-IOHANDLE io_stderr()
-{
- return stderr;
-}
-
-IOHANDLE io_current_exe()
-{
- // From https://stackoverflow.com/a/1024937.
-#if defined(CONF_FAMILY_WINDOWS)
- wchar_t wide_path[IO_MAX_PATH_LENGTH];
- if(GetModuleFileNameW(NULL, wide_path, std::size(wide_path)) == 0 || GetLastError() != ERROR_SUCCESS)
- {
- return 0;
- }
- const std::optional path = windows_wide_to_utf8(wide_path);
- return path.has_value() ? io_open(path.value().c_str(), IOFLAG_READ) : 0;
-#elif defined(CONF_PLATFORM_MACOS)
- char path[IO_MAX_PATH_LENGTH];
- uint32_t path_size = sizeof(path);
- if(_NSGetExecutablePath(path, &path_size))
- {
- return 0;
- }
- return io_open(path, IOFLAG_READ);
-#else
- static const char *NAMES[] = {
- "/proc/self/exe", // Linux, Android
- "/proc/curproc/exe", // NetBSD
- "/proc/curproc/file", // DragonFly
- };
- for(auto &name : NAMES)
- {
- IOHANDLE result = io_open(name, IOFLAG_READ);
- if(result)
- {
- return result;
- }
- }
- return 0;
-#endif
-}
-
static NETSTATS network_stats = {0};
#define VLEN 128
@@ -254,9 +199,9 @@ bool mem_has_null(const void *block, size_t size)
return false;
}
-IOHANDLE io_open_impl(const char *filename, int flags)
+IOHANDLE io_open(const char *filename, int flags)
{
- dbg_assert(flags == (IOFLAG_READ | IOFLAG_SKIP_BOM) || flags == IOFLAG_READ || flags == IOFLAG_WRITE || flags == IOFLAG_APPEND, "flags must be read, read+skipbom, write or append");
+ dbg_assert(flags == IOFLAG_READ || flags == IOFLAG_WRITE || flags == IOFLAG_APPEND, "flags must be read, write or append");
#if defined(CONF_FAMILY_WINDOWS)
const std::wstring wide_filename = windows_utf8_to_wide(filename);
DWORD desired_access;
@@ -271,7 +216,7 @@ IOHANDLE io_open_impl(const char *filename, int flags)
else if(flags == IOFLAG_WRITE)
{
desired_access = FILE_WRITE_DATA;
- creation_disposition = OPEN_ALWAYS;
+ creation_disposition = CREATE_ALWAYS;
open_mode = "wb";
}
else if(flags == IOFLAG_APPEND)
@@ -316,21 +261,6 @@ IOHANDLE io_open_impl(const char *filename, int flags)
#endif
}
-IOHANDLE io_open(const char *filename, int flags)
-{
- IOHANDLE result = io_open_impl(filename, flags);
- unsigned char buf[3];
- if((flags & IOFLAG_SKIP_BOM) == 0 || !result)
- {
- return result;
- }
- if(io_read(result, buf, sizeof(buf)) != 3 || buf[0] != 0xef || buf[1] != 0xbb || buf[2] != 0xbf)
- {
- io_seek(result, 0, IOSEEK_START);
- }
- return result;
-}
-
unsigned io_read(IOHANDLE io, void *buffer, unsigned size)
{
return fread(buffer, 1, size, (FILE *)io);
@@ -421,11 +351,6 @@ long int io_length(IOHANDLE io)
return length;
}
-int io_error(IOHANDLE io)
-{
- return ferror((FILE *)io);
-}
-
unsigned io_write(IOHANDLE io, const void *buffer, unsigned size)
{
return fwrite(buffer, 1, size, (FILE *)io);
@@ -463,6 +388,63 @@ int io_sync(IOHANDLE io)
#endif
}
+int io_error(IOHANDLE io)
+{
+ return ferror((FILE *)io);
+}
+
+IOHANDLE io_stdin()
+{
+ return stdin;
+}
+
+IOHANDLE io_stdout()
+{
+ return stdout;
+}
+
+IOHANDLE io_stderr()
+{
+ return stderr;
+}
+
+IOHANDLE io_current_exe()
+{
+ // From https://stackoverflow.com/a/1024937.
+#if defined(CONF_FAMILY_WINDOWS)
+ wchar_t wide_path[IO_MAX_PATH_LENGTH];
+ if(GetModuleFileNameW(NULL, wide_path, std::size(wide_path)) == 0 || GetLastError() != ERROR_SUCCESS)
+ {
+ return 0;
+ }
+ const std::optional path = windows_wide_to_utf8(wide_path);
+ return path.has_value() ? io_open(path.value().c_str(), IOFLAG_READ) : 0;
+#elif defined(CONF_PLATFORM_MACOS)
+ char path[IO_MAX_PATH_LENGTH];
+ uint32_t path_size = sizeof(path);
+ if(_NSGetExecutablePath(path, &path_size))
+ {
+ return 0;
+ }
+ return io_open(path, IOFLAG_READ);
+#else
+ static const char *NAMES[] = {
+ "/proc/self/exe", // Linux, Android
+ "/proc/curproc/exe", // NetBSD
+ "/proc/curproc/file", // DragonFly
+ };
+ for(auto &name : NAMES)
+ {
+ IOHANDLE result = io_open(name, IOFLAG_READ);
+ if(result)
+ {
+ return result;
+ }
+ }
+ return 0;
+#endif
+}
+
#define ASYNC_BUFSIZE (8 * 1024)
#define ASYNC_LOCAL_BUFSIZE (64 * 1024)
@@ -737,17 +719,6 @@ int aio_error(ASYNCIO *aio)
return aio->error;
}
-void aio_free(ASYNCIO *aio)
-{
- aio->lock.lock();
- if(aio->thread)
- {
- thread_detach(aio->thread);
- aio->thread = 0;
- }
- aio_handle_free_and_unlock(aio);
-}
-
void aio_close(ASYNCIO *aio)
{
{
@@ -773,6 +744,17 @@ void aio_wait(ASYNCIO *aio)
thread_wait(thread);
}
+void aio_free(ASYNCIO *aio)
+{
+ aio->lock.lock();
+ if(aio->thread)
+ {
+ thread_detach(aio->thread);
+ aio->thread = 0;
+ }
+ aio_handle_free_and_unlock(aio);
+}
+
struct THREAD_RUN
{
void (*threadfunc)(void *);
@@ -805,12 +787,12 @@ void *thread_init(void (*threadfunc)(void *), void *u, const char *name)
data->u = u;
#if defined(CONF_FAMILY_UNIX)
{
- pthread_t id;
pthread_attr_t attr;
- pthread_attr_init(&attr);
+ dbg_assert(pthread_attr_init(&attr) == 0, "pthread_attr_init failure");
#if defined(CONF_PLATFORM_MACOS) && defined(__MAC_10_10) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_10
- pthread_attr_set_qos_class_np(&attr, QOS_CLASS_USER_INTERACTIVE, 0);
+ dbg_assert(pthread_attr_set_qos_class_np(&attr, QOS_CLASS_USER_INTERACTIVE, 0) == 0, "pthread_attr_set_qos_class_np failure");
#endif
+ pthread_t id;
dbg_assert(pthread_create(&id, &attr, thread_run, data) == 0, "pthread_create failure");
return (void *)id;
}
@@ -827,12 +809,10 @@ void *thread_init(void (*threadfunc)(void *), void *u, const char *name)
void thread_wait(void *thread)
{
#if defined(CONF_FAMILY_UNIX)
- int result = pthread_join((pthread_t)thread, NULL);
- if(result != 0)
- dbg_msg("thread", "!! %d", result);
+ dbg_assert(pthread_join((pthread_t)thread, nullptr) == 0, "pthread_join failure");
#elif defined(CONF_FAMILY_WINDOWS)
- WaitForSingleObject((HANDLE)thread, INFINITE);
- CloseHandle(thread);
+ dbg_assert(WaitForSingleObject((HANDLE)thread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failure");
+ dbg_assert(CloseHandle(thread), "CloseHandle failure");
#else
#error not implemented
#endif
@@ -841,9 +821,7 @@ void thread_wait(void *thread)
void thread_yield()
{
#if defined(CONF_FAMILY_UNIX)
- int result = sched_yield();
- if(result != 0)
- dbg_msg("thread", "yield failed: %d", errno);
+ dbg_assert(sched_yield() == 0, "sched_yield failure");
#elif defined(CONF_FAMILY_WINDOWS)
Sleep(0);
#else
@@ -854,76 +832,92 @@ void thread_yield()
void thread_detach(void *thread)
{
#if defined(CONF_FAMILY_UNIX)
- int result = pthread_detach((pthread_t)(thread));
- if(result != 0)
- dbg_msg("thread", "detach failed: %d", result);
+ dbg_assert(pthread_detach((pthread_t)thread) == 0, "pthread_detach failure");
#elif defined(CONF_FAMILY_WINDOWS)
- CloseHandle(thread);
+ dbg_assert(CloseHandle(thread), "CloseHandle failure");
#else
#error not implemented
#endif
}
-bool thread_init_and_detach(void (*threadfunc)(void *), void *u, const char *name)
+void thread_init_and_detach(void (*threadfunc)(void *), void *u, const char *name)
{
void *thread = thread_init(threadfunc, u, name);
- if(thread)
- thread_detach(thread);
- return thread != nullptr;
+ thread_detach(thread);
}
#if defined(CONF_FAMILY_WINDOWS)
void sphore_init(SEMAPHORE *sem)
{
- *sem = CreateSemaphore(0, 0, 10000, 0);
+ *sem = CreateSemaphoreW(nullptr, 0, std::numeric_limits::max(), nullptr);
+ dbg_assert(*sem != nullptr, "CreateSemaphoreW failure");
+}
+void sphore_wait(SEMAPHORE *sem)
+{
+ dbg_assert(WaitForSingleObject((HANDLE)*sem, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failure");
+}
+void sphore_signal(SEMAPHORE *sem)
+{
+ dbg_assert(ReleaseSemaphore((HANDLE)*sem, 1, nullptr), "ReleaseSemaphore failure");
+}
+void sphore_destroy(SEMAPHORE *sem)
+{
+ dbg_assert(CloseHandle((HANDLE)*sem), "CloseHandle failure");
}
-void sphore_wait(SEMAPHORE *sem) { WaitForSingleObject((HANDLE)*sem, INFINITE); }
-void sphore_signal(SEMAPHORE *sem) { ReleaseSemaphore((HANDLE)*sem, 1, NULL); }
-void sphore_destroy(SEMAPHORE *sem) { CloseHandle((HANDLE)*sem); }
#elif defined(CONF_PLATFORM_MACOS)
void sphore_init(SEMAPHORE *sem)
{
char aBuf[64];
- str_format(aBuf, sizeof(aBuf), "%p", (void *)sem);
+ str_format(aBuf, sizeof(aBuf), "/%d.%p", pid(), (void *)sem);
*sem = sem_open(aBuf, O_CREAT | O_EXCL, S_IRWXU | S_IRWXG, 0);
if(*sem == SEM_FAILED)
- dbg_msg("sphore", "init failed: %d", errno);
+ {
+ char aError[128];
+ str_format(aError, sizeof(aError), "sem_open failure, errno=%d, name='%s'", errno, aBuf);
+ dbg_assert(false, aError);
+ }
+}
+void sphore_wait(SEMAPHORE *sem)
+{
+ while(true)
+ {
+ if(sem_wait(*sem) == 0)
+ break;
+ dbg_assert(errno == EINTR, "sem_wait failure");
+ }
+}
+void sphore_signal(SEMAPHORE *sem)
+{
+ dbg_assert(sem_post(*sem) == 0, "sem_post failure");
}
-void sphore_wait(SEMAPHORE *sem) { sem_wait(*sem); }
-void sphore_signal(SEMAPHORE *sem) { sem_post(*sem); }
void sphore_destroy(SEMAPHORE *sem)
{
+ dbg_assert(sem_close(*sem) == 0, "sem_close failure");
char aBuf[64];
- sem_close(*sem);
- str_format(aBuf, sizeof(aBuf), "%p", (void *)sem);
- sem_unlink(aBuf);
+ str_format(aBuf, sizeof(aBuf), "/%d.%p", pid(), (void *)sem);
+ dbg_assert(sem_unlink(aBuf) == 0, "sem_unlink failure");
}
#elif defined(CONF_FAMILY_UNIX)
void sphore_init(SEMAPHORE *sem)
{
- if(sem_init(sem, 0, 0) != 0)
- dbg_msg("sphore", "init failed: %d", errno);
+ dbg_assert(sem_init(sem, 0, 0) == 0, "sem_init failure");
}
-
void sphore_wait(SEMAPHORE *sem)
{
- do
+ while(true)
{
- errno = 0;
- if(sem_wait(sem) != 0)
- dbg_msg("sphore", "wait failed: %d", errno);
- } while(errno == EINTR);
+ if(sem_wait(sem) == 0)
+ break;
+ dbg_assert(errno == EINTR, "sem_wait failure");
+ }
}
-
void sphore_signal(SEMAPHORE *sem)
{
- if(sem_post(sem) != 0)
- dbg_msg("sphore", "post failed: %d", errno);
+ dbg_assert(sem_post(sem) == 0, "sem_post failure");
}
void sphore_destroy(SEMAPHORE *sem)
{
- if(sem_destroy(sem) != 0)
- dbg_msg("sphore", "destroy failed: %d", errno);
+ dbg_assert(sem_destroy(sem) == 0, "sem_destroy failure");
}
#endif
@@ -969,7 +963,7 @@ const NETADDR NETADDR_ZEROED = {NETTYPE_INVALID, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
static void netaddr_to_sockaddr_in(const NETADDR *src, struct sockaddr_in *dest)
{
mem_zero(dest, sizeof(struct sockaddr_in));
- if(src->type != NETTYPE_IPV4 && src->type != NETTYPE_WEBSOCKET_IPV4)
+ if(!(src->type & NETTYPE_IPV4) && !(src->type & NETTYPE_WEBSOCKET_IPV4))
{
dbg_msg("system", "couldn't convert NETADDR of type %d to ipv4", src->type);
return;
@@ -983,9 +977,9 @@ static void netaddr_to_sockaddr_in(const NETADDR *src, struct sockaddr_in *dest)
static void netaddr_to_sockaddr_in6(const NETADDR *src, struct sockaddr_in6 *dest)
{
mem_zero(dest, sizeof(struct sockaddr_in6));
- if(src->type != NETTYPE_IPV6)
+ if(!(src->type & NETTYPE_IPV6))
{
- dbg_msg("system", "couldn't not convert NETADDR of type %d to ipv6", src->type);
+ dbg_msg("system", "couldn't convert NETADDR of type %d to ipv6", src->type);
return;
}
@@ -1109,16 +1103,16 @@ void net_addr_str_v6(const unsigned short ip[8], int port, char *buffer, int buf
}
}
-void net_addr_str(const NETADDR *addr, char *string, int max_length, int add_port)
+bool net_addr_str(const NETADDR *addr, char *string, int max_length, int add_port)
{
- if(addr->type == NETTYPE_IPV4 || addr->type == NETTYPE_WEBSOCKET_IPV4)
+ if(addr->type & NETTYPE_IPV4 || addr->type & NETTYPE_WEBSOCKET_IPV4)
{
if(add_port != 0)
str_format(string, max_length, "%d.%d.%d.%d:%d", addr->ip[0], addr->ip[1], addr->ip[2], addr->ip[3], addr->port);
else
str_format(string, max_length, "%d.%d.%d.%d", addr->ip[0], addr->ip[1], addr->ip[2], addr->ip[3]);
}
- else if(addr->type == NETTYPE_IPV6)
+ else if(addr->type & NETTYPE_IPV6)
{
int port = -1;
unsigned short ip[8];
@@ -1134,7 +1128,11 @@ void net_addr_str(const NETADDR *addr, char *string, int max_length, int add_por
net_addr_str_v6(ip, port, string, max_length);
}
else
+ {
str_format(string, max_length, "unknown type %d", addr->type);
+ return false;
+ }
+ return true;
}
static int priv_net_extract(const char *hostname, char *host, int max_host, int *port)
@@ -1233,7 +1231,7 @@ static int parse_int(int *out, const char **str)
{
int i = 0;
*out = 0;
- if(**str < '0' || **str > '9')
+ if(!str_isnum(**str))
return -1;
i = **str - '0';
@@ -1241,7 +1239,7 @@ static int parse_int(int *out, const char **str)
while(true)
{
- if(**str < '0' || **str > '9')
+ if(!str_isnum(**str))
{
*out = i;
return 0;
@@ -1286,19 +1284,20 @@ static int parse_uint16(unsigned short *out, const char **str)
int net_addr_from_url(NETADDR *addr, const char *string, char *host_buf, size_t host_buf_size)
{
- char host[128];
- int length;
- int start = 0;
- int end;
- int failure;
+ bool sixup = false;
+ mem_zero(addr, sizeof(*addr));
const char *str = str_startswith(string, "tw-0.6+udp://");
+ if(!str && (str = str_startswith(string, "tw-0.7+udp://")))
+ {
+ addr->type |= NETTYPE_TW7;
+ sixup = true;
+ }
if(!str)
return 1;
- mem_zero(addr, sizeof(*addr));
-
- length = str_length(str);
- end = length;
+ int length = str_length(str);
+ int start = 0;
+ int end = length;
for(int i = 0; i < length; i++)
{
if(str[i] == '@')
@@ -1316,13 +1315,19 @@ int net_addr_from_url(NETADDR *addr, const char *string, char *host_buf, size_t
break;
}
}
+
+ char host[128];
str_truncate(host, sizeof(host), str + start, end - start);
if(host_buf)
str_copy(host_buf, host, host_buf_size);
- if((failure = net_addr_from_str(addr, host)))
+ int failure = net_addr_from_str(addr, host);
+ if(failure)
return failure;
+ if(sixup)
+ addr->type |= NETTYPE_TW7;
+
return failure;
}
@@ -1532,47 +1537,45 @@ NETSOCKET net_udp_create(NETADDR bindaddr)
{
NETSOCKET sock = (NETSOCKET_INTERNAL *)malloc(sizeof(*sock));
*sock = invalid_socket;
- NETADDR tmpbindaddr = bindaddr;
- int broadcast = 1;
- int socket = -1;
if(bindaddr.type & NETTYPE_IPV4)
{
struct sockaddr_in addr;
-
- /* bind, we should check for error */
+ NETADDR tmpbindaddr = bindaddr;
tmpbindaddr.type = NETTYPE_IPV4;
netaddr_to_sockaddr_in(&tmpbindaddr, &addr);
- socket = priv_net_create_socket(AF_INET, SOCK_DGRAM, (struct sockaddr *)&addr, sizeof(addr));
+ int socket = priv_net_create_socket(AF_INET, SOCK_DGRAM, (struct sockaddr *)&addr, sizeof(addr));
if(socket >= 0)
{
sock->type |= NETTYPE_IPV4;
sock->ipv4sock = socket;
/* set broadcast */
+ int broadcast = 1;
if(setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (const char *)&broadcast, sizeof(broadcast)) != 0)
- dbg_msg("socket", "Setting BROADCAST on ipv4 failed: %d", errno);
+ {
+ dbg_msg("socket", "Setting BROADCAST on ipv4 failed: %d", net_errno());
+ }
{
/* set DSCP/TOS */
int iptos = 0x10 /* IPTOS_LOWDELAY */;
- //int iptos = 46; /* High Priority */
if(setsockopt(socket, IPPROTO_IP, IP_TOS, (char *)&iptos, sizeof(iptos)) != 0)
- dbg_msg("socket", "Setting TOS on ipv4 failed: %d", errno);
+ {
+ dbg_msg("socket", "Setting TOS on ipv4 failed: %d", net_errno());
+ }
}
}
}
+
#if defined(CONF_WEBSOCKETS)
if(bindaddr.type & NETTYPE_WEBSOCKET_IPV4)
{
char addr_str[NETADDR_MAXSTRSIZE];
-
- /* bind, we should check for error */
+ NETADDR tmpbindaddr = bindaddr;
tmpbindaddr.type = NETTYPE_WEBSOCKET_IPV4;
-
net_addr_str(&tmpbindaddr, addr_str, sizeof(addr_str), 0);
- socket = websocket_create(addr_str, tmpbindaddr.port);
-
+ int socket = websocket_create(addr_str, tmpbindaddr.port);
if(socket >= 0)
{
sock->type |= NETTYPE_WEBSOCKET_IPV4;
@@ -1584,44 +1587,47 @@ NETSOCKET net_udp_create(NETADDR bindaddr)
if(bindaddr.type & NETTYPE_IPV6)
{
struct sockaddr_in6 addr;
-
- /* bind, we should check for error */
+ NETADDR tmpbindaddr = bindaddr;
tmpbindaddr.type = NETTYPE_IPV6;
netaddr_to_sockaddr_in6(&tmpbindaddr, &addr);
- socket = priv_net_create_socket(AF_INET6, SOCK_DGRAM, (struct sockaddr *)&addr, sizeof(addr));
+ int socket = priv_net_create_socket(AF_INET6, SOCK_DGRAM, (struct sockaddr *)&addr, sizeof(addr));
if(socket >= 0)
{
sock->type |= NETTYPE_IPV6;
sock->ipv6sock = socket;
/* set broadcast */
+ int broadcast = 1;
if(setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (const char *)&broadcast, sizeof(broadcast)) != 0)
- dbg_msg("socket", "Setting BROADCAST on ipv6 failed: %d", errno);
+ {
+ dbg_msg("socket", "Setting BROADCAST on ipv6 failed: %d", net_errno());
+ }
+ // TODO: setting IP_TOS on ipv6 with setsockopt is not supported on Windows, see https://github.com/ddnet/ddnet/issues/7605
+#if !defined(CONF_FAMILY_WINDOWS)
{
/* set DSCP/TOS */
int iptos = 0x10 /* IPTOS_LOWDELAY */;
- //int iptos = 46; /* High Priority */
if(setsockopt(socket, IPPROTO_IP, IP_TOS, (char *)&iptos, sizeof(iptos)) != 0)
- dbg_msg("socket", "Setting TOS on ipv6 failed: %d", errno);
+ {
+ dbg_msg("socket", "Setting TOS on ipv6 failed: %d", net_errno());
+ }
}
+#endif
}
}
- if(socket < 0)
+ if(sock->type == NETTYPE_INVALID)
{
free(sock);
sock = nullptr;
}
else
{
- /* set non-blocking */
net_set_non_blocking(sock);
-
net_buffer_init(&sock->buffer);
}
- /* return */
return sock;
}
@@ -1837,46 +1843,41 @@ NETSOCKET net_tcp_create(NETADDR bindaddr)
{
NETSOCKET sock = (NETSOCKET_INTERNAL *)malloc(sizeof(*sock));
*sock = invalid_socket;
- NETADDR tmpbindaddr = bindaddr;
- int socket = -1;
if(bindaddr.type & NETTYPE_IPV4)
{
struct sockaddr_in addr;
-
- /* bind, we should check for error */
+ NETADDR tmpbindaddr = bindaddr;
tmpbindaddr.type = NETTYPE_IPV4;
netaddr_to_sockaddr_in(&tmpbindaddr, &addr);
- socket = priv_net_create_socket(AF_INET, SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr));
- if(socket >= 0)
+ int socket4 = priv_net_create_socket(AF_INET, SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr));
+ if(socket4 >= 0)
{
sock->type |= NETTYPE_IPV4;
- sock->ipv4sock = socket;
+ sock->ipv4sock = socket4;
}
}
if(bindaddr.type & NETTYPE_IPV6)
{
struct sockaddr_in6 addr;
-
- /* bind, we should check for error */
+ NETADDR tmpbindaddr = bindaddr;
tmpbindaddr.type = NETTYPE_IPV6;
netaddr_to_sockaddr_in6(&tmpbindaddr, &addr);
- socket = priv_net_create_socket(AF_INET6, SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr));
- if(socket >= 0)
+ int socket6 = priv_net_create_socket(AF_INET6, SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr));
+ if(socket6 >= 0)
{
sock->type |= NETTYPE_IPV6;
- sock->ipv6sock = socket;
+ sock->ipv6sock = socket6;
}
}
- if(socket < 0)
+ if(sock->type == NETTYPE_INVALID)
{
free(sock);
sock = nullptr;
}
- /* return */
return sock;
}
@@ -1978,6 +1979,8 @@ int net_tcp_connect(NETSOCKET sock, const NETADDR *a)
{
struct sockaddr_in addr;
netaddr_to_sockaddr_in(a, &addr);
+ if(sock->ipv4sock < 0)
+ return -2;
return connect(sock->ipv4sock, (struct sockaddr *)&addr, sizeof(addr));
}
@@ -1985,6 +1988,8 @@ int net_tcp_connect(NETSOCKET sock, const NETADDR *a)
{
struct sockaddr_in6 addr;
netaddr_to_sockaddr_in6(a, &addr);
+ if(sock->ipv6sock < 0)
+ return -2;
return connect(sock->ipv6sock, (struct sockaddr *)&addr, sizeof(addr));
}
@@ -2285,17 +2290,20 @@ int fs_storage_path(const char *appname, char *path, int max)
int fs_makedir_rec_for(const char *path)
{
- char buffer[1024 * 2];
- char *p;
+ char buffer[IO_MAX_PATH_LENGTH];
str_copy(buffer, path);
- for(p = buffer + 1; *p != '\0'; p++)
+ for(int index = 1; buffer[index] != '\0'; ++index)
{
- if(*p == '/' && *(p + 1) != '\0')
+ // Do not try to create folder for drive letters on Windows,
+ // as this is not necessary and may fail for system drives.
+ if((buffer[index] == '/' || buffer[index] == '\\') && buffer[index + 1] != '\0' && buffer[index - 1] != ':')
{
- *p = '\0';
+ buffer[index] = '\0';
if(fs_makedir(buffer) < 0)
+ {
return -1;
- *p = '/';
+ }
+ buffer[index] = '/';
}
}
return 0;
@@ -2378,17 +2386,12 @@ int fs_is_relative_path(const char *path)
int fs_chdir(const char *path)
{
- if(fs_is_dir(path))
- {
#if defined(CONF_FAMILY_WINDOWS)
- const std::wstring wide_path = windows_utf8_to_wide(path);
- return SetCurrentDirectoryW(wide_path.c_str()) != 0 ? 0 : 1;
+ const std::wstring wide_path = windows_utf8_to_wide(path);
+ return SetCurrentDirectoryW(wide_path.c_str()) != 0 ? 0 : 1;
#else
- return chdir(path) ? 1 : 0;
+ return chdir(path) ? 1 : 0;
#endif
- }
- else
- return 1;
}
char *fs_getcwd(char *buffer, int buffer_size)
@@ -2396,15 +2399,7 @@ char *fs_getcwd(char *buffer, int buffer_size)
#if defined(CONF_FAMILY_WINDOWS)
const DWORD size_needed = GetCurrentDirectoryW(0, nullptr);
std::wstring wide_current_dir(size_needed, L'0');
- DWORD result = GetCurrentDirectoryW(size_needed, wide_current_dir.data());
- if(result == 0)
- {
- const DWORD LastError = GetLastError();
- const std::string ErrorMsg = windows_format_system_message(LastError);
- dbg_msg("filesystem", "GetCurrentDirectoryW failed: %ld %s", LastError, ErrorMsg.c_str());
- buffer[0] = '\0';
- return nullptr;
- }
+ dbg_assert(GetCurrentDirectoryW(size_needed, wide_current_dir.data()) == size_needed - 1, "GetCurrentDirectoryW failure");
const std::optional current_dir = windows_wide_to_utf8(wide_current_dir.c_str());
if(!current_dir.has_value())
{
@@ -2602,18 +2597,29 @@ int net_socket_read_wait(NETSOCKET sock, int time)
return 0;
}
-int time_timestamp()
+int64_t time_timestamp()
{
return time(0);
}
+static struct tm *time_localtime_threadlocal(time_t *time_data)
+{
+#if defined(CONF_FAMILY_WINDOWS)
+ // The result of localtime is thread-local on Windows
+ // https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/localtime-localtime32-localtime64
+ return localtime(time_data);
+#else
+ // Thread-local buffer for the result of localtime_r
+ thread_local struct tm time_info_buf;
+ return localtime_r(time_data, &time_info_buf);
+#endif
+}
+
int time_houroftheday()
{
time_t time_data;
- struct tm *time_info;
-
time(&time_data);
- time_info = localtime(&time_data);
+ struct tm *time_info = time_localtime_threadlocal(&time_data);
return time_info->tm_hour;
}
@@ -2640,7 +2646,7 @@ static bool time_iseasterday(time_t time_data, struct tm *time_info)
for(int day_offset = -1; day_offset <= 2; day_offset++)
{
time_data = time_data + day_offset * 60 * 60 * 24;
- time_info = localtime(&time_data);
+ time_info = time_localtime_threadlocal(&time_data);
if(time_info->tm_mon == month - 1 && time_info->tm_mday == day)
return true;
}
@@ -2651,7 +2657,7 @@ ETimeSeason time_season()
{
time_t time_data;
time(&time_data);
- struct tm *time_info = localtime(&time_data);
+ struct tm *time_info = time_localtime_threadlocal(&time_data);
if((time_info->tm_mon == 11 && time_info->tm_mday == 31) || (time_info->tm_mon == 0 && time_info->tm_mday == 1))
{
@@ -2762,6 +2768,15 @@ int str_format_v(char *buffer, int buffer_size, const char *format, va_list args
return str_utf8_fix_truncation(buffer);
}
+int str_format_int(char *buffer, size_t buffer_size, int value)
+{
+ buffer[0] = '\0'; // Fix false positive clang-analyzer-core.UndefinedBinaryOperatorResult when using result
+ auto result = std::to_chars(buffer, buffer + buffer_size - 1, value);
+ result.ptr[0] = '\0';
+ return result.ptr - buffer;
+}
+
+#undef str_format
int str_format(char *buffer, int buffer_size, const char *format, ...)
{
va_list args;
@@ -2770,6 +2785,9 @@ int str_format(char *buffer, int buffer_size, const char *format, ...)
va_end(args);
return length;
}
+#if !defined(CONF_DEBUG)
+#define str_format str_format_opt
+#endif
const char *str_trim_words(const char *str, int words)
{
@@ -2928,7 +2946,7 @@ int str_comp_filenames(const char *a, const char *b)
for(; *a && *b; ++a, ++b)
{
- if(*a >= '0' && *a <= '9' && *b >= '0' && *b <= '9')
+ if(str_isnum(*a) && str_isnum(*b))
{
result = 0;
do
@@ -2937,11 +2955,11 @@ int str_comp_filenames(const char *a, const char *b)
result = *a - *b;
++a;
++b;
- } while(*a >= '0' && *a <= '9' && *b >= '0' && *b <= '9');
+ } while(str_isnum(*a) && str_isnum(*b));
- if(*a >= '0' && *a <= '9')
+ if(str_isnum(*a))
return 1;
- else if(*b >= '0' && *b <= '9')
+ else if(str_isnum(*b))
return -1;
else if(result || *a == '\0' || *b == '\0')
return result;
@@ -3144,6 +3162,38 @@ const char *str_find(const char *haystack, const char *needle)
return 0;
}
+bool str_delimiters_around_offset(const char *haystack, const char *delim, int offset, int *start, int *end)
+{
+ bool found = true;
+ const char *search = haystack;
+ const int delim_len = str_length(delim);
+ *start = 0;
+ while(str_find(search, delim))
+ {
+ const char *test = str_find(search, delim) + delim_len;
+ int distance = test - haystack;
+ if(distance > offset)
+ break;
+
+ *start = distance;
+ search = test;
+ }
+ if(search == haystack)
+ found = false;
+
+ if(str_find(search, delim))
+ {
+ *end = str_find(search, delim) - haystack;
+ }
+ else
+ {
+ *end = str_length(haystack);
+ found = false;
+ }
+
+ return found;
+}
+
const char *str_rchr(const char *haystack, char needle)
{
return strrchr(haystack, needle);
@@ -3420,8 +3470,7 @@ int str_base64_decode(void *dst_raw, int dst_size, const char *data)
#endif
void str_timestamp_ex(time_t time_data, char *buffer, int buffer_size, const char *format)
{
- struct tm *time_info;
- time_info = localtime(&time_data);
+ struct tm *time_info = time_localtime_threadlocal(&time_data);
strftime(buffer, buffer_size, format, time_info);
buffer[buffer_size - 1] = 0; /* assure null termination */
}
@@ -3437,6 +3486,22 @@ void str_timestamp(char *buffer, int buffer_size)
{
str_timestamp_format(buffer, buffer_size, FORMAT_NOSPACE);
}
+
+bool timestamp_from_str(const char *string, const char *format, time_t *timestamp)
+{
+ std::tm tm{};
+ std::istringstream ss(string);
+ ss >> std::get_time(&tm, format);
+ if(ss.fail() || !ss.eof())
+ return false;
+
+ time_t result = mktime(&tm);
+ if(result < 0)
+ return false;
+
+ *timestamp = result;
+ return true;
+}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
@@ -3526,11 +3591,16 @@ char str_uppercase(char c)
return c;
}
+bool str_isnum(char c)
+{
+ return c >= '0' && c <= '9';
+}
+
int str_isallnum(const char *str)
{
while(*str)
{
- if(!(*str >= '0' && *str <= '9'))
+ if(!str_isnum(*str))
return 0;
str++;
}
@@ -3541,7 +3611,7 @@ int str_isallnum_hex(const char *str)
{
while(*str)
{
- if(!(*str >= '0' && *str <= '9') && !(*str >= 'a' && *str <= 'f') && !(*str >= 'A' && *str <= 'F'))
+ if(!str_isnum(*str) && !(*str >= 'a' && *str <= 'f') && !(*str >= 'A' && *str <= 'F'))
return 0;
str++;
}
@@ -3553,6 +3623,18 @@ int str_toint(const char *str)
return str_toint_base(str, 10);
}
+bool str_toint(const char *str, int *out)
+{
+ // returns true if conversion was successful
+ char *end;
+ int value = strtol(str, &end, 10);
+ if(*end != '\0')
+ return false;
+ if(out != nullptr)
+ *out = value;
+ return true;
+}
+
int str_toint_base(const char *str, int base)
{
return strtol(str, nullptr, base);
@@ -3573,11 +3655,16 @@ float str_tofloat(const char *str)
return strtod(str, nullptr);
}
-void str_from_int(int value, char *buffer, size_t buffer_size)
+bool str_tofloat(const char *str, float *out)
{
- buffer[0] = '\0'; // Fix false positive clang-analyzer-core.UndefinedBinaryOperatorResult when using result
- auto result = std::to_chars(buffer, buffer + buffer_size - 1, value);
- result.ptr[0] = '\0';
+ // returns true if conversion was successful
+ char *end;
+ float value = strtod(str, &end);
+ if(*end != '\0')
+ return false;
+ if(out != nullptr)
+ *out = value;
+ return true;
}
int str_utf8_comp_nocase(const char *a, const char *b)
@@ -3873,6 +3960,24 @@ int str_utf8_check(const char *str)
return 1;
}
+void str_utf8_copy_num(char *dst, const char *src, int dst_size, int num)
+{
+ int new_cursor;
+ int cursor = 0;
+
+ while(src[cursor] && num > 0)
+ {
+ new_cursor = str_utf8_forward(src, cursor);
+ if(new_cursor >= dst_size) // reserve 1 byte for the null termination
+ break;
+ else
+ cursor = new_cursor;
+ --num;
+ }
+
+ str_copy(dst, src, cursor < dst_size ? cursor + 1 : dst_size);
+}
+
void str_utf8_stats(const char *str, size_t max_size, size_t max_count, size_t *size, size_t *count)
{
const char *cursor = str;
@@ -4045,7 +4150,8 @@ void cmdline_free(int argc, const char **argv)
#endif
}
-PROCESS shell_execute(const char *file)
+#if !defined(CONF_PLATFORM_ANDROID)
+PROCESS shell_execute(const char *file, EShellExecuteWindowState window_state)
{
#if defined(CONF_FAMILY_WINDOWS)
const std::wstring wide_file = windows_utf8_to_wide(file);
@@ -4055,7 +4161,18 @@ PROCESS shell_execute(const char *file)
info.cbSize = sizeof(SHELLEXECUTEINFOW);
info.lpVerb = L"open";
info.lpFile = wide_file.c_str();
- info.nShow = SW_SHOWMINNOACTIVE;
+ switch(window_state)
+ {
+ case EShellExecuteWindowState::FOREGROUND:
+ info.nShow = SW_SHOW;
+ break;
+ case EShellExecuteWindowState::BACKGROUND:
+ info.nShow = SW_SHOWMINNOACTIVE;
+ break;
+ default:
+ dbg_assert(false, "window_state invalid");
+ dbg_break();
+ }
info.fMask = SEE_MASK_NOCLOSEPROCESS;
// Save and restore the FPU control word because ShellExecute might change it
fenv_t floating_point_environment;
@@ -4177,6 +4294,7 @@ int open_file(const char *path)
return open_link(buf);
#endif
}
+#endif // !defined(CONF_PLATFORM_ANDROID)
struct SECURE_RANDOM_DATA
{
@@ -4474,7 +4592,7 @@ void os_locale_str(char *locale, size_t length)
{
locale[i] = '-';
}
- else if(locale[i] != '-' && !(locale[i] >= 'a' && locale[i] <= 'z') && !(locale[i] >= 'A' && locale[i] <= 'Z') && !(locale[i] >= '0' && locale[i] <= '9'))
+ else if(locale[i] != '-' && !(locale[i] >= 'a' && locale[i] <= 'z') && !(locale[i] >= 'A' && locale[i] <= 'Z') && !(str_isnum(locale[i])))
{
locale[i] = '\0';
break;
diff --git a/src/base/system.h b/src/base/system.h
index c575949e62..cf75ce3092 100644
--- a/src/base/system.h
+++ b/src/base/system.h
@@ -219,13 +219,42 @@ bool mem_has_null(const void *block, size_t size);
*/
enum
{
+ /**
+ * Open file for reading.
+ *
+ * @see io_open
+ */
IOFLAG_READ = 1,
+ /**
+ * Open file for writing.
+ *
+ * @see io_open
+ */
IOFLAG_WRITE = 2,
+ /**
+ * Open file for appending at the end.
+ *
+ * @see io_open
+ */
IOFLAG_APPEND = 4,
- IOFLAG_SKIP_BOM = 8,
+ /**
+ * Start seeking from the beginning of the file.
+ *
+ * @see io_seek
+ */
IOSEEK_START = 0,
+ /**
+ * Start seeking from the current position.
+ *
+ * @see io_seek
+ */
IOSEEK_CUR = 1,
+ /**
+ * Start seeking from the end of the file.
+ *
+ * @see io_seek
+ */
IOSEEK_END = 2,
};
@@ -237,10 +266,9 @@ enum
* @param File to open.
* @param flags A set of IOFLAG flags.
*
- * @sa IOFLAG_READ, IOFLAG_WRITE, IOFLAG_APPEND, IOFLAG_SKIP_BOM.
- *
- * @return A handle to the file on success and 0 on failure.
+ * @see IOFLAG_READ, IOFLAG_WRITE, IOFLAG_APPEND.
*
+ * @return A handle to the file on success, or `nullptr` on failure.
*/
IOHANDLE io_open(const char *filename, int flags);
@@ -254,7 +282,6 @@ IOHANDLE io_open(const char *filename, int flags);
* @param size Number of bytes to read from the file.
*
* @return Number of bytes read.
- *
*/
unsigned io_read(IOHANDLE io, void *buffer, unsigned size);
@@ -280,7 +307,7 @@ void io_read_all(IOHANDLE io, void **result, unsigned *result_len);
*
* @param io Handle to the file to read data from.
*
- * @return The file's remaining contents or null on failure.
+ * @return The file's remaining contents, or `nullptr` on failure.
*
* @remark Guarantees that there are no internal null bytes.
* @remark Guarantees that result will contain zero-termination.
@@ -301,63 +328,63 @@ char *io_read_all_str(IOHANDLE io);
int io_skip(IOHANDLE io, int size);
/**
- * Writes data from a buffer to file.
+ * Seeks to a specified offset in the file.
*
* @ingroup File-IO
*
* @param io Handle to the file.
- * @param buffer Pointer to the data that should be written.
- * @param size Number of bytes to write.
+ * @param offset Offset from position to search.
+ * @param origin Position to start searching from.
*
- * @return Number of bytes written.
+ * @return `0` on success.
*/
-unsigned io_write(IOHANDLE io, const void *buffer, unsigned size);
+int io_seek(IOHANDLE io, int offset, int origin);
/**
- * Writes a platform dependent newline to file.
+ * Gets the current position in the file.
*
* @ingroup File-IO
*
* @param io Handle to the file.
*
- * @return true on success, false on failure.
+ * @return The current position, or `-1` on failure.
*/
-bool io_write_newline(IOHANDLE io);
+long int io_tell(IOHANDLE io);
/**
- * Seeks to a specified offset in the file.
+ * Gets the total length of the file. Resets cursor to the beginning.
*
* @ingroup File-IO
*
* @param io Handle to the file.
- * @param offset Offset from pos to stop.
- * @param origin Position to start searching from.
*
- * @return 0 on success.
+ * @return The total size, or `-1` on failure.
*/
-int io_seek(IOHANDLE io, int offset, int origin);
+long int io_length(IOHANDLE io);
/**
- * Gets the current position in the file.
+ * Writes data from a buffer to a file.
*
* @ingroup File-IO
*
* @param io Handle to the file.
+ * @param buffer Pointer to the data that should be written.
+ * @param size Number of bytes to write.
*
- * @return The current position. @c -1L if an error occurred.
+ * @return Number of bytes written.
*/
-long int io_tell(IOHANDLE io);
+unsigned io_write(IOHANDLE io, const void *buffer, unsigned size);
/**
- * Gets the total length of the file. Resetting cursor to the beginning
+ * Writes a platform dependent newline to a file.
*
* @ingroup File-IO
*
* @param io Handle to the file.
*
- * @return The total size. @c -1L if an error occurred.
+ * @return `true` on success, `false` on failure.
*/
-long int io_length(IOHANDLE io);
+bool io_write_newline(IOHANDLE io);
/**
* Closes a file.
@@ -366,7 +393,7 @@ long int io_length(IOHANDLE io);
*
* @param io Handle to the file.
*
- * @return 0 on success.
+ * @return `0` on success.
*/
int io_close(IOHANDLE io);
@@ -377,7 +404,7 @@ int io_close(IOHANDLE io);
*
* @param io Handle to the file.
*
- * @return 0 on success.
+ * @return `0` on success.
*/
int io_flush(IOHANDLE io);
@@ -388,7 +415,7 @@ int io_flush(IOHANDLE io);
*
* @param io Handle to the file.
*
- * @return 0 on success.
+ * @return `0` on success.
*/
int io_sync(IOHANDLE io);
@@ -399,34 +426,57 @@ int io_sync(IOHANDLE io);
*
* @param io Handle to the file.
*
- * @return nonzero on error, 0 otherwise.
+ * @return `0` on success, or non-`0` on error.
*/
int io_error(IOHANDLE io);
/**
* @ingroup File-IO
- * @return An to the standard input.
+ *
+ * Returns a handle for the standard input.
+ *
+ * @return An @link IOHANDLE @endlink for the standard input.
+ *
+ * @remark The handle must not be closed.
*/
IOHANDLE io_stdin();
/**
* @ingroup File-IO
- * @return An to the standard output.
+ *
+ * Returns a handle for the standard output.
+ *
+ * @return An @link IOHANDLE @endlink for the standard output.
+ *
+ * @remark The handle must not be closed.
*/
IOHANDLE io_stdout();
/**
* @ingroup File-IO
- * @return An to the standard error.
+ *
+ * Returns a handle for the standard error.
+ *
+ * @return An @link IOHANDLE @endlink for the standard error.
+ *
+ * @remark The handle must not be closed.
*/
IOHANDLE io_stderr();
/**
* @ingroup File-IO
- * @return An to the current executable.
+ *
+ * Returns a handle for the current executable.
+ *
+ * @return An @link IOHANDLE @endlink for the current executable.
*/
IOHANDLE io_current_exe();
+/**
+ * Wrapper for asynchronously writing to an @link IOHANDLE @endlink.
+ *
+ * @ingroup File-IO
+ */
typedef struct ASYNCIO ASYNCIO;
/**
@@ -437,12 +487,11 @@ typedef struct ASYNCIO ASYNCIO;
* @param io Handle to the file.
*
* @return The handle for asynchronous writing.
- *
*/
ASYNCIO *aio_new(IOHANDLE io);
/**
- * Locks the ASYNCIO structure so it can't be written into by
+ * Locks the `ASYNCIO` structure so it can't be written into by
* other threads.
*
* @ingroup File-IO
@@ -452,7 +501,7 @@ ASYNCIO *aio_new(IOHANDLE io);
void aio_lock(ASYNCIO *aio);
/**
- * Unlocks the ASYNCIO structure after finishing the contiguous
+ * Unlocks the `ASYNCIO` structure after finishing the contiguous
* write.
*
* @ingroup File-IO
@@ -478,12 +527,11 @@ void aio_write(ASYNCIO *aio, const void *buffer, unsigned size);
* @ingroup File-IO
*
* @param aio Handle to the file.
- *
*/
void aio_write_newline(ASYNCIO *aio);
/**
- * Queues a chunk of data for writing. The ASYNCIO struct must be
+ * Queues a chunk of data for writing. The `ASYNCIO` struct must be
* locked using @link aio_lock @endlink first.
*
* @ingroup File-IO
@@ -491,18 +539,16 @@ void aio_write_newline(ASYNCIO *aio);
* @param aio Handle to the file.
* @param buffer Pointer to the data that should be written.
* @param size Number of bytes to write.
- *
*/
void aio_write_unlocked(ASYNCIO *aio, const void *buffer, unsigned size);
/**
- * Queues a newline for writing. The ASYNCIO struct must be locked
+ * Queues a newline for writing. The `ASYNCIO` struct must be locked
* using @link aio_lock @endlink first.
*
* @ingroup File-IO
*
* @param aio Handle to the file.
- *
*/
void aio_write_newline_unlocked(ASYNCIO *aio);
@@ -510,16 +556,15 @@ void aio_write_newline_unlocked(ASYNCIO *aio);
* Checks whether errors have occurred during the asynchronous
* writing.
*
- * Call this function regularly to see if there are errors. Call
- * this function after to see if the process of writing
+ * Call this function regularly to see if there are errors. Call this
+ * function after @link aio_wait @endlink to see if the process of writing
* to the file succeeded.
*
* @ingroup File-IO
*
* @param aio Handle to the file.
*
- * @eturn 0 if no error occurred, and nonzero on error.
- *
+ * @return `0` on success, or non-`0` on error.
*/
int aio_error(ASYNCIO *aio);
@@ -529,7 +574,6 @@ int aio_error(ASYNCIO *aio);
* @ingroup File-IO
*
* @param aio Handle to the file.
- *
*/
void aio_close(ASYNCIO *aio);
@@ -539,17 +583,15 @@ void aio_close(ASYNCIO *aio);
* @ingroup File-IO
*
* @param aio Handle to the file.
- *
*/
void aio_wait(ASYNCIO *aio);
/**
- * Frees the resources associated to the asynchronous file handle.
+ * Frees the resources associated with the asynchronous file handle.
*
* @ingroup File-IO
*
* @param aio Handle to the file.
- *
*/
void aio_free(ASYNCIO *aio);
@@ -558,6 +600,7 @@ void aio_free(ASYNCIO *aio);
* Threading related functions.
*
* @see Locks
+ * @see Semaphore
*/
/**
@@ -567,7 +610,9 @@ void aio_free(ASYNCIO *aio);
*
* @param threadfunc Entry point for the new thread.
* @param user Pointer to pass to the thread.
- * @param name name describing the use of the thread
+ * @param name Name describing the use of the thread.
+ *
+ * @return Handle for the new thread.
*/
void *thread_init(void (*threadfunc)(void *), void *user, const char *name);
@@ -581,35 +626,33 @@ void *thread_init(void (*threadfunc)(void *), void *user, const char *name);
void thread_wait(void *thread);
/**
- * Yield the current threads execution slice.
+ * Yield the current thread's execution slice.
*
* @ingroup Threads
*/
void thread_yield();
/**
- * Puts the thread in the detached thread, guaranteeing that
+ * Puts the thread in the detached state, guaranteeing that
* resources of the thread will be freed immediately when the
* thread terminates.
*
* @ingroup Threads
*
- * @param thread Thread to detach
+ * @param thread Thread to detach.
*/
void thread_detach(void *thread);
/**
- * Creates a new thread and if it succeeded detaches it.
+ * Creates a new thread and detaches it.
*
* @ingroup Threads
*
* @param threadfunc Entry point for the new thread.
* @param user Pointer to pass to the thread.
- * @param name Name describing the use of the thread
- *
- * @return true on success, false on failure.
+ * @param name Name describing the use of the thread.
*/
-bool thread_init_and_detach(void (*threadfunc)(void *), void *user, const char *name);
+void thread_init_and_detach(void (*threadfunc)(void *), void *user, const char *name);
/**
* @defgroup Semaphore
@@ -697,7 +740,7 @@ int64_t time_freq();
*
* @return The time as a UNIX timestamp
*/
-int time_timestamp();
+int64_t time_timestamp();
/**
* Retrieves the hours since midnight (0..23)
@@ -812,9 +855,11 @@ int net_addr_comp_noport(const NETADDR *a, const NETADDR *b);
* @param max_length Maximum size of the string.
* @param add_port add port to string or not
*
+ * @return true on success
+ *
* @remark The string will always be zero terminated
*/
-void net_addr_str(const NETADDR *addr, char *string, int max_length, int add_port);
+bool net_addr_str(const NETADDR *addr, char *string, int max_length, int add_port);
/**
* Turns url string into a network address struct.
@@ -1228,6 +1273,32 @@ int str_format_v(char *buffer, int buffer_size, const char *format, va_list args
int str_format(char *buffer, int buffer_size, const char *format, ...)
GNUC_ATTRIBUTE((format(printf, 3, 4)));
+#if !defined(CONF_DEBUG)
+int str_format_int(char *buffer, size_t buffer_size, int value);
+
+template
+int str_format_opt(char *buffer, int buffer_size, const char *format, Args... args)
+{
+ static_assert(sizeof...(args) > 0, "Use str_copy instead of str_format without format arguments");
+ return str_format(buffer, buffer_size, format, args...);
+}
+
+template<>
+inline int str_format_opt(char *buffer, int buffer_size, const char *format, int val)
+{
+ if(strcmp(format, "%d") == 0)
+ {
+ return str_format_int(buffer, buffer_size, val);
+ }
+ else
+ {
+ return str_format(buffer, buffer_size, format, val);
+ }
+}
+
+#define str_format str_format_opt
+#endif
+
/**
* Trims specific number of words at the start of a string.
*
@@ -1580,6 +1651,22 @@ const char *str_find_nocase(const char *haystack, const char *needle);
*/
const char *str_find(const char *haystack, const char *needle);
+/**
+ * @ingroup Strings
+ *
+ * @param haystack String to search in
+ * @param delim String to search for
+ * @param offset Number of characters into the haystack
+ * @param start Will be set to the first delimiter on the left side of the offset (or haystack start)
+ * @param end Will be set to the first delimiter on the right side of the offset (or haystack end)
+ *
+ * @return `true` if both delimiters were found
+ * @return 'false' if a delimiter is missing (it uses haystack start and end as fallback)
+ *
+ * @remark The strings are treated as zero-terminated strings.
+ */
+bool str_delimiters_around_offset(const char *haystay, const char *delim, int offset, int *start, int *end);
+
/**
* Finds the last occurrence of a character
*
@@ -1711,6 +1798,21 @@ void str_timestamp_format(char *buffer, int buffer_size, const char *format)
void str_timestamp_ex(time_t time, char *buffer, int buffer_size, const char *format)
GNUC_ATTRIBUTE((format(strftime, 4, 0)));
+/**
+ * Parses a string into a timestamp following a specified format.
+ *
+ * @ingroup Timestamp
+ *
+ * @param string Pointer to the string to parse
+ * @param format The time format to use (for example FORMAT_NOSPACE below)
+ * @param timestamp Pointer to the timestamp result
+ *
+ * @return true on success, false if the string could not be parsed with the specified format
+ *
+ */
+bool timestamp_from_str(const char *string, const char *format, time_t *timestamp)
+ GNUC_ATTRIBUTE((format(strftime, 2, 0)));
+
#define FORMAT_TIME "%H:%M:%S"
#define FORMAT_SPACE "%Y-%m-%d %H:%M:%S"
#define FORMAT_NOSPACE "%Y-%m-%d_%H-%M-%S"
@@ -1823,11 +1925,11 @@ int fs_makedir(const char *path);
int fs_removedir(const char *path);
/**
- * Recursively create directories for a file.
+ * Recursively creates parent directories for a file or directory.
*
* @ingroup Filesystem
*
- * @param path - File for which to create directories.
+ * @param path File or directory for which to create parent directories.
*
* @return 0 on success. Negative value on failure.
*
@@ -2053,36 +2155,6 @@ int net_would_block();
int net_socket_read_wait(NETSOCKET sock, int time);
-/*
- Function: open_link
- Opens a link in the browser.
-
- Parameters:
- link - The link to open in a browser.
-
- Returns:
- Returns 1 on success, 0 on failure.
-
- Remarks:
- This may not be called with untrusted input or it'll result in arbitrary code execution, especially on Windows.
-*/
-int open_link(const char *link);
-
-/*
- Function: open_file
- Opens a file or directory with default program.
-
- Parameters:
- path - The path to open.
-
- Returns:
- Returns 1 on success, 0 on failure.
-
- Remarks:
- This may not be called with untrusted input or it'll result in arbitrary code execution, especially on Windows.
-*/
-int open_file(const char *path);
-
/**
* Swaps the endianness of data. Each element is swapped individually by reversing its bytes.
*
@@ -2105,18 +2177,12 @@ typedef struct
void net_stats(NETSTATS *stats);
int str_toint(const char *str);
+bool str_toint(const char *str, int *out);
int str_toint_base(const char *str, int base);
unsigned long str_toulong_base(const char *str, int base);
int64_t str_toint64_base(const char *str, int base = 10);
float str_tofloat(const char *str);
-
-void str_from_int(int value, char *buffer, size_t buffer_size);
-
-template
-void str_from_int(int value, char (&dst)[N])
-{
- str_from_int(value, dst, N);
-}
+bool str_tofloat(const char *str, float *out);
/**
* Determines whether a character is whitespace.
@@ -2133,6 +2199,8 @@ int str_isspace(char c);
char str_uppercase(char c);
+bool str_isnum(char c);
+
int str_isallnum(const char *str);
int str_isallnum_hex(const char *str);
@@ -2354,6 +2422,22 @@ int str_utf8_encode(char *ptr, int chr);
*/
int str_utf8_check(const char *str);
+/*
+ Function: str_utf8_copy_num
+ Copies a number of utf8 characters from one string to another.
+
+ Parameters:
+ dst - Pointer to a buffer that shall receive the string.
+ src - String to be copied.
+ dst_size - Size of the buffer dst.
+ num - maximum number of utf8 characters to be copied.
+
+ Remarks:
+ - The strings are treated as zero-terminated strings.
+ - Garantees that dst string will contain zero-termination.
+*/
+void str_utf8_copy_num(char *dst, const char *src, int dst_size, int num);
+
/*
Function: str_utf8_stats
Determines the byte size and utf8 character count of a utf8 string.
@@ -2457,162 +2541,247 @@ unsigned bytes_be_to_uint(const unsigned char *bytes);
*/
void uint_to_bytes_be(unsigned char *bytes, unsigned value);
-/*
- Function: pid
- Returns the pid of the current process.
+/**
+ * @defgroup Shell
+ * Shell, process management, OS specific functionality.
+ */
- Returns:
- pid of the current process
-*/
+/**
+ * Returns the ID of the current process.
+ *
+ * @ingroup Shell
+ *
+ * @return PID of the current process.
+ */
int pid();
-/*
- Function: cmdline_fix
- Fixes the command line arguments to be encoded in UTF-8 on all
- systems.
-
- Parameters:
- argc - A pointer to the argc parameter that was passed to the main function.
- argv - A pointer to the argv parameter that was passed to the main function.
-
- Remarks:
- - You need to call cmdline_free once you're no longer using the
- results.
-*/
+/**
+ * Fixes the command line arguments to be encoded in UTF-8 on all systems.
+ *
+ * @ingroup Shell
+ *
+ * @param argc A pointer to the argc parameter that was passed to the main function.
+ * @param argv A pointer to the argv parameter that was passed to the main function.
+ *
+ * @remark You need to call @link cmdline_free @endlink once you're no longer using the results.
+ */
void cmdline_fix(int *argc, const char ***argv);
-/*
- Function: cmdline_free
- Frees memory that was allocated by cmdline_fix.
-
- Parameters:
- argc - The argc obtained from cmdline_fix.
- argv - The argv obtained from cmdline_fix.
-
-*/
+/**
+ * Frees memory that was allocated by @link cmdline_fix @endlink.
+ *
+ * @ingroup Shell
+ *
+ * @param argc The argc obtained from `cmdline_fix`.
+ * @param argv The argv obtained from `cmdline_fix`.
+ */
void cmdline_free(int argc, const char **argv);
#if defined(CONF_FAMILY_WINDOWS)
+/**
+ * A handle for a process.
+ *
+ * @ingroup Shell
+ */
typedef void *PROCESS;
+/**
+ * A handle that denotes an invalid process.
+ *
+ * @ingroup Shell
+ */
constexpr PROCESS INVALID_PROCESS = nullptr;
#else
+/**
+ * A handle for a process.
+ *
+ * @ingroup Shell
+ */
typedef pid_t PROCESS;
+/**
+ * A handle that denotes an invalid process.
+ *
+ * @ingroup Shell
+ */
constexpr PROCESS INVALID_PROCESS = 0;
#endif
+#if !defined(CONF_PLATFORM_ANDROID)
+/**
+ * Determines the initial window state when using @link shell_execute @endlink
+ * to execute a process.
+ *
+ * @ingroup Shell
+ *
+ * @remark Currently only supported on Windows.
+ */
+enum class EShellExecuteWindowState
+{
+ /**
+ * The process window is opened in the foreground and activated.
+ */
+ FOREGROUND,
+
+ /**
+ * The process window is opened in the background without focus.
+ */
+ BACKGROUND,
+};
-/*
- Function: shell_execute
- Executes a given file.
-
- Returns:
- handle/pid of the new process
-*/
-PROCESS shell_execute(const char *file);
-
-/*
- Function: kill_process
- Sends kill signal to a process.
-
- Parameters:
- process - handle/pid of the process
+/**
+ * Executes a given file.
+ *
+ * @ingroup Shell
+ *
+ * @param file The file to execute.
+ * @param window_state The window state how the process window should be shown.
+ *
+ * @return Handle of the new process, or @link INVALID_PROCESS @endlink on error.
+ */
+PROCESS shell_execute(const char *file, EShellExecuteWindowState window_state);
- Returns:
- 0 - Error
- 1 - Success
-*/
+/**
+ * Sends kill signal to a process.
+ *
+ * @ingroup Shell
+ *
+ * @param process Handle of the process to kill.
+ *
+ * @return `1` on success, `0` on error.
+ */
int kill_process(PROCESS process);
/**
* Checks if a process is alive.
- *
+ *
+ * @ingroup Shell
+ *
* @param process Handle/PID of the process.
- *
- * @return bool Returns true if the process is currently running, false if the process is not running (dead).
+ *
+ * @return `true` if the process is currently running,
+ * `false` if the process is not running (dead).
*/
bool is_process_alive(PROCESS process);
-/*
- Function: generate_password
- Generates a null-terminated password of length `2 *
- random_length`.
+/**
+ * Opens a link in the browser.
+ *
+ * @ingroup Shell
+ *
+ * @param link The link to open in a browser.
+ *
+ * @return `1` on success, `0` on failure.
+ *
+ * @remark The strings are treated as zero-terminated strings.
+ * @remark This may not be called with untrusted input or it'll result in arbitrary code execution, especially on Windows.
+ */
+int open_link(const char *link);
- Parameters:
- buffer - Pointer to the start of the output buffer.
- length - Length of the buffer.
- random - Pointer to a randomly-initialized array of shorts.
- random_length - Length of the short array.
-*/
-void generate_password(char *buffer, unsigned length, const unsigned short *random, unsigned random_length);
+/**
+ * Opens a file or directory with the default program.
+ *
+ * @ingroup Shell
+ *
+ * @param path The file or folder to open with the default program.
+ *
+ * @return `1` on success, `0` on failure.
+ *
+ * @remark The strings are treated as zero-terminated strings.
+ * @remark This may not be called with untrusted input or it'll result in arbitrary code execution, especially on Windows.
+ */
+int open_file(const char *path);
+#endif // !defined(CONF_PLATFORM_ANDROID)
-/*
- Function: secure_random_init
- Initializes the secure random module.
- You *MUST* check the return value of this function.
+/**
+ * @defgroup Secure-Random
+ * Secure random number generation.
+ */
- Returns:
- 0 - Initialization succeeded.
- 1 - Initialization failed.
-*/
-int secure_random_init();
+/**
+ * Generates a null-terminated password of length `2 * random_length`.
+ *
+ * @ingroup Secure-Random
+ *
+ * @param buffer Pointer to the start of the output buffer.
+ * @param length Length of the buffer.
+ * @param random Pointer to a randomly-initialized array of shorts.
+ * @param random_length Length of the short array.
+ */
+void generate_password(char *buffer, unsigned length, const unsigned short *random, unsigned random_length);
-/*
- Function: secure_random_uninit
- Uninitializes the secure random module.
+/**
+ * Initializes the secure random module.
+ * You *MUST* check the return value of this function.
+ *
+ * @ingroup Secure-Random
+ *
+ * @return `0` on success.
+ */
+[[nodiscard]] int secure_random_init();
- Returns:
- 0 - Uninitialization succeeded.
- 1 - Uninitialization failed.
-*/
+/**
+ * Uninitializes the secure random module.
+ *
+ * @ingroup Secure-Random
+ *
+ * @return `0` on success.
+ */
int secure_random_uninit();
-/*
- Function: secure_random_password
- Fills the buffer with the specified amount of random password
- characters.
-
- The desired password length must be greater or equal to 6, even
- and smaller or equal to 128.
-
- Parameters:
- buffer - Pointer to the start of the buffer.
- length - Length of the buffer.
- pw_length - Length of the desired password.
-*/
+/**
+ * Fills the buffer with the specified amount of random password characters.
+ *
+ * @ingroup Secure-Random
+ *
+ * @param buffer Pointer to the start of the buffer.
+ * @param length Length of the buffer.
+ * @param pw_length Length of the desired password.
+ *
+ * @remark The desired password length must be greater or equal to 6,
+ * even and smaller or equal to 128.
+ */
void secure_random_password(char *buffer, unsigned length, unsigned pw_length);
-/*
- Function: secure_random_fill
- Fills the buffer with the specified amount of random bytes.
-
- Parameters:
- buffer - Pointer to the start of the buffer.
- length - Length of the buffer.
-*/
+/**
+ * Fills the buffer with the specified amount of random bytes.
+ *
+ * @ingroup Secure-Random
+ *
+ * @param buffer Pointer to the start of the buffer.
+ * @param length Length of the buffer.
+ */
void secure_random_fill(void *bytes, unsigned length);
-/*
- Function: secure_rand
- Returns random int (replacement for rand()).
-*/
+/**
+ * Returns random `int`.
+ *
+ * @ingroup Secure-Random
+ *
+ * @return Random int.
+ *
+ * @remark Can be used as a replacement for the `rand` function.
+ */
int secure_rand();
-/*
- Function: secure_rand_below
- Returns a random nonnegative integer below the given number,
- with a uniform distribution.
-
- Parameters:
- below - Upper limit (exclusive) of integers to return.
-*/
+/**
+ * Returns a random nonnegative integer below the given number,
+ * with a uniform distribution.
+ *
+ * @ingroup Secure-Random
+ *
+ * @param below Upper limit (exclusive) of integers to return.
+ *
+ * @return Random nonnegative below the given number.
+ */
int secure_rand_below(int below);
/**
* Returns a human-readable version string of the operating system.
*
+ * @ingroup Shell
+ *
* @param version Buffer to use for the output.
* @param length Length of the output buffer.
*
- * @return true on success, false on failure.
+ * @return `true` on success, `false` on failure.
*/
bool os_version_str(char *version, size_t length);
@@ -2623,6 +2792,8 @@ bool os_version_str(char *version, size_t length);
* If the preferred locale could not be determined this function
* falls back to the locale `"en-US"`.
*
+ * @ingroup Shell
+ *
* @param locale Buffer to use for the output.
* @param length Length of the output buffer.
*
@@ -2631,7 +2802,25 @@ bool os_version_str(char *version, size_t length);
void os_locale_str(char *locale, size_t length);
#if defined(CONF_EXCEPTION_HANDLING)
+/**
+ * @defgroup Exception-Handling
+ * Exception handling (crash logging).
+ */
+
+/**
+ * Initializes the exception handling module.
+ *
+ * @ingroup Exception-Handling
+ */
void init_exception_handler();
+
+/**
+ * Sets the filename for writing the crash log.
+ *
+ * @ingroup Exception-Handling
+ *
+ * @param log_file_path Absolute path to which crash log file should be written.
+ */
void set_exception_handler_log_file(const char *log_file_path);
#endif
@@ -2648,7 +2837,9 @@ int net_socket_read_wait(NETSOCKET sock, std::chrono::nanoseconds nanoseconds);
/**
* Fixes the command line arguments to be encoded in UTF-8 on all systems.
- * This is a RAII wrapper for cmdline_fix and cmdline_free.
+ * This is a RAII wrapper for @link cmdline_fix @endlink and @link cmdline_free @endlink.
+ *
+ * @ingroup Shell
*/
class CCmdlineFix
{
@@ -2670,25 +2861,29 @@ class CCmdlineFix
#if defined(CONF_FAMILY_WINDOWS)
/**
- * Converts a utf8 encoded string to a wide character string
+ * Converts a UTF-8 encoded string to a wide character string
* for use with the Windows API.
*
- * @param str The utf8 encoded string to convert.
+ * @ingroup Shell
+ *
+ * @param str The UTF-8 encoded string to convert.
*
* @return The argument as a wide character string.
*
* @remark The argument string must be zero-terminated.
- * @remark Fails with assertion error if passed utf8 is invalid.
+ * @remark Fails with assertion error if passed UTF-8 is invalid.
*/
std::wstring windows_utf8_to_wide(const char *str);
/**
* Converts a wide character string obtained from the Windows API
- * to a utf8 encoded string.
+ * to a UTF-8 encoded string.
+ *
+ * @ingroup Shell
*
* @param wide_str The wide character string to convert.
*
- * @return The argument as a utf8 encoded string, wrapped in an optional.
+ * @return The argument as a UTF-8 encoded string, wrapped in an optional.
* The optional is empty, if the wide string contains invalid codepoints.
*
* @remark The argument string must be zero-terminated.
@@ -2697,10 +2892,13 @@ std::optional windows_wide_to_utf8(const wchar_t *wide_str);
/**
* This is a RAII wrapper to initialize/uninitialize the Windows COM library,
- * which may be necessary for using the open_file and open_link functions.
+ * which may be necessary for using the @link open_file @endlink and
+ * @link open_link @endlink functions.
* Must be used on every thread. It's automatically used on threads created
- * with thread_init. Pass true to the constructor on threads that own a
- * window (i.e. pump a message queue).
+ * with @link thread_init @endlink. Pass `true` to the constructor on threads
+ * that own a window (i.e. pump a message queue).
+ *
+ * @ingroup Shell
*/
class CWindowsComLifecycle
{
@@ -2716,11 +2914,11 @@ class CWindowsComLifecycle
*
* @param protocol_name The name of the protocol.
* @param executable The absolute path of the executable that will be associated with the protocol.
- * @param updated Pointer to a variable that will be set to true, iff the shell needs to be updated.
+ * @param updated Pointer to a variable that will be set to `true`, iff the shell needs to be updated.
*
- * @return true on success, false on failure.
+ * @return `true` on success, `false` on failure.
*
- * @remark The caller must later call shell_update, iff the shell needs to be updated.
+ * @remark The caller must later call @link shell_update @endlink, iff the shell needs to be updated.
*/
bool shell_register_protocol(const char *protocol_name, const char *executable, bool *updated);
@@ -2733,11 +2931,11 @@ bool shell_register_protocol(const char *protocol_name, const char *executable,
* @param description A readable description for the file extension.
* @param executable_name A unique name that will used to describe the application.
* @param executable The absolute path of the executable that will be associated with the file extension.
- * @param updated Pointer to a variable that will be set to true, iff the shell needs to be updated.
+ * @param updated Pointer to a variable that will be set to `true`, iff the shell needs to be updated.
*
- * @return true on success, false on failure.
+ * @return `true` on success, `false` on failure.
*
- * @remark The caller must later call shell_update, iff the shell needs to be updated.
+ * @remark The caller must later call @link shell_update @endlink, iff the shell needs to be updated.
*/
bool shell_register_extension(const char *extension, const char *description, const char *executable_name, const char *executable, bool *updated);
@@ -2748,11 +2946,11 @@ bool shell_register_extension(const char *extension, const char *description, co
*
* @param name Readable name of the application.
* @param executable The absolute path of the executable being registered.
- * @param updated Pointer to a variable that will be set to true, iff the shell needs to be updated.
+ * @param updated Pointer to a variable that will be set to `true`, iff the shell needs to be updated.
*
- * @return true on success, false on failure.
+ * @return `true` on success, `false` on failure.
*
- * @remark The caller must later call shell_update, iff the shell needs to be updated.
+ * @remark The caller must later call @link shell_update @endlink, iff the shell needs to be updated.
*/
bool shell_register_application(const char *name, const char *executable, bool *updated);
@@ -2764,11 +2962,11 @@ bool shell_register_application(const char *name, const char *executable, bool *
* @param shell_class The shell class to delete.
* For protocols this is the name of the protocol.
* For file extensions this is the program ID associated with the file extension.
- * @param updated Pointer to a variable that will be set to true, iff the shell needs to be updated.
+ * @param updated Pointer to a variable that will be set to `true`, iff the shell needs to be updated.
*
- * @return true on success, false on failure.
+ * @return `true` on success, `false` on failure.
*
- * @remark The caller must later call shell_update, iff the shell needs to be updated.
+ * @remark The caller must later call @link shell_update @endlink, iff the shell needs to be updated.
*/
bool shell_unregister_class(const char *shell_class, bool *updated);
@@ -2778,11 +2976,11 @@ bool shell_unregister_class(const char *shell_class, bool *updated);
* @ingroup Shell
*
* @param executable The absolute path of the executable being unregistered.
- * @param updated Pointer to a variable that will be set to true, iff the shell needs to be updated.
+ * @param updated Pointer to a variable that will be set to `true`, iff the shell needs to be updated.
*
- * @return true on success, false on failure.
+ * @return `true` on success, `false` on failure.
*
- * @remark The caller must later call shell_update, iff the shell needs to be updated.
+ * @remark The caller must later call @link shell_update @endlink, iff the shell needs to be updated.
*/
bool shell_unregister_application(const char *executable, bool *updated);
diff --git a/src/base/types.h b/src/base/types.h
index ffa1b47ed2..b1d5af051c 100644
--- a/src/base/types.h
+++ b/src/base/types.h
@@ -10,6 +10,11 @@ enum class TRISTATE
ALL,
};
+/**
+ * Handle for input/output files/streams.
+ *
+ * @ingroup File-IO
+ */
typedef void *IOHANDLE;
typedef int (*FS_LISTDIR_CALLBACK)(const char *name, int is_dir, int dir_type, void *user);
@@ -45,9 +50,14 @@ enum
NETTYPE_IPV4 = 1,
NETTYPE_IPV6 = 2,
NETTYPE_WEBSOCKET_IPV4 = 8,
+ /**
+ * 0.7 address. This is a flag in NETADDR to avoid introducing a parameter to every networking function
+ * to differenciate between 0.6 and 0.7 connections.
+ */
+ NETTYPE_TW7 = 16,
NETTYPE_ALL = NETTYPE_IPV4 | NETTYPE_IPV6 | NETTYPE_WEBSOCKET_IPV4,
- NETTYPE_MASK = NETTYPE_ALL | NETTYPE_LINK_BROADCAST,
+ NETTYPE_MASK = NETTYPE_ALL | NETTYPE_LINK_BROADCAST | NETTYPE_TW7,
};
/**
diff --git a/src/engine/Cargo.toml b/src/engine/Cargo.toml
index b6d484cd01..48eab28c4e 100644
--- a/src/engine/Cargo.toml
+++ b/src/engine/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "ddnet-engine"
version = "0.0.1"
-edition = "2018"
+edition = "2021"
publish = false
license = "Zlib"
diff --git a/src/engine/antibot.h b/src/engine/antibot.h
index 0b432bb78b..22ab05fddd 100644
--- a/src/engine/antibot.h
+++ b/src/engine/antibot.h
@@ -11,15 +11,15 @@ class IAntibot : public IInterface
virtual void RoundEnd() = 0;
// Hooks
- virtual void OnPlayerInit(int ClientID) = 0;
- virtual void OnPlayerDestroy(int ClientID) = 0;
- virtual void OnSpawn(int ClientID) = 0;
- virtual void OnHammerFireReloading(int ClientID) = 0;
- virtual void OnHammerFire(int ClientID) = 0;
- virtual void OnHammerHit(int ClientID, int TargetID) = 0;
- virtual void OnDirectInput(int ClientID) = 0;
- virtual void OnCharacterTick(int ClientID) = 0;
- virtual void OnHookAttach(int ClientID, bool Player) = 0;
+ virtual void OnPlayerInit(int ClientId) = 0;
+ virtual void OnPlayerDestroy(int ClientId) = 0;
+ virtual void OnSpawn(int ClientId) = 0;
+ virtual void OnHammerFireReloading(int ClientId) = 0;
+ virtual void OnHammerFire(int ClientId) = 0;
+ virtual void OnHammerHit(int ClientId, int TargetId) = 0;
+ virtual void OnDirectInput(int ClientId) = 0;
+ virtual void OnCharacterTick(int ClientId) = 0;
+ virtual void OnHookAttach(int ClientId, bool Player) = 0;
// Commands
virtual void ConsoleCommand(const char *pCommand) = 0;
@@ -35,11 +35,11 @@ class IEngineAntibot : public IAntibot
// Hooks
virtual void OnEngineTick() = 0;
- virtual void OnEngineClientJoin(int ClientID, bool Sixup) = 0;
- virtual void OnEngineClientDrop(int ClientID, const char *pReason) = 0;
- virtual bool OnEngineClientMessage(int ClientID, const void *pData, int Size, int Flags) = 0;
- virtual bool OnEngineServerMessage(int ClientID, const void *pData, int Size, int Flags) = 0;
- virtual bool OnEngineSimulateClientMessage(int *pClientID, void *pBuffer, int BufferSize, int *pOutSize, int *pFlags) = 0;
+ virtual void OnEngineClientJoin(int ClientId, bool Sixup) = 0;
+ virtual void OnEngineClientDrop(int ClientId, const char *pReason) = 0;
+ virtual bool OnEngineClientMessage(int ClientId, const void *pData, int Size, int Flags) = 0;
+ virtual bool OnEngineServerMessage(int ClientId, const void *pData, int Size, int Flags) = 0;
+ virtual bool OnEngineSimulateClientMessage(int *pClientId, void *pBuffer, int BufferSize, int *pOutSize, int *pFlags) = 0;
virtual ~IEngineAntibot(){};
};
diff --git a/src/engine/client.h b/src/engine/client.h
index d4c9f3fd43..a9599f89b4 100644
--- a/src/engine/client.h
+++ b/src/engine/client.h
@@ -8,11 +8,16 @@
#include "message.h"
#include
+#include
+
#include
+#include
#include
#include
+#include
+
struct SWarning;
enum
@@ -22,8 +27,6 @@ enum
RECORDER_RACE = 2,
RECORDER_REPLAYS = 3,
RECORDER_MAX = 4,
-
- NUM_DUMMIES = 2,
};
typedef bool (*CLIENTFUNC_FILTER)(const void *pData, int DataSize, void *pUser);
@@ -61,11 +64,18 @@ class IClient : public IInterface
{
LOADING_STATE_DETAIL_INITIAL,
LOADING_STATE_DETAIL_LOADING_MAP,
+ LOADING_STATE_DETAIL_LOADING_DEMO,
LOADING_STATE_DETAIL_SENDING_READY,
LOADING_STATE_DETAIL_GETTING_READY,
};
- typedef std::function TMapLoadingCallbackFunc;
+ enum ELoadingCallbackDetail
+ {
+ LOADING_CALLBACK_DETAIL_MAP,
+ LOADING_CALLBACK_DETAIL_DEMO,
+ };
+ typedef std::function TLoadingCallback;
+ CTranslationContext m_TranslationContext;
protected:
// quick access to state of the client
@@ -88,7 +98,7 @@ class IClient : public IInterface
float m_RenderFrameTime = 0.0001f;
float m_FrameTimeAvg = 0.0001f;
- TMapLoadingCallbackFunc m_MapLoadingCBFunc = nullptr;
+ TLoadingCallback m_LoadingCallback = nullptr;
char m_aNews[3000] = "";
int m_Points = -1;
@@ -99,7 +109,8 @@ class IClient : public IInterface
{
public:
int m_Type;
- int m_ID;
+ int m_Id;
+ const void *m_pData;
int m_DataSize;
};
@@ -128,7 +139,7 @@ class IClient : public IInterface
inline int64_t StateStartTime() const { return m_StateStartTime; }
void SetLoadingStateDetail(ELoadingStateDetail LoadingStateDetail) { m_LoadingStateDetail = LoadingStateDetail; }
- void SetMapLoadingCBFunc(TMapLoadingCallbackFunc &&Func) { m_MapLoadingCBFunc = std::move(Func); }
+ void SetLoadingCallback(TLoadingCallback &&Func) { m_LoadingCallback = std::move(Func); }
// tick time access
inline int PrevGameTick(int Conn) const { return m_aPrevGameTick[Conn]; }
@@ -153,9 +164,10 @@ class IClient : public IInterface
// dummy
virtual void DummyDisconnect(const char *pReason) = 0;
virtual void DummyConnect() = 0;
- virtual bool DummyConnected() = 0;
- virtual bool DummyConnecting() = 0;
- virtual bool DummyAllowed() = 0;
+ virtual bool DummyConnected() const = 0;
+ virtual bool DummyConnecting() const = 0;
+ virtual bool DummyConnectingDelayed() const = 0;
+ virtual bool DummyAllowed() const = 0;
virtual void Restart() = 0;
virtual void Quit() = 0;
@@ -165,7 +177,7 @@ class IClient : public IInterface
#endif
virtual void DemoRecorder_Start(const char *pFilename, bool WithTimestamp, int Recorder, bool Verbose = false) = 0;
virtual void DemoRecorder_HandleAutoStart() = 0;
- virtual void DemoRecorder_Stop(int Recorder, bool RemoveFile = false) = 0;
+ virtual void DemoRecorder_UpdateReplayRecorder() = 0;
virtual class IDemoRecorder *DemoRecorder(int Recorder) = 0;
virtual void AutoScreenshot_Start() = 0;
virtual void AutoStatScreenshot_Start() = 0;
@@ -174,7 +186,7 @@ class IClient : public IInterface
// gfx
virtual void SwitchWindowScreen(int Index) = 0;
- virtual void SetWindowParams(int FullscreenMode, bool IsBorderless, bool AllowResizing) = 0;
+ virtual void SetWindowParams(int FullscreenMode, bool IsBorderless) = 0;
virtual void ToggleWindowVSync() = 0;
virtual void Notify(const char *pTitle, const char *pMessage) = 0;
virtual void OnWindowResize() = 0;
@@ -200,9 +212,12 @@ class IClient : public IInterface
virtual bool RconAuthed() const = 0;
virtual bool UseTempRconCommands() const = 0;
virtual void Rcon(const char *pLine) = 0;
+ virtual bool ReceivingRconCommands() const = 0;
+ virtual float GotRconCommandsPercentage() const = 0;
// server info
virtual void GetServerInfo(class CServerInfo *pServerInfo) const = 0;
+ virtual bool ServerCapAnyPlayerFlag() const = 0;
virtual int GetPredictionTime() = 0;
@@ -216,34 +231,41 @@ class IClient : public IInterface
};
// TODO: Refactor: should redo this a bit i think, too many virtual calls
- virtual int SnapNumItems(int SnapID) const = 0;
- virtual const void *SnapFindItem(int SnapID, int Type, int ID) const = 0;
- virtual void *SnapGetItem(int SnapID, int Index, CSnapItem *pItem) const = 0;
- virtual int SnapItemSize(int SnapID, int Index) const = 0;
+ virtual int SnapNumItems(int SnapId) const = 0;
+ virtual const void *SnapFindItem(int SnapId, int Type, int Id) const = 0;
+ virtual CSnapItem SnapGetItem(int SnapId, int Index) const = 0;
virtual void SnapSetStaticsize(int ItemType, int Size) = 0;
+ virtual void SnapSetStaticsize7(int ItemType, int Size) = 0;
virtual int SendMsg(int Conn, CMsgPacker *pMsg, int Flags) = 0;
virtual int SendMsgActive(CMsgPacker *pMsg, int Flags) = 0;
template
- int SendPackMsgActive(T *pMsg, int Flags)
+ int SendPackMsgActive(T *pMsg, int Flags, bool NoTranslate = false)
{
- CMsgPacker Packer(T::ms_MsgID, false);
+ CMsgPacker Packer(T::ms_MsgId, false, NoTranslate);
if(pMsg->Pack(&Packer))
return -1;
return SendMsgActive(&Packer, Flags);
}
+ template
+ int SendPackMsg(int Conn, T *pMsg, int Flags, bool NoTranslate = false)
+ {
+ CMsgPacker Packer(T::ms_MsgId, false, NoTranslate);
+ if(pMsg->Pack(&Packer))
+ return -1;
+ return SendMsg(Conn, &Packer, Flags);
+ }
+
//
virtual const char *PlayerName() const = 0;
- virtual const char *DummyName() const = 0;
+ virtual const char *DummyName() = 0;
virtual const char *ErrorString() const = 0;
virtual const char *LatestVersion() const = 0;
virtual bool ConnectionProblems() const = 0;
- virtual bool SoundInitFailed() const = 0;
-
virtual IGraphics::CTextureHandle GetDebugFont() const = 0; // TODO: remove this function
//DDRace
@@ -257,6 +279,9 @@ class IClient : public IInterface
int Points() const { return m_Points; }
int64_t ReconnectTime() const { return m_ReconnectTime; }
void SetReconnectTime(int64_t ReconnectTime) { m_ReconnectTime = ReconnectTime; }
+
+ virtual bool IsSixup() const = 0;
+
virtual int GetCurrentRaceTime() = 0;
virtual void RaceRecord_Start(const char *pFilename) = 0;
@@ -280,9 +305,29 @@ class IClient : public IInterface
virtual SWarning *GetCurWarning() = 0;
virtual CChecksumData *ChecksumData() = 0;
- virtual bool InfoTaskRunning() = 0;
virtual int UdpConnectivity(int NetType) = 0;
+ /**
+ * Opens a link in the browser.
+ *
+ * @param pLink The link to open in a browser.
+ *
+ * @return `true` on success, `false` on failure.
+ *
+ * @remark This may not be called with untrusted input or it'll result in arbitrary code execution, especially on Windows.
+ */
+ virtual bool ViewLink(const char *pLink) = 0;
+ /**
+ * Opens a file or directory with the default program.
+ *
+ * @param pFilename The file or folder to open with the default program.
+ *
+ * @return `true` on success, `false` on failure.
+ *
+ * @remark This may not be called with untrusted input or it'll result in arbitrary code execution, especially on Windows.
+ */
+ virtual bool ViewFile(const char *pFilename) = 0;
+
#if defined(CONF_FAMILY_WINDOWS)
virtual void ShellRegister() = 0;
virtual void ShellUnregister() = 0;
@@ -295,7 +340,7 @@ class IClient : public IInterface
MESSAGE_BOX_TYPE_INFO,
};
virtual void ShowMessageBox(const char *pTitle, const char *pMessage, EMessageBoxType Type = MESSAGE_BOX_TYPE_ERROR) = 0;
- virtual void GetGPUInfoString(char (&aGPUInfo)[256]) = 0;
+ virtual void GetGpuInfoString(char (&aGpuInfo)[256]) = 0;
};
class IGameClient : public IInterface
@@ -316,7 +361,7 @@ class IGameClient : public IInterface
virtual void OnUpdate() = 0;
virtual void OnStateChange(int NewState, int OldState) = 0;
virtual void OnConnected() = 0;
- virtual void OnMessage(int MsgID, CUnpacker *pUnpacker, int Conn, bool Dummy) = 0;
+ virtual void OnMessage(int MsgId, CUnpacker *pUnpacker, int Conn, bool Dummy) = 0;
virtual void OnPredict() = 0;
virtual void OnActivateEditor() = 0;
virtual void OnWindowResize() = 0;
@@ -329,19 +374,28 @@ class IGameClient : public IInterface
virtual const char *GetItemName(int Type) const = 0;
virtual const char *Version() const = 0;
virtual const char *NetVersion() const = 0;
+ virtual const char *NetVersion7() const = 0;
virtual int DDNetVersion() const = 0;
virtual const char *DDNetVersionStr() const = 0;
virtual void OnDummyDisconnect() = 0;
virtual void DummyResetInput() = 0;
virtual void Echo(const char *pString) = 0;
+
virtual bool CanDisplayWarning() const = 0;
- virtual bool IsDisplayingWarning() const = 0;
+ virtual void RenderShutdownMessage() = 0;
virtual CNetObjHandler *GetNetObjHandler() = 0;
+ virtual protocol7::CNetObjHandler *GetNetObjHandler7() = 0;
+
+ virtual int ClientVersion7() const = 0;
+
+ virtual void ApplySkin7InfoFromSnapObj(const protocol7::CNetObj_De_ClientInfo *pObj, int ClientId) = 0;
+ virtual int OnDemoRecSnap7(class CSnapshot *pFrom, class CSnapshot *pTo, int Conn) = 0;
+ virtual int TranslateSnap(class CSnapshot *pSnapDstSix, class CSnapshot *pSnapSrcSeven, int Conn, bool Dummy) = 0;
};
-void SnapshotRemoveExtraProjectileInfo(unsigned char *pData);
+void SnapshotRemoveExtraProjectileInfo(class CSnapshot *pSnap);
extern IGameClient *CreateGameClient();
#endif
diff --git a/src/engine/client/backend/backend_base.cpp b/src/engine/client/backend/backend_base.cpp
index 168598064f..37d3b31784 100644
--- a/src/engine/client/backend/backend_base.cpp
+++ b/src/engine/client/backend/backend_base.cpp
@@ -1,13 +1,7 @@
#include "backend_base.h"
#include
-#include
-void *CCommandProcessorFragment_GLBase::Resize(const unsigned char *pData, int Width, int Height, int NewWidth, int NewHeight, int BPP)
-{
- return ResizeImage((const uint8_t *)pData, Width, Height, NewWidth, NewHeight, BPP);
-}
-
-bool CCommandProcessorFragment_GLBase::Texture2DTo3D(void *pImageBuffer, int ImageWidth, int ImageHeight, size_t PixelSize, int SplitCountWidth, int SplitCountHeight, void *pTarget3DImageData, int &Target3DImageWidth, int &Target3DImageHeight)
+bool CCommandProcessorFragment_GLBase::Texture2DTo3D(uint8_t *pImageBuffer, int ImageWidth, int ImageHeight, size_t PixelSize, int SplitCountWidth, int SplitCountHeight, uint8_t *pTarget3DImageData, int &Target3DImageWidth, int &Target3DImageHeight)
{
Target3DImageWidth = ImageWidth / SplitCountWidth;
Target3DImageHeight = ImageHeight / SplitCountHeight;
@@ -23,10 +17,10 @@ bool CCommandProcessorFragment_GLBase::Texture2DTo3D(void *pImageBuffer, int Ima
int DepthIndex = X + Y * SplitCountWidth;
size_t TargetImageFullWidth = (size_t)Target3DImageWidth * PixelSize;
- size_t TargetImageFullSize = (size_t)TargetImageFullWidth * Target3DImageHeight;
+ size_t TargetImageFullSize = TargetImageFullWidth * Target3DImageHeight;
ptrdiff_t ImageOffset = (ptrdiff_t)(((size_t)Y * FullImageWidth * (size_t)Target3DImageHeight) + ((size_t)Y3D * FullImageWidth) + ((size_t)X * TargetImageFullWidth));
ptrdiff_t TargetImageOffset = (ptrdiff_t)(TargetImageFullSize * (size_t)DepthIndex + ((size_t)Y3D * TargetImageFullWidth));
- mem_copy(((uint8_t *)pTarget3DImageData) + TargetImageOffset, ((uint8_t *)pImageBuffer) + (ptrdiff_t)(ImageOffset), TargetImageFullWidth);
+ mem_copy(pTarget3DImageData + TargetImageOffset, pImageBuffer + ImageOffset, TargetImageFullWidth);
}
}
}
diff --git a/src/engine/client/backend/backend_base.h b/src/engine/client/backend/backend_base.h
index 19b7eba6f2..516fb91df1 100644
--- a/src/engine/client/backend/backend_base.h
+++ b/src/engine/client/backend/backend_base.h
@@ -84,9 +84,7 @@ class CCommandProcessorFragment_GLBase
SGfxErrorContainer m_Error;
SGfxWarningContainer m_Warning;
- static void *Resize(const unsigned char *pData, int Width, int Height, int NewWidth, int NewHeight, int BPP);
-
- static bool Texture2DTo3D(void *pImageBuffer, int ImageWidth, int ImageHeight, size_t PixelSize, int SplitCountWidth, int SplitCountHeight, void *pTarget3DImageData, int &Target3DImageWidth, int &Target3DImageHeight);
+ static bool Texture2DTo3D(uint8_t *pImageBuffer, int ImageWidth, int ImageHeight, size_t PixelSize, int SplitCountWidth, int SplitCountHeight, uint8_t *pTarget3DImageData, int &Target3DImageWidth, int &Target3DImageHeight);
virtual bool GetPresentedImageData(uint32_t &Width, uint32_t &Height, CImageInfo::EImageFormat &Format, std::vector &vDstData) = 0;
@@ -123,7 +121,7 @@ class CCommandProcessorFragment_GLBase
char *m_pVersionString;
char *m_pRendererString;
- TTWGraphicsGPUList *m_pGPUList;
+ TTwGraphicsGpuList *m_pGpuList;
};
struct SCommand_Init : public CCommandBuffer::SCommand
@@ -141,7 +139,7 @@ class CCommandProcessorFragment_GLBase
std::atomic *m_pStreamMemoryUsage;
std::atomic *m_pStagingMemoryUsage;
- TTWGraphicsGPUList *m_pGPUList;
+ TTwGraphicsGpuList *m_pGpuList;
TGLBackendReadPresentedImageData *m_pReadPresentedImageDataFunc;
diff --git a/src/engine/client/backend/opengl/backend_opengl.cpp b/src/engine/client/backend/opengl/backend_opengl.cpp
index a599a99037..3ca11ff59e 100644
--- a/src/engine/client/backend/opengl/backend_opengl.cpp
+++ b/src/engine/client/backend/opengl/backend_opengl.cpp
@@ -5,6 +5,7 @@
#include
#include
+#include
#if defined(BACKEND_AS_OPENGL_ES) || !defined(CONF_BACKEND_OPENGL_ES)
@@ -42,13 +43,6 @@ void CCommandProcessorFragment_OpenGL::Cmd_Update_Viewport(const CCommandBuffer:
glViewport(pCommand->m_X, pCommand->m_Y, pCommand->m_Width, pCommand->m_Height);
}
-int CCommandProcessorFragment_OpenGL::TexFormatToOpenGLFormat(int TexFormat)
-{
- if(TexFormat == CCommandBuffer::TEXFORMAT_RGBA)
- return GL_RGBA;
- return GL_RGBA;
-}
-
size_t CCommandProcessorFragment_OpenGL::GLFormatToPixelSize(int GLFormat)
{
switch(GLFormat)
@@ -194,7 +188,7 @@ static void ParseVersionString(EBackendType BackendType, const char *pStr, int &
bool LastWasNumber = false;
while(*pStr && TotalNumbersPassed < 3)
{
- if(*pStr >= '0' && *pStr <= '9')
+ if(str_isnum(*pStr))
{
aCurNumberStr[CurNumberStrLen++] = (char)*pStr;
LastWasNumber = true;
@@ -313,8 +307,9 @@ bool CCommandProcessorFragment_OpenGL::InitOpenGL(const SCommand_Init *pCommand)
{
m_IsOpenGLES = pCommand->m_RequestedBackend == BACKEND_TYPE_OPENGL_ES;
- TGLBackendReadPresentedImageData &ReadPresentedImgDataFunc = *pCommand->m_pReadPresentedImageDataFunc;
- ReadPresentedImgDataFunc = [this](uint32_t &Width, uint32_t &Height, CImageInfo::EImageFormat &Format, std::vector &vDstData) { return GetPresentedImageData(Width, Height, Format, vDstData); };
+ *pCommand->m_pReadPresentedImageDataFunc = [this](uint32_t &Width, uint32_t &Height, CImageInfo::EImageFormat &Format, std::vector &vDstData) {
+ return GetPresentedImageData(Width, Height, Format, vDstData);
+ };
const char *pVendorString = (const char *)glGetString(GL_VENDOR);
dbg_msg("opengl", "Vendor string: %s", pVendorString);
@@ -325,9 +320,9 @@ bool CCommandProcessorFragment_OpenGL::InitOpenGL(const SCommand_Init *pCommand)
const char *pRendererString = (const char *)glGetString(GL_RENDERER);
- str_copy(pCommand->m_pVendorString, pVendorString, gs_GPUInfoStringSize);
- str_copy(pCommand->m_pVersionString, pVersionString, gs_GPUInfoStringSize);
- str_copy(pCommand->m_pRendererString, pRendererString, gs_GPUInfoStringSize);
+ str_copy(pCommand->m_pVendorString, pVendorString, gs_GpuInfoStringSize);
+ str_copy(pCommand->m_pVersionString, pVersionString, gs_GpuInfoStringSize);
+ str_copy(pCommand->m_pRendererString, pRendererString, gs_GpuInfoStringSize);
// parse version string
ParseVersionString(pCommand->m_RequestedBackend, pVersionString, pCommand->m_pCapabilities->m_ContextMajor, pCommand->m_pCapabilities->m_ContextMinor, pCommand->m_pCapabilities->m_ContextPatch);
@@ -617,7 +612,7 @@ bool CCommandProcessorFragment_OpenGL::Cmd_Init(const SCommand_Init *pCommand)
return true;
}
-void CCommandProcessorFragment_OpenGL::TextureUpdate(int Slot, int X, int Y, int Width, int Height, int GLFormat, void *pTexData)
+void CCommandProcessorFragment_OpenGL::TextureUpdate(int Slot, int X, int Y, int Width, int Height, int GLFormat, uint8_t *pTexData)
{
glBindTexture(GL_TEXTURE_2D, m_vTextures[Slot].m_Tex);
@@ -630,7 +625,7 @@ void CCommandProcessorFragment_OpenGL::TextureUpdate(int Slot, int X, int Y, int
int ResizedW = (int)(Width * ResizeW);
int ResizedH = (int)(Height * ResizeH);
- void *pTmpData = Resize(static_cast(pTexData), Width, Height, ResizedW, ResizedH, GLFormatToPixelSize(GLFormat));
+ uint8_t *pTmpData = ResizeImage(pTexData, Width, Height, ResizedW, ResizedH, GLFormatToPixelSize(GLFormat));
free(pTexData);
pTexData = pTmpData;
@@ -652,7 +647,7 @@ void CCommandProcessorFragment_OpenGL::TextureUpdate(int Slot, int X, int Y, int
Y /= 2;
}
- void *pTmpData = Resize(static_cast(pTexData), OldWidth, OldHeight, Width, Height, GLFormatToPixelSize(GLFormat));
+ uint8_t *pTmpData = ResizeImage(pTexData, OldWidth, OldHeight, Width, Height, GLFormatToPixelSize(GLFormat));
free(pTexData);
pTexData = pTmpData;
}
@@ -661,11 +656,6 @@ void CCommandProcessorFragment_OpenGL::TextureUpdate(int Slot, int X, int Y, int
free(pTexData);
}
-void CCommandProcessorFragment_OpenGL::Cmd_Texture_Update(const CCommandBuffer::SCommand_Texture_Update *pCommand)
-{
- TextureUpdate(pCommand->m_Slot, pCommand->m_X, pCommand->m_Y, pCommand->m_Width, pCommand->m_Height, TexFormatToOpenGLFormat(pCommand->m_Format), pCommand->m_pData);
-}
-
void CCommandProcessorFragment_OpenGL::DestroyTexture(int Slot)
{
m_pTextureMemoryUsage->store(m_pTextureMemoryUsage->load(std::memory_order_relaxed) - m_vTextures[Slot].m_MemSize, std::memory_order_relaxed);
@@ -704,7 +694,7 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Destroy(const CCommandBuffer:
DestroyTexture(pCommand->m_Slot);
}
-void CCommandProcessorFragment_OpenGL::TextureCreate(int Slot, int Width, int Height, int GLFormat, int GLStoreFormat, int Flags, void *pTexData)
+void CCommandProcessorFragment_OpenGL::TextureCreate(int Slot, int Width, int Height, int GLFormat, int GLStoreFormat, int Flags, uint8_t *pTexData)
{
#ifndef BACKEND_GL_MODERN_API
@@ -727,7 +717,7 @@ void CCommandProcessorFragment_OpenGL::TextureCreate(int Slot, int Width, int He
int PowerOfTwoHeight = HighestBit(Height);
if(Width != PowerOfTwoWidth || Height != PowerOfTwoHeight)
{
- void *pTmpData = Resize(static_cast(pTexData), Width, Height, PowerOfTwoWidth, PowerOfTwoHeight, GLFormatToPixelSize(GLFormat));
+ uint8_t *pTmpData = ResizeImage(pTexData, Width, Height, PowerOfTwoWidth, PowerOfTwoHeight, GLFormatToPixelSize(GLFormat));
free(pTexData);
pTexData = pTmpData;
@@ -759,7 +749,7 @@ void CCommandProcessorFragment_OpenGL::TextureCreate(int Slot, int Width, int He
if(NeedsResize)
{
- void *pTmpData = Resize(static_cast(pTexData), OldWidth, OldHeight, Width, Height, GLFormatToPixelSize(GLFormat));
+ uint8_t *pTmpData = ResizeImage(pTexData, OldWidth, OldHeight, Width, Height, GLFormatToPixelSize(GLFormat));
free(pTexData);
pTexData = pTmpData;
}
@@ -866,9 +856,7 @@ void CCommandProcessorFragment_OpenGL::TextureCreate(int Slot, int Width, int He
glBindSampler(0, 0);
}
- uint8_t *p3DImageData = NULL;
-
- p3DImageData = (uint8_t *)malloc((size_t)Width * Height * PixelSize);
+ uint8_t *p3DImageData = static_cast(malloc((size_t)Width * Height * PixelSize));
int Image3DWidth, Image3DHeight;
int ConvertWidth = Width;
@@ -879,7 +867,7 @@ void CCommandProcessorFragment_OpenGL::TextureCreate(int Slot, int Width, int He
dbg_msg("gfx", "3D/2D array texture was resized");
int NewWidth = maximum(HighestBit(ConvertWidth), 16);
int NewHeight = maximum(HighestBit(ConvertHeight), 16);
- uint8_t *pNewTexData = (uint8_t *)Resize((const uint8_t *)pTexData, ConvertWidth, ConvertHeight, NewWidth, NewHeight, GLFormatToPixelSize(GLFormat));
+ uint8_t *pNewTexData = ResizeImage(pTexData, ConvertWidth, ConvertHeight, NewWidth, NewHeight, GLFormatToPixelSize(GLFormat));
ConvertWidth = NewWidth;
ConvertHeight = NewHeight;
@@ -888,7 +876,7 @@ void CCommandProcessorFragment_OpenGL::TextureCreate(int Slot, int Width, int He
pTexData = pNewTexData;
}
- if((Texture2DTo3D(pTexData, ConvertWidth, ConvertHeight, PixelSize, 16, 16, p3DImageData, Image3DWidth, Image3DHeight)))
+ if(Texture2DTo3D(pTexData, ConvertWidth, ConvertHeight, PixelSize, 16, 16, p3DImageData, Image3DWidth, Image3DHeight))
{
glTexImage3D(Target, 0, GLStoreFormat, Image3DWidth, Image3DHeight, 256, 0, GLFormat, GL_UNSIGNED_BYTE, p3DImageData);
}
@@ -916,7 +904,7 @@ void CCommandProcessorFragment_OpenGL::TextureCreate(int Slot, int Width, int He
void CCommandProcessorFragment_OpenGL::Cmd_Texture_Create(const CCommandBuffer::SCommand_Texture_Create *pCommand)
{
- TextureCreate(pCommand->m_Slot, pCommand->m_Width, pCommand->m_Height, TexFormatToOpenGLFormat(pCommand->m_Format), TexFormatToOpenGLFormat(pCommand->m_StoreFormat), pCommand->m_Flags, pCommand->m_pData);
+ TextureCreate(pCommand->m_Slot, pCommand->m_Width, pCommand->m_Height, GL_RGBA, GL_RGBA, pCommand->m_Flags, pCommand->m_pData);
}
void CCommandProcessorFragment_OpenGL::Cmd_TextTexture_Update(const CCommandBuffer::SCommand_TextTexture_Update *pCommand)
@@ -983,10 +971,27 @@ void CCommandProcessorFragment_OpenGL::Cmd_Render(const CCommandBuffer::SCommand
#endif
}
-void CCommandProcessorFragment_OpenGL::Cmd_Screenshot(const CCommandBuffer::SCommand_TrySwapAndScreenshot *pCommand)
+void CCommandProcessorFragment_OpenGL::Cmd_ReadPixel(const CCommandBuffer::SCommand_TrySwapAndReadPixel *pCommand)
{
- *pCommand->m_pSwapped = false;
+ // get size of viewport
+ GLint aViewport[4] = {0, 0, 0, 0};
+ glGetIntegerv(GL_VIEWPORT, aViewport);
+ const int h = aViewport[3];
+ // fetch the pixel
+ uint8_t aPixelData[3];
+ GLint Alignment;
+ glGetIntegerv(GL_PACK_ALIGNMENT, &Alignment);
+ glPixelStorei(GL_PACK_ALIGNMENT, 1);
+ glReadPixels(pCommand->m_Position.x, h - 1 - pCommand->m_Position.y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, aPixelData);
+ glPixelStorei(GL_PACK_ALIGNMENT, Alignment);
+
+ // fill in the information
+ *pCommand->m_pColor = ColorRGBA(aPixelData[0] / 255.0f, aPixelData[1] / 255.0f, aPixelData[2] / 255.0f, 1.0f);
+}
+
+void CCommandProcessorFragment_OpenGL::Cmd_Screenshot(const CCommandBuffer::SCommand_TrySwapAndScreenshot *pCommand)
+{
// fetch image data
GLint aViewport[4] = {0, 0, 0, 0};
glGetIntegerv(GL_VIEWPORT, aViewport);
@@ -1047,9 +1052,6 @@ ERunCommandReturnTypes CCommandProcessorFragment_OpenGL::RunCommand(const CComma
case CCommandBuffer::CMD_TEXTURE_DESTROY:
Cmd_Texture_Destroy(static_cast(pBaseCommand));
break;
- case CCommandBuffer::CMD_TEXTURE_UPDATE:
- Cmd_Texture_Update(static_cast(pBaseCommand));
- break;
case CCommandBuffer::CMD_TEXT_TEXTURES_CREATE:
Cmd_TextTextures_Create(static_cast(pBaseCommand));
break;
@@ -1068,6 +1070,9 @@ ERunCommandReturnTypes CCommandProcessorFragment_OpenGL::RunCommand(const CComma
case CCommandBuffer::CMD_RENDER_TEX3D:
Cmd_RenderTex3D(static_cast(pBaseCommand));
break;
+ case CCommandBuffer::CMD_TRY_SWAP_AND_READ_PIXEL:
+ Cmd_ReadPixel(static_cast(pBaseCommand));
+ break;
case CCommandBuffer::CMD_TRY_SWAP_AND_SCREENSHOT:
Cmd_Screenshot(static_cast(pBaseCommand));
break;
@@ -1643,7 +1648,7 @@ bool CCommandProcessorFragment_OpenGL2::Cmd_Init(const SCommand_Init *pCommand)
m_pTileProgram->AddShader(&VertexShader);
m_pTileProgram->AddShader(&FragmentShader);
- glBindAttribLocation(m_pTileProgram->GetProgramID(), 0, "inVertex");
+ glBindAttribLocation(m_pTileProgram->GetProgramId(), 0, "inVertex");
m_pTileProgram->LinkProgram();
@@ -1670,8 +1675,8 @@ bool CCommandProcessorFragment_OpenGL2::Cmd_Init(const SCommand_Init *pCommand)
m_pTileProgramTextured->AddShader(&VertexShader);
m_pTileProgramTextured->AddShader(&FragmentShader);
- glBindAttribLocation(m_pTileProgram->GetProgramID(), 0, "inVertex");
- glBindAttribLocation(m_pTileProgram->GetProgramID(), 1, "inVertexTexCoord");
+ glBindAttribLocation(m_pTileProgram->GetProgramId(), 0, "inVertex");
+ glBindAttribLocation(m_pTileProgram->GetProgramId(), 1, "inVertexTexCoord");
m_pTileProgramTextured->LinkProgram();
@@ -1696,7 +1701,7 @@ bool CCommandProcessorFragment_OpenGL2::Cmd_Init(const SCommand_Init *pCommand)
m_pBorderTileProgram->AddShader(&VertexShader);
m_pBorderTileProgram->AddShader(&FragmentShader);
- glBindAttribLocation(m_pBorderTileProgram->GetProgramID(), 0, "inVertex");
+ glBindAttribLocation(m_pBorderTileProgram->GetProgramId(), 0, "inVertex");
m_pBorderTileProgram->LinkProgram();
@@ -1725,8 +1730,8 @@ bool CCommandProcessorFragment_OpenGL2::Cmd_Init(const SCommand_Init *pCommand)
m_pBorderTileProgramTextured->AddShader(&VertexShader);
m_pBorderTileProgramTextured->AddShader(&FragmentShader);
- glBindAttribLocation(m_pBorderTileProgramTextured->GetProgramID(), 0, "inVertex");
- glBindAttribLocation(m_pBorderTileProgramTextured->GetProgramID(), 1, "inVertexTexCoord");
+ glBindAttribLocation(m_pBorderTileProgramTextured->GetProgramId(), 0, "inVertex");
+ glBindAttribLocation(m_pBorderTileProgramTextured->GetProgramId(), 1, "inVertexTexCoord");
m_pBorderTileProgramTextured->LinkProgram();
@@ -1843,17 +1848,17 @@ void CCommandProcessorFragment_OpenGL2::Cmd_CreateBufferObject(const CCommandBuf
}
}
- GLuint VertBufferID = 0;
+ GLuint VertBufferId = 0;
- glGenBuffers(1, &VertBufferID);
- glBindBuffer(GL_ARRAY_BUFFER, VertBufferID);
+ glGenBuffers(1, &VertBufferId);
+ glBindBuffer(GL_ARRAY_BUFFER, VertBufferId);
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(pCommand->m_DataSize), pUploadData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
SBufferObject &BufferObject = m_vBufferObjectIndices[Index];
- BufferObject.m_BufferObjectID = VertBufferID;
+ BufferObject.m_BufferObjectId = VertBufferId;
BufferObject.m_DataSize = pCommand->m_DataSize;
- BufferObject.m_pData = malloc(pCommand->m_DataSize);
+ BufferObject.m_pData = static_cast(malloc(pCommand->m_DataSize));
if(pUploadData)
mem_copy(BufferObject.m_pData, pUploadData, pCommand->m_DataSize);
@@ -1867,13 +1872,13 @@ void CCommandProcessorFragment_OpenGL2::Cmd_RecreateBufferObject(const CCommandB
int Index = pCommand->m_BufferIndex;
SBufferObject &BufferObject = m_vBufferObjectIndices[Index];
- glBindBuffer(GL_ARRAY_BUFFER, BufferObject.m_BufferObjectID);
+ glBindBuffer(GL_ARRAY_BUFFER, BufferObject.m_BufferObjectId);
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(pCommand->m_DataSize), pUploadData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
BufferObject.m_DataSize = pCommand->m_DataSize;
free(BufferObject.m_pData);
- BufferObject.m_pData = malloc(pCommand->m_DataSize);
+ BufferObject.m_pData = static_cast(malloc(pCommand->m_DataSize));
if(pUploadData)
mem_copy(BufferObject.m_pData, pUploadData, pCommand->m_DataSize);
@@ -1887,12 +1892,12 @@ void CCommandProcessorFragment_OpenGL2::Cmd_UpdateBufferObject(const CCommandBuf
int Index = pCommand->m_BufferIndex;
SBufferObject &BufferObject = m_vBufferObjectIndices[Index];
- glBindBuffer(GL_ARRAY_BUFFER, BufferObject.m_BufferObjectID);
+ glBindBuffer(GL_ARRAY_BUFFER, BufferObject.m_BufferObjectId);
glBufferSubData(GL_ARRAY_BUFFER, (GLintptr)(pCommand->m_pOffset), (GLsizeiptr)(pCommand->m_DataSize), pUploadData);
glBindBuffer(GL_ARRAY_BUFFER, 0);
if(pUploadData)
- mem_copy(((uint8_t *)BufferObject.m_pData) + (ptrdiff_t)pCommand->m_pOffset, pUploadData, pCommand->m_DataSize);
+ mem_copy(BufferObject.m_pData + (ptrdiff_t)pCommand->m_pOffset, pUploadData, pCommand->m_DataSize);
if(pCommand->m_DeletePointer)
free(pUploadData);
@@ -1906,10 +1911,10 @@ void CCommandProcessorFragment_OpenGL2::Cmd_CopyBufferObject(const CCommandBuffe
SBufferObject &ReadBufferObject = m_vBufferObjectIndices[ReadIndex];
SBufferObject &WriteBufferObject = m_vBufferObjectIndices[WriteIndex];
- mem_copy(((uint8_t *)WriteBufferObject.m_pData) + (ptrdiff_t)pCommand->m_WriteOffset, ((uint8_t *)ReadBufferObject.m_pData) + (ptrdiff_t)pCommand->m_ReadOffset, pCommand->m_CopySize);
+ mem_copy(WriteBufferObject.m_pData + (ptrdiff_t)pCommand->m_WriteOffset, ReadBufferObject.m_pData + (ptrdiff_t)pCommand->m_ReadOffset, pCommand->m_CopySize);
- glBindBuffer(GL_ARRAY_BUFFER, WriteBufferObject.m_BufferObjectID);
- glBufferSubData(GL_ARRAY_BUFFER, (GLintptr)(pCommand->m_WriteOffset), (GLsizeiptr)(pCommand->m_CopySize), ((uint8_t *)WriteBufferObject.m_pData) + (ptrdiff_t)pCommand->m_WriteOffset);
+ glBindBuffer(GL_ARRAY_BUFFER, WriteBufferObject.m_BufferObjectId);
+ glBufferSubData(GL_ARRAY_BUFFER, (GLintptr)(pCommand->m_WriteOffset), (GLsizeiptr)(pCommand->m_CopySize), WriteBufferObject.m_pData + (ptrdiff_t)pCommand->m_WriteOffset);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
@@ -1918,7 +1923,7 @@ void CCommandProcessorFragment_OpenGL2::Cmd_DeleteBufferObject(const CCommandBuf
int Index = pCommand->m_BufferIndex;
SBufferObject &BufferObject = m_vBufferObjectIndices[Index];
- glDeleteBuffers(1, &BufferObject.m_BufferObjectID);
+ glDeleteBuffers(1, &BufferObject.m_BufferObjectId);
free(BufferObject.m_pData);
BufferObject.m_pData = NULL;
@@ -1971,13 +1976,13 @@ void CCommandProcessorFragment_OpenGL2::Cmd_DeleteBufferContainer(const CCommand
if(pCommand->m_DestroyAllBO)
{
- int VertBufferID = BufferContainer.m_ContainerInfo.m_VertBufferBindingIndex;
- if(VertBufferID != -1)
+ int VertBufferId = BufferContainer.m_ContainerInfo.m_VertBufferBindingIndex;
+ if(VertBufferId != -1)
{
- glDeleteBuffers(1, &m_vBufferObjectIndices[VertBufferID].m_BufferObjectID);
+ glDeleteBuffers(1, &m_vBufferObjectIndices[VertBufferId].m_BufferObjectId);
- free(m_vBufferObjectIndices[VertBufferID].m_pData);
- m_vBufferObjectIndices[VertBufferID].m_pData = NULL;
+ free(m_vBufferObjectIndices[VertBufferId].m_pData);
+ m_vBufferObjectIndices[VertBufferId].m_pData = NULL;
}
}
@@ -2014,7 +2019,7 @@ void CCommandProcessorFragment_OpenGL2::Cmd_RenderBorderTile(const CCommandBuffe
SBufferObject &BufferObject = m_vBufferObjectIndices[(size_t)BufferContainer.m_ContainerInfo.m_VertBufferBindingIndex];
- glBindBuffer(GL_ARRAY_BUFFER, BufferObject.m_BufferObjectID);
+ glBindBuffer(GL_ARRAY_BUFFER, BufferObject.m_BufferObjectId);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, false, BufferContainer.m_ContainerInfo.m_Stride, BufferContainer.m_ContainerInfo.m_vAttributes[0].m_pOffset);
@@ -2066,7 +2071,7 @@ void CCommandProcessorFragment_OpenGL2::Cmd_RenderTileLayer(const CCommandBuffer
SBufferObject &BufferObject = m_vBufferObjectIndices[(size_t)BufferContainer.m_ContainerInfo.m_VertBufferBindingIndex];
- glBindBuffer(GL_ARRAY_BUFFER, BufferObject.m_BufferObjectID);
+ glBindBuffer(GL_ARRAY_BUFFER, BufferObject.m_BufferObjectId);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, false, BufferContainer.m_ContainerInfo.m_Stride, BufferContainer.m_ContainerInfo.m_vAttributes[0].m_pOffset);
diff --git a/src/engine/client/backend/opengl/backend_opengl.h b/src/engine/client/backend/opengl/backend_opengl.h
index 2d339c0fdb..f0d833cc48 100644
--- a/src/engine/client/backend/opengl/backend_opengl.h
+++ b/src/engine/client/backend/opengl/backend_opengl.h
@@ -82,15 +82,13 @@ class CCommandProcessorFragment_OpenGL : public CCommandProcessorFragment_GLBase
bool GetPresentedImageData(uint32_t &Width, uint32_t &Height, CImageInfo::EImageFormat &Format, std::vector &vDstData) override;
- static int TexFormatToOpenGLFormat(int TexFormat);
static size_t GLFormatToPixelSize(int GLFormat);
- void TextureUpdate(int Slot, int X, int Y, int Width, int Height, int GLFormat, void *pTexData);
- void TextureCreate(int Slot, int Width, int Height, int GLFormat, int GLStoreFormat, int Flags, void *pTexData);
+ void TextureUpdate(int Slot, int X, int Y, int Width, int Height, int GLFormat, uint8_t *pTexData);
+ void TextureCreate(int Slot, int Width, int Height, int GLFormat, int GLStoreFormat, int Flags, uint8_t *pTexData);
virtual bool Cmd_Init(const SCommand_Init *pCommand);
virtual void Cmd_Shutdown(const SCommand_Shutdown *pCommand) {}
- virtual void Cmd_Texture_Update(const CCommandBuffer::SCommand_Texture_Update *pCommand);
virtual void Cmd_Texture_Destroy(const CCommandBuffer::SCommand_Texture_Destroy *pCommand);
virtual void Cmd_Texture_Create(const CCommandBuffer::SCommand_Texture_Create *pCommand);
virtual void Cmd_TextTexture_Update(const CCommandBuffer::SCommand_TextTexture_Update *pCommand);
@@ -99,6 +97,7 @@ class CCommandProcessorFragment_OpenGL : public CCommandProcessorFragment_GLBase
virtual void Cmd_Clear(const CCommandBuffer::SCommand_Clear *pCommand);
virtual void Cmd_Render(const CCommandBuffer::SCommand_Render *pCommand);
virtual void Cmd_RenderTex3D(const CCommandBuffer::SCommand_RenderTex3D *pCommand) { dbg_assert(false, "Call of unsupported Cmd_RenderTex3D"); }
+ virtual void Cmd_ReadPixel(const CCommandBuffer::SCommand_TrySwapAndReadPixel *pCommand);
virtual void Cmd_Screenshot(const CCommandBuffer::SCommand_TrySwapAndScreenshot *pCommand);
virtual void Cmd_Update_Viewport(const CCommandBuffer::SCommand_Update_Viewport *pCommand);
@@ -143,14 +142,14 @@ class CCommandProcessorFragment_OpenGL2 : public CCommandProcessorFragment_OpenG
struct SBufferObject
{
- SBufferObject(TWGLuint BufferObjectID) :
- m_BufferObjectID(BufferObjectID)
+ SBufferObject(TWGLuint BufferObjectId) :
+ m_BufferObjectId(BufferObjectId)
{
m_pData = NULL;
m_DataSize = 0;
}
- TWGLuint m_BufferObjectID;
- void *m_pData;
+ TWGLuint m_BufferObjectId;
+ uint8_t *m_pData;
size_t m_DataSize;
};
diff --git a/src/engine/client/backend/opengl/backend_opengl3.cpp b/src/engine/client/backend/opengl/backend_opengl3.cpp
index 315dd887d7..95dbf3d366 100644
--- a/src/engine/client/backend/opengl/backend_opengl3.cpp
+++ b/src/engine/client/backend/opengl/backend_opengl3.cpp
@@ -30,19 +30,12 @@ static constexpr GLenum BUFFER_INIT_VERTEX_TARGET = GL_COPY_WRITE_BUFFER;
#endif
// ------------ CCommandProcessorFragment_OpenGL3_3
-int CCommandProcessorFragment_OpenGL3_3::TexFormatToNewOpenGLFormat(int TexFormat)
-{
- if(TexFormat == CCommandBuffer::TEXFORMAT_RGBA)
- return GL_RGBA;
- return GL_RGBA;
-}
-
void CCommandProcessorFragment_OpenGL3_3::UseProgram(CGLSLTWProgram *pProgram)
{
- if(m_LastProgramID != pProgram->GetProgramID())
+ if(m_LastProgramId != pProgram->GetProgramId())
{
pProgram->UseProgram();
- m_LastProgramID = pProgram->GetProgramID();
+ m_LastProgramId = pProgram->GetProgramId();
}
}
@@ -114,7 +107,7 @@ bool CCommandProcessorFragment_OpenGL3_3::Cmd_Init(const SCommand_Init *pCommand
m_pPrimitiveExProgramRotationless = new CGLSLPrimitiveExProgram;
m_pPrimitiveExProgramTexturedRotationless = new CGLSLPrimitiveExProgram;
m_pSpriteProgramMultiple = new CGLSLSpriteMultipleProgram;
- m_LastProgramID = 0;
+ m_LastProgramId = 0;
CGLSLCompiler ShaderCompiler(g_Config.m_GfxGLMajor, g_Config.m_GfxGLMinor, g_Config.m_GfxGLPatch, m_IsOpenGLES, m_OpenGLTextureLodBIAS / 1000.0f);
@@ -366,15 +359,15 @@ bool CCommandProcessorFragment_OpenGL3_3::Cmd_Init(const SCommand_Init *pCommand
m_LastStreamBuffer = 0;
- glGenBuffers(MAX_STREAM_BUFFER_COUNT, m_aPrimitiveDrawBufferID);
- glGenVertexArrays(MAX_STREAM_BUFFER_COUNT, m_aPrimitiveDrawVertexID);
- glGenBuffers(1, &m_PrimitiveDrawBufferIDTex3D);
- glGenVertexArrays(1, &m_PrimitiveDrawVertexIDTex3D);
+ glGenBuffers(MAX_STREAM_BUFFER_COUNT, m_aPrimitiveDrawBufferId);
+ glGenVertexArrays(MAX_STREAM_BUFFER_COUNT, m_aPrimitiveDrawVertexId);
+ glGenBuffers(1, &m_PrimitiveDrawBufferIdTex3D);
+ glGenVertexArrays(1, &m_PrimitiveDrawVertexIdTex3D);
for(int i = 0; i < MAX_STREAM_BUFFER_COUNT; ++i)
{
- glBindBuffer(GL_ARRAY_BUFFER, m_aPrimitiveDrawBufferID[i]);
- glBindVertexArray(m_aPrimitiveDrawVertexID[i]);
+ glBindBuffer(GL_ARRAY_BUFFER, m_aPrimitiveDrawBufferId[i]);
+ glBindVertexArray(m_aPrimitiveDrawVertexId[i]);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
@@ -386,8 +379,8 @@ bool CCommandProcessorFragment_OpenGL3_3::Cmd_Init(const SCommand_Init *pCommand
m_aLastIndexBufferBound[i] = 0;
}
- glBindBuffer(GL_ARRAY_BUFFER, m_PrimitiveDrawBufferIDTex3D);
- glBindVertexArray(m_PrimitiveDrawVertexIDTex3D);
+ glBindBuffer(GL_ARRAY_BUFFER, m_PrimitiveDrawBufferIdTex3D);
+ glBindVertexArray(m_PrimitiveDrawVertexIdTex3D);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
@@ -400,8 +393,8 @@ bool CCommandProcessorFragment_OpenGL3_3::Cmd_Init(const SCommand_Init *pCommand
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_MaxTexSize);
glBindVertexArray(0);
- glGenBuffers(1, &m_QuadDrawIndexBufferID);
- glBindBuffer(BUFFER_INIT_INDEX_TARGET, m_QuadDrawIndexBufferID);
+ glGenBuffers(1, &m_QuadDrawIndexBufferId);
+ glBindBuffer(BUFFER_INIT_INDEX_TARGET, m_QuadDrawIndexBufferId);
unsigned int aIndices[CCommandBuffer::MAX_VERTICES / 4 * 6];
int Primq = 0;
@@ -469,11 +462,11 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_Shutdown(const SCommand_Shutdown *
delete m_pSpriteProgramMultiple;
glBindVertexArray(0);
- glDeleteBuffers(MAX_STREAM_BUFFER_COUNT, m_aPrimitiveDrawBufferID);
- glDeleteBuffers(1, &m_QuadDrawIndexBufferID);
- glDeleteVertexArrays(MAX_STREAM_BUFFER_COUNT, m_aPrimitiveDrawVertexID);
- glDeleteBuffers(1, &m_PrimitiveDrawBufferIDTex3D);
- glDeleteVertexArrays(1, &m_PrimitiveDrawVertexIDTex3D);
+ glDeleteBuffers(MAX_STREAM_BUFFER_COUNT, m_aPrimitiveDrawBufferId);
+ glDeleteBuffers(1, &m_QuadDrawIndexBufferId);
+ glDeleteVertexArrays(MAX_STREAM_BUFFER_COUNT, m_aPrimitiveDrawVertexId);
+ glDeleteBuffers(1, &m_PrimitiveDrawBufferIdTex3D);
+ glDeleteVertexArrays(1, &m_PrimitiveDrawVertexIdTex3D);
for(int i = 0; i < (int)m_vTextures.size(); ++i)
{
@@ -488,7 +481,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_Shutdown(const SCommand_Shutdown *
m_vBufferContainers.clear();
}
-void CCommandProcessorFragment_OpenGL3_3::TextureUpdate(int Slot, int X, int Y, int Width, int Height, int GLFormat, void *pTexData)
+void CCommandProcessorFragment_OpenGL3_3::TextureUpdate(int Slot, int X, int Y, int Width, int Height, int GLFormat, uint8_t *pTexData)
{
glBindTexture(GL_TEXTURE_2D, m_vTextures[Slot].m_Tex);
@@ -503,7 +496,7 @@ void CCommandProcessorFragment_OpenGL3_3::TextureUpdate(int Slot, int X, int Y,
Y /= 2;
}
- void *pTmpData = Resize(static_cast(pTexData), Width, Height, Width, Height, GLFormatToPixelSize(GLFormat));
+ uint8_t *pTmpData = ResizeImage(pTexData, Width, Height, Width, Height, GLFormatToPixelSize(GLFormat));
free(pTexData);
pTexData = pTmpData;
}
@@ -512,11 +505,6 @@ void CCommandProcessorFragment_OpenGL3_3::TextureUpdate(int Slot, int X, int Y,
free(pTexData);
}
-void CCommandProcessorFragment_OpenGL3_3::Cmd_Texture_Update(const CCommandBuffer::SCommand_Texture_Update *pCommand)
-{
- TextureUpdate(pCommand->m_Slot, pCommand->m_X, pCommand->m_Y, pCommand->m_Width, pCommand->m_Height, TexFormatToOpenGLFormat(pCommand->m_Format), pCommand->m_pData);
-}
-
void CCommandProcessorFragment_OpenGL3_3::Cmd_Texture_Destroy(const CCommandBuffer::SCommand_Texture_Destroy *pCommand)
{
int Slot = 0;
@@ -525,7 +513,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_Texture_Destroy(const CCommandBuff
DestroyTexture(pCommand->m_Slot);
}
-void CCommandProcessorFragment_OpenGL3_3::TextureCreate(int Slot, int Width, int Height, int GLFormat, int GLStoreFormat, int Flags, void *pTexData)
+void CCommandProcessorFragment_OpenGL3_3::TextureCreate(int Slot, int Width, int Height, int GLFormat, int GLStoreFormat, int Flags, uint8_t *pTexData)
{
while(Slot >= (int)m_vTextures.size())
m_vTextures.resize(m_vTextures.size() * 2);
@@ -543,7 +531,7 @@ void CCommandProcessorFragment_OpenGL3_3::TextureCreate(int Slot, int Width, int
++RescaleCount;
} while(Width > m_MaxTexSize || Height > m_MaxTexSize);
- void *pTmpData = Resize(static_cast(pTexData), Width, Height, Width, Height, GLFormatToPixelSize(GLFormat));
+ uint8_t *pTmpData = ResizeImage(pTexData, Width, Height, Width, Height, GLFormatToPixelSize(GLFormat));
free(pTexData);
pTexData = pTmpData;
}
@@ -618,9 +606,7 @@ void CCommandProcessorFragment_OpenGL3_3::TextureCreate(int Slot, int Width, int
glSamplerParameterf(m_vTextures[Slot].m_Sampler2DArray, GL_TEXTURE_LOD_BIAS, ((GLfloat)m_OpenGLTextureLodBIAS / 1000.0f));
#endif
- uint8_t *p3DImageData = NULL;
-
- p3DImageData = (uint8_t *)malloc((size_t)Width * Height * PixelSize);
+ uint8_t *p3DImageData = static_cast(malloc((size_t)Width * Height * PixelSize));
int Image3DWidth, Image3DHeight;
int ConvertWidth = Width;
@@ -631,7 +617,7 @@ void CCommandProcessorFragment_OpenGL3_3::TextureCreate(int Slot, int Width, int
dbg_msg("gfx", "3D/2D array texture was resized");
int NewWidth = maximum(HighestBit(ConvertWidth), 16);
int NewHeight = maximum(HighestBit(ConvertHeight), 16);
- uint8_t *pNewTexData = (uint8_t *)Resize((const uint8_t *)pTexData, ConvertWidth, ConvertHeight, NewWidth, NewHeight, GLFormatToPixelSize(GLFormat));
+ uint8_t *pNewTexData = ResizeImage(pTexData, ConvertWidth, ConvertHeight, NewWidth, NewHeight, GLFormatToPixelSize(GLFormat));
ConvertWidth = NewWidth;
ConvertHeight = NewHeight;
@@ -640,7 +626,7 @@ void CCommandProcessorFragment_OpenGL3_3::TextureCreate(int Slot, int Width, int
pTexData = pNewTexData;
}
- if((Texture2DTo3D(pTexData, ConvertWidth, ConvertHeight, PixelSize, 16, 16, p3DImageData, Image3DWidth, Image3DHeight)))
+ if(Texture2DTo3D(pTexData, ConvertWidth, ConvertHeight, PixelSize, 16, 16, p3DImageData, Image3DWidth, Image3DHeight))
{
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GLStoreFormat, Image3DWidth, Image3DHeight, 256, 0, GLFormat, GL_UNSIGNED_BYTE, p3DImageData);
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
@@ -668,7 +654,7 @@ void CCommandProcessorFragment_OpenGL3_3::TextureCreate(int Slot, int Width, int
void CCommandProcessorFragment_OpenGL3_3::Cmd_Texture_Create(const CCommandBuffer::SCommand_Texture_Create *pCommand)
{
- TextureCreate(pCommand->m_Slot, pCommand->m_Width, pCommand->m_Height, TexFormatToOpenGLFormat(pCommand->m_Format), TexFormatToOpenGLFormat(pCommand->m_StoreFormat), pCommand->m_Flags, pCommand->m_pData);
+ TextureCreate(pCommand->m_Slot, pCommand->m_Width, pCommand->m_Height, GL_RGBA, GL_RGBA, pCommand->m_Flags, pCommand->m_pData);
}
void CCommandProcessorFragment_OpenGL3_3::Cmd_TextTexture_Update(const CCommandBuffer::SCommand_TextTexture_Update *pCommand)
@@ -727,9 +713,9 @@ void CCommandProcessorFragment_OpenGL3_3::UploadStreamBufferData(unsigned int Pr
};
if(AsTex3D)
- glBindBuffer(GL_ARRAY_BUFFER, m_PrimitiveDrawBufferIDTex3D);
+ glBindBuffer(GL_ARRAY_BUFFER, m_PrimitiveDrawBufferIdTex3D);
else
- glBindBuffer(GL_ARRAY_BUFFER, m_aPrimitiveDrawBufferID[m_LastStreamBuffer]);
+ glBindBuffer(GL_ARRAY_BUFFER, m_aPrimitiveDrawBufferId[m_LastStreamBuffer]);
glBufferData(GL_ARRAY_BUFFER, VertSize * Count, pVertices, GL_STREAM_DRAW);
}
@@ -744,7 +730,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_Render(const CCommandBuffer::SComm
UploadStreamBufferData(pCommand->m_PrimType, pCommand->m_pVertices, sizeof(CCommandBuffer::SVertex), pCommand->m_PrimCount);
- glBindVertexArray(m_aPrimitiveDrawVertexID[m_LastStreamBuffer]);
+ glBindVertexArray(m_aPrimitiveDrawVertexId[m_LastStreamBuffer]);
switch(pCommand->m_PrimType)
{
@@ -756,10 +742,10 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_Render(const CCommandBuffer::SComm
glDrawArrays(GL_TRIANGLES, 0, pCommand->m_PrimCount * 3);
break;
case CCommandBuffer::PRIMTYPE_QUADS:
- if(m_aLastIndexBufferBound[m_LastStreamBuffer] != m_QuadDrawIndexBufferID)
+ if(m_aLastIndexBufferBound[m_LastStreamBuffer] != m_QuadDrawIndexBufferId)
{
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferID);
- m_aLastIndexBufferBound[m_LastStreamBuffer] = m_QuadDrawIndexBufferID;
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId);
+ m_aLastIndexBufferBound[m_LastStreamBuffer] = m_QuadDrawIndexBufferId;
}
glDrawElements(GL_TRIANGLES, pCommand->m_PrimCount * 6, GL_UNSIGNED_INT, 0);
break;
@@ -780,7 +766,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderTex3D(const CCommandBuffer::
UploadStreamBufferData(pCommand->m_PrimType, pCommand->m_pVertices, sizeof(CCommandBuffer::SVertexTex3DStream), pCommand->m_PrimCount, true);
- glBindVertexArray(m_PrimitiveDrawVertexIDTex3D);
+ glBindVertexArray(m_PrimitiveDrawVertexIdTex3D);
switch(pCommand->m_PrimType)
{
@@ -789,7 +775,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderTex3D(const CCommandBuffer::
glDrawArrays(GL_LINES, 0, pCommand->m_PrimCount * 2);
break;
case CCommandBuffer::PRIMTYPE_QUADS:
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferID);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId);
glDrawElements(GL_TRIANGLES, pCommand->m_PrimCount * 6, GL_UNSIGNED_INT, 0);
break;
default:
@@ -800,16 +786,16 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderTex3D(const CCommandBuffer::
void CCommandProcessorFragment_OpenGL3_3::DestroyBufferContainer(int Index, bool DeleteBOs)
{
SBufferContainer &BufferContainer = m_vBufferContainers[Index];
- if(BufferContainer.m_VertArrayID != 0)
- glDeleteVertexArrays(1, &BufferContainer.m_VertArrayID);
+ if(BufferContainer.m_VertArrayId != 0)
+ glDeleteVertexArrays(1, &BufferContainer.m_VertArrayId);
// all buffer objects can deleted automatically, so the program doesn't need to deal with them (e.g. causing crashes because of driver bugs)
if(DeleteBOs)
{
- int VertBufferID = BufferContainer.m_ContainerInfo.m_VertBufferBindingIndex;
- if(VertBufferID != -1)
+ int VertBufferId = BufferContainer.m_ContainerInfo.m_VertBufferBindingIndex;
+ if(VertBufferId != -1)
{
- glDeleteBuffers(1, &m_vBufferObjectIndices[VertBufferID]);
+ glDeleteBuffers(1, &m_vBufferObjectIndices[VertBufferId]);
}
}
@@ -835,10 +821,10 @@ void CCommandProcessorFragment_OpenGL3_3::AppendIndices(unsigned int NewIndicesC
Primq += 4;
}
- glBindBuffer(GL_COPY_READ_BUFFER, m_QuadDrawIndexBufferID);
- GLuint NewIndexBufferID;
- glGenBuffers(1, &NewIndexBufferID);
- glBindBuffer(BUFFER_INIT_INDEX_TARGET, NewIndexBufferID);
+ glBindBuffer(GL_COPY_READ_BUFFER, m_QuadDrawIndexBufferId);
+ GLuint NewIndexBufferId;
+ glGenBuffers(1, &NewIndexBufferId);
+ glBindBuffer(BUFFER_INIT_INDEX_TARGET, NewIndexBufferId);
GLsizeiptr size = sizeof(unsigned int);
glBufferData(BUFFER_INIT_INDEX_TARGET, (GLsizeiptr)NewIndicesCount * size, NULL, GL_STATIC_DRAW);
glCopyBufferSubData(GL_COPY_READ_BUFFER, BUFFER_INIT_INDEX_TARGET, 0, 0, (GLsizeiptr)m_CurrentIndicesInBuffer * size);
@@ -846,8 +832,8 @@ void CCommandProcessorFragment_OpenGL3_3::AppendIndices(unsigned int NewIndicesC
glBindBuffer(BUFFER_INIT_INDEX_TARGET, 0);
glBindBuffer(GL_COPY_READ_BUFFER, 0);
- glDeleteBuffers(1, &m_QuadDrawIndexBufferID);
- m_QuadDrawIndexBufferID = NewIndexBufferID;
+ glDeleteBuffers(1, &m_QuadDrawIndexBufferId);
+ m_QuadDrawIndexBufferId = NewIndexBufferId;
for(unsigned int &i : m_aLastIndexBufferBound)
i = 0;
@@ -873,13 +859,13 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_CreateBufferObject(const CCommandB
}
}
- GLuint VertBufferID = 0;
+ GLuint VertBufferId = 0;
- glGenBuffers(1, &VertBufferID);
- glBindBuffer(BUFFER_INIT_VERTEX_TARGET, VertBufferID);
+ glGenBuffers(1, &VertBufferId);
+ glBindBuffer(BUFFER_INIT_VERTEX_TARGET, VertBufferId);
glBufferData(BUFFER_INIT_VERTEX_TARGET, (GLsizeiptr)(pCommand->m_DataSize), pUploadData, GL_STATIC_DRAW);
- m_vBufferObjectIndices[Index] = VertBufferID;
+ m_vBufferObjectIndices[Index] = VertBufferId;
if(pCommand->m_DeletePointer)
free(pUploadData);
@@ -942,8 +928,8 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_CreateBufferContainer(const CComma
}
SBufferContainer &BufferContainer = m_vBufferContainers[Index];
- glGenVertexArrays(1, &BufferContainer.m_VertArrayID);
- glBindVertexArray(BufferContainer.m_VertArrayID);
+ glGenVertexArrays(1, &BufferContainer.m_VertArrayId);
+ glBindVertexArray(BufferContainer.m_VertArrayId);
BufferContainer.m_LastIndexBufferBound = 0;
@@ -971,7 +957,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_UpdateBufferContainer(const CComma
{
SBufferContainer &BufferContainer = m_vBufferContainers[pCommand->m_BufferContainerIndex];
- glBindVertexArray(BufferContainer.m_VertArrayID);
+ glBindVertexArray(BufferContainer.m_VertArrayId);
// disable all old attributes
for(size_t i = 0; i < BufferContainer.m_ContainerInfo.m_vAttributes.size(); ++i)
@@ -1017,7 +1003,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderBorderTile(const CCommandBuf
return;
SBufferContainer &BufferContainer = m_vBufferContainers[Index];
- if(BufferContainer.m_VertArrayID == 0)
+ if(BufferContainer.m_VertArrayId == 0)
return;
CGLSLTileProgram *pProgram = NULL;
@@ -1033,11 +1019,11 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderBorderTile(const CCommandBuf
pProgram->SetUniformVec2(pProgram->m_LocOffset, 1, (float *)&pCommand->m_Offset);
pProgram->SetUniformVec2(pProgram->m_LocScale, 1, (float *)&pCommand->m_Scale);
- glBindVertexArray(BufferContainer.m_VertArrayID);
- if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferID)
+ glBindVertexArray(BufferContainer.m_VertArrayId);
+ if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferId)
{
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferID);
- BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferID;
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId);
+ BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferId;
}
glDrawElements(GL_TRIANGLES, pCommand->m_DrawNum * 6, GL_UNSIGNED_INT, pCommand->m_pIndicesOffset);
}
@@ -1050,7 +1036,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderTileLayer(const CCommandBuff
return;
SBufferContainer &BufferContainer = m_vBufferContainers[Index];
- if(BufferContainer.m_VertArrayID == 0)
+ if(BufferContainer.m_VertArrayId == 0)
return;
if(pCommand->m_IndicesDrawNum == 0)
@@ -1071,11 +1057,11 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderTileLayer(const CCommandBuff
SetState(pCommand->m_State, pProgram, true);
pProgram->SetUniformVec4(pProgram->m_LocColor, 1, (float *)&pCommand->m_Color);
- glBindVertexArray(BufferContainer.m_VertArrayID);
- if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferID)
+ glBindVertexArray(BufferContainer.m_VertArrayId);
+ if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferId)
{
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferID);
- BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferID;
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId);
+ BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferId;
}
for(int i = 0; i < pCommand->m_IndicesDrawNum; ++i)
{
@@ -1091,7 +1077,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderQuadLayer(const CCommandBuff
return;
SBufferContainer &BufferContainer = m_vBufferContainers[Index];
- if(BufferContainer.m_VertArrayID == 0)
+ if(BufferContainer.m_VertArrayId == 0)
return;
if(pCommand->m_QuadNum == 0)
@@ -1110,11 +1096,11 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderQuadLayer(const CCommandBuff
UseProgram(pProgram);
SetState(pCommand->m_State, pProgram);
- glBindVertexArray(BufferContainer.m_VertArrayID);
- if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferID)
+ glBindVertexArray(BufferContainer.m_VertArrayId);
+ if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferId)
{
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferID);
- BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferID;
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId);
+ BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferId;
}
int QuadsLeft = pCommand->m_QuadNum;
@@ -1209,14 +1195,14 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderText(const CCommandBuffer::S
return;
SBufferContainer &BufferContainer = m_vBufferContainers[Index];
- if(BufferContainer.m_VertArrayID == 0)
+ if(BufferContainer.m_VertArrayId == 0)
return;
- glBindVertexArray(BufferContainer.m_VertArrayID);
- if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferID)
+ glBindVertexArray(BufferContainer.m_VertArrayId);
+ if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferId)
{
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferID);
- BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferID;
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId);
+ BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferId;
}
RenderText(pCommand->m_State, pCommand->m_DrawNum, pCommand->m_TextTextureIndex, pCommand->m_TextOutlineTextureIndex, pCommand->m_TextureSize, pCommand->m_TextColor, pCommand->m_TextOutlineColor);
@@ -1235,14 +1221,14 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderQuadContainer(const CCommand
return;
SBufferContainer &BufferContainer = m_vBufferContainers[Index];
- if(BufferContainer.m_VertArrayID == 0)
+ if(BufferContainer.m_VertArrayId == 0)
return;
- glBindVertexArray(BufferContainer.m_VertArrayID);
- if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferID)
+ glBindVertexArray(BufferContainer.m_VertArrayId);
+ if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferId)
{
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferID);
- BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferID;
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId);
+ BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferId;
}
CGLSLTWProgram *pProgram = m_pPrimitiveProgram;
@@ -1267,14 +1253,14 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderQuadContainerEx(const CComma
return;
SBufferContainer &BufferContainer = m_vBufferContainers[Index];
- if(BufferContainer.m_VertArrayID == 0)
+ if(BufferContainer.m_VertArrayId == 0)
return;
- glBindVertexArray(BufferContainer.m_VertArrayID);
- if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferID)
+ glBindVertexArray(BufferContainer.m_VertArrayId);
+ if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferId)
{
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferID);
- BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferID;
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId);
+ BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferId;
}
CGLSLPrimitiveExProgram *pProgram = m_pPrimitiveExProgramRotationless;
@@ -1328,14 +1314,14 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderQuadContainerAsSpriteMultipl
return;
SBufferContainer &BufferContainer = m_vBufferContainers[Index];
- if(BufferContainer.m_VertArrayID == 0)
+ if(BufferContainer.m_VertArrayId == 0)
return;
- glBindVertexArray(BufferContainer.m_VertArrayID);
- if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferID)
+ glBindVertexArray(BufferContainer.m_VertArrayId);
+ if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferId)
{
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferID);
- BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferID;
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId);
+ BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferId;
}
UseProgram(m_pSpriteProgramMultiple);
diff --git a/src/engine/client/backend/opengl/backend_opengl3.h b/src/engine/client/backend/opengl/backend_opengl3.h
index 5b3b883605..7b68d813d0 100644
--- a/src/engine/client/backend/opengl/backend_opengl3.h
+++ b/src/engine/client/backend/opengl/backend_opengl3.h
@@ -37,18 +37,18 @@ class CCommandProcessorFragment_OpenGL3_3 : public CCommandProcessorFragment_Ope
CGLSLPrimitiveExProgram *m_pPrimitiveExProgramTexturedRotationless;
CGLSLSpriteMultipleProgram *m_pSpriteProgramMultiple;
- TWGLuint m_LastProgramID;
+ TWGLuint m_LastProgramId;
- TWGLuint m_aPrimitiveDrawVertexID[MAX_STREAM_BUFFER_COUNT];
- TWGLuint m_PrimitiveDrawVertexIDTex3D;
- TWGLuint m_aPrimitiveDrawBufferID[MAX_STREAM_BUFFER_COUNT];
- TWGLuint m_PrimitiveDrawBufferIDTex3D;
+ TWGLuint m_aPrimitiveDrawVertexId[MAX_STREAM_BUFFER_COUNT];
+ TWGLuint m_PrimitiveDrawVertexIdTex3D;
+ TWGLuint m_aPrimitiveDrawBufferId[MAX_STREAM_BUFFER_COUNT];
+ TWGLuint m_PrimitiveDrawBufferIdTex3D;
TWGLuint m_aLastIndexBufferBound[MAX_STREAM_BUFFER_COUNT];
int m_LastStreamBuffer;
- TWGLuint m_QuadDrawIndexBufferID;
+ TWGLuint m_QuadDrawIndexBufferId;
unsigned int m_CurrentIndicesInBuffer;
void DestroyBufferContainer(int Index, bool DeleteBOs = true);
@@ -58,8 +58,8 @@ class CCommandProcessorFragment_OpenGL3_3 : public CCommandProcessorFragment_Ope
struct SBufferContainer
{
SBufferContainer() :
- m_VertArrayID(0), m_LastIndexBufferBound(0) {}
- TWGLuint m_VertArrayID;
+ m_VertArrayId(0), m_LastIndexBufferBound(0) {}
+ TWGLuint m_VertArrayId;
TWGLuint m_LastIndexBufferBound;
SBufferContainerInfo m_ContainerInfo;
};
@@ -71,19 +71,17 @@ class CCommandProcessorFragment_OpenGL3_3 : public CCommandProcessorFragment_Ope
void InitPrimExProgram(CGLSLPrimitiveExProgram *pProgram, class CGLSLCompiler *pCompiler, class IStorage *pStorage, bool Textured, bool Rotationless);
- static int TexFormatToNewOpenGLFormat(int TexFormat);
bool IsNewApi() override { return true; }
void UseProgram(CGLSLTWProgram *pProgram);
void UploadStreamBufferData(unsigned int PrimitiveType, const void *pVertices, size_t VertSize, unsigned int PrimitiveCount, bool AsTex3D = false);
void RenderText(const CCommandBuffer::SState &State, int DrawNum, int TextTextureIndex, int TextOutlineTextureIndex, int TextureSize, const ColorRGBA &TextColor, const ColorRGBA &TextOutlineColor);
- void TextureUpdate(int Slot, int X, int Y, int Width, int Height, int GLFormat, void *pTexData);
- void TextureCreate(int Slot, int Width, int Height, int GLFormat, int GLStoreFormat, int Flags, void *pTexData);
+ void TextureUpdate(int Slot, int X, int Y, int Width, int Height, int GLFormat, uint8_t *pTexData);
+ void TextureCreate(int Slot, int Width, int Height, int GLFormat, int GLStoreFormat, int Flags, uint8_t *pTexData);
bool Cmd_Init(const SCommand_Init *pCommand) override;
void Cmd_Shutdown(const SCommand_Shutdown *pCommand) override;
- void Cmd_Texture_Update(const CCommandBuffer::SCommand_Texture_Update *pCommand) override;
void Cmd_Texture_Destroy(const CCommandBuffer::SCommand_Texture_Destroy *pCommand) override;
void Cmd_Texture_Create(const CCommandBuffer::SCommand_Texture_Create *pCommand) override;
void Cmd_TextTexture_Update(const CCommandBuffer::SCommand_TextTexture_Update *pCommand) override;
diff --git a/src/engine/client/backend/opengl/opengl_sl.cpp b/src/engine/client/backend/opengl/opengl_sl.cpp
index 046e4168d7..a8b16c6af5 100644
--- a/src/engine/client/backend/opengl/opengl_sl.cpp
+++ b/src/engine/client/backend/opengl/opengl_sl.cpp
@@ -23,10 +23,10 @@ bool CGLSL::LoadShader(CGLSLCompiler *pCompiler, IStorage *pStorage, const char
{
if(m_IsLoaded)
return true;
- IOHANDLE f = pStorage->OpenFile(pFile, IOFLAG_READ | IOFLAG_SKIP_BOM, IStorage::TYPE_ALL);
+ CLineReader LineReader;
std::vector vLines;
- if(f)
+ if(LineReader.OpenFile(pStorage->OpenFile(pFile, IOFLAG_READ, IStorage::TYPE_ALL)))
{
EBackendType BackendType = pCompiler->m_IsOpenGLES ? BACKEND_TYPE_OPENGL_ES : BACKEND_TYPE_OPENGL;
bool IsNewOpenGL = (BackendType == BACKEND_TYPE_OPENGL ? (pCompiler->m_OpenGLVersionMajor >= 4 || (pCompiler->m_OpenGLVersionMajor == 3 && pCompiler->m_OpenGLVersionMinor == 3)) : pCompiler->m_OpenGLVersionMajor >= 3);
@@ -81,17 +81,13 @@ bool CGLSL::LoadShader(CGLSLCompiler *pCompiler, IStorage *pStorage, const char
vLines.emplace_back("#extension GL_EXT_texture_array : enable\r\n");
}
- CLineReader LineReader;
- LineReader.Init(f);
- char *pReadLine = NULL;
- while((pReadLine = LineReader.Get()))
+ while(const char *pReadLine = LineReader.Get())
{
std::string Line;
pCompiler->ParseLine(Line, pReadLine, Type == GL_FRAGMENT_SHADER ? GLSL_SHADER_COMPILER_TYPE_FRAGMENT : GLSL_SHADER_COMPILER_TYPE_VERTEX);
Line.append("\r\n");
vLines.push_back(Line);
}
- io_close(f);
const char **ShaderCode = new const char *[vLines.size()];
@@ -126,7 +122,7 @@ bool CGLSL::LoadShader(CGLSLCompiler *pCompiler, IStorage *pStorage, const char
m_Type = Type;
m_IsLoaded = true;
- m_ShaderID = shader;
+ m_ShaderId = shader;
return true;
}
@@ -139,7 +135,7 @@ void CGLSL::DeleteShader()
if(!IsLoaded())
return;
m_IsLoaded = false;
- glDeleteShader(m_ShaderID);
+ glDeleteShader(m_ShaderId);
}
bool CGLSL::IsLoaded() const
@@ -147,9 +143,9 @@ bool CGLSL::IsLoaded() const
return m_IsLoaded;
}
-TWGLuint CGLSL::GetShaderID() const
+TWGLuint CGLSL::GetShaderId() const
{
- return m_ShaderID;
+ return m_ShaderId;
}
CGLSL::CGLSL()
diff --git a/src/engine/client/backend/opengl/opengl_sl.h b/src/engine/client/backend/opengl/opengl_sl.h
index 3c2a640023..79024af8ee 100644
--- a/src/engine/client/backend/opengl/opengl_sl.h
+++ b/src/engine/client/backend/opengl/opengl_sl.h
@@ -21,13 +21,13 @@ class CGLSL
void DeleteShader();
bool IsLoaded() const;
- TWGLuint GetShaderID() const;
+ TWGLuint GetShaderId() const;
CGLSL();
virtual ~CGLSL();
private:
- TWGLuint m_ShaderID;
+ TWGLuint m_ShaderId;
int m_Type;
bool m_IsLoaded;
};
diff --git a/src/engine/client/backend/opengl/opengl_sl_program.cpp b/src/engine/client/backend/opengl/opengl_sl_program.cpp
index 2ba94325b1..0ad2e2ed37 100644
--- a/src/engine/client/backend/opengl/opengl_sl_program.cpp
+++ b/src/engine/client/backend/opengl/opengl_sl_program.cpp
@@ -14,7 +14,7 @@
void CGLSLProgram::CreateProgram()
{
- m_ProgramID = glCreateProgram();
+ m_ProgramId = glCreateProgram();
}
void CGLSLProgram::DeleteProgram()
@@ -22,14 +22,14 @@ void CGLSLProgram::DeleteProgram()
if(!m_IsLinked)
return;
m_IsLinked = false;
- glDeleteProgram(m_ProgramID);
+ glDeleteProgram(m_ProgramId);
}
bool CGLSLProgram::AddShader(CGLSL *pShader) const
{
if(pShader->IsLoaded())
{
- glAttachShader(m_ProgramID, pShader->GetShaderID());
+ glAttachShader(m_ProgramId, pShader->GetShaderId());
return true;
}
return false;
@@ -39,27 +39,27 @@ void CGLSLProgram::DetachShader(CGLSL *pShader) const
{
if(pShader->IsLoaded())
{
- DetachShaderByID(pShader->GetShaderID());
+ DetachShaderById(pShader->GetShaderId());
}
}
-void CGLSLProgram::DetachShaderByID(TWGLuint ShaderID) const
+void CGLSLProgram::DetachShaderById(TWGLuint ShaderId) const
{
- glDetachShader(m_ProgramID, ShaderID);
+ glDetachShader(m_ProgramId, ShaderId);
}
void CGLSLProgram::LinkProgram()
{
- glLinkProgram(m_ProgramID);
+ glLinkProgram(m_ProgramId);
int LinkStatus;
- glGetProgramiv(m_ProgramID, GL_LINK_STATUS, &LinkStatus);
+ glGetProgramiv(m_ProgramId, GL_LINK_STATUS, &LinkStatus);
m_IsLinked = LinkStatus == GL_TRUE;
if(!m_IsLinked)
{
char aInfoLog[1024];
char aFinalMessage[1536];
- int iLogLength;
- glGetProgramInfoLog(m_ProgramID, 1024, &iLogLength, aInfoLog);
+ int LogLength;
+ glGetProgramInfoLog(m_ProgramId, 1024, &LogLength, aInfoLog);
str_format(aFinalMessage, sizeof(aFinalMessage), "Error! Shader program wasn't linked! The linker returned:\n\n%s", aInfoLog);
dbg_msg("glslprogram", "%s", aFinalMessage);
}
@@ -74,13 +74,13 @@ void CGLSLProgram::DetachAllShaders() const
GLsizei ReturnedCount = 0;
while(true)
{
- glGetAttachedShaders(m_ProgramID, 100, &ReturnedCount, aShaders);
+ glGetAttachedShaders(m_ProgramId, 100, &ReturnedCount, aShaders);
if(ReturnedCount > 0)
{
for(GLsizei i = 0; i < ReturnedCount; ++i)
{
- DetachShaderByID(aShaders[i]);
+ DetachShaderById(aShaders[i]);
}
}
@@ -121,18 +121,18 @@ void CGLSLProgram::SetUniform(int Loc, const bool Value)
int CGLSLProgram::GetUniformLoc(const char *pName) const
{
- return glGetUniformLocation(m_ProgramID, pName);
+ return glGetUniformLocation(m_ProgramId, pName);
}
void CGLSLProgram::UseProgram() const
{
if(m_IsLinked)
- glUseProgram(m_ProgramID);
+ glUseProgram(m_ProgramId);
}
-TWGLuint CGLSLProgram::GetProgramID() const
+TWGLuint CGLSLProgram::GetProgramId() const
{
- return m_ProgramID;
+ return m_ProgramId;
}
CGLSLProgram::CGLSLProgram()
diff --git a/src/engine/client/backend/opengl/opengl_sl_program.h b/src/engine/client/backend/opengl/opengl_sl_program.h
index f278731c86..404c7a6f08 100644
--- a/src/engine/client/backend/opengl/opengl_sl_program.h
+++ b/src/engine/client/backend/opengl/opengl_sl_program.h
@@ -26,10 +26,10 @@ class CGLSLProgram
void LinkProgram();
void UseProgram() const;
- TWGLuint GetProgramID() const;
+ TWGLuint GetProgramId() const;
void DetachShader(CGLSL *pShader) const;
- void DetachShaderByID(TWGLuint ShaderID) const;
+ void DetachShaderById(TWGLuint ShaderId) const;
void DetachAllShaders() const;
//Support various types
@@ -47,7 +47,7 @@ class CGLSLProgram
virtual ~CGLSLProgram();
protected:
- TWGLuint m_ProgramID;
+ TWGLuint m_ProgramId;
bool m_IsLinked;
};
diff --git a/src/engine/client/backend/vulkan/backend_vulkan.cpp b/src/engine/client/backend/vulkan/backend_vulkan.cpp
index 84a8b48d86..f49025d86e 100644
--- a/src/engine/client/backend/vulkan/backend_vulkan.cpp
+++ b/src/engine/client/backend/vulkan/backend_vulkan.cpp
@@ -15,26 +15,23 @@
#include
#include
-#include
-#include