This commit is contained in:
VDm 2025-03-09 20:17:52 +00:00 committed by GitHub
commit 38a912a934
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
30 changed files with 918 additions and 92 deletions

View File

@ -21,9 +21,20 @@
#include <storm/Error.hpp> #include <storm/Error.hpp>
#include <storm/Log.hpp> #include <storm/Log.hpp>
#include <bc/os/Path.hpp> #include <bc/os/Path.hpp>
#include <bc/file/File.hpp>
CVar* Client::g_accountListVar; CVar* Client::g_accountListVar;
HEVENTCONTEXT Client::g_clientEventContext; HEVENTCONTEXT Client::g_clientEventContext;
char Client::g_currentLocaleName[5] = {};
static uint8_t s_expansionLevel = 0;
static bool g_hasIsoLocale[12] = {};
static char* s_localeArray[12] = {
"deDE", "enGB", "enUS", "esES", "frFR", "koKR",
"zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU"
};
void AsyncFileInitialize() { void AsyncFileInitialize() {
// TODO // TODO
@ -139,6 +150,32 @@ int32_t InitializeEngineCallback(const void* a1, void* a2) {
return 1; return 1;
} }
uint8_t GetExpansionLevel() {
return s_expansionLevel;
}
const char* UpdateInstallLocation() {
// TODO
return nullptr;
}
bool UpdateInstallLocationForName(int32_t a1, size_t size, const char* filename, char* buffer, const char* locale) {
if (a1 == 2) {
auto location = UpdateInstallLocation();
if (!location) {
return false;
}
SStrPrintf(buffer, size, "%s%s%s", location, "Data\\", filename);
} else {
SStrPrintf(buffer, size, "%s%s", "Data\\", filename);
}
for (auto i = SStrStr(buffer, "****"); i; i = SStrStr(buffer, "****")) {
size_t offset = static_cast<size_t>(i - buffer);
memcpy(&buffer[offset], locale, 4);
}
return true;
}
void SetPaths() { void SetPaths() {
// SFile::DisableSFileCheckDisk(); // SFile::DisableSFileCheckDisk();
// SFile::EnableDirectAccess(0); // SFile::EnableDirectAccess(0);
@ -158,12 +195,109 @@ void SetPaths() {
OsSetCurrentDirectory(datadir); OsSetCurrentDirectory(datadir);
} }
bool IsCommonMpqExists() {
char path1[1024];
SStrPrintf(path1, sizeof(path1), "%s%s", "Data\\", "common.MPQ");
for (auto i = SStrStr(path1, "****"); i; i = SStrStr(path1, "****")) {
size_t offset = static_cast<size_t>(i - path1);
memcpy(&path1[offset], "----", 4);
}
char path2[1024];
SStrPrintf(path2, sizeof(path2), "%s%s", "..\\Data\\", "common.MPQ");
for (auto i = SStrStr(path2, "****"); i; i = SStrStr(path2, "****")) {
size_t offset = static_cast<size_t>(i - path2);
memcpy(&path2[offset], "----", 4);
}
auto location = UpdateInstallLocation();
if (location) {
char path3[1024];
SStrPrintf(path3, sizeof(path3), "%s%s%s", location, "Data\\", "common.MPQ");
for (auto i = SStrStr(path3, "****"); i; i = SStrStr(path3, "****")) {
size_t offset = static_cast<size_t>(i - path3);
memcpy(&path3[offset], "----", 4);
}
if (!Blizzard::File::Exists(path1) && !Blizzard::File::Exists(path2)) {
return Blizzard::File::Exists(path3);
}
} else if (!Blizzard::File::Exists(path1)) {
return Blizzard::File::Exists(path2);
}
return true;
}
size_t GetLocaleIndex(const char* locale) {
for (size_t i = 0; i < 12; ++i) {
if (SStrCmpI(locale, s_localeArray[i], 4) == 0) {
return i;
}
}
return 2; // s_localeArray[2] == "enUS"
}
void CheckAvailableLocales(char* locale) {
if (!IsCommonMpqExists()) {
return;
}
for (size_t localeIndex = 0; localeIndex < 12; ++localeIndex) {
g_hasIsoLocale[localeIndex] = false;
const char* filename = "****\\locale-****.MPQ";
char path[1024];
SStrPrintf(path, sizeof(path), "%s%s", "Data\\", filename);
for (auto i = SStrStr(path, "****"); i; i = SStrStr(path, "****")) {
size_t offset = static_cast<size_t>(i - path);
memcpy(&path[offset], s_localeArray[localeIndex], 4);
}
if (Blizzard::File::Exists(path)) {
g_hasIsoLocale[localeIndex] = true;
continue;
}
SStrPrintf(path, sizeof(path), "%s%s", "..\\Data\\", filename);
for (auto i = SStrStr(path, "****"); i; i = SStrStr(path, "****")) {
size_t offset = static_cast<size_t>(i - path);
memcpy(&path[offset], s_localeArray[localeIndex], 4);
}
if (Blizzard::File::Exists(path)) {
g_hasIsoLocale[localeIndex] = true;
continue;
}
if (UpdateInstallLocationForName(2, sizeof(path), filename, path, s_localeArray[localeIndex]) &&
Blizzard::File::Exists(path)) {
g_hasIsoLocale[localeIndex] = true;
}
}
size_t localeIndex = GetLocaleIndex(locale);
for (size_t i = 0; i < 12; ++i) {
if (g_hasIsoLocale[localeIndex]) {
break;
}
localeIndex = (localeIndex + 1) % 12;
}
SStrCopy(locale, s_localeArray[localeIndex], STORM_MAX_STR);
}
bool LocaleChangedCallback(CVar*, const char*, const char* value, void*) {
SStrCopy(Client::g_currentLocaleName, value, sizeof(Client::g_currentLocaleName));
return true;
}
int32_t InitializeGlobal() { int32_t InitializeGlobal() {
// TODO
ProcessCommandLine(); ProcessCommandLine();
SetPaths();
// sub_403600("WoW.mfil"); // TODO:
// WowConfigureFileSystem::ReadBuildKeyFromFile("WoW.mfil");
// if (dword_B2FA10 != 2) { // if (dword_B2FA10 != 2) {
// sub_403560(); // sub_403560();
@ -175,58 +309,83 @@ int32_t InitializeGlobal() {
// LOBYTE(v24) = OsDirectoryExists((int)"WTF/Account") == 0; // LOBYTE(v24) = OsDirectoryExists((int)"WTF/Account") == 0;
// } // }
// ClientServices::LoadCDKey(); ClientServices::LoadCDKey();
SetPaths();
OpenArchives();
ConsoleInitializeClientCommand(); ConsoleInitializeClientCommand();
ConsoleInitializeClientCVar("Config.wtf"); ConsoleInitializeClientCVar("Config.wtf");
// TODO: CVar::ArchiveCodeRegisteredOnly();
// TODO
// replace enUS with detected locale
ClientServices::InitLoginServerCVars(1, "enUS");
// sub_7663F0();
// v18 = 0; // v18 = 0;
// v19 = 0; // v19 = 0;
// ptr = 0; // ptr = 0;
// v21 = 0; // v21 = 0;
// sub_406740(&v18, &CVar::Load); // ::ForEveryRunOnceWTF::Execute(&v18, &CVar::Load);
// if (ptr) { // if (ptr) {
// SMemFree(ptr, a_pad, -2, 0); // SMemFree(ptr, a_pad, -2, 0);
// } // }
// CVar::Register("dbCompress", "Database compression", 0, "-1", 0, 5, 0, 0, 0); CVar::Register(
"dbCompress",
"Database compression",
0,
"-1",
nullptr,
CATEGORY::DEFAULT,
false,
nullptr,
false
);
// v2 = CVar::Register("locale", "Set the game locale", 0, "****", &LocaleChangedCallback, 5, 0, 0, 0); CVar* locale = CVar::Register(
"locale",
"Set the game locale",
0,
"****",
&LocaleChangedCallback,
CATEGORY::DEFAULT,
false,
nullptr,
false
);
// if (!SStrCmp(v2->m_stringValue.m_str, "****", 0x7FFFFFFFu)) { if (!SStrCmp(locale->GetString(), "****", STORM_MAX_STR)) {
// CVar::Set(v2, "enUS", 1, 0, 0, 1); locale->Set("enUS", true, false, false, true);
// } }
// CVar::Register("useEnglishAudio", "override the locale and use English audio", 0, "0", 0, 5, 0, 0, 0); CVar::Register(
"useEnglishAudio",
"override the locale and use English audio",
0,
"0",
nullptr,
CATEGORY::DEFAULT,
false,
nullptr,
false
);
// TODO: SFile::IsTrial() check
// if (sub_422140()) { // if (sub_422140()) {
// sub_4036B0(v24, 0, a2, (int)v2, (char)v24); // sub_4036B0(v24, 0, a2, (int)v2, (char)v24);
// } // }
// SStrCopy(&a1a, v2->m_stringValue.m_str, 5); char existingLocale[5] = {};
SStrCopy(existingLocale, locale->GetString(), sizeof(existingLocale));
CheckAvailableLocales(existingLocale);
locale->Set(existingLocale, true, false, false, true);
// sub_402D50(&a1a); char path[STORM_MAX_PATH];
SStrPrintf(path, sizeof(path), "%s%s", "Data\\", locale->GetString());
SFile::SetDataPathAlternate(path);
SFile::RebuildHash();
// CVar::Set(v2, &a1a, 1, 0, 0, 1);
// SStrPrintf(dest, 260, "%s%s", *(_DWORD *)off_AB6158, v2->m_stringValue.m_str); OpenArchives();
// sub_421B50(dest); // TODO: This method should be placed inside OpenArchives
ClientServices::InitLoginServerCVars(1, locale->GetString());
// sub_423D70();
// sub_405DD0(); // sub_405DD0();
@ -343,19 +502,36 @@ int32_t InitializeGlobal() {
void CommonMain() { void CommonMain() {
StormInitialize(); StormInitialize();
// TODO // TODO:
// - error log setup // SErrCatchUnhandledExceptions();
// - misc other setup // OsSystemInitialize("Blizzard Entertainment World of Warcraft", 0);
// int option = 1;
// StormSetOption(10, &option, sizeof(option));
// StormSetOption(11, &option, sizeof(option));
// OsSystemEnableCpuLog();
// SetPaths() moved into InitializeGlobal()
// int sendErrorLogs = 1;
// if (!SRegLoadValue("World of Warcraft\\Client", "SendErrorLogs", 0, &sendErrorLogs)) {
// sendErrorLogs = 1;
// SRegSaveValue("World of Warcraft\\Client", "SendErrorLogs", 0, sendErrorLogs);
// }
// SErrSetLogTitleString("World of WarCraft (build 12340)");
// SErrSetLogTitleCallback(WowLogHeader);
// if (sendErrorLogs) {
// SErrRegisterHandler(SendErrorLog);
// }
if (InitializeGlobal()) { if (InitializeGlobal()) {
EventDoMessageLoop(); EventDoMessageLoop();
// TODO: DestroyGlobal();
// TODO
// sub_406B70();
} }
// TODO // TODO:
// - misc cleanup // StormDestroy();
// Misc Cleanup
} }
void BlizzardAssertCallback(const char* a1, const char* a2, const char* a3, uint32_t a4) { void BlizzardAssertCallback(const char* a1, const char* a2, const char* a3, uint32_t a4) {

View File

@ -9,10 +9,13 @@ class CVar;
namespace Client { namespace Client {
extern CVar* g_accountListVar; extern CVar* g_accountListVar;
extern HEVENTCONTEXT g_clientEventContext; extern HEVENTCONTEXT g_clientEventContext;
extern char g_currentLocaleName[5];
} }
void ClientPostClose(int32_t a1); void ClientPostClose(int32_t a1);
const char* UpdateInstallLocation();
void CommonMain(); void CommonMain();
void StormInitialize(); void StormInitialize();

View File

@ -264,6 +264,11 @@ const char* ClientServices::GetDefaultPatchListString() {
return "public-test.patch.battle.net:1119/patch"; return "public-test.patch.battle.net:1119/patch";
} }
bool ClientServices::LoadCDKey() {
// TODO
return true;
}
void ClientServices::InitLoginServerCVars(int32_t overwrite, const char* locale) { void ClientServices::InitLoginServerCVars(int32_t overwrite, const char* locale) {
if ((ClientServices::s_realmListBNVar == nullptr || ClientServices::s_realmListVar == nullptr) || overwrite != 0 ) { if ((ClientServices::s_realmListBNVar == nullptr || ClientServices::s_realmListVar == nullptr) || overwrite != 0 ) {
ClientServices::s_decorateAccountName = CVar::Register( ClientServices::s_decorateAccountName = CVar::Register(

View File

@ -45,6 +45,7 @@ class ClientServices : public LoginResponse {
static void InitLoginServerCVars(int32_t overwrite, const char* locale); static void InitLoginServerCVars(int32_t overwrite, const char* locale);
static const char* GetDefaultRealmlistString(); static const char* GetDefaultRealmlistString();
static const char* GetDefaultPatchListString(); static const char* GetDefaultPatchListString();
static bool LoadCDKey();
// Virtual member functions // Virtual member functions
virtual int32_t GetLoginServerType(); virtual int32_t GetLoginServerType();

65
src/client/Patch.cpp Normal file
View File

@ -0,0 +1,65 @@
#include "client/Patch.hpp"
#include <storm/String.hpp>
#include "client/Client.hpp"
PatchFiles::PatchFiles() {
this->path = nullptr;
}
void PatchFiles::SearchArchives(const char* locale, int32_t a3) {
char fullPath[256] = {};
char pattern[256] = {};
char path[256] = {};
const size_t listSize = 12;
ListEntry list[listSize] = {
{ 0, 0, false, "Data\\", "patch-?.MPQ" },
{ 0, 0, false, "Data\\%s\\", "patch-%s-?.MPQ" },
{ 1, 0, false, "Data\\", "patch.MPQ" },
{ 1, 0, false, "Data\\%s\\", "patch-%s.MPQ" },
{ 1, 1, false, "Data\\", "patch-4.MPQ" },
{ 1, 1, false, "Data\\%s\\", "patch-%s-4.MPQ" },
{ 1, 1, false, "Data\\", "patch-3.MPQ" },
{ 1, 1, false, "Data\\%s\\", "patch-%s-3.MPQ" },
{ 1, 1, false, "..\\Data\\", "patch-2.MPQ" },
{ 1, 1, false, "..\\Data\\%s\\", "patch-%s-2.MPQ" },
{ 1, 1, false, "..\\Data\\", "patch.MPQ" },
{ 1, 1, false, "..\\Data\\%s\\", "patch-%s.MPQ" },
};
const char* installRoot = UpdateInstallLocation();
// Warning: assigning pointer to a temporary variable
// Need this for OsFileList's callback
this->path = path;
for (size_t i = 0; i <= 2; ++i) {
for (size_t j = 0; j < listSize; ++j) {
auto entry = &list[j];
if (entry->num1 != i || entry->num2 != (a3 != 0)) {
continue;
}
SStrPrintf(path, sizeof(path), entry->dataDir, locale);
SStrPrintf(pattern, sizeof(pattern), entry->pattern, locale);
if (entry->absolute && installRoot && installRoot[0]) {
SStrPrintf(fullPath, sizeof(fullPath), "%s%s", installRoot, path);
SStrCopy(path, fullPath, sizeof(path));
}
// TODO: OsFileList(this->path, pattern, PatchFiles::EnumPatchArchives, this, 0);
}
if (i == 0) {
std::qsort(this->files.Ptr(), this->files.Count(), sizeof(char*), &PatchFiles::qsortpatchfiles);
}
}
}
int PatchFiles::qsortpatchfiles(const void* a1, const void* a2) {
return -SStrCmpI(*((const char**) a1), *((const char**) a2), STORM_MAX_STR);
}

33
src/client/Patch.hpp Normal file
View File

@ -0,0 +1,33 @@
#ifndef CLIENT_PATCH_HPP
#define CLIENT_PATCH_HPP
#include <storm/Array.hpp>
class PatchFiles {
public:
PatchFiles();
void SearchArchives(const char* locale, int32_t a3);
public:
char* path;
TSGrowableArray<char*> files;
private:
static int qsortpatchfiles(const void* a1, const void* a2);
private:
struct ListEntry {
uint32_t num1;
uint32_t num2;
bool absolute;
const char* dataDir;
const char* pattern;
};
};
#endif

View File

@ -37,7 +37,7 @@ class CVar : public TSHashObject<CVar, HASHKEY_STRI> {
int32_t GetInt(); int32_t GetInt();
const char* GetString(void); const char* GetString(void);
void InternalSet(const char*, bool, bool, bool, bool); void InternalSet(const char*, bool, bool, bool, bool);
bool Set(const char*, bool, bool, bool, bool); bool Set(const char* value, bool setValue, bool setReset, bool setDefault, bool a6);
bool Reset(); bool Reset();
bool Default(); bool Default();
int32_t Update(); int32_t Update();

View File

@ -274,6 +274,7 @@ void ConsoleDeviceInitialize(const char* title) {
s_requestedFormat.hwTnL = true; s_requestedFormat.hwTnL = true;
// TODO // TODO
s_requestedFormat.hwCursor = true;
CGxFormat format; CGxFormat format;
memcpy(&format, &s_requestedFormat, sizeof(s_requestedFormat)); memcpy(&format, &s_requestedFormat, sizeof(s_requestedFormat));

View File

@ -4,6 +4,7 @@
#include "console/Command.hpp" #include "console/Command.hpp"
#include "console/Screen.hpp" #include "console/Screen.hpp"
#include "event/Event.hpp" #include "event/Event.hpp"
#include "storm/Unicode.hpp"
#include <cstdint> #include <cstdint>
static int32_t s_historyIndex = 0; static int32_t s_historyIndex = 0;
@ -11,7 +12,7 @@ static int32_t s_historyIndex = 0;
namespace { namespace {
int32_t OnChar(const EVENT_DATA_CHAR* data, void* param) { int32_t OnChar(const EVENT_DATA_CHAR* data, void* param) {
char character[2]; char character[2] = {};
if (ConsoleAccessGetEnabled() && EventIsKeyDown(ConsoleGetHotKey())) { if (ConsoleAccessGetEnabled() && EventIsKeyDown(ConsoleGetHotKey())) {
return 0; return 0;
@ -26,9 +27,6 @@ int32_t OnChar(const EVENT_DATA_CHAR* data, void* param) {
return 0; return 0;
} }
// SUniSPutUTF8(data->ch, character);
return 1; return 1;
} }

View File

@ -8,6 +8,142 @@
#include "event/sdl/Input.hpp" #include "event/sdl/Input.hpp"
#endif #endif
static const uint32_t s_latin5lookup[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11,
0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,
0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23,
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C,
0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E,
0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62,
0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B,
0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74,
0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D,
0x7E, 0x7F, 0x20AC, 0x20, 0x201A, 0x192, 0x201E, 0x2026, 0x2020,
0x2021, 0x2C6, 0x2030, 0x160, 0x2039, 0x152, 0x20, 0x20, 0x20,
0x20, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x2DC,
0x2122, 0x161, 0x203A, 0x153, 0x20, 0x20, 0x178, 0x0A0, 0x0A1,
0x0A2, 0x0A3, 0x0A4, 0x0A5, 0x0A6, 0x0A7, 0x0A8, 0x0A9, 0x0AA,
0x0AB, 0x0AC, 0x0AD, 0x0AE, 0x0AF, 0x0B0, 0x0B1, 0x0B2, 0x0B3,
0x0B4, 0x0B5, 0x0B6, 0x0B7, 0x0B8, 0x0B9, 0x0BA, 0x0BB, 0x0BC,
0x0BD, 0x0BE, 0x0BF, 0x0C0, 0x0C1, 0x0C2, 0x0C3, 0x0C4, 0x0C5,
0x0C6, 0x0C7, 0x0C8, 0x0C9, 0x0CA, 0x0CB, 0x0CC, 0x0CD, 0x0CE,
0x0CF, 0x11E, 0x0D1, 0x0D2, 0x0D3, 0x0D4, 0x0D5, 0x0D6, 0x0D7,
0x0D8, 0x0D9, 0x0DA, 0x0DB, 0x0DC, 0x130, 0x15E, 0x0DF, 0x0E0,
0x0E1, 0x0E2, 0x0E3, 0x0E4, 0x0E5, 0x0E6, 0x0E7, 0x0E8, 0x0E9,
0x0EA, 0x0EB, 0x0EC, 0x0ED, 0x0EE, 0x0EF, 0x11F, 0x0F1, 0x0F2,
0x0F3, 0x0F4, 0x0F5, 0x0F6, 0x0F7, 0x0F8, 0x0F9, 0x0FA, 0x0FB,
0x0FC, 0x131, 0x15F, 0x0FF
};
static const uint32_t s_latin1lookup[32] = {
0x0FFFE, 0x0FFFE, 0x201A, 0x192, 0x201E, 0x2026, 0x2020, 0x2021,
0x2C6, 0x2030, 0x160, 0x2039, 0x152, 0x0FFFE, 0x0FFFE, 0x0FFFE,
0x0FFFE, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x2DC, 0x2122, 0x161, 0x203A, 0x153, 0x0FFFE, 0x0FFFE, 0x178
};
static const uint32_t s_cyrilliclookup[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11,
0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,
0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23,
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C,
0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E,
0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62,
0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B,
0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74,
0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D,
0x7E, 0x7F, 0x402, 0x403, 0x201A, 0x453, 0x201E, 0x2026, 0x2020,
0x2021, 0x20AC, 0x2030, 0x409, 0x2039, 0x40A, 0x40C, 0x40B, 0x40F,
0x452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x20,
0x2122, 0x459, 0x203A, 0x45A, 0x45C, 0x45B, 0x45F, 0x0A0, 0x40E,
0x45E, 0x408, 0x0A4, 0x490, 0x0A6, 0x0A7, 0x401, 0x0A9, 0x404,
0x0AB, 0x0AC, 0x0AD, 0x0AE, 0x407, 0x0B0, 0x0B1, 0x406, 0x456,
0x491, 0x0B5, 0x0B6, 0x0B7, 0x451, 0x2116, 0x454, 0x0BB, 0x458,
0x405, 0x455, 0x457, 0x410, 0x411, 0x412, 0x413, 0x414, 0x415,
0x416, 0x417, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E,
0x41F, 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427,
0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F, 0x430,
0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, 0x438, 0x439,
0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x441, 0x442,
0x443, 0x444, 0x445, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B,
0x44C, 0x44D, 0x44E, 0x44F
};
static const uint32_t s_latin2lookup[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11,
0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,
0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23,
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C,
0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E,
0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62,
0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B,
0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74,
0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D,
0x7E, 0x7F, 0x20AC, 0x0FFFE, 0x201A, 0x0FFFE, 0x201E, 0x2026, 0x2020,
0x2021, 0x0FFFE, 0x2030, 0x160, 0x2039, 0x15A, 0x164, 0x17D, 0x179,
0x0FFFE, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0FFFE,
0x2122, 0x161, 0x203A, 0x15B, 0x165, 0x17E, 0x17A, 0x0A0, 0x2C7,
0x2D8, 0x141, 0x0A4, 0x104, 0x0A6, 0x0A7, 0x0A8, 0x0A9, 0x15E,
0x0AB, 0x0AC, 0x0AD, 0x0AE, 0x17B, 0x0B0, 0x0B1, 0x2DB, 0x142,
0x0B4, 0x0B5, 0x0B6, 0x0B7, 0x0B8, 0x105, 0x15F, 0x0BB, 0x13D,
0x2DD, 0x13E, 0x17C, 0x154, 0x0C1, 0x0C2, 0x102, 0x0C4, 0x139,
0x106, 0x0C7, 0x10C, 0x0C9, 0x118, 0x0CB, 0x11A, 0x0CD, 0x0CE,
0x10E, 0x110, 0x143, 0x147, 0x0D3, 0x0D4, 0x150, 0x0D6, 0x0D7,
0x158, 0x16E, 0x0DA, 0x170, 0x0DC, 0x0DD, 0x162, 0x0DF, 0x155,
0x0E1, 0x0E2, 0x103, 0x0E4, 0x13A, 0x107, 0x0E7, 0x10D, 0x0E9,
0x119, 0x0EB, 0x11B, 0x0ED, 0x0EE, 0x10F, 0x111, 0x144, 0x148,
0x0F3, 0x0F4, 0x151, 0x0F6, 0x0F7, 0x159, 0x16F, 0x0FA, 0x171,
0x0FC, 0x0FD, 0x163, 0x2D9
};
static const uint32_t s_thailookup[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11,
0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,
0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23,
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C,
0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E,
0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62,
0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B,
0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74,
0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D,
0x7E, 0x7F, 0x20AC, 0x20, 0x20, 0x20, 0x20, 0x2026, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0A0, 0x0E01,
0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, 0x0E08, 0x0E09, 0x0E0A,
0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, 0x0E10, 0x0E11, 0x0E12, 0x0E13,
0x0E14, 0x0E15, 0x0E16, 0x0E17, 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C,
0x0E1D, 0x0E1E, 0x0E1F, 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25,
0x0E26, 0x0E27, 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E,
0x0E2F, 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37,
0x0E38, 0x0E39, 0x0E3A, 0x20, 0x20, 0x20, 0x20, 0x0E3F, 0x0E40,
0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, 0x0E48, 0x0E49,
0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, 0x0E50, 0x0E51, 0x0E52,
0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, 0x0E58, 0x0E59, 0x0E5A, 0x0E5B,
0x20, 0x20, 0x20, 0x20
};
static RECT s_defaultWindowRect; static RECT s_defaultWindowRect;
static int32_t s_savedResize; static int32_t s_savedResize;
@ -469,7 +605,13 @@ void OsInputGetMousePosition(int32_t* x, int32_t* y) {
} }
} }
uint32_t OsInputGetCodePage() {
return ::GetACP();
}
int32_t OsWindowProc(void* window, uint32_t message, uintptr_t wparam, intptr_t lparam) { int32_t OsWindowProc(void* window, uint32_t message, uintptr_t wparam, intptr_t lparam) {
static uint32_t s_codepage = 0;
auto hwnd = static_cast<HWND>(window); auto hwnd = static_cast<HWND>(window);
// TODO // TODO
@ -539,11 +681,28 @@ int32_t OsWindowProc(void* window, uint32_t message, uintptr_t wparam, intptr_t
uint32_t character = wparam; uint32_t character = wparam;
if (wparam >= 128) { if (wparam >= 128) {
// TODO if (s_codepage == 0) {
s_codepage = OsInputGetCodePage();
}
if (s_codepage == 1254) {
// ANSI Turkish; Turkish (Windows)
character = s_latin5lookup[wparam % 256];
} else if (s_codepage == 1252 && wparam < 0xA0) {
// ANSI Latin 1; Western European (Windows)
character = s_latin1lookup[wparam % 32];
} else if (s_codepage == 1251) {
// ANSI Cyrillic; Cyrillic (Windows)
character = s_cyrilliclookup[wparam % 256];
} else if (s_codepage == 1250) {
// ANSI Central European; Central European (Windows)
character = s_latin2lookup[wparam % 256];
} else if (s_codepage == 874) {
// Thai (Windows)
character = s_thailookup[wparam % 256];
}
} }
OsQueuePut(OS_INPUT_CHAR, character, LOWORD(lparam), 0, 0); OsQueuePut(OS_INPUT_CHAR, character, LOWORD(lparam), 0, 0);
return 0; return 0;
} }

View File

@ -366,46 +366,48 @@ void CGlueMgr::PollAccountLogin(int32_t errorCode, const char* msg, int32_t comp
FrameScript_SignalEvent(4, "%s", msg); FrameScript_SignalEvent(4, "%s", msg);
} }
if (complete) { if (!complete) {
if (result == 0) { return;
if (errorCode != 2) { }
if (result == 0) {
if (errorCode != 2) {
// TODO
}
CGlueMgr::m_idleState = IDLE_NONE;
CGlueMgr::m_showedDisconnect = 0;
if (errorCode == 2) {
// TODO CGlueMgr::m_disconnectPending = 1;
// TODO ClientServices::Connection()->Disconnect();
}
if (errorCode != 13) {
// TODO CCharacterSelection::ClearCharacterList();
if (ClientServices::GetInstance()->m_realmList.Count()) {
FrameScript_SignalEvent(5, nullptr);
CRealmList::UpdateList();
} else {
// TODO // TODO
} }
CGlueMgr::m_idleState = IDLE_NONE;
CGlueMgr::m_showedDisconnect = 0;
if (errorCode == 2) {
// TODO CGlueMgr::m_disconnectPending = 1;
// TODO ClientServices::Connection()->Disconnect();
}
if (errorCode != 13) {
// TODO CCharacterSelection::ClearCharacterList();
if (ClientServices::GetInstance()->m_realmList.Count()) {
FrameScript_SignalEvent(5, nullptr);
CRealmList::UpdateList();
} else {
// TODO
}
return;
}
if (!SStrCmpI(CGlueMgr::m_currentScreen, "charselect", STORM_MAX_STR)) {
CGlueMgr::SetScreen("login");
return;
}
return; return;
} }
if (op == COP_CONNECT) { if (!SStrCmpI(CGlueMgr::m_currentScreen, "charselect", STORM_MAX_STR)) {
// TODO CGlueMgr::SetScreen("login");
return; return;
} }
return;
}
if (op == COP_CONNECT) {
// TODO
return;
} }
} }

View File

@ -333,7 +333,7 @@ void CGxDevice::ICursorDraw() {
// Turn off everything // Turn off everything
GxRsSet(GxRs_PolygonOffset, 0); GxRsSet(GxRs_PolygonOffset, 0);
GxRsSet(GxRs_NormalizeNormals, 0); GxRsSet(GxRs_NormalizeNormals, 0);
GxRsSet(GxRs_BlendingMode, 1); GxRsSet(GxRs_BlendingMode, GxBlend_AlphaKey);
GxRsSetAlphaRef(); GxRsSetAlphaRef();
GxRsSet(GxRs_Lighting, 0); GxRsSet(GxRs_Lighting, 0);
GxRsSet(GxRs_Fog, 0); GxRsSet(GxRs_Fog, 0);
@ -355,6 +355,9 @@ void CGxDevice::ICursorDraw() {
float cursorDepth = 1.0f; float cursorDepth = 1.0f;
C44Matrix projection; C44Matrix projection;
// Workaround for software cursor
// C44Matrix projection(2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0.002, 0, -1, -1, 0, 1);
// this->XformSetProjection(projection);
if (!this->StereoEnabled() || if (!this->StereoEnabled() ||
(CGxDevice::s_uiVertexShader == 0 || !s_uiVertexShader->Valid()) || (CGxDevice::s_uiVertexShader == 0 || !s_uiVertexShader->Valid()) ||

View File

@ -334,11 +334,17 @@ LRESULT CGxDeviceD3d::WindowProcD3d(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
case WM_SETCURSOR: { case WM_SETCURSOR: {
if (device) { if (device) {
if (device->m_d3dDevice && lParam == 1) { if (device->m_d3dDevice && LOWORD(lParam) == HTCLIENT) {
SetCursor(nullptr); SetCursor(nullptr);
BOOL show = device->m_cursorVisible && device->m_hardwareCursor ? TRUE : FALSE; BOOL show = device->m_cursorVisible && device->m_hardwareCursor ? TRUE : FALSE;
device->m_d3dDevice->ShowCursor(show); device->m_d3dDevice->ShowCursor(show);
} else {
// Uncomment when the "glove" cursor will be fixed
//break;
} }
} else {
// Uncomment when the "glove" cursor will be fixed
//break;
} }
return 1; return 1;
@ -488,8 +494,7 @@ int32_t CGxDeviceD3d::DeviceSetFormat(const CGxFormat& format) {
if (this->ICreateWindow(createFormat) && this->ICreateD3dDevice(createFormat) && this->CGxDevice::DeviceSetFormat(format)) { if (this->ICreateWindow(createFormat) && this->ICreateD3dDevice(createFormat) && this->CGxDevice::DeviceSetFormat(format)) {
this->intF64 = 1; this->intF64 = 1;
this->m_hwCursorNeedsUpdate = 1;
// TODO
if (this->m_format.window == 0) { if (this->m_format.window == 0) {
RECT windowRect; RECT windowRect;
@ -1102,6 +1107,17 @@ void CGxDeviceD3d::IRsSendToHw(EGxRenderState which) {
break; break;
} }
case GxRs_Lighting: {
int32_t lightingEnable = 0;
if (this->MasterEnable(GxMasterEnable_Lighting)) {
lightingEnable = static_cast<int32_t>(state->m_value);
}
this->m_d3dDevice->SetRenderState(D3DRS_LIGHTING, lightingEnable);
break;
}
case GxRs_DepthTest: case GxRs_DepthTest:
case GxRs_DepthFunc: { case GxRs_DepthFunc: {
auto depthTest = static_cast<uint32_t>((&this->m_appRenderStates[GxRs_DepthTest])->m_value); auto depthTest = static_cast<uint32_t>((&this->m_appRenderStates[GxRs_DepthTest])->m_value);
@ -1249,6 +1265,11 @@ void CGxDeviceD3d::CursorSetVisible(int32_t visible) {
} }
} }
void CGxDeviceD3d::CursorUnlock(uint32_t x, uint32_t y) {
CGxDevice::CursorUnlock(x, y);
this->m_hwCursorNeedsUpdate = 1;
}
void CGxDeviceD3d::ICursorDraw() { void CGxDeviceD3d::ICursorDraw() {
if (!this->m_hardwareCursor) { if (!this->m_hardwareCursor) {
this->ISceneBegin(); this->ISceneBegin();

View File

@ -252,6 +252,7 @@ class CGxDeviceD3d : public CGxDevice {
virtual void ICursorDestroy(); virtual void ICursorDestroy();
virtual void ICursorDraw(); virtual void ICursorDraw();
virtual void CursorSetVisible(int32_t visible); virtual void CursorSetVisible(int32_t visible);
virtual void CursorUnlock(uint32_t x, uint32_t y);
virtual int32_t DeviceCreate(int32_t (*windowProc)(void* window, uint32_t message, uintptr_t wparam, intptr_t lparam), const CGxFormat& format); virtual int32_t DeviceCreate(int32_t (*windowProc)(void* window, uint32_t message, uintptr_t wparam, intptr_t lparam), const CGxFormat& format);
virtual int32_t DeviceSetFormat(const CGxFormat& format); virtual int32_t DeviceSetFormat(const CGxFormat& format);
virtual void* DeviceWindow(); virtual void* DeviceWindow();

View File

@ -1578,7 +1578,7 @@ GLTexture* GLSDLDevice::CreateTextureCubeMap(uint32_t size, uint32_t numMipMap,
} }
void GLSDLDevice::Draw(GLEnum primitive, uint32_t a3, uint32_t a4) { void GLSDLDevice::Draw(GLEnum primitive, uint32_t a3, uint32_t a4) {
// TODO this->GLSDLDraw(primitive, a3, a3 + a4, 0, 0, 0);
} }
void GLSDLDevice::DrawIndexed(GLEnum primitive, uint32_t a3, uint32_t a4, uint32_t a5, uint32_t a6, uint32_t count) { void GLSDLDevice::DrawIndexed(GLEnum primitive, uint32_t a3, uint32_t a4, uint32_t a5, uint32_t a6, uint32_t count) {

View File

@ -110,7 +110,7 @@ int32_t RealmConnection::HandleAuthChallenge(AuthenticationChallenge* challenge)
// TODO switch to WDataStore // TODO switch to WDataStore
CDataStore msg; CDataStore msg;
uint32_t localChallenge; uint32_t localChallenge = 0;
msg.Put(static_cast<uint32_t>(CMSG_AUTH_SESSION)); msg.Put(static_cast<uint32_t>(CMSG_AUTH_SESSION));

View File

@ -152,6 +152,13 @@ void CBackdropGenerator::LoadXML(XMLNode* node, CStatus* status) {
} }
} }
void CBackdropGenerator::SetVertexColor(const CImVector& color) {
this->m_color = color;
if (this->m_backgroundTexture) {
this->m_backgroundTexture->SetVertexColor(color);
}
}
void CBackdropGenerator::SetBorderVertexColor(const CImVector& borderColor) { void CBackdropGenerator::SetBorderVertexColor(const CImVector& borderColor) {
this->m_borderColor = borderColor; this->m_borderColor = borderColor;

View File

@ -42,6 +42,7 @@ class CBackdropGenerator {
CBackdropGenerator(); CBackdropGenerator();
void Generate(const CRect* rect); void Generate(const CRect* rect);
void LoadXML(XMLNode* node, CStatus* status); void LoadXML(XMLNode* node, CStatus* status);
void SetVertexColor(const CImVector& color);
void SetBorderVertexColor(const CImVector& borderColor); void SetBorderVertexColor(const CImVector& borderColor);
void SetOutput(CSimpleFrame* frame); void SetOutput(CSimpleFrame* frame);
}; };

View File

@ -871,6 +871,11 @@ int32_t CSimpleEditBox::OnLayerKeyDown(const CKeyEvent& evt) {
return 1; return 1;
} }
case KEY_TAB: {
// TODO correct implementation
this->RunOnTabPressedScript();
}
// TODO // TODO
// - remaining keys // - remaining keys
@ -994,6 +999,12 @@ void CSimpleEditBox::RunOnEnterPressedScript() {
} }
} }
void CSimpleEditBox::RunOnTabPressedScript() {
if (this->m_onTabPressed.luaRef) {
this->RunScript(this->m_onTabPressed, 0, 0);
}
}
void CSimpleEditBox::RunOnTextChangedScript(int32_t changed) { void CSimpleEditBox::RunOnTextChangedScript(int32_t changed) {
if (this->m_onTextChanged.luaRef) { if (this->m_onTextChanged.luaRef) {
auto L = FrameScript_GetContext(); auto L = FrameScript_GetContext();

View File

@ -98,6 +98,7 @@ class CSimpleEditBox : public CSimpleFrame, CSimpleFontedFrame {
void RunOnEditFocusGainedScript(); void RunOnEditFocusGainedScript();
void RunOnEditFocusLostScript(); void RunOnEditFocusLostScript();
void RunOnEnterPressedScript(); void RunOnEnterPressedScript();
void RunOnTabPressedScript();
void RunOnTextChangedScript(int32_t changed); void RunOnTextChangedScript(int32_t changed);
void SetCursorPosition(int32_t position); void SetCursorPosition(int32_t position);
void SetHistoryLines(int32_t a2); void SetHistoryLines(int32_t a2);

View File

@ -176,11 +176,34 @@ int32_t CSimpleEditBox_GetTextInsets(lua_State* L) {
} }
int32_t CSimpleEditBox_SetFocus(lua_State* L) { int32_t CSimpleEditBox_SetFocus(lua_State* L) {
WHOA_UNIMPLEMENTED(0); if (lua_type(L, 1) != LUA_TTABLE) {
luaL_error(L, "Attempt to find 'this' in non-table object (used '.' instead of ':' ?)");
}
lua_rawgeti(L, 1, 0);
auto object = reinterpret_cast<CSimpleEditBox*>(lua_touserdata(L, -1));
lua_settop(L, -2);
STORM_ASSERT(object);
CSimpleEditBox::SetKeyboardFocus(object);
return 0;
} }
int32_t CSimpleEditBox_ClearFocus(lua_State* L) { int32_t CSimpleEditBox_ClearFocus(lua_State* L) {
WHOA_UNIMPLEMENTED(0); if (lua_type(L, 1) != LUA_TTABLE) {
luaL_error(L, "Attempt to find 'this' in non-table object (used '.' instead of ':' ?)");
}
lua_rawgeti(L, 1, 0);
auto object = reinterpret_cast<CSimpleEditBox*>(lua_touserdata(L, -1));
lua_settop(L, -2);
STORM_ASSERT(object);
// TODO
// CSimpleEditBox::ClearKeyboardFocus(object);
return 0;
} }
int32_t CSimpleEditBox_HasFocus(lua_State* L) { int32_t CSimpleEditBox_HasFocus(lua_State* L) {

View File

@ -4,6 +4,8 @@
#include "util/Lua.hpp" #include "util/Lua.hpp"
#include "util/Unimplemented.hpp" #include "util/Unimplemented.hpp"
#include <cstdint> #include <cstdint>
#include <cctype>
int32_t CSimpleFontString_IsObjectType(lua_State* L) { int32_t CSimpleFontString_IsObjectType(lua_State* L) {
WHOA_UNIMPLEMENTED(0); WHOA_UNIMPLEMENTED(0);
@ -132,7 +134,24 @@ int32_t CSimpleFontString_SetText(lua_State* L) {
} }
int32_t CSimpleFontString_SetFormattedText(lua_State* L) { int32_t CSimpleFontString_SetFormattedText(lua_State* L) {
WHOA_UNIMPLEMENTED(0); if (lua_type(L, 1) != LUA_TTABLE) {
luaL_error(L, "Attempt to find 'this' in non-table object (used '.' instead of ':' ?)");
return 0;
}
auto type = CSimpleFontString::GetObjectType();
auto string = static_cast<CSimpleFontString*>(FrameScript_GetObjectThis(L, type));
if (!string->m_font) {
luaL_error(L, "%s:SetText(): Font not set", string->GetDisplayName());
return 0;
}
char text[2048] = {};
FrameScript_Sprintf(L, 2, text, sizeof(text));
string->SetText(text, 0);
return 0;
} }
int32_t CSimpleFontString_GetTextColor(lua_State* L) { int32_t CSimpleFontString_GetTextColor(lua_State* L) {

View File

@ -1327,7 +1327,19 @@ void CSimpleFrame::SetBeingScrolled(int32_t a2, int32_t a3) {
} }
void CSimpleFrame::SetFrameAlpha(uint8_t alpha) { void CSimpleFrame::SetFrameAlpha(uint8_t alpha) {
// TODO if (this->m_alpha == alpha) {
return;
}
this->m_alpha = alpha;
for (auto region = this->m_regions.Head(); region; region = this->m_regions.Link(region)->Next()) {
region->OnColorChanged(true);
}
for (auto child = this->m_children.Head(); child; child = this->m_children.Link(child)->Next()) {
child->frame->SetFrameAlpha(alpha);
}
} }
void CSimpleFrame::SetFrameFlag(int32_t flag, int32_t on) { void CSimpleFrame::SetFrameFlag(int32_t flag, int32_t on) {

View File

@ -37,6 +37,7 @@ class CSimpleFrame : public CScriptRegion {
float m_depth = 0.0; float m_depth = 0.0;
FRAME_STRATA m_strata = FRAME_STRATA_MEDIUM; FRAME_STRATA m_strata = FRAME_STRATA_MEDIUM;
int32_t m_level = 0; int32_t m_level = 0;
uint8_t m_alpha = 255;
uint32_t m_eventmask = 0; uint32_t m_eventmask = 0;
int32_t m_shown = 0; int32_t m_shown = 0;
int32_t m_visible = 0; int32_t m_visible = 0;

View File

@ -2,6 +2,7 @@
#include "gx/Coordinate.hpp" #include "gx/Coordinate.hpp"
#include "ui/CSimpleFrame.hpp" #include "ui/CSimpleFrame.hpp"
#include "ui/FrameScript.hpp" #include "ui/FrameScript.hpp"
#include "ui/CBackdropGenerator.hpp"
#include "util/Lua.hpp" #include "util/Lua.hpp"
#include "util/Unimplemented.hpp" #include "util/Unimplemented.hpp"
#include <algorithm> #include <algorithm>
@ -460,7 +461,28 @@ int32_t CSimpleFrame_GetBackdropColor(lua_State* L) {
} }
int32_t CSimpleFrame_SetBackdropColor(lua_State* L) { int32_t CSimpleFrame_SetBackdropColor(lua_State* L) {
WHOA_UNIMPLEMENTED(0); if (lua_type(L, 1) != LUA_TTABLE) {
luaL_error(L, "Attempt to find 'this' in non-table object (used '.' instead of ':' ?)");
}
lua_rawgeti(L, 1, 0);
auto object = reinterpret_cast<CSimpleFrame*>(lua_touserdata(L, -1));
lua_settop(L, -2);
STORM_ASSERT(object);
CImVector color;
auto red = lua_tonumber(L, 2);
auto green = lua_tonumber(L, 3);
auto blue = lua_tonumber(L, 4);
auto alpha = lua_isnumber(L, 5) ? lua_tonumber(L, 5) : 1.0;
color.Set(alpha, red, green, blue);
if (object->m_backdrop) {
object->m_backdrop->SetVertexColor(color);
}
return 0;
} }
int32_t CSimpleFrame_GetBackdropBorderColor(lua_State* L) { int32_t CSimpleFrame_GetBackdropBorderColor(lua_State* L) {
@ -468,7 +490,28 @@ int32_t CSimpleFrame_GetBackdropBorderColor(lua_State* L) {
} }
int32_t CSimpleFrame_SetBackdropBorderColor(lua_State* L) { int32_t CSimpleFrame_SetBackdropBorderColor(lua_State* L) {
WHOA_UNIMPLEMENTED(0); if (lua_type(L, 1) != LUA_TTABLE) {
luaL_error(L, "Attempt to find 'this' in non-table object (used '.' instead of ':' ?)");
}
lua_rawgeti(L, 1, 0);
auto object = reinterpret_cast<CSimpleFrame*>(lua_touserdata(L, -1));
lua_settop(L, -2);
STORM_ASSERT(object);
CImVector color;
auto red = lua_tonumber(L, 2);
auto green = lua_tonumber(L, 3);
auto blue = lua_tonumber(L, 4);
auto alpha = lua_isnumber(L, 5) ? lua_tonumber(L, 5) : 1.0;
color.Set(alpha, red, green, blue);
if (object->m_backdrop) {
object->m_backdrop->SetBorderVertexColor(color);
}
return 0;
} }
int32_t CSimpleFrame_SetDepth(lua_State* L) { int32_t CSimpleFrame_SetDepth(lua_State* L) {

View File

@ -10,6 +10,7 @@
#include <storm/Array.hpp> #include <storm/Array.hpp>
#include <storm/String.hpp> #include <storm/String.hpp>
#include <tempest/Vector.hpp> #include <tempest/Vector.hpp>
#include <cctype>
const char* g_glueScriptEvents[41]; const char* g_glueScriptEvents[41];
const char* g_scriptEvents[722]; const char* g_scriptEvents[722];
@ -867,6 +868,216 @@ void FrameScript_UnregisterScriptEvent(FrameScript_Object* object, FrameScript_E
} }
} }
static void addchar(char* buffer, size_t bufferSize, char ch) {
auto length = SStrLen(buffer);
if (length + 1 < bufferSize)
{
buffer[length++] = ch;
buffer[length] = '\0';
}
}
static void addstring(char* buffer, size_t bufferSize, const char* source) {
uint32_t dsize = 0;
uint32_t size = 0;
dsize = SStrLen(buffer);
size = SStrLen(source);
if (dsize + size >= bufferSize) {
size = bufferSize - dsize;
// Check for space for trailing zero
if (size < 2) {
size = 0;
} else {
size--;
}
}
if (size > 0)
memmove(&buffer[dsize], source, size);
buffer[dsize + size] = '\0';
}
static void addstring(char* buffer, size_t bufferSize, const char* source, size_t count) {
uint32_t dsize = 0;
uint32_t size = 0;
dsize = SStrLen(buffer);
size = std::min(SStrLen(source), count);
if (dsize + size >= bufferSize) {
size = bufferSize - dsize;
// Check for space for trailing zero
if (size < 2) {
size = 0;
} else {
size--;
}
}
if (size > 0)
memmove(&buffer[dsize], source, size);
buffer[dsize + size] = '\0';
}
static void addquoted(lua_State* L, char* buffer, size_t bufferSize, int arg) {
size_t l;
const char* s = luaL_checklstring(L, arg, &l);
addchar(buffer, bufferSize, '"');
while (l--) {
switch (*s) {
case '"':
case '\\':
case '\n': {
addchar(buffer, bufferSize, '\\');
addchar(buffer, bufferSize, *s);
break;
}
case '\r': {
addstring(buffer, bufferSize, "\\r");
break;
}
case '\0': {
addstring(buffer, bufferSize, "\\000");
break;
}
default: {
addchar(buffer, bufferSize, *s);
break;
}
}
s++;
}
addchar(buffer, bufferSize, '"');
}
#define FORMAT_FLAGS "-+ #0"
static const char* scanformat(lua_State* L, const char* strfrmt, char* form) {
const char* flags = "-+ #0";
const char* p = strfrmt;
while (*p != '\0' && SStrChrR(FORMAT_FLAGS, *p) != NULL) {
p++; /* skip flags */
}
if ((size_t)(p - strfrmt) >= sizeof(FORMAT_FLAGS)) {
luaL_error(L, "invalid format (repeated flags)");
}
if (isdigit((unsigned char)(*p))) {
p++; /* skip width */
}
if (isdigit((unsigned char)(*p))) {
p++; /* (2 digits at most) */
}
if (*p == '.') {
p++;
if (isdigit((unsigned char)(*p))) {
p++; /* skip precision */
}
if (isdigit((unsigned char)(*p))) {
p++; /* (2 digits at most) */
}
}
if (isdigit((unsigned char)(*p))) {
luaL_error(L, "invalid format (width or precision too long)");
}
*(form++) = '%';
strncpy(form, strfrmt, p - strfrmt + 1);
form += p - strfrmt + 1;
*form = '\0';
return p;
}
static void addintlen(char* form) {
size_t l = SStrLen(form);
char spec = form[l - 1];
strcpy(form + l - 1, LUA_INTFRMLEN);
form[l + sizeof(LUA_INTFRMLEN) - 2] = spec;
form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0';
}
void FrameScript_Sprintf(lua_State* L, int startIndex, char* buffer, uint32_t bufferSize) {
// maximum size of each formatted item (> len(format('%99.99f', -1e308)))
const size_t MAX_ITEM = 512;
// maximum size of each format specification (such as '%-099.99d')
// (+10 accounts for %99.99x plus margin of error)
const size_t MAX_FORMAT = sizeof(FORMAT_FLAGS) + sizeof(LUA_INTFRMLEN) + 10;
int arg = startIndex;
size_t sfl;
const char* strfrmt = luaL_checklstring(L, arg, &sfl);
const char* strfrmt_end = strfrmt + sfl;
while (strfrmt < strfrmt_end) {
if (*strfrmt != '%') {
addchar(buffer, bufferSize, *strfrmt++);
} else if (*++strfrmt == '%') {
addchar(buffer, bufferSize, *strfrmt++); /* %% */
} else { /* format item */
char form[MAX_FORMAT]; /* to store the format (`%...') */
char buff[MAX_ITEM]; /* to store the formatted item */
arg++;
strfrmt = scanformat(L, strfrmt, form);
switch (*strfrmt++) {
case 'c': {
sprintf(buff, form, (int)luaL_checknumber(L, arg));
break;
}
case 'd':
case 'i': {
addintlen(form);
sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg));
break;
}
case 'o':
case 'u':
case 'x':
case 'X': {
addintlen(form);
sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));
break;
}
case 'e':
case 'E':
case 'f':
case 'g':
case 'G': {
sprintf(buff, form, (double)luaL_checknumber(L, arg));
break;
}
case 'q': {
addquoted(L, buffer, bufferSize, arg);
continue; /* skip the 'addsize' at the end */
}
case 's': {
size_t l;
const char* s = luaL_checklstring(L, arg, &l);
if (!strchr(form, '.') && l >= 100) {
/* no precision and string is too long to be formatted;
keep original string */
continue; /* skip the `addsize' at the end */
} else {
sprintf(buff, form, s);
break;
}
}
default: { /* also treat cases `pnLlh' */
luaL_error(L, "invalid option " LUA_QL("%%%c") " to " LUA_QL("format"), *(strfrmt - 1));
}
}
addstring(buffer, bufferSize, buff);
}
}
}
void GlueScriptEventsInitialize() { void GlueScriptEventsInitialize() {
g_glueScriptEvents[0] = "SET_GLUE_SCREEN"; g_glueScriptEvents[0] = "SET_GLUE_SCREEN";
g_glueScriptEvents[1] = "START_GLUE_MUSIC"; g_glueScriptEvents[1] = "START_GLUE_MUSIC";

View File

@ -100,6 +100,8 @@ void FrameScript_SignalEvent(uint32_t index, const char* format, ...);
void FrameScript_UnregisterScriptEvent(FrameScript_Object* object, FrameScript_EventObject* event); void FrameScript_UnregisterScriptEvent(FrameScript_Object* object, FrameScript_EventObject* event);
void FrameScript_Sprintf(lua_State* L, int startIndex, char* buffer, uint32_t bufferSize);
void GlueScriptEventsInitialize(); void GlueScriptEventsInitialize();
void ScriptEventsInitialize(); void ScriptEventsInitialize();

View File

@ -19,7 +19,15 @@ int32_t Script_IsShiftKeyDown(lua_State* L) {
} }
int32_t Script_GetBuildInfo(lua_State* L) { int32_t Script_GetBuildInfo(lua_State* L) {
WHOA_UNIMPLEMENTED(0); auto szVersion = FrameScript_GetText("VERSION", -1, GENDER_NOT_APPLICABLE);
auto szVersionType = FrameScript_GetText("RELEASE_BUILD", -1, GENDER_NOT_APPLICABLE);
lua_pushstring(L, szVersion);
lua_pushstring(L, szVersionType);
lua_pushstring(L, "3.3.5");
lua_pushstring(L, "12340");
lua_pushstring(L, "Jun 24 2010");
return 5;
} }
int32_t Script_GetLocale(lua_State* L) { int32_t Script_GetLocale(lua_State* L) {
@ -27,7 +35,9 @@ int32_t Script_GetLocale(lua_State* L) {
} }
int32_t Script_GetSavedAccountName(lua_State* L) { int32_t Script_GetSavedAccountName(lua_State* L) {
WHOA_UNIMPLEMENTED(0); // TODO
lua_pushstring(L, "");
return 1;
} }
int32_t Script_SetSavedAccountName(lua_State* L) { int32_t Script_SetSavedAccountName(lua_State* L) {

View File

@ -8,8 +8,9 @@
#include <bc/file/File.hpp> #include <bc/file/File.hpp>
#include "util/Filesystem.hpp" #include "util/Filesystem.hpp"
static char s_basepath[STORM_MAX_PATH] = {0}; static char s_basepath[STORM_MAX_PATH] = { 0 };
static char s_datapath[STORM_MAX_PATH] = {0}; static char s_datapath[STORM_MAX_PATH] = { 0 };
static char s_datapath2[STORM_MAX_PATH] = { 0 };
// TODO Proper implementation // TODO Proper implementation
int32_t SFile::Close(SFile* file) { int32_t SFile::Close(SFile* file) {
@ -279,3 +280,17 @@ int32_t SFile::GetDataPath(char* buffer, size_t bufferchars) {
SStrCopy(buffer, s_datapath, bufferchars); SStrCopy(buffer, s_datapath, bufferchars);
return 1; return 1;
} }
int32_t SFile::SetDataPathAlternate(const char* path) {
SStrCopy(s_datapath2, path, STORM_MAX_PATH);
size_t length = SStrLen(s_datapath2);
if (length && s_datapath2[length - 1] != '\\' && s_datapath2[length - 1] != '/') {
SStrPack(s_datapath2, "\\", STORM_MAX_PATH);
}
return 1;
}
int32_t SFile::RebuildHash() {
// TODO
return 1;
}

View File

@ -39,6 +39,8 @@ class SFile {
static int32_t SetDataPath(const char* path); static int32_t SetDataPath(const char* path);
static int32_t GetBasePath(char* path, size_t capacity); static int32_t GetBasePath(char* path, size_t capacity);
static int32_t GetDataPath(char* path, size_t capacity); static int32_t GetDataPath(char* path, size_t capacity);
static int32_t SetDataPathAlternate(const char* path);
static int32_t RebuildHash();
// Member variables // Member variables
SFILE_TYPE m_type; SFILE_TYPE m_type;