diff --git a/Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt b/Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt
index 77721250c6c..a74cd8baf2c 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt
+++ b/Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt
@@ -162,6 +162,8 @@ if(WIN32)
rcfile.h
registry.cpp
registry.h
+ Usp10Loader.cpp
+ Usp10Loader.h
verchk.cpp
verchk.h
WWCOMUtil.cpp
diff --git a/Core/Libraries/Source/WWVegas/WWLib/Usp10Loader.cpp b/Core/Libraries/Source/WWVegas/WWLib/Usp10Loader.cpp
new file mode 100644
index 00000000000..6f09f861dae
--- /dev/null
+++ b/Core/Libraries/Source/WWVegas/WWLib/Usp10Loader.cpp
@@ -0,0 +1,163 @@
+/*
+** Command & Conquer Generals Zero Hour(tm)
+** Copyright 2026 TheSuperHackers
+**
+** This program is free software: you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation, either version 3 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program. If not, see .
+*/
+
+#include "Usp10Loader.h"
+
+
+CriticalSectionClass Usp10Loader::CriticalSection;
+HMODULE Usp10Loader::Module = HMODULE(nullptr);
+bool Usp10Loader::LoadAttempted = false;
+Usp10Loader::ScriptIsComplex_t Usp10Loader::ScriptIsComplexPtr = nullptr;
+Usp10Loader::ScriptItemize_t Usp10Loader::ScriptItemizePtr = nullptr;
+Usp10Loader::ScriptBreak_t Usp10Loader::ScriptBreakPtr = nullptr;
+Usp10Loader::ScriptLayout_t Usp10Loader::ScriptLayoutPtr = nullptr;
+Usp10Loader::ScriptStringAnalyse_t Usp10Loader::ScriptStringAnalysePtr = nullptr;
+Usp10Loader::ScriptStringFree_t Usp10Loader::ScriptStringFreePtr = nullptr;
+Usp10Loader::ScriptString_pSize_t Usp10Loader::ScriptString_pSizePtr = nullptr;
+Usp10Loader::ScriptStringOut_t Usp10Loader::ScriptStringOutPtr = nullptr;
+
+
+bool Usp10Loader::load()
+{
+ if (LoadAttempted) {
+ return Module != HMODULE(nullptr);
+ }
+ LoadAttempted = true;
+
+ char dll_path[MAX_PATH];
+ const char dll_name[] = "\\usp10.dll";
+ const UINT path_length = ::GetSystemDirectoryA(dll_path, ARRAY_SIZE(dll_path));
+ if (path_length == 0 || path_length + ARRAY_SIZE(dll_name) > ARRAY_SIZE(dll_path)) {
+ return false;
+ }
+ strcpy(dll_path + path_length, dll_name);
+
+ Module = ::LoadLibraryA(dll_path);
+ if (Module == HMODULE(nullptr)) {
+ return false;
+ }
+
+ ScriptIsComplexPtr = reinterpret_cast(::GetProcAddress(Module, "ScriptIsComplex"));
+ ScriptItemizePtr = reinterpret_cast(::GetProcAddress(Module, "ScriptItemize"));
+ ScriptBreakPtr = reinterpret_cast(::GetProcAddress(Module, "ScriptBreak"));
+ ScriptLayoutPtr = reinterpret_cast(::GetProcAddress(Module, "ScriptLayout"));
+ ScriptStringAnalysePtr = reinterpret_cast(::GetProcAddress(Module, "ScriptStringAnalyse"));
+ ScriptStringFreePtr = reinterpret_cast(::GetProcAddress(Module, "ScriptStringFree"));
+ ScriptString_pSizePtr = reinterpret_cast(::GetProcAddress(Module, "ScriptString_pSize"));
+ ScriptStringOutPtr = reinterpret_cast(::GetProcAddress(Module, "ScriptStringOut"));
+
+ if (ScriptIsComplexPtr == nullptr || ScriptItemizePtr == nullptr || ScriptBreakPtr == nullptr ||
+ ScriptLayoutPtr == nullptr || ScriptStringAnalysePtr == nullptr || ScriptStringFreePtr == nullptr ||
+ ScriptString_pSizePtr == nullptr || ScriptStringOutPtr == nullptr)
+ {
+ freeResources();
+ return false;
+ }
+
+ return true;
+}
+
+
+void Usp10Loader::unload()
+{
+ CriticalSectionClass::LockClass lock(CriticalSection);
+
+ freeResources();
+ LoadAttempted = false;
+}
+
+
+void Usp10Loader::freeResources()
+{
+ if (Module != HMODULE(nullptr)) {
+ ::FreeLibrary(Module);
+ Module = HMODULE(nullptr);
+ }
+
+ ScriptIsComplexPtr = nullptr;
+ ScriptItemizePtr = nullptr;
+ ScriptBreakPtr = nullptr;
+ ScriptLayoutPtr = nullptr;
+ ScriptStringAnalysePtr = nullptr;
+ ScriptStringFreePtr = nullptr;
+ ScriptString_pSizePtr = nullptr;
+ ScriptStringOutPtr = nullptr;
+}
+
+
+HRESULT Usp10Loader::ScriptIsComplex(const WCHAR *text, int text_length, DWORD flags)
+{
+ CriticalSectionClass::LockClass lock(CriticalSection);
+ return load() ? ScriptIsComplexPtr(text, text_length, flags) : E_FAIL;
+}
+
+
+HRESULT Usp10Loader::ScriptItemize(const WCHAR *text, int text_length, int item_capacity,
+ const ScriptControl *control, const ScriptState *state, ScriptItem *items, int *item_count)
+{
+ CriticalSectionClass::LockClass lock(CriticalSection);
+ return load() ? ScriptItemizePtr(text, text_length, item_capacity, control, state, items, item_count) : E_FAIL;
+}
+
+
+HRESULT Usp10Loader::ScriptBreak(const WCHAR *text, int text_length, const ScriptAnalysis *analysis,
+ ScriptLogAttr *attributes)
+{
+ CriticalSectionClass::LockClass lock(CriticalSection);
+ return load() ? ScriptBreakPtr(text, text_length, analysis, attributes) : E_FAIL;
+}
+
+
+HRESULT Usp10Loader::ScriptLayout(int run_count, const BYTE *levels, int *visual_to_logical,
+ int *logical_to_visual)
+{
+ CriticalSectionClass::LockClass lock(CriticalSection);
+ return load() ? ScriptLayoutPtr(run_count, levels, visual_to_logical, logical_to_visual) : E_FAIL;
+}
+
+
+HRESULT Usp10Loader::ScriptStringAnalyse(HDC dc, const void *text, int text_length, int glyph_count,
+ int charset, DWORD flags, int required_width, ScriptControl *control, ScriptState *state,
+ const int *spacing, ScriptTabDefinition *tabs, const BYTE *character_classes, ScriptStringAnalysis *analysis)
+{
+ CriticalSectionClass::LockClass lock(CriticalSection);
+ return load() ? ScriptStringAnalysePtr(dc, text, text_length, glyph_count, charset, flags, required_width,
+ control, state, spacing, tabs, character_classes, analysis) : E_FAIL;
+}
+
+
+HRESULT Usp10Loader::ScriptStringFree(ScriptStringAnalysis *analysis)
+{
+ CriticalSectionClass::LockClass lock(CriticalSection);
+ return load() ? ScriptStringFreePtr(analysis) : E_FAIL;
+}
+
+
+const SIZE *Usp10Loader::ScriptString_pSize(ScriptStringAnalysis analysis)
+{
+ CriticalSectionClass::LockClass lock(CriticalSection);
+ return load() ? ScriptString_pSizePtr(analysis) : nullptr;
+}
+
+
+HRESULT Usp10Loader::ScriptStringOut(ScriptStringAnalysis analysis, int x, int y, UINT options,
+ const RECT *rect, int minimum_selection, int maximum_selection, BOOL disabled)
+{
+ CriticalSectionClass::LockClass lock(CriticalSection);
+ return load() ? ScriptStringOutPtr(analysis, x, y, options, rect, minimum_selection, maximum_selection, disabled) : E_FAIL;
+}
diff --git a/Core/Libraries/Source/WWVegas/WWLib/Usp10Loader.h b/Core/Libraries/Source/WWVegas/WWLib/Usp10Loader.h
new file mode 100644
index 00000000000..3b35b03b82b
--- /dev/null
+++ b/Core/Libraries/Source/WWVegas/WWLib/Usp10Loader.h
@@ -0,0 +1,121 @@
+/*
+** Command & Conquer Generals Zero Hour(tm)
+** Copyright 2026 TheSuperHackers
+**
+** This program is free software: you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation, either version 3 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program. If not, see .
+*/
+
+#pragma once
+
+#include "mutex.h"
+#include "win.h"
+
+
+// This static class loads usp10.dll on first use and unloads it during engine shutdown.
+
+class Usp10Loader
+{
+public:
+
+ typedef void *ScriptStringAnalysis;
+ struct ScriptControl;
+ struct ScriptTabDefinition;
+
+ struct ScriptState
+ {
+ WORD bidi_level : 5;
+ WORD reserved : 11;
+ };
+
+ struct ScriptAnalysis
+ {
+ WORD script : 10;
+ WORD right_to_left : 1;
+ WORD layout_right_to_left : 1;
+ WORD link_before : 1;
+ WORD link_after : 1;
+ WORD logical_order : 1;
+ WORD no_glyph_index : 1;
+ ScriptState state;
+ };
+
+ struct ScriptItem
+ {
+ int character_position;
+ ScriptAnalysis analysis;
+ };
+
+ struct ScriptLogAttr
+ {
+ BYTE soft_break : 1;
+ BYTE white_space : 1;
+ BYTE char_stop : 1;
+ BYTE word_stop : 1;
+ BYTE invalid : 1;
+ BYTE reserved : 3;
+ };
+
+ enum
+ {
+ SIC_COMPLEX = 0x00000001,
+ SSA_FALLBACK = 0x00000020,
+ SSA_GLYPHS = 0x00000080,
+ SSA_RTL = 0x00000100,
+ };
+
+ static HRESULT ScriptIsComplex(const WCHAR *text, int text_length, DWORD flags);
+ static HRESULT ScriptItemize(const WCHAR *text, int text_length, int item_capacity,
+ const ScriptControl *control, const ScriptState *state, ScriptItem *items, int *item_count);
+ static HRESULT ScriptBreak(const WCHAR *text, int text_length, const ScriptAnalysis *analysis,
+ ScriptLogAttr *attributes);
+ static HRESULT ScriptLayout(int run_count, const BYTE *levels, int *visual_to_logical,
+ int *logical_to_visual);
+ static HRESULT ScriptStringAnalyse(HDC dc, const void *text, int text_length, int glyph_count,
+ int charset, DWORD flags, int required_width, ScriptControl *control, ScriptState *state,
+ const int *spacing, ScriptTabDefinition *tabs, const BYTE *character_classes,
+ ScriptStringAnalysis *analysis);
+ static HRESULT ScriptStringFree(ScriptStringAnalysis *analysis);
+ static const SIZE *ScriptString_pSize(ScriptStringAnalysis analysis);
+ static HRESULT ScriptStringOut(ScriptStringAnalysis analysis, int x, int y, UINT options,
+ const RECT *rect, int minimum_selection, int maximum_selection, BOOL disabled);
+ static void unload();
+
+private:
+
+ static bool load();
+ static void freeResources();
+
+ typedef HRESULT (WINAPI *ScriptIsComplex_t)(const WCHAR *, int, DWORD);
+ typedef HRESULT (WINAPI *ScriptItemize_t)(const WCHAR *, int, int, const ScriptControl *,
+ const ScriptState *, ScriptItem *, int *);
+ typedef HRESULT (WINAPI *ScriptBreak_t)(const WCHAR *, int, const ScriptAnalysis *, ScriptLogAttr *);
+ typedef HRESULT (WINAPI *ScriptLayout_t)(int, const BYTE *, int *, int *);
+ typedef HRESULT (WINAPI *ScriptStringAnalyse_t)(HDC, const void *, int, int, int, DWORD, int,
+ ScriptControl *, ScriptState *, const int *, ScriptTabDefinition *, const BYTE *, ScriptStringAnalysis *);
+ typedef HRESULT (WINAPI *ScriptStringFree_t)(ScriptStringAnalysis *);
+ typedef const SIZE *(WINAPI *ScriptString_pSize_t)(ScriptStringAnalysis);
+ typedef HRESULT (WINAPI *ScriptStringOut_t)(ScriptStringAnalysis, int, int, UINT, const RECT *, int, int, BOOL);
+
+ static CriticalSectionClass CriticalSection;
+ static HMODULE Module;
+ static bool LoadAttempted;
+ static ScriptIsComplex_t ScriptIsComplexPtr;
+ static ScriptItemize_t ScriptItemizePtr;
+ static ScriptBreak_t ScriptBreakPtr;
+ static ScriptLayout_t ScriptLayoutPtr;
+ static ScriptStringAnalyse_t ScriptStringAnalysePtr;
+ static ScriptStringFree_t ScriptStringFreePtr;
+ static ScriptString_pSize_t ScriptString_pSizePtr;
+ static ScriptStringOut_t ScriptStringOutPtr;
+};