Merge branch 'master' into Grunt-state-enum

This commit is contained in:
fallenoak 2025-09-25 09:15:03 -07:00 committed by GitHub
commit d1bbf86723
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
323 changed files with 75719 additions and 8398 deletions

View File

@ -27,6 +27,7 @@ IncludeCategories:
- Regex: ".*"
Priority: 1
SortPriority: 0
IndentAccessModifiers: true
IndentGotoLabels: false
IndentWidth: 4
MaxEmptyLinesToKeep: 1

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.1)
cmake_minimum_required(VERSION 3.1...3.5)
if (${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
message(FATAL_ERROR
@ -24,8 +24,6 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_BUILD_TYPE Debug)
include(lib/system/cmake/system.cmake)
# Some templates abuse offsetof
@ -65,6 +63,17 @@ if(WHOA_SYSTEM_LINUX OR WHOA_SYSTEM_MAC)
find_package(Threads REQUIRED)
endif()
# Library search paths
if(WHOA_SYSTEM_MAC)
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH "@executable_path")
elseif(WHOA_SYSTEM_LINUX)
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH "$ORIGIN")
endif()
add_subdirectory(lib)
add_subdirectory(src)
add_subdirectory(test)

2
lib/bc

@ -1 +1 @@
Subproject commit e21b610abfe7b491b3996ce57520fcfba889e120
Subproject commit 5a8d14766308be0746368d169b3b1ee834d91e4a

@ -1 +1 @@
Subproject commit 43b5def8777ca979b603398916ca162437597958
Subproject commit 92a540a549c6882b6ebd87593ed97174865100c9

@ -1 +1 @@
Subproject commit bebe40f7814ca36f898f95b39c21fa8c42ae88cf
Subproject commit a96d1270d4a1f5d6fa6756c30696a13f87b08a0a

@ -1 +1 @@
Subproject commit f886ab5bc35b2e0d968baa8dec3faaccf385fbc3
Subproject commit 63f4f710e47d37e82930d4a1750c7d3b36b700ec

@ -1 +1 @@
Subproject commit fdefabe4f09b6413fd33242c05243121c296c91c
Subproject commit f191151f1694ae471396c0cad6b89811fb6fa6ca

View File

@ -1,6 +1,7 @@
add_subdirectory(app)
add_subdirectory(async)
add_subdirectory(client)
add_subdirectory(console)
add_subdirectory(db)
add_subdirectory(event)
add_subdirectory(glue)

View File

@ -36,6 +36,7 @@ target_include_directories(client
target_link_libraries(client
PRIVATE
async
console
db
event
gx

View File

@ -1,19 +1,20 @@
#include "client/Client.hpp"
#include "client/ClientServices.hpp"
#include "client/Console.hpp"
#include "db/Db.hpp"
#include "async/AsyncFile.hpp"
#include "client/ClientHandlers.hpp"
#include "client/ClientServices.hpp"
#include "console/CVar.hpp"
#include "console/Device.hpp"
#include "console/Initialize.hpp"
#include "console/Screen.hpp"
#include "db/Db.hpp"
#include "glue/CGlueMgr.hpp"
#include "gx/Device.hpp"
#include "gx/Screen.hpp"
#include "gx/Texture.hpp"
#include "model/Model2.hpp"
#include "net/Poll.hpp"
#include "ui/FrameScript.hpp"
#include "ui/FrameXML.hpp"
#include "util/CVar.hpp"
#include "world/World.hpp"
#include <cstring>
#include <bc/Debug.hpp>
#include <common/Prop.hpp>
#include <storm/Error.hpp>
@ -30,6 +31,33 @@ void BaseInitializeGlobal() {
PropInitialize();
}
int32_t ClientIdle(const void* data, void* param) {
// TODO
// ClientGameTimeTickHandler(data, param);
// Player_C_ZoneUpdateHandler(data, param);
return 1;
}
void ClientInitializeGame(uint32_t mapId, C3Vector position) {
// TODO
EventRegister(EVENT_ID_IDLE, ClientIdle);
// TODO
ClientServices::SetMessageHandler(SMSG_NOTIFICATION, NotifyHandler, nullptr);
ClientServices::SetMessageHandler(SMSG_PLAYED_TIME, PlayedTimeHandler, nullptr);
ClientServices::SetMessageHandler(SMSG_NEW_WORLD, NewWorldHandler, nullptr);
ClientServices::SetMessageHandler(SMSG_TRANSFER_PENDING, TransferPendingHandler, nullptr);
ClientServices::SetMessageHandler(SMSG_TRANSFER_ABORTED, TransferAbortedHandler, nullptr);
ClientServices::SetMessageHandler(SMSG_LOGIN_VERIFY_WORLD, LoginVerifyWorldHandler, nullptr);
ClientServices::SetMessageHandler(SMSG_KICK_REASON, CGlueMgr::OnKickReasonMsg, nullptr);
// TODO
}
void ClientMiscInitialize() {
// TODO
@ -73,7 +101,7 @@ int32_t InitializeEngineCallback(const void* a1, void* a2) {
// }
ScrnInitialize(0);
// ConsoleScreenInitialize(a2);
ConsoleScreenInitialize(nullptr); // TODO argument
// s_cvarTextureFilteringMode = CVar::Register(
// "textureFilteringMode",

View File

@ -2,7 +2,7 @@
#define CLIENT_CLIENT_HPP
#include "event/Event.hpp"
#include <cstdint>
#include <tempest/Vector.hpp>
class CVar;
@ -11,6 +11,8 @@ namespace Client {
extern HEVENTCONTEXT g_clientEventContext;
}
void ClientInitializeGame(uint32_t mapId, C3Vector position);
void ClientPostClose(int32_t a1);
void CommonMain();

View File

@ -0,0 +1,37 @@
#include "client/ClientHandlers.hpp"
int32_t LoginVerifyWorldHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg) {
// TODO
return 0;
}
int32_t NewWorldHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg) {
// TODO
return 0;
}
int32_t NotifyHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg) {
// TODO
return 0;
}
int32_t PlayedTimeHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg) {
// TODO
return 0;
}
int32_t TransferAbortedHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg) {
// TODO
return 0;
}
int32_t TransferPendingHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg) {
// TODO
return 0;
}

View File

@ -0,0 +1,21 @@
#ifndef CLIENT_CLIENT_HANDLERS_HPP
#define CLIENT_CLIENT_HANDLERS_HPP
#include "net/Types.hpp"
#include <cstdint>
class CDataStore;
int32_t LoginVerifyWorldHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg);
int32_t NewWorldHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg);
int32_t NotifyHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg);
int32_t PlayedTimeHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg);
int32_t TransferAbortedHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg);
int32_t TransferPendingHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg);
#endif

View File

@ -0,0 +1,18 @@
#include "client/ClientRealmResponseAdapter.hpp"
void AccountDataInitialize(bool a1) {
// TODO
}
void ClientRealmResponseAdapter::HandleAuthResponse(RealmConnection* realmConnection, uint8_t authResult) {
auto clientConnection = static_cast<ClientConnection*>(realmConnection);
// AUTH_WAIT_QUEUE
if (authResult == 27) {
clientConnection->AccountLogin_Queued();
} else {
clientConnection->AccountLogin_Finish(authResult);
}
AccountDataInitialize(true);
}

View File

@ -5,6 +5,9 @@
class ClientRealmResponseAdapter : public RealmResponse {
public:
// Virtual member functions
virtual void HandleAuthResponse(RealmConnection* realmConnection, uint8_t authResult);
virtual void GameServerResult(RealmConnection* realmConnection, const char* a2, const char* a3, const char* a4) {};
};
#endif

View File

@ -3,7 +3,7 @@
#include "glue/CGlueMgr.hpp"
#include "net/Connection.hpp"
#include "net/Login.hpp"
#include "util/CVar.hpp"
#include "console/CVar.hpp"
#include <storm/Memory.hpp>
#include <storm/String.hpp>
#include <new>
@ -22,12 +22,12 @@ bool ClientServices::s_selectRealmInfoValid;
void ClientServices::ConnectToSelectedServer() {
if (!ClientServices::s_selectRealmInfoValid && !ClientServices::SetSelectedRealmInfo(0)) {
ClientServices::Connection()->SetStatus(0, 39);
ClientServices::Connection()->Complete(0, 39);
return;
}
if (ClientServices::Connection()->GetState() != NS_INITIALIZED) {
ClientServices::Connection()->SetStatus(0, 39);
ClientServices::Connection()->Complete(0, 39);
return;
}
@ -154,6 +154,13 @@ void ClientServices::SetAccountName(const char* accountName) {
SStrCopy(ClientServices::s_accountName, accountName, sizeof(ClientServices::s_accountName));
}
void ClientServices::SetMessageHandler(NETMESSAGE msgId, MESSAGE_HANDLER handler, void* param) {
STORM_ASSERT(handler);
STORM_ASSERT(ClientServices::s_currentConnection);
ClientServices::s_currentConnection->SetMessageHandler(msgId, handler, param);
}
int32_t ClientServices::SetSelectedRealmInfo(int32_t a1) {
auto instance = ClientServices::GetInstance();
@ -210,12 +217,12 @@ void ClientServices::RealmEnumCallback(uint32_t a2) {
auto connection = ClientServices::Connection();
if (a2 == 1) {
connection->SetStatus(0, 23);
connection->Complete(0, 23);
return;
}
if (a2 == 2 || a2 == 3 || a2 == 4) {
connection->SetStatus(0, 37);
connection->Complete(0, 37);
return;
}

View File

@ -1,6 +1,7 @@
#ifndef CLIENT_CLIENT_SERVICES_HPP
#define CLIENT_CLIENT_SERVICES_HPP
#include "net/connection/NetClient.hpp"
#include "net/login/LoginResponse.hpp"
class ClientConnection;
@ -33,6 +34,7 @@ class ClientServices : public LoginResponse {
static void Logon(const char* accountName, const char* password);
static void SelectRealm(const char* realmName);
static void SetAccountName(const char* accountName);
static void SetMessageHandler(NETMESSAGE msgId, MESSAGE_HANDLER handler, void* param);
static int32_t SetSelectedRealmInfo(int32_t a1);
// Virtual member functions

View File

@ -1,16 +0,0 @@
#ifndef CLIENT_CONSOLE_HPP
#define CLIENT_CONSOLE_HPP
#include "gx/CGxFormat.hpp"
struct DefaultSettings {
CGxFormat format;
};
void ConsoleInitializeClientCommand();
void ConsoleInitializeClientCVar(const char* a1);
void ConsoleDeviceInitialize(const char* title);
#endif

View File

@ -0,0 +1,21 @@
file(GLOB PRIVATE_SOURCES
"*.cpp"
)
add_library(console STATIC
${PRIVATE_SOURCES}
)
target_include_directories(console
PRIVATE
${CMAKE_SOURCE_DIR}/src
)
target_link_libraries(console
PUBLIC
common
gx
storm
PRIVATE
client
)

View File

@ -1,9 +1,31 @@
#include "util/CVar.hpp"
#include "console/CVar.hpp"
#include "console/Command.hpp"
#include "console/CVarHandlers.hpp"
#include <storm/String.hpp>
bool CVar::m_initialized;
bool CVar::m_needsSave;
TSHashTable<CVar, HASHKEY_STRI> CVar::s_registeredCVars;
void CVar::Initialize() {
CVar::m_initialized = true;
char basePath[STORM_MAX_PATH];
// TODO
// SFile::GetBasePath(basePath, 260);
// SStrPrintf(basePath, sizeof(basePath), "%s%s\\", basePath, "WTF");
// s_CreatePathDirectories(basePath);
ConsoleCommandRegister("set", CVarSetCommandHandler, DEFAULT, "Set the value of a CVar");
ConsoleCommandRegister("cvar_reset", CVarResetCommandHandler, DEFAULT, "Set the value of a CVar to it's startup value");
ConsoleCommandRegister("cvar_default", CVarDefaultCommandHandler, DEFAULT, "Set the value of a CVar to it's coded default value");
ConsoleCommandRegister("cvarlist", CVarListCommandHandler, DEFAULT, "List cvars");
}
void CVar::Load(const char* filename) {
// TODO
}
CVar* CVar::Lookup(const char* name) {
return name
? CVar::s_registeredCVars.Ptr(name)

View File

@ -1,5 +1,5 @@
#ifndef UTIL_C_VAR_HPP
#define UTIL_C_VAR_HPP
#ifndef CONSOLE_C_VAR_HPP
#define CONSOLE_C_VAR_HPP
#include <cstdint>
#include <common/String.hpp>
@ -8,10 +8,13 @@
class CVar : public TSHashObject<CVar, HASHKEY_STRI> {
public:
// Static variables
static bool m_initialized;
static TSHashTable<CVar, HASHKEY_STRI> s_registeredCVars;
static bool m_needsSave;
// Static functions
static void Initialize();
static void Load(const char* filename);
static CVar* Lookup(const char* name);
static CVar* Register(const char*, const char*, uint32_t, const char*, bool (*)(CVar*, const char*, const char*, void*), uint32_t, bool, void*, bool);

View File

@ -0,0 +1,25 @@
#include "console/CVarHandlers.hpp"
int32_t CVarDefaultCommandHandler(const char* command, const char* arguments) {
// TODO
return 0;
}
int32_t CVarListCommandHandler(const char* command, const char* arguments) {
// TODO
return 0;
}
int32_t CVarSetCommandHandler(const char* command, const char* arguments) {
// TODO
return 0;
}
int32_t CVarResetCommandHandler(const char* command, const char* arguments) {
// TODO
return 0;
}

View File

@ -0,0 +1,14 @@
#ifndef CONSOLE_C_VAR_HANDLERS_HPP
#define CONSOLE_C_VAR_HANDLERS_HPP
#include <cstdint>
int32_t CVarDefaultCommandHandler(const char* command, const char* arguments);
int32_t CVarListCommandHandler(const char* command, const char* arguments);
int32_t CVarSetCommandHandler(const char* command, const char* arguments);
int32_t CVarResetCommandHandler(const char* command, const char* arguments);
#endif

71
src/console/Command.cpp Normal file
View File

@ -0,0 +1,71 @@
#include "console/Command.hpp"
#include "console/CommandHandlers.hpp"
#include <storm/Error.hpp>
int32_t ValidateFileName(const char* filename) {
if (SStrStr(filename, "..") || SStrStr(filename, "\\")) {
// TODO
// ConsoleWrite("File Name cannot contain '\\' or '..'", ERROR_COLOR);
return 0;
}
const char* extension = SStrChrR(filename, '.');
if (extension && SStrCmpI(extension, ".wtf", -1)) {
// TODO
// ConsoleWrite("Only .wtf extensions are allowed", ERROR_COLOR);
return 0;
}
return 1;
}
TSHashTable<CONSOLECOMMAND, HASHKEY_STRI> g_consoleCommandHash;
char g_commandHistory[HISTORY_DEPTH][CMD_BUFFER_SIZE];
uint32_t g_commandHistoryIndex;
void ConsoleCommandDestroy() {
g_consoleCommandHash.Clear();
}
char* ConsoleCommandHistory(uint32_t index) {
// Return a pointer to the buffer at the specified index
return g_commandHistory[((g_commandHistoryIndex + (HISTORY_DEPTH - 1) - index) & (HISTORY_DEPTH - 1))];
}
uint32_t ConsoleCommandHistoryDepth() {
return HISTORY_DEPTH;
}
void ConsoleCommandInitialize() {
ConsoleCommandRegister("help", ConsoleCommand_Help, CONSOLE, "Provides help information about a command.");
}
int32_t ConsoleCommandRegister(const char* command, int32_t (*handler)(const char*, const char*), CATEGORY category, const char* helpText) {
STORM_ASSERT(command);
STORM_ASSERT(handler);
if (SStrLen(command) > (MAX_CMD_LENGTH - 1) || g_consoleCommandHash.Ptr(command)) {
// The command name exceeds MAX_CMD_LENGTH, minus the null terminator
// or it has already been registered
return 0;
}
// Register the new command
auto commandPtr = g_consoleCommandHash.New(command, 0, 0);
commandPtr->command = command;
commandPtr->handler = handler;
commandPtr->helpText = helpText;
commandPtr->category = category;
return 1;
}
void ConsoleCommandUnregister(const char* command) {
if (command) {
auto commandPtr = g_consoleCommandHash.Ptr(command);
if (commandPtr) {
g_consoleCommandHash.Delete(commandPtr);
}
}
}

51
src/console/Command.hpp Normal file
View File

@ -0,0 +1,51 @@
#ifndef CONSOLE_COMMAND_HPP
#define CONSOLE_COMMAND_HPP
#include <storm/Hash.hpp>
#include <cstdint>
#define EXEC_BUFFER_SIZE 8192
#define CMD_BUFFER_SIZE 1024
#define MAX_CMD_LENGTH 64
#define HISTORY_DEPTH 32
#define NOHELP nullptr
enum CATEGORY {
DEBUG,
GRAPHICS,
CONSOLE,
COMBAT,
GAME,
DEFAULT,
NET,
SOUND,
GM,
NONE,
LAST
};
struct CONSOLECOMMAND : TSHashObject<CONSOLECOMMAND, HASHKEY_STRI> {
const char* command;
int32_t (*handler)(const char*, const char*);
const char* helpText;
CATEGORY category;
};
extern TSHashTable<CONSOLECOMMAND, HASHKEY_STRI> g_consoleCommandHash;
extern char g_commandHistory[HISTORY_DEPTH][CMD_BUFFER_SIZE];
extern uint32_t g_commandHistoryIndex;
extern char g_ExecBuffer[EXEC_BUFFER_SIZE];
void ConsoleCommandDestroy();
char* ConsoleCommandHistory(uint32_t index);
uint32_t ConsoleCommandHistoryDepth();
void ConsoleCommandInitialize();
int32_t ConsoleCommandRegister(const char* command, int32_t (*handler)(const char*, const char*), CATEGORY category, const char* helpText);
void ConsoleCommandUnregister(const char* command);
#endif

View File

@ -0,0 +1,24 @@
#include "console/CommandHandlers.hpp"
int32_t ConsoleCommand_Help(const char* command, const char* arguments) {
// TODO
return 0;
}
int32_t ConsoleCommand_Quit(const char* command, const char* arguments) {
// TODO
// ConsolePostClose()
return 0;
}
int32_t ConsoleCommand_SetMap(const char* command, const char* arguments) {
return 1;
}
int32_t ConsoleCommand_Ver(const char* command, const char* arguments) {
// TODO
return 0;
}

View File

@ -0,0 +1,14 @@
#ifndef CONSOLE_COMMAND_HANDLERS_HPP
#define CONSOLE_COMMAND_HANDLERS_HPP
#include <cstdint>
int32_t ConsoleCommand_Help(const char* command, const char* arguments);
int32_t ConsoleCommand_Quit(const char* command, const char* arguments);
int32_t ConsoleCommand_SetMap(const char* command, const char* arguments);
int32_t ConsoleCommand_Ver(const char* command, const char* arguments);
#endif

38
src/console/Console.cpp Normal file
View File

@ -0,0 +1,38 @@
#include "console/Console.hpp"
static int32_t s_active;
static int32_t s_consoleAccessEnabled;
static KEY s_consoleKey = KEY_TILDE;
static CONSOLERESIZESTATE s_consoleResizeState = CS_NONE;
int32_t ConsoleAccessGetEnabled() {
return s_consoleAccessEnabled;
}
void ConsoleAccessSetEnabled(int32_t enable) {
s_consoleAccessEnabled = enable;
}
int32_t ConsoleGetActive() {
return s_active;
}
KEY ConsoleGetHotKey() {
return s_consoleKey;
}
CONSOLERESIZESTATE ConsoleGetResizeState() {
return s_consoleResizeState;
}
void ConsoleSetActive(int32_t active) {
s_active = active;
}
void ConsoleSetHotKey(KEY hotkey) {
s_consoleKey = hotkey;
}
void ConsoleSetResizeState(CONSOLERESIZESTATE state) {
s_consoleResizeState = state;
}

24
src/console/Console.hpp Normal file
View File

@ -0,0 +1,24 @@
#ifndef CONSOLE_CONSOLE_HPP
#define CONSOLE_CONSOLE_HPP
#include "console/Types.hpp"
#include "event/Types.hpp"
#include <cstdint>
int32_t ConsoleAccessGetEnabled();
void ConsoleAccessSetEnabled(int32_t enable);
int32_t ConsoleGetActive();
KEY ConsoleGetHotKey();
CONSOLERESIZESTATE ConsoleGetResizeState();
void ConsoleSetActive(int32_t active);
void ConsoleSetHotKey(KEY hotkey);
void ConsoleSetResizeState(CONSOLERESIZESTATE state);
#endif // ifndef CONSOLE_CONSOLE_HPP

View File

@ -1,8 +1,9 @@
#include "client/Console.hpp"
#include "console/Device.hpp"
#include "client/Gui.hpp"
#include "console/Console.hpp"
#include "console/CVar.hpp"
#include "event/Input.hpp"
#include "gx/Device.hpp"
#include "util/CVar.hpp"
#include <cstring>
CVar* s_cvGxMaximize;
@ -141,20 +142,15 @@ void SetGxCVars(const CGxFormat& format) {
UpdateGxCVars();
}
void ConsoleInitializeClientCommand() {
// TODO
}
void ConsoleInitializeClientCVar(const char* a1) {
// TODO
}
void ConsoleDeviceInitialize(const char* title) {
// TODO
// TODO proper logic
s_hwDetect = true;
// TODO ConsoleAccessSetEnabled(CmdLineGetBool(35));
ConsoleAccessSetEnabled(1);
// TODO
RegisterGxCVars();

12
src/console/Device.hpp Normal file
View File

@ -0,0 +1,12 @@
#ifndef CONSOLE_DEVICE_HPP
#define CONSOLE_DEVICE_HPP
#include "gx/CGxFormat.hpp"
struct DefaultSettings {
CGxFormat format;
};
void ConsoleDeviceInitialize(const char* title);
#endif

View File

@ -0,0 +1,80 @@
#include "console/Console.hpp"
#include "console/EventHandlers.hpp"
#include "console/Screen.hpp"
#include "event/Event.hpp"
#include <cstdint>
namespace {
int32_t OnChar(const EVENT_DATA_CHAR* data, void* param) {
// TODO
return 1;
}
int32_t OnIdle(const EVENT_DATA_IDLE* data, void* param) {
// TODO repeat buffer logic
ConsoleScreenAnimate(data->elapsedSec);
return 1;
}
int32_t OnKeyDown(const EVENT_DATA_KEY* data, void* param) {
if (data->key == ConsoleGetHotKey() && ConsoleAccessGetEnabled()) {
// Toggle the console on/off if the console hotkey is pressed down
// and the console access is enabled for the client
ConsoleSetActive(!ConsoleGetActive());
// Reset the highlight when toggled off
if (!ConsoleGetActive()) {
// TODO ResetHighlight();
}
return 0;
}
if (EventIsKeyDown(ConsoleGetHotKey()) || !ConsoleGetActive()) {
return 1;
}
// TODO
return 0;
}
int32_t OnKeyDownRepeat(const EVENT_DATA_KEY* data, void* param) {
// TODO
return 1;
}
int32_t OnKeyUp(const EVENT_DATA_KEY* data, void* param) {
// TODO
return 1;
}
int32_t OnMouseDown(const EVENT_DATA_MOUSE* data, void* param) {
// TODO
return 1;
}
int32_t OnMouseMove(const EVENT_DATA_MOUSE* data, void* param) {
// TODO
return 1;
}
int32_t OnMouseUp(const EVENT_DATA_MOUSE* data, void* param) {
// TODO
return 1;
}
}
void RegisterHandlers() {
EventRegisterEx(EVENT_ID_CHAR, reinterpret_cast<EVENTHANDLERFUNC>(OnChar), nullptr, 7.0f);
EventRegisterEx(EVENT_ID_IDLE, reinterpret_cast<EVENTHANDLERFUNC>(OnIdle), nullptr, 7.0f);
EventRegisterEx(EVENT_ID_KEYDOWN, reinterpret_cast<EVENTHANDLERFUNC>(OnKeyDown), nullptr, 7.0f);
EventRegisterEx(EVENT_ID_KEYUP, reinterpret_cast<EVENTHANDLERFUNC>(OnKeyUp), nullptr, 7.0f);
EventRegisterEx(EVENT_ID_KEYDOWN_REPEATING, reinterpret_cast<EVENTHANDLERFUNC>(OnKeyDownRepeat), nullptr, 7.0f);
EventRegisterEx(EVENT_ID_MOUSEDOWN, reinterpret_cast<EVENTHANDLERFUNC>(OnMouseDown), nullptr, 7.0f);
EventRegisterEx(EVENT_ID_MOUSEUP, reinterpret_cast<EVENTHANDLERFUNC>(OnMouseUp), nullptr, 7.0f);
EventRegisterEx(EVENT_ID_MOUSEMOVE, reinterpret_cast<EVENTHANDLERFUNC>(OnMouseMove), nullptr, 7.0f);
}

View File

@ -0,0 +1,6 @@
#ifndef CONSOLE_EVENT_HANDLERS_HPP
#define CONSOLE_EVENT_HANDLERS_HPP
void RegisterHandlers();
#endif

View File

@ -0,0 +1,30 @@
#include "console/Initialize.hpp"
#include "console/Command.hpp"
#include "console/CommandHandlers.hpp"
#include "console/CVar.hpp"
static const char* s_filename;
void ConsoleInitializeCommonCommand() {
ConsoleCommandRegister("quit", ConsoleCommand_Quit, DEFAULT, NOHELP);
ConsoleCommandRegister("ver", ConsoleCommand_Ver, DEFAULT, NOHELP);
ConsoleCommandRegister("setmap", ConsoleCommand_SetMap, DEFAULT, NOHELP);
}
void ConsoleInitializeDebugCommand() {
// Unknown without debug build
}
void ConsoleInitializeClientCommand() {
ConsoleCommandInitialize();
ConsoleInitializeCommonCommand();
ConsoleInitializeDebugCommand();
}
void ConsoleInitializeClientCVar(const char* filename) {
s_filename = filename;
CVar::Initialize();
CVar::Load(s_filename);
}

View File

@ -0,0 +1,8 @@
#ifndef CONSOLE_INITIALIZE_HPP
#define CONSOLE_INITIALIZE_HPP
void ConsoleInitializeClientCommand();
void ConsoleInitializeClientCVar(const char* filename);
#endif

137
src/console/Screen.cpp Normal file
View File

@ -0,0 +1,137 @@
#include "console/Screen.hpp"
#include "console/Console.hpp"
#include "console/EventHandlers.hpp"
#include "console/Types.hpp"
#include "gx/Buffer.hpp"
#include "gx/Coordinate.hpp"
#include "gx/Device.hpp"
#include "gx/Draw.hpp"
#include "gx/Font.hpp"
#include "gx/Gx.hpp"
#include "gx/RenderState.hpp"
#include "gx/Screen.hpp"
#include <storm/String.hpp>
#include <tempest/Rect.hpp>
#include <algorithm>
static CGxStringBatch* s_batch;
static float s_caretpixwidth;
static float s_caretpixheight;
static float s_consoleLines = 10.0f;
static float s_fontHeight = 0.02f;
static float s_consoleHeight = s_consoleLines * s_fontHeight;
static char s_fontName[STORM_MAX_PATH];
static int32_t s_highlightState;
static HLAYER s_layerBackground;
static HLAYER s_layerText;
static RECTF s_rect = { 0.0f, 1.0f, 1.0f, 1.0f };
static HTEXTFONT s_textFont;
static CImVector s_colorArray[] = {
{ 0xFF, 0xFF, 0xFF, 0xFF }, // DEFAULT_COLOR
{ 0xFF, 0xFF, 0xFF, 0xFF }, // INPUT_COLOR
{ 0x80, 0x80, 0x80, 0xFF }, // ECHO_COLOR
{ 0x00, 0x00, 0xFF, 0xFF }, // ERROR_COLOR
{ 0x00, 0xFF, 0xFF, 0xFF }, // WARNING_COLOR
{ 0xFF, 0xFF, 0xFF, 0xFF }, // GLOBAL_COLOR
{ 0xFF, 0xFF, 0xFF, 0xFF }, // ADMIN_COLOR
{ 0xFF, 0xFF, 0xFF, 0x80 }, // HIGHLIGHT_COLOR
{ 0x00, 0x00, 0x00, 0xC0 }, // BACKGROUND_COLOR
};
void DrawBackground() {
uint16_t indices[] = {
0, 1, 2, 3
};
C3Vector position[] = {
{ s_rect.left, s_rect.bottom, 0.0f },
{ s_rect.right, s_rect.bottom, 0.0f },
{ s_rect.left, s_rect.top, 0.0f },
{ s_rect.right, s_rect.top, 0.0f }
};
GxRsPush();
GxRsSet(GxRs_Lighting, 0);
GxRsSet(GxRs_Fog, 0);
GxRsSet(GxRs_DepthTest, 0);
GxRsSet(GxRs_DepthWrite, 0);
GxRsSet(GxRs_Culling, 0);
GxRsSet(GxRs_PolygonOffset, 0.0f);
GxRsSet(GxRs_BlendingMode, GxBlend_Alpha);
GxRsSet(GxRs_AlphaRef, CGxDevice::s_alphaRef[GxBlend_Alpha]);
GxPrimLockVertexPtrs(4, position, sizeof(C3Vector), nullptr, 0, &s_colorArray[BACKGROUND_COLOR], 0, nullptr, 0, nullptr, 0, nullptr, 0);
GxDrawLockedElements(GxPrim_TriangleStrip, 4, indices);
GxPrimUnlockVertexPtrs();
GxRsPop();
}
void DrawHighLight() {
// TODO
}
void PaintBackground(void* param, const RECTF* rect, const RECTF* visible, float elapsedSec) {
if (s_rect.bottom < 1.0f) {
DrawBackground();
if (s_highlightState) {
DrawHighLight();
}
}
}
void PaintText(void* param, const RECTF* rect, const RECTF* visible, float elapsedSec) {
// TODO
}
void ConsoleScreenAnimate(float elapsedSec) {
auto finalPos = ConsoleGetActive() ? std::min(1.0f - s_consoleHeight, 1.0f) : 1.0f;
finalPos = std::max(finalPos, 0.0f);
if (s_rect.bottom == finalPos) {
return;
}
auto currentPos = finalPos;
if (ConsoleGetResizeState() == CS_NONE) {
auto direction = s_rect.bottom <= finalPos ? 1.0f : -1.0f;
currentPos = s_rect.bottom + direction * elapsedSec * 5.0f;
currentPos = ConsoleGetActive() ? std::max(currentPos, finalPos) : std::min(currentPos, finalPos);
}
s_rect.bottom = currentPos;
ScrnLayerSetRect(s_layerBackground, &s_rect);
ScrnLayerSetRect(s_layerText, &s_rect);
}
void ConsoleScreenInitialize(const char* title) {
CRect windowSize;
GxCapsWindowSize(windowSize);
auto width = windowSize.maxX - windowSize.minX;
auto height = windowSize.maxY - windowSize.minY;
s_caretpixwidth = width == 0.0f ? 1.0f : 1.0f / width;
s_caretpixheight = height == 0.0f ? 1.0f : 1.0f / height;
SStrCopy(s_fontName, "Fonts\\ARIALN.ttf", sizeof(s_fontName));
s_textFont = TextBlockGenerateFont(s_fontName, 0, NDCToDDCHeight(s_fontHeight));
ScrnLayerCreate(&s_rect, 6.0f, 0x1 | 0x2, nullptr, PaintBackground, &s_layerBackground);
ScrnLayerCreate(&s_rect, 7.0f, 0x1 | 0x2, nullptr, PaintText, &s_layerText);
RegisterHandlers();
// TODO register commands
// TODO EventSetConfirmCloseCallback(EventCloseCallback, 0);
// TODO ConsoleCommandExecute("ver", 1);
s_batch = GxuFontCreateBatch(false, false);
}

8
src/console/Screen.hpp Normal file
View File

@ -0,0 +1,8 @@
#ifndef CONSOLE_SCREEN_HPP
#define CONSOLE_SCREEN_HPP
void ConsoleScreenAnimate(float elapsedSec);
void ConsoleScreenInitialize(const char* title);
#endif

23
src/console/Types.hpp Normal file
View File

@ -0,0 +1,23 @@
#ifndef CONSOLE_TYPES_HPP
#define CONSOLE_TYPES_HPP
enum COLOR_T {
DEFAULT_COLOR,
INPUT_COLOR,
ECHO_COLOR,
ERROR_COLOR,
WARNING_COLOR,
GLOBAL_COLOR,
ADMIN_COLOR,
HIGHLIGHT_COLOR,
BACKGROUND_COLOR,
NUM_COLORTYPES,
};
enum CONSOLERESIZESTATE {
CS_NONE,
CS_STRETCH,
NUM_CONSOLERESIZESTATES,
};
#endif

View File

@ -5,6 +5,7 @@ WowClientDB<AchievementRec> g_achievementDB;
WowClientDB<Cfg_CategoriesRec> g_cfg_CategoriesDB;
WowClientDB<Cfg_ConfigsRec> g_cfg_ConfigsDB;
WowClientDB<ChrRacesRec> g_chrRacesDB;
WowClientDB<MapRec> g_mapDB;
void LoadDB(WowClientDB_Base* db, const char* filename, int32_t linenumber) {
db->Load(filename, linenumber);
@ -15,6 +16,7 @@ void StaticDBLoadAll(void (*loadFn)(WowClientDB_Base*, const char*, int32_t)) {
loadFn(&g_cfg_CategoriesDB, __FILE__, __LINE__);
loadFn(&g_cfg_ConfigsDB, __FILE__, __LINE__);
loadFn(&g_chrRacesDB, __FILE__, __LINE__);
loadFn(&g_mapDB, __FILE__, __LINE__);
};
void ClientDBInitialize() {

View File

@ -1,16 +1,18 @@
#ifndef DB_DB_HPP
#define DB_DB_HPP
#include "db/WowClientDB.hpp"
#include "db/rec/AchievementRec.hpp"
#include "db/rec/Cfg_CategoriesRec.hpp"
#include "db/rec/Cfg_ConfigsRec.hpp"
#include "db/rec/ChrRacesRec.hpp"
#include "db/WowClientDB.hpp"
#include "db/rec/MapRec.hpp"
extern WowClientDB<AchievementRec> g_achievementDB;
extern WowClientDB<Cfg_CategoriesRec> g_cfg_CategoriesDB;
extern WowClientDB<Cfg_ConfigsRec> g_cfg_ConfigsDB;
extern WowClientDB<ChrRacesRec> g_chrRacesDB;
extern WowClientDB<MapRec> g_mapDB;
void ClientDBInitialize();

View File

@ -1,6 +1,8 @@
#ifndef DB_I_DATABASE_HPP
#define DB_I_DATABASE_HPP
#include <cstdint>
template <class T>
class IDatabase {
public:

View File

@ -1,4 +1,6 @@
// DO NOT EDIT: generated by whoa-autocode
#include "db/rec/AchievementRec.hpp"
#include "util/Locale.hpp"
#include "util/SFile.hpp"
const char* AchievementRec::GetFilename() {
@ -13,10 +15,18 @@ uint32_t AchievementRec::GetRowSize() {
return 248;
}
bool AchievementRec::NeedIDAssigned() {
return false;
}
int32_t AchievementRec::GetID() {
return this->m_ID;
}
void AchievementRec::SetID(int32_t id) {
this->m_ID = id;
}
bool AchievementRec::Read(SFile* f, const char* stringBuffer) {
uint32_t titleOfs[16];
uint32_t titleMask;
@ -30,62 +40,62 @@ bool AchievementRec::Read(SFile* f, const char* stringBuffer) {
|| !SFile::Read(f, &this->m_faction, sizeof(this->m_faction), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_instanceID, sizeof(this->m_instanceID), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_supercedes, sizeof(this->m_supercedes), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[0], sizeof(titleOfs[0]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[1], sizeof(titleOfs[1]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[2], sizeof(titleOfs[2]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[3], sizeof(titleOfs[3]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[4], sizeof(titleOfs[4]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[5], sizeof(titleOfs[5]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[6], sizeof(titleOfs[6]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[7], sizeof(titleOfs[7]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[8], sizeof(titleOfs[8]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[9], sizeof(titleOfs[9]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[10], sizeof(titleOfs[10]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[11], sizeof(titleOfs[11]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[12], sizeof(titleOfs[12]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[13], sizeof(titleOfs[13]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[14], sizeof(titleOfs[14]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[15], sizeof(titleOfs[15]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleMask, sizeof(titleMask), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[0], sizeof(descriptionOfs[0]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[1], sizeof(descriptionOfs[1]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[2], sizeof(descriptionOfs[2]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[3], sizeof(descriptionOfs[3]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[4], sizeof(descriptionOfs[4]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[5], sizeof(descriptionOfs[5]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[6], sizeof(descriptionOfs[6]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[7], sizeof(descriptionOfs[7]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[8], sizeof(descriptionOfs[8]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[9], sizeof(descriptionOfs[9]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[10], sizeof(descriptionOfs[10]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[11], sizeof(descriptionOfs[11]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[12], sizeof(descriptionOfs[12]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[13], sizeof(descriptionOfs[13]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[14], sizeof(descriptionOfs[14]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[15], sizeof(descriptionOfs[15]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionMask, sizeof(descriptionMask), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[0], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[1], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[2], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[3], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[4], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[5], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[6], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[7], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[8], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[9], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[10], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[11], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[12], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[13], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[14], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleOfs[15], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &titleMask, sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[0], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[1], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[2], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[3], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[4], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[5], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[6], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[7], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[8], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[9], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[10], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[11], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[12], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[13], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[14], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionOfs[15], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &descriptionMask, sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_category, sizeof(this->m_category), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_points, sizeof(this->m_points), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_uiOrder, sizeof(this->m_uiOrder), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_flags, sizeof(this->m_flags), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_iconID, sizeof(this->m_iconID), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[0], sizeof(rewardOfs[0]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[1], sizeof(rewardOfs[1]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[2], sizeof(rewardOfs[2]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[3], sizeof(rewardOfs[3]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[4], sizeof(rewardOfs[4]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[5], sizeof(rewardOfs[5]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[6], sizeof(rewardOfs[6]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[7], sizeof(rewardOfs[7]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[8], sizeof(rewardOfs[8]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[9], sizeof(rewardOfs[9]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[10], sizeof(rewardOfs[10]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[11], sizeof(rewardOfs[11]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[12], sizeof(rewardOfs[12]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[13], sizeof(rewardOfs[13]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[14], sizeof(rewardOfs[14]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[15], sizeof(rewardOfs[15]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardMask, sizeof(rewardMask), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[0], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[1], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[2], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[3], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[4], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[5], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[6], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[7], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[8], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[9], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[10], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[11], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[12], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[13], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[14], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardOfs[15], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &rewardMask, sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_minimumCriteria, sizeof(this->m_minimumCriteria), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_sharesCriteria, sizeof(this->m_sharesCriteria), nullptr, nullptr, nullptr)
) {
@ -93,9 +103,9 @@ bool AchievementRec::Read(SFile* f, const char* stringBuffer) {
}
if (stringBuffer) {
this->m_title = &stringBuffer[titleOfs[0]];
this->m_description = &stringBuffer[descriptionOfs[0]];
this->m_reward = &stringBuffer[rewardOfs[0]];
this->m_title = &stringBuffer[titleOfs[CURRENT_LANGUAGE]];
this->m_description = &stringBuffer[descriptionOfs[CURRENT_LANGUAGE]];
this->m_reward = &stringBuffer[rewardOfs[CURRENT_LANGUAGE]];
} else {
this->m_title = "";
this->m_description = "";

View File

@ -1,3 +1,4 @@
// DO NOT EDIT: generated by whoa-autocode
#ifndef DB_REC_ACHIEVEMENT_REC_HPP
#define DB_REC_ACHIEVEMENT_REC_HPP
@ -25,8 +26,9 @@ class AchievementRec {
static const char* GetFilename();
static uint32_t GetNumColumns();
static uint32_t GetRowSize();
static bool NeedIDAssigned();
int32_t GetID();
void SetID(int32_t id);
bool Read(SFile* f, const char* stringBuffer);
};

View File

@ -1,4 +1,6 @@
// DO NOT EDIT: generated by whoa-autocode
#include "db/rec/Cfg_CategoriesRec.hpp"
#include "util/Locale.hpp"
#include "util/SFile.hpp"
const char* Cfg_CategoriesRec::GetFilename() {
@ -13,10 +15,18 @@ uint32_t Cfg_CategoriesRec::GetRowSize() {
return 84;
}
bool Cfg_CategoriesRec::NeedIDAssigned() {
return false;
}
int32_t Cfg_CategoriesRec::GetID() {
return this->m_ID;
}
void Cfg_CategoriesRec::SetID(int32_t id) {
this->m_ID = id;
}
bool Cfg_CategoriesRec::Read(SFile* f, const char* stringBuffer) {
uint32_t nameOfs[16];
uint32_t nameMask;
@ -26,29 +36,29 @@ bool Cfg_CategoriesRec::Read(SFile* f, const char* stringBuffer) {
|| !SFile::Read(f, &this->m_localeMask, sizeof(this->m_localeMask), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_createCharsetMask, sizeof(this->m_createCharsetMask), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_flags, sizeof(this->m_flags), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[0], sizeof(nameOfs[0]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[1], sizeof(nameOfs[1]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[2], sizeof(nameOfs[2]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[3], sizeof(nameOfs[3]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[4], sizeof(nameOfs[4]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[5], sizeof(nameOfs[5]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[6], sizeof(nameOfs[6]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[7], sizeof(nameOfs[7]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[8], sizeof(nameOfs[8]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[9], sizeof(nameOfs[9]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[10], sizeof(nameOfs[10]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[11], sizeof(nameOfs[11]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[12], sizeof(nameOfs[12]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[13], sizeof(nameOfs[13]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[14], sizeof(nameOfs[14]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[15], sizeof(nameOfs[15]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameMask, sizeof(nameMask), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[0], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[1], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[2], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[3], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[4], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[5], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[6], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[7], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[8], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[9], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[10], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[11], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[12], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[13], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[14], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameOfs[15], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &nameMask, sizeof(uint32_t), nullptr, nullptr, nullptr)
) {
return false;
}
if (stringBuffer) {
this->m_name = &stringBuffer[nameOfs[0]];
this->m_name = &stringBuffer[nameOfs[CURRENT_LANGUAGE]];
} else {
this->m_name = "";
}

View File

@ -1,3 +1,4 @@
// DO NOT EDIT: generated by whoa-autocode
#ifndef DB_REC_CFG_CATEGORIES_REC_HPP
#define DB_REC_CFG_CATEGORIES_REC_HPP
@ -11,13 +12,14 @@ class Cfg_CategoriesRec {
int32_t m_localeMask;
int32_t m_createCharsetMask;
int32_t m_flags;
const char *m_name;
const char* m_name;
static const char* GetFilename();
static uint32_t GetNumColumns();
static uint32_t GetRowSize();
static bool NeedIDAssigned();
int32_t GetID();
void SetID(int32_t id);
bool Read(SFile* f, const char* stringBuffer);
};

View File

@ -1,4 +1,6 @@
// DO NOT EDIT: generated by whoa-autocode
#include "db/rec/Cfg_ConfigsRec.hpp"
#include "util/Locale.hpp"
#include "util/SFile.hpp"
const char* Cfg_ConfigsRec::GetFilename() {
@ -13,10 +15,18 @@ uint32_t Cfg_ConfigsRec::GetRowSize() {
return 16;
}
bool Cfg_ConfigsRec::NeedIDAssigned() {
return false;
}
int32_t Cfg_ConfigsRec::GetID() {
return this->m_ID;
}
void Cfg_ConfigsRec::SetID(int32_t id) {
this->m_ID = id;
}
bool Cfg_ConfigsRec::Read(SFile* f, const char* stringBuffer) {
if (
!SFile::Read(f, &this->m_ID, sizeof(this->m_ID), nullptr, nullptr, nullptr)

View File

@ -1,3 +1,4 @@
// DO NOT EDIT: generated by whoa-autocode
#ifndef DB_REC_CFG_CONFIGS_REC_HPP
#define DB_REC_CFG_CONFIGS_REC_HPP
@ -15,8 +16,9 @@ class Cfg_ConfigsRec {
static const char* GetFilename();
static uint32_t GetNumColumns();
static uint32_t GetRowSize();
static bool NeedIDAssigned();
int32_t GetID();
void SetID(int32_t id);
bool Read(SFile* f, const char* stringBuffer);
};

View File

@ -1,5 +1,6 @@
// DO NOT EDIT: generated by whoa-autocode
#include "db/rec/ChrRacesRec.hpp"
#include "util/Locale.hpp"
#include "util/SFile.hpp"
const char* ChrRacesRec::GetFilename() {
@ -115,9 +116,9 @@ bool ChrRacesRec::Read(SFile* f, const char* stringBuffer) {
if (stringBuffer) {
this->m_clientPrefix = &stringBuffer[clientPrefixOfs];
this->m_clientFileString = &stringBuffer[clientFileStringOfs];
this->m_name = &stringBuffer[nameOfs[0]];
this->m_nameFemale = &stringBuffer[nameFemaleOfs[0]];
this->m_nameMale = &stringBuffer[nameMaleOfs[0]];
this->m_name = &stringBuffer[nameOfs[CURRENT_LANGUAGE]];
this->m_nameFemale = &stringBuffer[nameFemaleOfs[CURRENT_LANGUAGE]];
this->m_nameMale = &stringBuffer[nameMaleOfs[CURRENT_LANGUAGE]];
this->m_facialHairCustomization[0] = &stringBuffer[facialHairCustomizationOfs[0]];
this->m_facialHairCustomization[1] = &stringBuffer[facialHairCustomizationOfs[1]];
this->m_hairCustomization = &stringBuffer[hairCustomizationOfs];

123
src/db/rec/MapRec.cpp Normal file
View File

@ -0,0 +1,123 @@
// DO NOT EDIT: generated by whoa-autocode
#include "db/rec/MapRec.hpp"
#include "util/Locale.hpp"
#include "util/SFile.hpp"
const char* MapRec::GetFilename() {
return "DBFilesClient\\Map.dbc";
}
uint32_t MapRec::GetNumColumns() {
return 66;
}
uint32_t MapRec::GetRowSize() {
return 264;
}
bool MapRec::NeedIDAssigned() {
return false;
}
int32_t MapRec::GetID() {
return this->m_ID;
}
void MapRec::SetID(int32_t id) {
this->m_ID = id;
}
bool MapRec::Read(SFile* f, const char* stringBuffer) {
uint32_t directoryOfs;
uint32_t mapNameOfs[16];
uint32_t mapNameMask;
uint32_t mapDescription0Ofs[16];
uint32_t mapDescription0Mask;
uint32_t mapDescription1Ofs[16];
uint32_t mapDescription1Mask;
if (
!SFile::Read(f, &this->m_ID, sizeof(this->m_ID), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &directoryOfs, sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_instanceType, sizeof(this->m_instanceType), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_flags, sizeof(this->m_flags), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_pvp, sizeof(this->m_pvp), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapNameOfs[0], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapNameOfs[1], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapNameOfs[2], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapNameOfs[3], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapNameOfs[4], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapNameOfs[5], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapNameOfs[6], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapNameOfs[7], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapNameOfs[8], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapNameOfs[9], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapNameOfs[10], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapNameOfs[11], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapNameOfs[12], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapNameOfs[13], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapNameOfs[14], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapNameOfs[15], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapNameMask, sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_areaTableID, sizeof(this->m_areaTableID), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription0Ofs[0], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription0Ofs[1], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription0Ofs[2], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription0Ofs[3], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription0Ofs[4], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription0Ofs[5], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription0Ofs[6], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription0Ofs[7], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription0Ofs[8], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription0Ofs[9], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription0Ofs[10], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription0Ofs[11], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription0Ofs[12], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription0Ofs[13], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription0Ofs[14], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription0Ofs[15], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription0Mask, sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription1Ofs[0], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription1Ofs[1], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription1Ofs[2], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription1Ofs[3], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription1Ofs[4], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription1Ofs[5], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription1Ofs[6], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription1Ofs[7], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription1Ofs[8], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription1Ofs[9], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription1Ofs[10], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription1Ofs[11], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription1Ofs[12], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription1Ofs[13], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription1Ofs[14], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription1Ofs[15], sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &mapDescription1Mask, sizeof(uint32_t), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_loadingScreenID, sizeof(this->m_loadingScreenID), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_minimapIconScale, sizeof(this->m_minimapIconScale), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_corpseMapID, sizeof(this->m_corpseMapID), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_corpse[0], sizeof(m_corpse[0]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_corpse[1], sizeof(m_corpse[0]), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_timeOfDayOverride, sizeof(this->m_timeOfDayOverride), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_expansionID, sizeof(this->m_expansionID), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_raidOffset, sizeof(this->m_raidOffset), nullptr, nullptr, nullptr)
|| !SFile::Read(f, &this->m_maxPlayers, sizeof(this->m_maxPlayers), nullptr, nullptr, nullptr)
) {
return false;
}
if (stringBuffer) {
this->m_directory = &stringBuffer[directoryOfs];
this->m_mapName = &stringBuffer[mapNameOfs[CURRENT_LANGUAGE]];
this->m_mapDescription0 = &stringBuffer[mapDescription0Ofs[CURRENT_LANGUAGE]];
this->m_mapDescription1 = &stringBuffer[mapDescription1Ofs[CURRENT_LANGUAGE]];
} else {
this->m_directory = "";
this->m_mapName = "";
this->m_mapDescription0 = "";
this->m_mapDescription1 = "";
}
return true;
}

38
src/db/rec/MapRec.hpp Normal file
View File

@ -0,0 +1,38 @@
// DO NOT EDIT: generated by whoa-autocode
#ifndef DB_REC_MAP_REC_HPP
#define DB_REC_MAP_REC_HPP
#include <cstdint>
class SFile;
class MapRec {
public:
int32_t m_ID;
const char* m_directory;
int32_t m_instanceType;
int32_t m_flags; // unconfirmed
int32_t m_pvp;
const char* m_mapName;
int32_t m_areaTableID;
const char* m_mapDescription0;
const char* m_mapDescription1;
int32_t m_loadingScreenID;
float m_minimapIconScale;
int32_t m_corpseMapID;
float m_corpse[2];
int32_t m_timeOfDayOverride;
int32_t m_expansionID;
int32_t m_raidOffset;
int32_t m_maxPlayers;
static const char* GetFilename();
static uint32_t GetNumColumns();
static uint32_t GetRowSize();
static bool NeedIDAssigned();
int32_t GetID();
void SetID(int32_t id);
bool Read(SFile* f, const char* stringBuffer);
};
#endif

View File

@ -4,10 +4,8 @@
#include "event/Input.hpp"
#include "event/Queue.hpp"
#include "event/Scheduler.hpp"
#include <cstring>
#include <common/Prop.hpp>
#include <common/Time.hpp>
#include <storm/String.hpp>
SEvent Event::s_startEvent = SEvent(1, 0);
SEvent Event::s_shutdownEvent = SEvent(1, 0);
@ -71,6 +69,14 @@ void EventDoMessageLoop() {
IEvtSchedulerProcess();
}
HEVENTCONTEXT EventGetCurrentContext() {
return PropGet(PROP_EVENTCONTEXT);
}
void EventPostClose() {
EventPostCloseEx(nullptr);
}
void EventPostCloseEx(HEVENTCONTEXT contextHandle) {
if (!contextHandle) {
contextHandle = PropGet(PROP_EVENTCONTEXT);
@ -109,12 +115,11 @@ void EventRegister(EVENTID id, EVENTHANDLERFUNC handler) {
}
void EventRegisterEx(EVENTID id, EVENTHANDLERFUNC handler, void* param, float priority) {
STORM_ASSERT(id >= 0);
STORM_VALIDATE(id >= 0, ERROR_INVALID_PARAMETER);
STORM_ASSERT(id < EVENTIDS);
STORM_VALIDATE(id < EVENTIDS, ERROR_INVALID_PARAMETER);
STORM_ASSERT(handler);
STORM_VALIDATE(handler, ERROR_INVALID_PARAMETER);
STORM_VALIDATE_BEGIN;
STORM_VALIDATE(id >= 0);
STORM_VALIDATE(id < EVENTIDS);
STORM_VALIDATE(handler);
STORM_VALIDATE_END_VOID;
HEVENTCONTEXT hContext = PropGet(PROP_EVENTCONTEXT);

View File

@ -37,6 +37,8 @@ HEVENTCONTEXT EventCreateContextEx(int32_t interactive, int32_t (*initializeHand
void EventDoMessageLoop();
HEVENTCONTEXT EventGetCurrentContext();
void EventInitialize(int32_t threadCount, int32_t netServer);
void EventInitiateShutdown();
@ -47,6 +49,8 @@ int32_t EventIsKeyDown(KEY key);
int32_t EventIsShiftKeyDown();
void EventPostClose();
void EventPostCloseEx(HEVENTCONTEXT contextHandle);
void EventRegister(EVENTID id, int32_t (*handler)(const void*, void*));

View File

@ -192,8 +192,9 @@ void PostSize(EvtContext* context, int32_t w, int32_t h) {
}
void ProcessInput(const int32_t param[], OSINPUT id, int32_t* shutdown, EvtContext* context) {
STORM_ASSERT(context);
STORM_VALIDATE(context, ERROR_INVALID_PARAMETER);
STORM_VALIDATE_BEGIN;
STORM_VALIDATE(context);
STORM_VALIDATE_END_VOID;
switch (id) {
case OS_INPUT_CAPTURE_CHANGED:
@ -361,8 +362,9 @@ void ConvertPosition(int32_t clientx, int32_t clienty, float* x, float* y) {
}
void EventSetMouseMode(MOUSEMODE mode, uint32_t holdButton) {
STORM_ASSERT(mode < MOUSE_MODES);
STORM_VALIDATE(mode < MOUSE_MODES, ERROR_INVALID_PARAMETER);
STORM_VALIDATE_BEGIN;
STORM_VALIDATE(mode < MOUSE_MODES);
STORM_VALIDATE_END_VOID;
auto contextId = *reinterpret_cast<uint32_t*>(PropGet(PROP_EVENTCONTEXT));
int32_t findMask;
@ -468,8 +470,9 @@ void IEvtInputInitialize() {
}
int32_t IEvtInputProcess(EvtContext* context, int32_t* shutdown) {
STORM_ASSERT(context);
STORM_VALIDATE(context, ERROR_INVALID_PARAMETER, 0);
STORM_VALIDATE_BEGIN;
STORM_VALIDATE(context);
STORM_VALIDATE_END;
int32_t v4 = 0;
OSINPUT id;
@ -484,8 +487,9 @@ int32_t IEvtInputProcess(EvtContext* context, int32_t* shutdown) {
}
void IEvtInputSetMouseMode(EvtContext* context, MOUSEMODE mode, uint32_t holdButton) {
STORM_ASSERT(context);
STORM_VALIDATE(context, ERROR_INVALID_PARAMETER);
STORM_VALIDATE_BEGIN;
STORM_VALIDATE(context);
STORM_VALIDATE_END_VOID;
if ((Input::s_buttonState & holdButton) == holdButton) {
Input::s_mouseHoldButton = holdButton;

View File

@ -63,5 +63,5 @@ void IEvtQueueRegister(EvtContext* context, EVENTID id, int32_t (*handler)(const
h = handlerList->Link(h)->Next();
}
handlerList->LinkNode(evtHandler, 1, h);
handlerList->LinkNode(evtHandler, 2, h);
}

View File

@ -159,7 +159,99 @@ int32_t ConvertKeyCode(uint32_t vkey, KEY* key) {
return 1;
}
// TODO remaining vkeys
case VK_SNAPSHOT: {
*key = KEY_PRINTSCREEN;
return 1;
}
case VK_INSERT: {
*key = KEY_INSERT;
return 1;
}
case VK_DELETE: {
*key = KEY_DELETE;
return 1;
}
case VK_NUMPAD0:
case VK_NUMPAD1:
case VK_NUMPAD2:
case VK_NUMPAD3:
case VK_NUMPAD4:
case VK_NUMPAD5:
case VK_NUMPAD6:
case VK_NUMPAD7:
case VK_NUMPAD8:
case VK_NUMPAD9: {
*key = static_cast<KEY>(KEY_NUMPAD0 + (vkey - VK_NUMPAD0));
return 1;
}
case VK_MULTIPLY: {
*key = KEY_NUMPAD_MULTIPLY;
return 1;
}
case VK_ADD: {
*key = KEY_NUMPAD_PLUS;
return 1;
}
case VK_SUBTRACT: {
*key = KEY_NUMPAD_MINUS;
return 1;
}
case VK_DECIMAL: {
*key = KEY_NUMPAD_DECIMAL;
return 1;
}
case VK_DIVIDE: {
*key = KEY_NUMPAD_DIVIDE;
return 1;
}
case VK_NUMLOCK: {
*key = KEY_NUMLOCK;
return 1;
}
case VK_SCROLL: {
*key = KEY_SCROLLLOCK;
return 1;
}
case VK_LSHIFT: {
*key = KEY_LSHIFT;
return 1;
}
case VK_RSHIFT: {
*key = KEY_RSHIFT;
return 1;
}
case VK_LCONTROL: {
*key = KEY_LCONTROL;
return 1;
}
case VK_RCONTROL: {
*key = KEY_RCONTROL;
return 1;
}
case VK_LMENU: {
*key = KEY_LALT;
return 1;
}
case VK_RMENU: {
*key = KEY_RALT;
return 1;
}
default: {
auto character = MapVirtualKey(vkey, MAPVK_VK_TO_CHAR);
@ -316,8 +408,9 @@ int32_t OsInputGet(OSINPUT* id, int32_t* param0, int32_t* param1, int32_t* param
}
void OsInputSetMouseMode(OS_MOUSE_MODE mode) {
STORM_ASSERT(mode < OS_MOUSE_MODES);
STORM_VALIDATE(mode < OS_MOUSE_MODES, ERROR_INVALID_PARAMETER);
STORM_VALIDATE_BEGIN;
STORM_VALIDATE(mode < OS_MOUSE_MODES);
STORM_VALIDATE_END_VOID;
if (Input::s_osMouseMode == mode) {
return;

View File

@ -1,9 +1,11 @@
#include "glue/CGlueMgr.hpp"
#include "glue/CRealmList.hpp"
#include "client/Client.hpp"
#include "client/ClientServices.hpp"
#include "console/CVar.hpp"
#include "glue/CRealmList.hpp"
#include "gx/Coordinate.hpp"
#include "gx/Device.hpp"
#include "gx/LoadingScreen.hpp"
#include "math/Utils.hpp"
#include "net/Connection.hpp"
#include "net/Login.hpp"
@ -14,11 +16,10 @@
#include "ui/FrameXML.hpp"
#include "ui/Interface.hpp"
#include "ui/ScriptFunctions.hpp"
#include "util/CVar.hpp"
#include "util/Filesystem.hpp"
#include "util/Log.hpp"
#include <cstdio>
#include <common/MD5.hpp>
#include <cstdio>
unsigned char InterfaceKey[256] = {
0xC3, 0x5B, 0x50, 0x84, 0xB9, 0x3E, 0x32, 0x42, 0x8C, 0xD0, 0xC7, 0x48, 0xFA, 0x0E, 0x5D, 0x54,
@ -202,10 +203,10 @@ int32_t CGlueMgr::Idle(const void* a1, void* a2) {
if (CGlueMgr::m_idleState == IDLE_NONE) {
if (CGlueMgr::m_reload) {
if (!CGlueMgr::m_suspended) {
// TODO CGlueMgr::Suspend();
// TODO CGlueMgr::Resume();
CGlueMgr::Suspend();
CGlueMgr::Resume();
// TODO Sub4DA360();
// TODO CGlueMgr::SetScreen(ByteB6A9E0);
CGlueMgr::SetScreen(CGlueMgr::m_currentScreen);
}
CGlueMgr::m_reload = 0;
@ -241,6 +242,11 @@ int32_t CGlueMgr::Idle(const void* a1, void* a2) {
break;
}
case IDLE_ENTER_WORLD: {
CGlueMgr::PollEnterWorld();
break;
}
// TODO other idle states
default:
@ -334,8 +340,10 @@ void CGlueMgr::LoginServerLogin(const char* accountName, const char* password) {
memset(const_cast<char*>(password), 0, SStrLen(password));
}
void CGlueMgr::QuitGame() {
ClientPostClose(0);
int32_t CGlueMgr::OnKickReasonMsg(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg) {
// TODO
return 0;
}
void CGlueMgr::PollAccountLogin(int32_t errorCode, const char* msg, int32_t complete, int32_t result, WOWCS_OPS op) {
@ -407,6 +415,29 @@ void CGlueMgr::PollAccountLogin(int32_t errorCode, const char* msg, int32_t comp
}
}
void CGlueMgr::PollEnterWorld() {
if (!LoadingScreenDrawing()) {
return;
}
if (CGlueMgr::m_suspended) {
CGlueMgr::m_idleState = IDLE_NONE;
CGlueMgr::m_showedDisconnect = 0;
// TODO SI Logic
// TODO ClientConnection::CharacterLogin()
return;
}
// TODO Get map ID and position from character info
uint32_t mapId = 0;
C3Vector position = { 0.0f, 0.0f, 0.0f };
CGlueMgr::Suspend();
ClientInitializeGame(mapId, position);
}
void CGlueMgr::PollLoginServerLogin() {
if (CGlueMgr::m_loginState != LOGIN_STATE_PIN_WAIT) {
CGlueMgr::DisplayLoginStatus();
@ -468,6 +499,10 @@ void CGlueMgr::PollLoginServerLogin() {
}
}
void CGlueMgr::QuitGame() {
ClientPostClose(0);
}
void CGlueMgr::Resume() {
// TODO
// CGlueMgr::m_disconnectPending = 0;
@ -655,7 +690,7 @@ void CGlueMgr::StatusDialogClick() {
case IDLE_4:
case IDLE_5:
case IDLE_6:
case IDLE_10: {
case IDLE_ENTER_WORLD: {
ClientServices::Connection()->Cancel(2);
CGlueMgr::m_showedDisconnect = 0;
@ -703,6 +738,19 @@ void CGlueMgr::Sub4D8BA0() {
}
void CGlueMgr::Suspend() {
CGlueMgr::m_suspended = 1;
// TODO
if (CGlueMgr::m_simpleTop) {
delete CGlueMgr::m_simpleTop;
CGlueMgr::m_simpleTop = nullptr;
}
// TODO
FrameXML_FreeHashNodes();
// TODO
}

View File

@ -5,6 +5,7 @@
#include "net/Types.hpp"
#include <cstdint>
class CDataStore;
class CSimpleTop;
class CGlueMgr {
@ -21,7 +22,7 @@ class CGlueMgr {
IDLE_7 = 7,
IDLE_8 = 8,
IDLE_9 = 9,
IDLE_10 = 10,
IDLE_ENTER_WORLD = 10,
IDLE_11 = 11,
IDLE_12 = 12,
IDLE_13 = 13
@ -62,9 +63,11 @@ class CGlueMgr {
static int32_t Idle(const void* a1, void* a2);
static void Initialize();
static void LoginServerLogin(const char* accountName, const char* password);
static void QuitGame();
static int32_t OnKickReasonMsg(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg);
static void PollAccountLogin(int32_t errorCode, const char* msg, int32_t complete, int32_t result, WOWCS_OPS op);
static void PollEnterWorld();
static void PollLoginServerLogin();
static void QuitGame();
static void Resume();
static void SetCurrentAccount(const char* accountName);
static void SetLoginStateAndResult(LOGIN_STATE state, LOGIN_RESULT result, char const* addrStr, char const* stateStr, char const* resultStr, uint8_t flags);

View File

@ -12,6 +12,7 @@ target_include_directories(glue
target_link_libraries(glue
PRIVATE
client
console
db
event
gx

View File

@ -1,5 +1,8 @@
#include "gx/Buffer.hpp"
#include "gx/Device.hpp"
#include "gx/Gx.hpp"
#include "gx/CGxBatch.hpp"
#include <bc/Debug.hpp>
CGxVertexAttrib vertexAttribsP[] = {
{ GxVA_Position, 4, GxVertexAttribOffset(GxVBF_P, GxVA_Position), 12 }
@ -179,6 +182,8 @@ int32_t Buffer::s_vertexBufOffset[GxVertexBufferFormats_Last][GxVAs_Last] = {
{ 0, -1, -1, 12, 24, 28, 32, 40, -1, -1, -1, -1, -1, -1 }
};
uint32_t Buffer::s_lockVertexCount = 0;
uint32_t GxVertexAttribOffset(EGxVertexBufferFormat format, EGxVertexAttrib attrib) {
return Buffer::s_vertexBufOffset[format][attrib];
}
@ -187,6 +192,15 @@ CGxBuf* GxBufCreate(CGxPool* pool, uint32_t itemSize, uint32_t itemCount, uint32
return g_theGxDevicePtr->BufCreate(pool, itemSize, itemCount, index);
}
void GxBufData(CGxBuf* buf, const void* data, uint32_t size, uint32_t offset) {
if (size == 0) {
size = buf->m_itemSize * buf->m_itemCount;
}
g_theGxDevicePtr->BufData(buf, data, size, offset);
buf->unk1C = 1;
}
char* GxBufLock(CGxBuf* buf) {
return g_theGxDevicePtr->BufLock(buf);
}
@ -204,6 +218,16 @@ void GxPrimIndexPtr(CGxBuf* buf) {
g_theGxDevicePtr->PrimIndexPtr(buf);
}
void GxPrimIndexPtr(uint32_t indexCount, const uint16_t* indices) {
auto buf = g_theGxDevicePtr->BufStream(GxPoolTarget_Index, 2, indexCount);
g_theGxDevicePtr->BufData(buf, indices, buf->m_itemCount * buf->m_itemSize, 0);
buf->unk1C = 1;
g_theGxDevicePtr->PrimIndexPtr(buf);
}
void GxPrimVertexPtr(CGxBuf* buf, EGxVertexBufferFormat format) {
auto desc = &Buffer::s_vertexBufDesc[format];
@ -211,3 +235,126 @@ void GxPrimVertexPtr(CGxBuf* buf, EGxVertexBufferFormat format) {
g_theGxDevicePtr->PrimVertexMask(desc->mask);
g_theGxDevicePtr->PrimVertexPtr(buf, format);
}
void GxPrimVertexPtr(uint32_t vertexCount, const C3Vector* pos, uint32_t posStride, const C3Vector* normal, uint32_t normalStride, const CImVector* color, uint32_t colorStride, const C2Vector* tex0, uint32_t tex0Stride, const C2Vector* tex1, uint32_t tex1Stride) {
// Select vertex buffer format based on given parameters
auto format = GxVBF_P;
if (pos && normal && color) {
format = GxVBF_PNC;
if (tex0 && tex1) {
format = GxVBF_PNCT2;
} else if (tex0) {
format = GxVBF_PNCT;
}
} else if (pos && normal) {
format = GxVBF_PN;
if (tex0 && tex1) {
format = GxVBF_PNT2;
} else if (tex0) {
format = GxVBF_PNT;
}
} else if (pos && color) {
format = GxVBF_PC;
if (tex0 && tex1) {
format = GxVBF_PCT2;
} else if (tex0) {
format = GxVBF_PCT;
}
} else if (pos) {
if (tex0 && tex1) {
format = GxVBF_PT2;
} else if (tex0) {
format = GxVBF_PT;
}
}
auto vertexSize = Buffer::s_vertexBufDesc[format].size;
auto buf = g_theGxDevicePtr->BufStream(GxPoolTarget_Vertex, vertexSize, vertexCount);
auto bufData = g_theGxDevicePtr->BufLock(buf);
C3Vector emptyNormal = { 0.0f, 0.0f, 0.0f };
CImVector emptyColor = { 0x00, 0x00, 0x00, 0x00 };
C2Vector emptyTex0 = { 0.0f, 0.0f };
C2Vector emptyTex1 = { 0.0f, 0.0f };
auto bufPos = reinterpret_cast<C3Vector*>(bufData + GxVertexAttribOffset(format, GxVA_Position));
auto bufPosStride = vertexSize;
auto bufNormal = reinterpret_cast<C3Vector*>(bufData + GxVertexAttribOffset(format, GxVA_Normal));
auto bufNormalStride = vertexSize;
if (!normal) {
normal = &emptyNormal;
normalStride = 0;
bufNormal = &emptyNormal;
bufNormalStride = 0;
}
auto bufColor = reinterpret_cast<CImVector*>(bufData + GxVertexAttribOffset(format, GxVA_Color0));
auto bufColorStride = vertexSize;
if (!color) {
color = &emptyColor;
colorStride = 0;
bufColor = &emptyColor;
bufColorStride = 0;
}
auto bufTex0 = reinterpret_cast<C2Vector*>(bufData + GxVertexAttribOffset(format, GxVA_TexCoord0));
auto bufTex0Stride = vertexSize;
if (!tex0) {
tex0 = &emptyTex0;
tex0Stride = 0;
bufTex0 = &emptyTex0;
bufTex0Stride = 0;
}
auto bufTex1 = reinterpret_cast<C2Vector*>(bufData + GxVertexAttribOffset(format, GxVA_TexCoord1));
auto bufTex1Stride = vertexSize;
if (!tex1) {
tex1 = &emptyTex1;
tex1Stride = 0;
bufTex1 = &emptyTex1;
bufTex1Stride = 0;
}
for (uint32_t i = 0; i < vertexCount; i++) {
*bufPos = *pos;
pos = reinterpret_cast<const C3Vector*>(reinterpret_cast<uintptr_t>(pos) + posStride);
bufPos = reinterpret_cast<C3Vector*>(reinterpret_cast<uintptr_t>(bufPos) + bufPosStride);
*bufNormal = *normal;
normal = reinterpret_cast<const C3Vector*>(reinterpret_cast<uintptr_t>(normal) + normalStride);
bufNormal = reinterpret_cast<C3Vector*>(reinterpret_cast<uintptr_t>(bufNormal) + bufNormalStride);
*bufColor = *color;
GxFormatColor(*bufColor);
color = reinterpret_cast<const CImVector*>(reinterpret_cast<uintptr_t>(color) + colorStride);
bufColor = reinterpret_cast<CImVector*>(reinterpret_cast<uintptr_t>(bufColor) + bufColorStride);
*bufTex0 = *tex0;
tex0 = reinterpret_cast<const C2Vector*>(reinterpret_cast<uintptr_t>(tex0) + tex0Stride);
bufTex0 = reinterpret_cast<C2Vector*>(reinterpret_cast<uintptr_t>(bufTex0) + bufTex0Stride);
*bufTex1 = *tex1;
tex1 = reinterpret_cast<const C2Vector*>(reinterpret_cast<uintptr_t>(tex1) + tex1Stride);
bufTex1 = reinterpret_cast<C2Vector*>(reinterpret_cast<uintptr_t>(bufTex1) + bufTex1Stride);
}
GxBufUnlock(buf, vertexSize * vertexCount);
GxPrimVertexPtr(buf, format);
}
void GxPrimLockVertexPtrs(uint32_t vertexCount, const C3Vector* pos, uint32_t posStride, const C3Vector* normal, uint32_t normalStride, const CImVector* color, uint32_t colorStride, const uint8_t* bone, uint32_t boneStride, const C2Vector* tex0, uint32_t tex0Stride, const C2Vector* tex1, uint32_t tex1Stride) {
BLIZZARD_ASSERT(Buffer::s_lockVertexCount == 0);
Buffer::s_lockVertexCount = vertexCount;
GxPrimVertexPtr(vertexCount, pos, posStride, normal, normalStride, color, colorStride, tex0, tex0Stride, tex1, tex1Stride);
}
void GxPrimUnlockVertexPtrs() {
Buffer::s_lockVertexCount = 0;
}

View File

@ -4,6 +4,7 @@
#include "gx/buffer/CGxBuf.hpp"
#include "gx/buffer/CGxPool.hpp"
#include "gx/buffer/Types.hpp"
#include "gx/Types.hpp"
#include <cstdint>
class CGxBuf;
@ -19,12 +20,15 @@ struct VertexBufDesc {
namespace Buffer {
extern VertexBufDesc s_vertexBufDesc[GxVertexBufferFormats_Last];
extern int32_t s_vertexBufOffset[GxVertexBufferFormats_Last][GxVAs_Last];
extern uint32_t s_lockVertexCount;
}
uint32_t GxVertexAttribOffset(EGxVertexBufferFormat, EGxVertexAttrib);
CGxBuf* GxBufCreate(CGxPool*, uint32_t, uint32_t, uint32_t);
void GxBufData(CGxBuf* buf, const void* data, uint32_t size, uint32_t offset);
char* GxBufLock(CGxBuf* buf);
void GxBufUnlock(CGxBuf*, uint32_t);
@ -33,6 +37,14 @@ CGxPool* GxPoolCreate(EGxPoolTarget, EGxPoolUsage, uint32_t, EGxPoolHintBits, ch
void GxPrimIndexPtr(CGxBuf*);
void GxPrimIndexPtr(uint32_t indexCount, const uint16_t* indices);
void GxPrimVertexPtr(CGxBuf*, EGxVertexBufferFormat);
void GxPrimVertexPtr(uint32_t vertexCount, const C3Vector* pos, uint32_t posStride, const C3Vector* normal, uint32_t normalStride, const CImVector* color, uint32_t colorStride, const C2Vector* tex0, uint32_t tex0Stride, const C2Vector* tex1, uint32_t tex1Stride);
void GxPrimLockVertexPtrs(uint32_t vertexCount, const C3Vector* pos, uint32_t posStride, const C3Vector* normal, uint32_t normalStride, const CImVector* color, uint32_t colorStride, const uint8_t* bone, uint32_t boneStride, const C2Vector* tex0, uint32_t tex0Stride, const C2Vector* tex1, uint32_t tex1Stride);
void GxPrimUnlockVertexPtrs();
#endif

View File

@ -194,6 +194,11 @@ int32_t CGxDevice::BufUnlock(CGxBuf* buf, uint32_t size) {
return 1;
}
void CGxDevice::BufData(CGxBuf* buf, const void* data, size_t size, uintptr_t offset) {
buf->unk1E = 1;
buf->unk1F = 0;
}
const CGxCaps& CGxDevice::Caps() const {
return this->m_caps;
}
@ -427,7 +432,7 @@ void CGxDevice::IRsSync(int32_t force) {
this->IRsForceUpdate();
}
for (int32_t i = 0; i < this->m_dirtyStates.Count(); i++) {
for (int32_t i = this->m_dirtyStates.Count() - 1; i >= 0; i--) {
auto ds = this->m_dirtyStates[i];
auto rs = &this->m_appRenderStates[ds];
auto hs = &this->m_hwRenderStates[ds];
@ -729,8 +734,11 @@ void CGxDevice::RsPop() {
auto topOfStack = this->m_stackOffsets[this->m_stackOffsets.Count() - 1];
if (this->m_pushedStates.Count() > topOfStack) {
for (int32_t i = this->m_pushedStates.Count() - 1; i > topOfStack; i--) {
auto ps = &this->m_pushedStates[i];
auto bottomOfStack = this->m_pushedStates.Count() - 1;
auto stackSize = this->m_pushedStates.Count() - topOfStack;
for (uint32_t stackOffset = 0; stackOffset < stackSize; stackOffset++) {
auto ps = &this->m_pushedStates[bottomOfStack - stackOffset];
auto rs = &this->m_appRenderStates[ps->m_which];
if (!rs->m_dirty) {
@ -1044,8 +1052,7 @@ void CGxDevice::XformSetViewport(float minX, float maxX, float minY, float maxY,
return;
}
// TODO
// this->unk4[4] = 1;
this->intF6C = 1;
this->m_viewport.x.l = minX;
this->m_viewport.x.h = maxX;

View File

@ -120,6 +120,7 @@ class CGxDevice {
virtual void PoolSizeSet(CGxPool*, uint32_t) = 0;
virtual char* BufLock(CGxBuf*);
virtual int32_t BufUnlock(CGxBuf*, uint32_t);
virtual void BufData(CGxBuf* buf, const void* data, size_t size, uintptr_t offset);
virtual int32_t TexCreate(EGxTexTarget, uint32_t, uint32_t, uint32_t, EGxTexFormat, EGxTexFormat, CGxTexFlags, void*, void (*)(EGxTexCommand, uint32_t, uint32_t, uint32_t, uint32_t, void*, uint32_t&, const void*&), const char*, CGxTex*&);
virtual void TexDestroy(CGxTex* texId);
virtual void ShaderCreate(CGxShader*[], EGxShTarget, const char*, const char*, int32_t);

View File

@ -1,7 +1,7 @@
#include "gx/CGxMatrixStack.hpp"
CGxMatrixStack::CGxMatrixStack() {
this->m_flags[0] = 0x1;
this->m_flags[0] = F_Identity;
}
void CGxMatrixStack::Pop() {
@ -25,6 +25,10 @@ void CGxMatrixStack::Push() {
C44Matrix& CGxMatrixStack::Top() {
this->m_dirty = 1;
this->m_flags[this->m_level] &= 0xFFFFFFFE;
this->m_flags[this->m_level] &= ~F_Identity;
return this->m_mtx[this->m_level];
}
const C44Matrix& CGxMatrixStack::TopConst() {
return this->m_mtx[this->m_level];
}

View File

@ -6,6 +6,11 @@
class CGxMatrixStack {
public:
// Types
enum EMatrixFlags {
F_Identity = 0x1,
};
// Member variables
uint32_t m_level = 0;
int8_t m_dirty = 0;
@ -14,9 +19,10 @@ class CGxMatrixStack {
// Member functions
CGxMatrixStack();
void Pop(void);
void Push(void);
C44Matrix& Top(void);
void Pop();
void Push();
C44Matrix& Top();
const C44Matrix& TopConst();
};
#endif

View File

@ -8,7 +8,7 @@ const CGxStateBom& CGxStateBom::operator=(int32_t value) {
}
const CGxStateBom& CGxStateBom::operator=(uint32_t value) {
this->m_data.i[0] = value;
this->m_data.u[0] = value;
return *this;
}
@ -33,20 +33,42 @@ const CGxStateBom& CGxStateBom::operator=(C3Vector& value) {
return *this;
}
bool CGxStateBom::operator!=(int32_t value) {
return this->m_data.i[0] != value;
bool CGxStateBom::operator==(float value) {
return this->m_data.f[0] == value;
}
bool CGxStateBom::operator!=(uint32_t value) {
return this->m_data.i[0] != value;
bool CGxStateBom::operator==(int32_t value) {
return this->m_data.i[0] == value;
}
bool CGxStateBom::operator==(uint32_t value) {
return this->m_data.u[0] == value;
}
bool CGxStateBom::operator==(void* value) {
return this->m_data.p == value;
}
bool CGxStateBom::operator==(C3Vector& value) {
return this->m_data.f[0] == value.x
|| this->m_data.f[1] == value.y
|| this->m_data.f[2] == value.z;
}
bool CGxStateBom::operator!=(float value) {
return this->m_data.f[0] != value;
return !(*this == value);
}
bool CGxStateBom::operator!=(int32_t value) {
return !(*this == value);
}
bool CGxStateBom::operator!=(uint32_t value) {
return !(*this == value);
}
bool CGxStateBom::operator!=(void* value) {
return this->m_data.p != value;
return !(*this == value);
}
bool CGxStateBom::operator!=(C3Vector& value) {
@ -64,7 +86,7 @@ bool CGxStateBom::operator!=(CGxStateBom& value) {
CGxStateBom::operator CImVector() const {
CImVector color;
color.value = this->m_data.i[0];
color.value = this->m_data.u[0];
return color;
}
@ -77,7 +99,7 @@ CGxStateBom::operator int32_t() const {
}
CGxStateBom::operator uint32_t() const {
return this->m_data.i[0];
return this->m_data.u[0];
}
CGxStateBom::operator void*() const {

View File

@ -11,6 +11,7 @@ class CGxStateBom {
// Member variables
union {
int32_t i[3];
uint32_t u[3];
float f[3];
void* p;
} m_data;
@ -23,6 +24,11 @@ class CGxStateBom {
const CGxStateBom& operator=(uint32_t);
const CGxStateBom& operator=(void*);
const CGxStateBom& operator=(C3Vector&);
bool operator==(float);
bool operator==(int32_t);
bool operator==(uint32_t);
bool operator==(void*);
bool operator==(C3Vector&);
bool operator!=(float);
bool operator!=(int32_t);
bool operator!=(uint32_t);

View File

@ -1,19 +1,44 @@
#include "gx/Buffer.hpp"
#include "gx/Draw.hpp"
#include "gx/Device.hpp"
#include <bc/Debug.hpp>
void GxDraw(CGxBatch* batch, int32_t indexed) {
g_theGxDevicePtr->Draw(batch, indexed);
}
void GxDrawLockedElements(EGxPrim primType, uint32_t indexCount, const uint16_t* indices) {
if (Buffer::s_lockVertexCount == 0) {
return;
}
GxPrimIndexPtr(indexCount, indices);
CGxBatch batch;
batch.m_primType = primType;
batch.m_minIndex = 0;
batch.m_maxIndex = Buffer::s_lockVertexCount - 1;
batch.m_start = 0;
batch.m_count = indexCount;
BLIZZARD_ASSERT(batch.m_count > 0);
g_theGxDevicePtr->Draw(&batch, 1);
}
void GxSceneClear(uint32_t mask, CImVector color) {
g_theGxDevicePtr->SceneClear(mask, color);
}
void GxScenePresent() {
void GxScenePresent(uint32_t a2) {
g_theGxDevicePtr->ScenePresent();
}
void GxSub682A00() {
C3Vector v2 = { 0.0f, 0.0f, 0.0f };
GxuFlushDrawList(GxuCat_2, v2);
g_theGxDevicePtr->ScenePresent();
GxScenePresent(0);
}
void GxuFlushDrawList(EGxuDrawListCategory a1, const C3Vector& a2) {

View File

@ -10,9 +10,13 @@ class CImVector;
void GxDraw(CGxBatch* batch, int32_t indexed);
void GxDrawLockedElements(EGxPrim primType, uint32_t indexCount, const uint16_t* indices);
void GxSceneClear(uint32_t, CImVector);
void GxScenePresent(void);
void GxScenePresent(uint32_t a2);
void GxSub682A00();
void GxuFlushDrawList(EGxuDrawListCategory, const C3Vector&);

8
src/gx/LoadingScreen.cpp Normal file
View File

@ -0,0 +1,8 @@
#include "gx/LoadingScreen.hpp"
#include "gx/Screen.hpp"
static HLAYER s_loadingScreenLayer;
bool LoadingScreenDrawing() {
return s_loadingScreenLayer != nullptr;
}

6
src/gx/LoadingScreen.hpp Normal file
View File

@ -0,0 +1,6 @@
#ifndef GX_LOADING_SCREEN_HPP
#define GX_LOADING_SCREEN_HPP
bool LoadingScreenDrawing();
#endif

View File

@ -6,14 +6,15 @@
#include "gx/Gx.hpp"
#include "gx/Transform.hpp"
#include "util/Filesystem.hpp"
#include <storm/String.hpp>
#include <tempest/Matrix.hpp>
int32_t Screen::s_captureScreen = 0;
float Screen::s_elapsedSec = 0.0f;
int32_t Screen::s_presentDisable = 0;
HOBJECT Screen::s_stockObjects[];
float Screen::s_stockObjectHeights[] = { 0.01953125f, 0.01953125f };
STORM_EXPLICIT_LIST(CILayer, zorderlink) Screen::s_zorderlist;
static HOBJECT s_stockObjects[SCRNSTOCKOBJECTS];
static float s_stockObjectHeights[SCRNSTOCKOBJECTS] = { 0.01953125f, 0.01953125f };
static STORM_EXPLICIT_LIST(CILayer, zorderlink) s_zOrderList;
int32_t OnIdle(const EVENT_DATA_IDLE* data, void* a2) {
Screen::s_elapsedSec = data->elapsedSec + Screen::s_elapsedSec;
@ -30,47 +31,34 @@ int32_t OnPaint(const void* a1, void* a2) {
// return 1;
// }
CILayer* layer;
CSRgn rgn;
SRgnCreate(&rgn.m_handle, 0);
RECTF baseRect;
RECTF baseRect = { 0.0f, 0.0f, 1.0f, 1.0f };
SRgnCombineRectf(rgn.m_handle, &baseRect, nullptr, 2);
baseRect.left = 0.0f;
baseRect.bottom = 0.0f;
baseRect.right = 1.0f;
baseRect.top = 1.0f;
SRgnCombineRectf(&rgn.m_handle, &baseRect, 0, 2);
layer = Screen::s_zorderlist.Head();
while (layer) {
SRgnGetBoundingRectf(&rgn.m_handle, &layer->visible);
// Walk the layer list backward (highest z-order to lowest) to establish visibility rects
for (auto layer = s_zOrderList.Tail(); layer; layer = layer->zorderlink.Prev()) {
SRgnGetBoundingRectf(rgn.m_handle, &layer->visible);
layer->visible.left = std::max(layer->visible.left, layer->rect.left);
layer->visible.bottom = std::max(layer->visible.bottom, layer->rect.bottom);
layer->visible.right = std::max(layer->visible.right, layer->rect.right);
layer->visible.top = std::max(layer->visible.top, layer->rect.top);
layer->visible.right = std::min(layer->visible.right, layer->rect.right);
layer->visible.top = std::min(layer->visible.top, layer->rect.top);
if (layer->flags & 0x1) {
SRgnCombineRectf(&rgn.m_handle, &layer->rect, 0, 4);
if (!(layer->flags & 0x1)) {
SRgnCombineRectf(rgn.m_handle, &layer->rect, nullptr, 4);
}
}
layer = layer->zorderlink.Next();
}
SRgnDelete(&rgn.m_handle);
SRgnDelete(rgn.m_handle);
// Save viewport
float minX, maxX, minY, maxY, minZ, maxZ;
GxXformViewport(minX, maxX, minY, maxY, minZ, maxZ);
layer = Screen::s_zorderlist.Head();
while (layer) {
// Walk the layer list forward (lowest z-order to highest) to paint visible layers
for (auto layer = s_zOrderList.Head(); layer; layer = layer->zorderlink.Next()) {
if (layer->visible.right > layer->visible.left && layer->visible.top > layer->visible.bottom) {
if (layer->flags & 0x4) {
GxXformSetViewport(
@ -116,8 +104,6 @@ int32_t OnPaint(const void* a1, void* a2) {
Screen::s_elapsedSec
);
}
layer = layer->zorderlink.Next();
}
// Restore viewport
@ -129,14 +115,14 @@ int32_t OnPaint(const void* a1, void* a2) {
if (Screen::s_captureScreen) {
// TODO
GxScenePresent();
GxSub682A00();
// TODO
return 1;
}
GxScenePresent();
GxSub682A00();
}
Screen::s_elapsedSec = 0.0f;
@ -152,9 +138,8 @@ void ILayerInitialize() {
void IStockInitialize() {
GxuFontInitialize();
char fontFile[260];
OsBuildFontFilePath("FRIZQT__.TTF", fontFile, 260);
char fontFile[STORM_MAX_PATH];
OsBuildFontFilePath("FRIZQT__.TTF", fontFile, sizeof(fontFile));
if (*fontFile) {
ScrnSetStockFont(STOCK_SYSFONT, fontFile);
@ -180,57 +165,44 @@ void ScrnInitialize(int32_t a1) {
IStockInitialize();
}
void ScrnLayerCreate(const RECTF* rect, float zorder, unsigned long flags, void* param, void (*paintFunc)(void*, const RECTF*, const RECTF*, float), HLAYER* layer) {
void ScrnLayerCreate(const RECTF* rect, float zOrder, uint32_t flags, void* param, void (*paintFunc)(void*, const RECTF*, const RECTF*, float), HLAYER* layerPtr) {
static RECTF defaultrect = { 0.0f, 0.0f, 1.0f, 1.0f };
const RECTF* r = rect ? rect : &defaultrect;
auto m = SMemAlloc(sizeof(CILayer), __FILE__, __LINE__, 0x0);
auto l = new (m) CILayer();
auto layer = new (m) CILayer();
l->rect.left = r->left;
l->rect.bottom = r->bottom;
l->rect.right = r->right;
l->rect.top = r->top;
layer->rect.left = r->left;
layer->rect.bottom = r->bottom;
layer->rect.right = r->right;
layer->rect.top = r->top;
l->zorder = zorder;
l->flags = flags;
l->param = param;
l->paintfunc = paintFunc;
layer->zorder = zOrder;
layer->flags = flags;
layer->param = param;
layer->paintfunc = paintFunc;
auto node = Screen::s_zorderlist.Head();
auto node = s_zOrderList.Head();
while (node && zorder < node->zorder) {
while (node && zOrder < node->zorder) {
node = node->zorderlink.Next();
}
Screen::s_zorderlist.LinkNode(l, 1, node);
s_zOrderList.LinkNode(layer, 1, node);
*layer = HandleCreate(l);
*layerPtr = HandleCreate(layer);
}
void ScrnLayerSetRect(HLAYER layer, const RECTF* rect) {
static_cast<CILayer*>(HandleDereference(layer))->rect = *rect;
}
void ScrnSetStockFont(SCRNSTOCK stockID, const char* fontTexturePath) {
if (Screen::s_stockObjects[stockID]) {
HandleClose(Screen::s_stockObjects[stockID]);
if (s_stockObjects[stockID]) {
HandleClose(s_stockObjects[stockID]);
}
float fontHeight = NDCToDDCHeight(Screen::s_stockObjectHeights[stockID]);
float fontHeight = NDCToDDCHeight(s_stockObjectHeights[stockID]);
HTEXTFONT font = TextBlockGenerateFont(fontTexturePath, 0, fontHeight);
Screen::s_stockObjects[stockID] = font;
}
void SRgnCombineRectf(HSRGN* handle, RECTF* rect, void* param, int32_t combinemode) {
// TODO
}
void SRgnCreate(HSRGN* handle, uint32_t reserved) {
// TODO
}
void SRgnDelete(HSRGN* handle) {
// TODO
}
void SRgnGetBoundingRectf(HSRGN* handle, RECTF* rect) {
// TODO
s_stockObjects[stockID] = font;
}

View File

@ -4,9 +4,9 @@
#include <cstdint>
#include <common/Handle.hpp>
#include <storm/List.hpp>
#include <storm/Region.hpp>
typedef HOBJECT HLAYER;
typedef HOBJECT HSRGN;
enum SCRNSTOCK {
STOCK_SYSFONT = 0,
@ -14,13 +14,6 @@ enum SCRNSTOCK {
SCRNSTOCKOBJECTS = 2
};
struct RECTF {
float left;
float bottom;
float right;
float top;
};
class CILayer : public CHandleObject {
public:
RECTF rect;
@ -41,27 +34,18 @@ namespace Screen {
extern int32_t s_captureScreen;
extern float s_elapsedSec;
extern int32_t s_presentDisable;
extern HOBJECT s_stockObjects[SCRNSTOCKOBJECTS];
extern float s_stockObjectHeights[SCRNSTOCKOBJECTS];
extern STORM_EXPLICIT_LIST(CILayer, zorderlink) s_zorderlist;
}
void ILayerInitialize(void);
void ILayerInitialize();
void IStockInitialize(void);
void IStockInitialize();
void ScrnInitialize(int32_t);
void ScrnInitialize(int32_t a1);
void ScrnLayerCreate(const RECTF*, float, unsigned long, void*, void (*)(void*, const RECTF*, const RECTF*, float), HLAYER*);
void ScrnLayerCreate(const RECTF* rect, float zOrder, uint32_t flags, void* param, void (*paintFunc)(void*, const RECTF*, const RECTF*, float), HLAYER* layerPtr);
void ScrnSetStockFont(SCRNSTOCK, const char*);
void ScrnLayerSetRect(HLAYER layer, const RECTF* rect);
void SRgnCombineRectf(HSRGN*, RECTF*, void*, int32_t);
void SRgnCreate(HSRGN*, uint32_t);
void SRgnDelete(HSRGN*);
void SRgnGetBoundingRectf(HSRGN*, RECTF*);
void ScrnSetStockFont(SCRNSTOCK stockID, const char* fontTexturePath);
#endif

View File

@ -141,9 +141,9 @@ void GxuXformCreateOrtho(float minX, float maxX, float minY, float maxY, float m
dst.c2 = 2.0 / v12;
dst.c3 = 0.0f;
dst.d0 = 0.0f;
dst.d1 = 0.0f;
dst.d2 = 0.0f;
dst.d0 = -((minX + maxX) / v10);
dst.d1 = -((minY + maxY) / v11);
dst.d2 = -((minZ + maxZ) / v12);
dst.d3 = 1.0f;
}

View File

@ -394,6 +394,14 @@ int32_t CGxDeviceD3d::BufUnlock(CGxBuf* buf, uint32_t size) {
return 1;
}
void CGxDeviceD3d::BufData(CGxBuf* buf, const void* data, size_t size, uintptr_t offset) {
CGxDevice::BufData(buf, data, size, offset);
auto bufData = this->IBufLock(buf);
memcpy(&bufData[offset], data, size);
this->IBufUnlock(buf);
}
void CGxDeviceD3d::CapsWindowSize(CRect& dst) {
dst = this->DeviceCurWindow();
}
@ -1572,7 +1580,11 @@ void CGxDeviceD3d::IStateSync() {
this->IShaderConstantsFlush();
this->IRsSync(0);
// TODO ffp if vertex shader is disabled
if (this->m_hwRenderStates[GxRs_VertexShader] == nullptr && this->m_appRenderStates[GxRs_VertexShader].m_value == nullptr) {
this->IStateSyncLights();
this->IStateSyncMaterial();
this->IStateSyncXforms();
}
this->IStateSyncEnables();
@ -1582,6 +1594,10 @@ void CGxDeviceD3d::IStateSync() {
this->IStateSyncIndexPtr();
// TODO
if (this->intF6C) {
this->IXformSetViewport();
}
}
void CGxDeviceD3d::IStateSyncEnables() {
@ -1603,6 +1619,14 @@ void CGxDeviceD3d::IStateSyncIndexPtr() {
}
}
void CGxDeviceD3d::IStateSyncLights() {
// TODO
}
void CGxDeviceD3d::IStateSyncMaterial() {
// TODO
}
void CGxDeviceD3d::IStateSyncVertexPtrs() {
if (this->m_primVertexFormat < GxVertexBufferFormats_Last && this->m_d3dVertexDecl[this->m_primVertexFormat]) {
auto d3dVertexDecl = this->m_d3dVertexDecl[this->m_primVertexFormat];
@ -1683,6 +1707,22 @@ void CGxDeviceD3d::IStateSyncVertexPtrs() {
}
}
void CGxDeviceD3d::IStateSyncXforms() {
if (this->m_xforms[GxXform_Projection].m_dirty) {
this->m_d3dDevice->SetTransform(D3DTS_PROJECTION, reinterpret_cast<D3DMATRIX*>(&this->m_projNative));
this->m_xforms[GxXform_Projection].m_dirty = 0;
}
if (this->m_xforms[GxXform_View].m_dirty) {
this->m_d3dDevice->SetTransform(D3DTS_VIEW, reinterpret_cast<const D3DMATRIX*>(&this->m_xforms[GxXform_View].TopConst()));
this->m_xforms[GxXform_View].m_dirty = 0;
}
// TODO world
// TODO tex
}
void CGxDeviceD3d::ITexCreate(CGxTex* texId) {
uint32_t width, height, startLevel, endLevel;
this->ITexWHDStartEnd(texId, width, height, startLevel, endLevel);
@ -1910,6 +1950,30 @@ void CGxDeviceD3d::IXformSetProjection(const C44Matrix& matrix) {
memcpy(&this->m_projNative, &projNative, sizeof(this->m_projNative));
}
void CGxDeviceD3d::IXformSetViewport() {
const auto& gxViewport = this->m_viewport;
auto windowRect = this->DeviceCurWindow();
D3DVIEWPORT9 d3dViewport;
d3dViewport.X = (gxViewport.x.l * windowRect.maxX) + 0.5;
d3dViewport.Y = ((1.0 - gxViewport.y.h) * windowRect.maxY) + 0.5;
// TODO account for negative X value
d3dViewport.Width = (gxViewport.x.h * windowRect.maxX) - d3dViewport.X + 0.5;
d3dViewport.Height = ((1.0 - gxViewport.y.l) * windowRect.maxY) - d3dViewport.Y + 0.5;
d3dViewport.MinZ = gxViewport.z.l;
d3dViewport.MaxZ = gxViewport.z.h;
// TODO conditionally adjust Y value
this->m_d3dDevice->SetViewport(&d3dViewport);
this->intF6C = 0;
}
void CGxDeviceD3d::PoolSizeSet(CGxPool* pool, uint32_t size) {
// TODO
}
@ -1930,7 +1994,7 @@ void CGxDeviceD3d::SceneClear(uint32_t mask, CImVector color) {
}
if (this->intF6C) {
// TODO
this->IXformSetViewport();
}
D3DCOLOR d3dColor = color.b | (color.g | (color.r << 8) << 8);

View File

@ -258,6 +258,7 @@ class CGxDeviceD3d : public CGxDevice {
virtual void PoolSizeSet(CGxPool* pool, uint32_t size);
virtual char* BufLock(CGxBuf* buf);
virtual int32_t BufUnlock(CGxBuf* buf, uint32_t size);
virtual void BufData(CGxBuf* buf, const void* data, size_t size, uintptr_t offset);
virtual void IShaderCreate(CGxShader* shader);
virtual void ShaderCreate(CGxShader* shaders[], EGxShTarget target, const char* a4, const char* a5, int32_t permutations);
virtual int32_t StereoEnabled();
@ -293,10 +294,14 @@ class CGxDeviceD3d : public CGxDevice {
void IStateSync();
void IStateSyncEnables();
void IStateSyncIndexPtr();
void IStateSyncLights();
void IStateSyncMaterial();
void IStateSyncVertexPtrs();
void IStateSyncXforms();
void ITexCreate(CGxTex* texId);
void ITexUpload(CGxTex* texId);
void IXformSetProjection(const C44Matrix& matrix);
void IXformSetViewport();
};
#endif

View File

@ -686,7 +686,7 @@ void CGxFont::ClearGlyphs() {
this->m_activeCharacters.Clear();
this->m_activeCharacterCache.DeleteAll();
this->m_activeCharacterCache.Clear();
this->m_kernInfo.Clear();
}

View File

@ -29,7 +29,7 @@ FT_Face FontFaceGetFace(HFACE handle) {
const char* FontFaceGetFontName(HFACE handle) {
STORM_ASSERT(handle);
return reinterpret_cast<FACEDATA*>(handle)->m_key.m_str;
return reinterpret_cast<FACEDATA*>(handle)->m_key.GetString();
}
HFACE FontFaceGetHandle(const char* fileName, FT_Library library) {

View File

@ -1,7 +1,6 @@
#include "gx/font/FreeType.hpp"
#include "gx/font/FreeTypeInternal.hpp"
#include "freetype/ftmodule.h"
#include <storm/Memory.hpp>
FT_Library g_FTLibrary;

View File

@ -4,7 +4,6 @@
#include "gx/Blit.hpp"
#include "gx/CGxBatch.hpp"
#include "gx/Shader.hpp"
#include "gx/Texture.hpp"
#include "gx/Window.hpp"
#include "gx/texture/CGxTex.hpp"
#include <cmath>
@ -117,6 +116,14 @@ int32_t CGxDeviceGLL::BufUnlock(CGxBuf* buf, uint32_t size) {
return this->IBufUnlock(buf);
}
void CGxDeviceGLL::BufData(CGxBuf* buf, const void* data, size_t size, uintptr_t offset) {
CGxDevice::BufData(buf, data, size, offset);
auto bufData = this->IBufLock(buf);
memcpy(&bufData[offset], data, size);
this->IBufUnlock(buf);
}
void CGxDeviceGLL::CapsWindowSize(CRect& rect) {
CRect windowRect = this->DeviceCurWindow();
@ -785,7 +792,7 @@ void CGxDeviceGLL::IShaderCreatePixel(CGxShader* ps) {
GLShader::ShaderType::ePixelShader,
codeStr,
codeLen,
ps->m_key.m_str
ps->m_key.GetString()
);
glShader->Compile(nullptr);
@ -811,7 +818,7 @@ void CGxDeviceGLL::IShaderCreateVertex(CGxShader* vs) {
GLShader::ShaderType::eVertexShader,
code,
codeLen,
vs->m_key.m_str
vs->m_key.GetString()
);
glShader->Compile(nullptr);

View File

@ -43,6 +43,7 @@ class CGxDeviceGLL : public CGxDevice {
virtual void PoolSizeSet(CGxPool*, uint32_t);
virtual char* BufLock(CGxBuf*);
virtual int32_t BufUnlock(CGxBuf*, uint32_t);
virtual void BufData(CGxBuf* buf, const void* data, size_t size, uintptr_t offset);
virtual void TexDestroy(CGxTex* texId);
virtual void IShaderCreate(CGxShader*);
virtual void ShaderCreate(CGxShader*[], EGxShTarget, const char*, const char*, int32_t);

View File

@ -1,6 +1,5 @@
#include "gx/gll/GLAbstractWindow.h"
#include <cmath>
#include <ApplicationServices/ApplicationServices.h>
int32_t GLAbstractWindow::GetBackingWidth() {
return static_cast<int32_t>(std::floor(this->GetBackingRect().size.width));

View File

@ -628,8 +628,59 @@ void GLDevice::ApplyGLStates(const GLStates& states, bool force) {
{
glMatrixMode(GL_PROJECTION);
// TODO
// - some interesting logic to manipulate the projection matrix before loading
GLTransform projection = {
true,
{
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f,
},
true
};
if (!states.fixedFunc.transforms.projection.isIdentity) {
projection.isIdentity = false;
memcpy(projection.m, states.fixedFunc.transforms.projection.m, sizeof(projection.m));
projection.isDirty = true;
}
if (projection.isIdentity) {
projection.SetIdentity();
}
projection.a1 *= -1.0f;
projection.b1 *= -1.0f;
projection.c1 *= -1.0f;
projection.d1 *= -1.0f;
auto isIdentity = projection.a0 == 1.0f
&& projection.a1 == 0.0f
&& projection.a2 == 0.0f
&& projection.a3 == 0.0f
&& projection.b0 == 0.0f
&& projection.b1 == 1.0f
&& projection.b2 == 0.0f
&& projection.b3 == 0.0f
&& projection.c0 == 0.0f
&& projection.c1 == 0.0f
&& projection.c2 == 1.0f
&& projection.c3 == 0.0f
&& projection.d0 == 0.0f
&& projection.d1 == 0.0f
&& projection.d2 == 0.0f
&& projection.d3 == 1.0f;
projection.isDirty = true;
if (isIdentity) {
glLoadIdentity();
} else {
glLoadMatrixf(projection.m);
}
projection.isDirty = false;
}
glMatrixMode(states.fixedFunc.transforms.matrixMode);
@ -892,7 +943,53 @@ void GLDevice::ApplyShaderConstants() {
}
void GLDevice::ApplyTransforms() {
// TODO
this->SetModelView(GL_MODELVIEW);
auto& projection = this->m_States.fixedFunc.transforms.projection;
if (projection.isDirty) {
if (projection.isIdentity) {
projection.SetIdentity();
}
projection.a1 *= -1.0f;
projection.b1 *= -1.0f;
projection.c1 *= -1.0f;
projection.d1 *= -1.0f;
projection.isIdentity = projection.a0 == 1.0f
&& projection.a1 == 0.0f
&& projection.a2 == 0.0f
&& projection.a3 == 0.0f
&& projection.b0 == 0.0f
&& projection.b1 == 1.0f
&& projection.b2 == 0.0f
&& projection.b3 == 0.0f
&& projection.c0 == 0.0f
&& projection.c1 == 0.0f
&& projection.c2 == 1.0f
&& projection.c3 == 0.0f
&& projection.d0 == 0.0f
&& projection.d1 == 0.0f
&& projection.d2 == 0.0f
&& projection.d3 == 1.0f;
projection.isDirty = true;
if (this->m_States.fixedFunc.transforms.matrixMode != GL_PROJECTION) {
glMatrixMode(GL_PROJECTION);
this->m_States.fixedFunc.transforms.matrixMode = GL_PROJECTION;
}
if (projection.isIdentity) {
glLoadIdentity();
} else {
glLoadMatrixf(projection.m);
}
projection.isDirty = false;
}
// TODO texture transforms
}
void GLDevice::BindBuffer(GLBuffer* buffer, GLEnum target) {
@ -2103,29 +2200,29 @@ void GLDevice::SetAlphaTestEnable(bool enable) {
}
}
void GLDevice::SetClearColor(const GLColor4f& a2) {
void GLDevice::SetClearColor(const GLColor4f& clearColor) {
if (
this->m_States.clear.clearColor.r != a2.r
|| this->m_States.clear.clearColor.g != a2.g
|| this->m_States.clear.clearColor.b != a2.b
|| this->m_States.clear.clearColor.a != a2.a
this->m_States.clear.clearColor.r != clearColor.r
|| this->m_States.clear.clearColor.g != clearColor.g
|| this->m_States.clear.clearColor.b != clearColor.b
|| this->m_States.clear.clearColor.a != clearColor.a
) {
glClearColor(a2.r, a2.g, a2.b, a2.a);
this->m_States.clear.clearColor = { a2.r, a2.g, a2.b, a2.a };
glClearColor(clearColor.r, clearColor.g, clearColor.b, clearColor.a);
this->m_States.clear.clearColor = { clearColor.r, clearColor.g, clearColor.b, clearColor.a };
}
}
void GLDevice::SetClearDepth(double depth) {
if (this->m_States.clear.clearDepth != depth) {
glClearDepth(depth);
this->m_States.clear.clearDepth = depth;
void GLDevice::SetClearDepth(double clearDepth) {
if (this->m_States.clear.clearDepth != clearDepth) {
glClearDepth(clearDepth);
this->m_States.clear.clearDepth = clearDepth;
}
}
void GLDevice::SetClearStencil(int32_t s) {
if (this->m_States.clear.clearStencil != s) {
glClearStencil(s);
this->m_States.clear.clearStencil = s;
void GLDevice::SetClearStencil(int32_t clearStencil) {
if (this->m_States.clear.clearStencil != clearStencil) {
glClearStencil(clearStencil);
this->m_States.clear.clearStencil = clearStencil;
}
}
@ -2315,6 +2412,57 @@ void GLDevice::SetLightingEnable(bool enable) {
}
}
void GLDevice::SetModelView(GLEnum transform) {
if (transform == 'VIEW') {
// TODO
return;
}
if (transform == 'WRLD') {
// TODO
return;
}
if (transform != GL_MODELVIEW) {
BLIZZARD_ASSERT(false);
}
auto& world = this->m_States.fixedFunc.transforms.world;
auto& view = this->m_States.fixedFunc.transforms.view;
auto& modelView = this->m_States.fixedFunc.transforms.modelView;
if (this->m_States.fixedFunc.transforms.modelviewStatus != transform || modelView.isDirty) {
if (world.isIdentity && view.isIdentity) {
modelView.isIdentity = true;
modelView.isDirty = true;
} else if (world.isIdentity) {
modelView = view;
modelView.isIdentity = false;
modelView.isDirty = true;
} else if (view.isIdentity) {
modelView = world;
modelView.isIdentity = false;
modelView.isDirty = true;
} else {
// TODO assign model * view to modelView
BLIZZARD_ASSERT(!"Unimplemented");
}
if (this->m_States.fixedFunc.transforms.matrixMode != GL_MODELVIEW) {
glMatrixMode(GL_MODELVIEW);
this->m_States.fixedFunc.transforms.matrixMode = GL_MODELVIEW;
}
if (modelView.isIdentity) {
glLoadIdentity();
} else {
glLoadMatrixf(modelView.m);
}
this->m_States.fixedFunc.transforms.modelviewStatus = transform;
}
}
void GLDevice::SetScissor(bool a2, const GLRect& a3) {
// TODO
}
@ -2469,15 +2617,13 @@ void GLDevice::SetTransform(GLEnum transform, const float* a3) {
BLIZZARD_ASSERT(false);
}
// TODO
// int32_t needsUpdate = !(t == a3); // GLTransform::operator==()
// if (needsUpdate) {
// t.Set(a3);
// }
if (*t != a3) {
t->Set(a3);
}
if (t->isDirty) {
if (transform == 'VIEW' || transform == 'WRLD') {
this->m_States.fixedFunc.transforms.modelView.isDirty = 1;
this->m_States.fixedFunc.transforms.modelView.isDirty = true;
}
}
}

View File

@ -63,13 +63,13 @@ class GLDevice {
static GLFramebuffer* m_F8330C;
// Static functions
static GLDevice* Get(void);
static void Set(GLDevice*);
static void InitPools(void);
static RendererInfo GetRendererInfo(void);
static void InitRendererInfo(void);
static void SetOption(GLDeviceOption, bool);
static void StaticInit(void);
static GLDevice* Get();
static void Set(GLDevice* device);
static void InitPools();
static RendererInfo GetRendererInfo();
static void InitRendererInfo();
static void SetOption(GLDeviceOption option, bool enable);
static void StaticInit();
// Member variables
std::basic_string<char, std::char_traits<char>, std::allocator<char>> m_DebugName;
@ -121,71 +121,72 @@ class GLDevice {
// Member functions
GLDevice();
void ApplyGLBindings(const GLStates&, bool);
void ApplyGLStates(const GLStates&, bool);
void ApplyShaderConstants(void);
void ApplyTransforms(void);
void BindBuffer(GLBuffer*, GLEnum);
void BindFramebuffer(GLFramebuffer*);
void BindGLSLProgram(GLGLSLProgram*);
void BindShader(GLShader*);
void BindTexture(GLEnum, GLTexture*);
void BindVertexArray(GLVertexArray*);
void BlitFramebuffer(GLMipmap*, const GLRect*, GLMipmap*, const GLRect*, GLEnum, GLEnum);
void CheckDepthTarget(void);
void Clear(uint32_t, const GLColor4f&, double, int32_t);
void CopyTex(uint32_t, uint32_t, GLMipmap*, const GLRect*);
GLBuffer* CreateBuffer(GLEnum, uint32_t, const void*, GLEnum, GLEnum);
GLShader* CreateShader(GLShader::ShaderType, const void*, int32_t, const char*);
GLTexture* CreateTexture2D(uint32_t, uint32_t, uint32_t, GLTextureFormat, uint32_t);
GLTexture* CreateTextureCubeMap(uint32_t, uint32_t, GLTextureFormat, uint32_t);
void Draw(GLEnum, uint32_t, uint32_t);
void DrawIndexed(GLEnum, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
void DrawRect(void);
GLFramebuffer* GetCurrentTarget(void); // invented name
uint32_t GetID(void);
GLShader* GetShader(GLShader::ShaderType);
void ApplyGLBindings(const GLStates& states, bool a3);
void ApplyGLStates(const GLStates& states, bool force);
void ApplyShaderConstants();
void ApplyTransforms();
void BindBuffer(GLBuffer* buffer, GLEnum target);
void BindFramebuffer(GLFramebuffer* framebuffer);
void BindGLSLProgram(GLGLSLProgram* a2);
void BindShader(GLShader* shader);
void BindTexture(GLEnum textureType, GLTexture* texture);
void BindVertexArray(GLVertexArray* a2);
void BlitFramebuffer(GLMipmap* src, const GLRect* srcRect, GLMipmap* dst, const GLRect* dstRect, GLEnum mask, GLEnum filter);
void CheckDepthTarget();
void Clear(uint32_t clearMask, const GLColor4f& clearColor, double clearDepth, int32_t clearStencil);
void CopyTex(uint32_t a2, uint32_t a3, GLMipmap* dst, const GLRect* framebufferRect);
GLBuffer* CreateBuffer(GLEnum type, uint32_t a3, const void* a4, GLEnum usage, GLEnum format);
GLShader* CreateShader(GLShader::ShaderType type, const void* buf, int32_t codeLen, const char* name);
GLTexture* CreateTexture2D(uint32_t width, uint32_t height, uint32_t numMipMap, GLTextureFormat format, uint32_t flags);
GLTexture* CreateTextureCubeMap(uint32_t size, uint32_t numMipMap, GLTextureFormat format, uint32_t flags);
void Draw(GLEnum primitive, uint32_t a3, uint32_t a4);
void DrawIndexed(GLEnum primitive, uint32_t a3, uint32_t a4, uint32_t a5, uint32_t a6, uint32_t count);
void DrawRect();
GLFramebuffer* GetCurrentTarget(); // invented name
uint32_t GetID();
GLShader* GetShader(GLShader::ShaderType shaderType);
const GLStates::VertexArrayObject& GetVertexArrayStates();
void GLLDraw(GLEnum, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
void Init(GLAbstractWindow*, const char*, uint32_t, GLTextureFormat);
void LoadDefaultStates(void);
void GLLDraw(GLEnum mode, uint32_t start, uint32_t end, uint32_t a5, uint32_t a6, uint32_t count);
void Init(GLAbstractWindow* a2, const char* a3, uint32_t a4, GLTextureFormat a5);
void LoadDefaultStates();
void ResetBackbuffer(uint32_t width, uint32_t height, GLTextureFormat colorFormat, GLTextureFormat depthFormat, uint32_t sampleCount);
void Resize(uint32_t width, uint32_t height);
void RestoreTextures(void);
void SetActiveTexture(uint32_t);
void SetAlphaBlend(GLEnum, GLEnum, GLEnum);
void SetAlphaBlendEnable(bool);
void SetAlphaTest(GLEnum, float);
void SetAlphaTestEnable(bool);
void SetClearColor(const GLColor4f&);
void SetClearDepth(double);
void SetClearStencil(int32_t);
void RestoreTextures();
void SetActiveTexture(uint32_t a2);
void SetAlphaBlend(GLEnum srcBlend, GLEnum dstBlend, GLEnum blendOp);
void SetAlphaBlendEnable(bool enable);
void SetAlphaTest(GLEnum func, float ref);
void SetAlphaTestEnable(bool enable);
void SetClearColor(const GLColor4f& clearColor);
void SetClearDepth(double clearDepth);
void SetClearStencil(int32_t clearStencil);
void SetColorWriteMask(bool red, bool green, bool blue, bool alpha, uint32_t index);
void SetCullMode(GLEnum);
void SetCullMode(GLEnum cullMode);
void SetDepthBias(float constantBias, float slopeScaledBias);
void SetDepthTestEnable(bool);
void SetDepthTestFunc(GLEnum);
void SetDepthWriteMask(bool);
void SetDisplay(uint32_t, uint32_t, GLTextureFormat, GLTextureFormat, uint32_t, bool, bool, uint32_t);
void SetDepthTestEnable(bool enable);
void SetDepthTestFunc(GLEnum func);
void SetDepthWriteMask(bool enable);
void SetDisplay(uint32_t width, uint32_t height, GLTextureFormat a4, GLTextureFormat a5, uint32_t a6, bool a7, bool a8, uint32_t a9);
void SetFogColor(float r, float g, float b, float a);
void SetFogEnable(bool enable);
void SetFogParam(GLEnum param, float value);
void SetIndexBuffer(GLBuffer*);
void SetIndexBuffer(GLBuffer* buffer);
void SetLightingEnable(bool enable);
void SetScissor(bool, const GLRect&);
void SetShader(GLShader::ShaderType, GLShader*);
void SetShaderConstants(GLShader::ShaderType, uint32_t, const float*, uint32_t);
void SetShaderConstantsInternal(GLShader::ShaderType, uint32_t, const float*, uint32_t);
void SetTexture(uint32_t, GLTexture*);
void SetTransform(GLEnum, const float*);
void SetUnpackClientStorage(bool);
void SetVertexBuffer(uint32_t, GLBuffer*, uint32_t, uint32_t);
void SetVertexFormat(GLVertexFormat*);
void SetViewport(const GLRect&, double, double);
void SetModelView(GLEnum transform);
void SetScissor(bool a2, const GLRect& a3);
void SetShader(GLShader::ShaderType shaderType, GLShader* shader);
void SetShaderConstants(GLShader::ShaderType shaderType, uint32_t index, const float* constants, uint32_t count);
void SetShaderConstantsInternal(GLShader::ShaderType shaderType, uint32_t index, const float* constants, uint32_t count);
void SetTexture(uint32_t stage, GLTexture* texture);
void SetTransform(GLEnum transform, const float* a3);
void SetUnpackClientStorage(bool enable);
void SetVertexBuffer(uint32_t index, GLBuffer* buffer, uint32_t offset, uint32_t stride);
void SetVertexFormat(GLVertexFormat* format);
void SetViewport(const GLRect& viewport, double zNear, double zFar);
void Sub34BB0(GLEnum a2, GLMipmap* a3, uint32_t index);
void Sub38460(bool);
void Swap(void);
void UpdateFFPTexturing(void);
void Sub38460(bool a2);
void Swap();
void UpdateFFPTexturing();
};
#endif

View File

@ -1,5 +1,58 @@
#include "gx/gll/GLTypes.h"
#include <cstring>
GLColor4f GLColor4f::ZERO = { 0.0, 0.0, 0.0, 0.0 };
GLColor4f GLColor4f::WHITE = { 1.0, 1.0, 1.0, 1.0 };
GLColor4f GLColor4f::BLACK = { 0.0, 0.0, 0.0, 1.0 };
bool GLTransform::operator==(const float m[16]) const {
return this->m[0] == m[0]
&& this->m[1] == m[1]
&& this->m[2] == m[2]
&& this->m[3] == m[3]
&& this->m[4] == m[4]
&& this->m[5] == m[5]
&& this->m[6] == m[6]
&& this->m[7] == m[7]
&& this->m[8] == m[8]
&& this->m[9] == m[9]
&& this->m[10] == m[10]
&& this->m[11] == m[11]
&& this->m[12] == m[12]
&& this->m[13] == m[13]
&& this->m[14] == m[14]
&& this->m[15] == m[15];
}
bool GLTransform::operator!=(const float m[16]) const {
return !(*this == m);
}
void GLTransform::Set(const float m[16]) {
memcpy(this->m, m, sizeof(this->m));
this->isDirty = true;
this->isIdentity = this->a0 == 1.0f
&& this->a1 == 0.0f
&& this->a2 == 0.0f
&& this->a3 == 0.0f
&& this->b0 == 0.0f
&& this->b1 == 1.0f
&& this->b2 == 0.0f
&& this->b3 == 0.0f
&& this->c0 == 0.0f
&& this->c1 == 0.0f
&& this->c2 == 1.0f
&& this->c3 == 0.0f
&& this->d0 == 0.0f
&& this->d1 == 0.0f
&& this->d2 == 0.0f
&& this->d3 == 1.0f;
}
void GLTransform::SetIdentity() {
memset(this->m, 0, sizeof(this->m));
this->a0 = 1.0f;
this->b1 = 1.0f;
this->c2 = 1.0f;
this->d3 = 1.0f;
}

View File

@ -138,6 +138,11 @@ struct GLTransform {
};
bool isIdentity;
bool operator==(const float m[16]) const;
bool operator!=(const float m[16]) const;
void Set(const float m[16]);
void SetIdentity();
};
struct GLStates {

View File

@ -124,7 +124,7 @@ void GLVertexArray::ApplyVertexFormat(GLDevice* device) {
auto vertexBuffer = this->GetProperties().m_VertexBuffer[attrib.stream];
if (useVertexShader || attrib.slot - 1 > 1) {
if (useVertexShader || static_cast<uint32_t>(attrib.slot - 1) > 1) {
if (this->m_GLStates.buffers[0] != vertexBuffer->m_BufferID) {
glBindBuffer(vertexBuffer->m_Type, vertexBuffer->m_BufferID);
this->m_GLStates.buffers[0] = vertexBuffer->m_BufferID;
@ -147,38 +147,164 @@ void GLVertexArray::ApplyVertexFormat(GLDevice* device) {
reinterpret_cast<void*>(offset)
);
} else {
// TODO
switch (attrib.slot) {
case 0: {
glVertexPointer(
k_VertexTypeInfo[attrib.type].m_Size,
k_VertexTypeInfo[attrib.type].m_Type,
stride,
reinterpret_cast<void*>(offset)
);
break;
}
case 3: {
glNormalPointer(
k_VertexTypeInfo[attrib.type].m_Type,
stride,
reinterpret_cast<void*>(offset)
);
break;
}
case 4: {
glColorPointer(
k_VertexTypeInfo[attrib.type].m_Size,
k_VertexTypeInfo[attrib.type].m_Type,
stride,
reinterpret_cast<void*>(offset)
);
break;
}
case 5: {
glSecondaryColorPointer(
k_VertexTypeInfo[attrib.type].m_Size,
k_VertexTypeInfo[attrib.type].m_Type,
stride,
reinterpret_cast<void*>(offset)
);
break;
}
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13: {
auto tmu = attrib.slot - 6;
auto texCoordIndex = device->m_States.fixedFunc.texCoordIndex[tmu];
glClientActiveTextureARB(GL_TEXTURE0 + texCoordIndex);
glTexCoordPointer(
k_VertexTypeInfo[attrib.type].m_Size,
k_VertexTypeInfo[attrib.type].m_Type,
stride,
reinterpret_cast<void*>(offset)
);
break;
}
}
}
}
}
for (int32_t s = 0; s < 16; s++) {
bool* prevAttribEnable;
// Shader
if (useVertexShader) {
prevAttribEnable = &this->m_GLStates.vertexAttribs[s].enable;
} else {
// TODO
}
auto prevAttribEnable = &this->m_GLStates.vertexAttribs[s].enable;
if (*prevAttribEnable != attribEnable[s]) {
if (attribEnable[s]) {
if (useVertexShader) {
glEnableVertexAttribArrayARB(s);
} else {
// TODO
}
} else {
if (useVertexShader) {
glDisableVertexAttribArrayARB(s);
}
}
*prevAttribEnable = attribEnable[s];
// FFP
} else {
// TODO
bool* prevAttribEnable = nullptr;
GLenum glArray = GL_NONE;
switch (s) {
case 0: {
prevAttribEnable = &this->m_GLStates.position.enable;
glArray = GL_VERTEX_ARRAY;
break;
}
case 3: {
prevAttribEnable = &this->m_GLStates.normal.enable;
glArray = GL_NORMAL_ARRAY;
break;
}
case 4: {
prevAttribEnable = &this->m_GLStates.color0.enable;
glArray = GL_COLOR_ARRAY;
break;
}
case 5: {
prevAttribEnable = &this->m_GLStates.color1.enable;
glArray = GL_SECONDARY_COLOR_ARRAY;
break;
}
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13: {
auto tmu = s - 6;
auto texCoordIndex = device->m_States.fixedFunc.texCoordIndex[tmu];
prevAttribEnable = &this->m_GLStates.texCoord[texCoordIndex].enable;
glArray = GL_TEXTURE_COORD_ARRAY;
glClientActiveTextureARB(GL_TEXTURE0 + texCoordIndex);
break;
}
default:
break;
}
if (prevAttribEnable) {
if (*prevAttribEnable != attribEnable[s]) {
if (attribEnable[s]) {
glEnableClientState(glArray);
} else {
glDisableClientState(glArray);
}
}
*prevAttribEnable = attribEnable[s];
}
}
}
if (!useVertexShader) {
// TODO device->SetColorMaterial(this->m_GLStates.color0.enable);
}
}
GLVertexArray::Properties& GLVertexArray::GetProperties() {

View File

@ -132,8 +132,9 @@ int32_t CBLPFile::LockChain2(const char* fileName, PIXEL_FORMAT format, MipBits*
}
int32_t CBLPFile::Open(const char* filename, int32_t a3) {
STORM_ASSERT(filename);
STORM_VALIDATE(filename, ERROR_INVALID_PARAMETER, 0);
STORM_VALIDATE_BEGIN;
STORM_VALIDATE(filename);
STORM_VALIDATE_END;
this->m_inMemoryImage = nullptr;

View File

@ -1,6 +1,4 @@
#include "math/Types.hpp"
#include "math/Utils.hpp"
#include <cmath>
fixed16::operator float() const {
return this->n / 32767.0f;

View File

@ -67,8 +67,8 @@ int32_t CM2SceneRender::s_shadedList[M2BLEND_COUNT] = {
0 // M2BLEND_MOD_2X
};
void CM2SceneRender::Draw(M2PASS pass, M2Element* elements, uint32_t* a4, uint32_t a5) {
if (!a5) {
void CM2SceneRender::Draw(M2PASS pass, M2Element* elements, uint32_t* indices, uint32_t count) {
if (!count) {
return;
}
@ -103,9 +103,8 @@ void CM2SceneRender::Draw(M2PASS pass, M2Element* elements, uint32_t* a4, uint32
this->m_curPass = pass;
for (int32_t i = 0; i < a5; i++) {
uint32_t index = a4[i];
auto element = &elements[index];
for (int32_t i = 0; i < count; i++) {
auto element = &elements[indices[i]];
if (element->type == 2 || element->type == 4 || !element->model->m_flag2000) {
this->m_curElement = element;
@ -136,7 +135,7 @@ void CM2SceneRender::Draw(M2PASS pass, M2Element* elements, uint32_t* a4, uint32
}
case 2: {
this->DrawBatchDoodad(elements, &a4[i]);
this->DrawBatchDoodad(elements, &indices[i]);
// TODO
// i += this->m_curElement->dword1C - 1;
break;
@ -148,7 +147,7 @@ void CM2SceneRender::Draw(M2PASS pass, M2Element* elements, uint32_t* a4, uint32
}
case 4: {
i += this->DrawParticle(i, elements, a4, a5);
i += this->DrawParticle(i, elements, indices, count);
break;
}

View File

@ -1,7 +1,7 @@
#include "model/Model2.hpp"
#include "model/CM2Cache.hpp"
#include "model/M2Internal.hpp"
#include "util/CVar.hpp"
#include "console/CVar.hpp"
#include "util/Filesystem.hpp"
#include <cstring>
#include <new>

View File

@ -1,4 +1,24 @@
file(GLOB PRIVATE_SOURCES "*.cpp" "connection/*.cpp" "grunt/*.cpp" "login/*.cpp" "srp/*.cpp")
file(GLOB PRIVATE_SOURCES
"*.cpp"
"connection/*.cpp"
"grunt/*.cpp"
"login/*.cpp"
"srp/*.cpp"
)
if(WHOA_SYSTEM_WIN)
file(GLOB WINSOCK_SOURCES
"connection/winsock/*.cpp"
)
list(APPEND PRIVATE_SOURCES ${WINSOCK_SOURCES})
endif()
if(WHOA_SYSTEM_MAC OR WHOA_SYSTEM_LINUX)
file(GLOB BSD_SOURCES
"connection/bsd/*.cpp"
)
list(APPEND PRIVATE_SOURCES ${BSD_SOURCES})
endif()
add_library(net STATIC
${PRIVATE_SOURCES}

View File

@ -110,15 +110,22 @@ const char* s_errorCodeTokens[] = {
"CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME",
};
void ClientConnection::AccountLogin_Finish(int32_t errorCode) {
this->Complete(errorCode == 12, errorCode);
}
void ClientConnection::AccountLogin_Queued() {
this->m_statusCop = COP_WAIT_QUEUE;
this->m_errorCode = 27;
this->m_statusComplete = 0;
// TODO LogConnectionStatus(this->m_statusCop, 27, 1);
// TODO CGlueMgr::UpdateWaitQueue(this->m_queuePosition);
}
void ClientConnection::Cancel(int32_t errorCode) {
this->Cleanup();
this->m_statusResult = 0;
this->m_errorCode = errorCode;
this->m_statusComplete = 1;
// TODO
// LogConnectionStatus(this->m_statusCop, errorCode, 0);
this->Complete(0, errorCode);
}
void ClientConnection::Cleanup() {
@ -128,6 +135,16 @@ void ClientConnection::Cleanup() {
}
}
void ClientConnection::Complete(int32_t result, int32_t errorCode) {
this->Cleanup();
this->m_statusResult = result;
this->m_errorCode = errorCode;
this->m_statusComplete = 1;
// TODO LogConnectionStatus(this->m_statusCop, errorCode, 0);
}
void ClientConnection::Connect() {
// TODO
@ -146,6 +163,25 @@ int32_t ClientConnection::Disconnect() {
return 0;
}
int32_t ClientConnection::HandleConnect() {
this->Complete(1, 5);
this->m_connected = 1;
// TODO WardenClient_Initialize();
return this->NetClient::HandleConnect();
}
void ClientConnection::Initiate(WOWCS_OPS op, int32_t errorCode, void (*cleanup)()) {
this->m_cleanup = cleanup;
this->m_statusCop = op;
this->m_errorCode = errorCode;
this->m_statusComplete = 0;
// TODO LogConnectionStatus(this->m_statusCop, errorCode, 1);
}
int32_t ClientConnection::IsConnected() {
return this->m_connected;
}
@ -179,13 +215,3 @@ int32_t ClientConnection::PollStatus(WOWCS_OPS& op, const char** msg, int32_t& r
return this->m_statusComplete;
}
void ClientConnection::SetStatus(int32_t result, int32_t errorCode) {
this->Cleanup();
this->m_statusResult = result;
this->m_errorCode = errorCode;
this->m_statusComplete = 1;
// TODO LogConnectionStatus(this->m_statusCop, errorCode, 0);
}

View File

@ -16,17 +16,23 @@ class ClientConnection : public RealmConnection {
int32_t m_errorCode = 0;
void (*m_cleanup)() = nullptr;
// Virtual member functions
virtual int32_t HandleConnect();
// Member functions
ClientConnection(RealmResponse* realmResponse)
: RealmConnection(realmResponse)
{};
void AccountLogin_Finish(int32_t authResult);
void AccountLogin_Queued();
void Cancel(int32_t errorCode);
void Cleanup();
void Complete(int32_t result, int32_t errorCode);
void Connect();
int32_t Disconnect();
void Initiate(WOWCS_OPS op, int32_t errorCode, void (*cleanup)());
int32_t IsConnected();
int32_t PollStatus(WOWCS_OPS& op, const char** msg, int32_t& result, int32_t& errorCode);
void SetStatus(int32_t result, int32_t errorCode);
};
#endif

View File

@ -5,7 +5,6 @@
#include <new>
#include <common/DataStore.hpp>
#include <common/Prop.hpp>
#include <common/SHA1.hpp>
#include <common/Time.hpp>
#include <storm/Error.hpp>
#include <storm/String.hpp>
@ -94,7 +93,7 @@ void NETEVENTQUEUE::Poll() {
client->DelRef();
this->m_eventQueue.DeleteAll();
this->m_eventQueue.Clear();
this->m_critSect.Leave();
}
@ -140,7 +139,7 @@ void NetClient::Connect(const char* addrStr) {
port = atoi(portDelim + 1);
}
this->m_serverConnection->SetEncryptionType(WC_ENCRYPT_0);
this->m_serverConnection->SetEncryption(false);
this->m_netState = NS_INITIALIZED;
this->ConnectInternal(host, port);
}
@ -166,10 +165,29 @@ void NetClient::DelRef() {
}
}
void NetClient::EnableEncryption(WowConnection* conn, uint8_t* seed, uint8_t seedLen) {
conn->SetEncryptionKey(
this->m_loginData.m_sessionKey,
sizeof(this->m_loginData.m_sessionKey),
1,
seed,
seedLen
);
conn->uint375 = 4;
conn->uint376 = 2;
conn->SetEncryption(true);
}
bool NetClient::GetDelete() {
return this->m_deleteMe;
}
const LoginData& NetClient::GetLoginData() {
return this->m_loginData;
}
NETSTATE NetClient::GetState() {
return this->m_netState;
}
@ -190,7 +208,14 @@ int32_t NetClient::HandleConnect() {
}
int32_t NetClient::HandleData(uint32_t timeReceived, void* data, int32_t size) {
// TODO
// TODO push obj mgr
CDataStore msg = CDataStore(static_cast<uint8_t*>(data), size);
this->ProcessMessage(timeReceived, &msg, 0);
// TODO pop obj mgr
return 1;
}
@ -240,6 +265,53 @@ void NetClient::PongHandler(WowConnection* conn, CDataStore* msg) {
// TODO
}
void NetClient::ProcessMessage(uint32_t timeReceived, CDataStore* msg, int32_t a4) {
// TODO s_stats.messagesReceived++
uint16_t msgId;
msg->Get(msgId);
// TODO virtual function call on NetClient
if (msgId >= NUM_MSG_TYPES || !this->m_handlers[msgId]) {
msg->Reset();
return;
}
this->m_handlers[msgId](
this->m_handlerParams[msgId],
static_cast<NETMESSAGE>(msgId),
timeReceived,
msg
);
}
void NetClient::Send(CDataStore* msg) {
if (this->m_netState != NS_CONNECTED) {
return;
}
auto v4 = msg->Size() - msg->Tell();
if (!v4) {
return;
}
if (this->m_suspended) {
// TODO
} else {
this->m_serverConnection->Send(msg, 0);
// TODO
this->m_bytesSent += v4;
if (!this->m_serverConnection->m_encrypt) {
this->EnableEncryption(this->m_serverConnection, nullptr, 0);
}
}
}
void NetClient::SetDelete() {
this->m_deleteMe = true;
}
@ -282,12 +354,12 @@ void NetClient::WCDisconnected(WowConnection* conn, uint32_t timeStamp, NETCONNA
void NetClient::WCMessageReady(WowConnection* conn, uint32_t timeStamp, CDataStore* msg) {
uint8_t* data;
msg->GetDataInSitu(reinterpret_cast<void*&>(data), msg->m_size);
msg->GetDataInSitu(reinterpret_cast<void*&>(data), msg->Size());
// TODO increment byte counter
// SInterlockedExchangeAdd(this->m_bytesReceived, msg->m_size);
msg->m_read = 0;
msg->Seek(0);
uint16_t msgId;
msg->Get(msgId);
@ -305,8 +377,8 @@ void NetClient::WCMessageReady(WowConnection* conn, uint32_t timeStamp, CDataSto
}
if (conn == this->m_serverConnection && !this->m_suspended) {
msg->m_read = msg->m_size;
this->m_netEventQueue->AddEvent(EVENT_ID_NET_DATA, conn, this, data, msg->m_size);
msg->Seek(msg->Size());
this->m_netEventQueue->AddEvent(EVENT_ID_NET_DATA, conn, this, data, msg->Size());
} else {
conn->Disconnect();
}

View File

@ -64,12 +64,16 @@ class NetClient : public WowConnectionResponse {
void Connect(const char* addrStr);
int32_t ConnectInternal(const char* host, uint16_t port);
void DelRef();
void EnableEncryption(WowConnection* conn, uint8_t* seed, uint8_t seedLen);
bool GetDelete();
const LoginData& GetLoginData();
NETSTATE GetState();
void HandleIdle();
int32_t Initialize();
void PollEventQueue();
void PongHandler(WowConnection* conn, CDataStore* msg);
void ProcessMessage(uint32_t timeReceived, CDataStore* msg, int32_t a4);
void Send(CDataStore* msg);
void SetDelete();
void SetLoginData(LoginData* loginData);
void SetMessageHandler(NETMESSAGE msgId, MESSAGE_HANDLER handler, void* param);

View File

@ -1,12 +1,72 @@
#include "net/connection/RealmConnection.hpp"
#include "net/connection/RealmResponse.hpp"
#include "net/Types.hpp"
#include <common/DataStore.hpp>
#include <common/SHA1.hpp>
#include <storm/String.hpp>
SCritSect RealmConnection::s_AllRealmConnectionsCrit;
STORM_LIST(RealmConnection::REALMCONNECTIONNODE) RealmConnection::s_AllRealmConnections;
int32_t RealmConnection::MessageHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg) {
auto connection = static_cast<RealmConnection*>(param);
int32_t result = 0;
switch (msgId) {
case SMSG_AUTH_RESPONSE: {
result = connection->HandleAuthResponse(msgId, time, msg);
break;
}
case SMSG_CREATE_CHAR: {
// TODO
return 0;
break;
}
case SMSG_ENUM_CHARACTERS_RESULT: {
// TODO
break;
}
case SMSG_DELETE_CHAR: {
// TODO
break;
}
case SMSG_CHARACTER_LOGIN_FAILED: {
// TODO
break;
}
case SMSG_ADDON_INFO: {
// TODO
break;
}
case SMSG_LOGOUT_CANCEL_ACK: {
// TODO
break;
}
case SMSG_LOGOUT_COMPLETE: {
// TODO
break;
}
case SMSG_LOGOUT_RESPONSE: {
// TODO
break;
}
default:
break;
}
if (!msg->IsRead()) {
// TODO
}
return result;
}
void RealmConnection::PollNet() {
@ -46,6 +106,90 @@ RealmConnection::RealmConnection(RealmResponse* realmResponse) {
int32_t RealmConnection::HandleAuthChallenge(AuthenticationChallenge* challenge) {
// TODO
// TODO switch to WDataStore
CDataStore msg;
uint32_t localChallenge;
msg.Put(static_cast<uint32_t>(CMSG_AUTH_SESSION));
msg.Put(static_cast<uint32_t>(12340));
msg.Put(static_cast<uint32_t>(this->GetLoginData().m_loginServerID));
msg.PutString(this->GetLoginData().m_account);
msg.Put(static_cast<uint32_t>(this->GetLoginData().m_loginServerType));
// TODO
msg.Put(localChallenge);
// TODO
msg.Put(static_cast<uint32_t>(0));
msg.Put(static_cast<uint32_t>(0));
msg.Put(static_cast<uint32_t>(1));
// TODO
msg.Put(static_cast<uint64_t>(0));
uint32_t msgId = 0;
SHA1_CONTEXT ctx;
SHA1_Init(&ctx);
SHA1_Update(&ctx, reinterpret_cast<const uint8_t*>(this->GetLoginData().m_account), SStrLen(this->GetLoginData().m_account));
SHA1_Update(&ctx, reinterpret_cast<uint8_t*>(&msgId), sizeof(msgId));
SHA1_Update(&ctx, reinterpret_cast<uint8_t*>(&localChallenge), sizeof(localChallenge));
SHA1_Update(&ctx, reinterpret_cast<uint8_t*>(&challenge->uint0), sizeof(challenge->uint0));
SHA1_Update(&ctx, this->GetLoginData().m_sessionKey, sizeof(this->GetLoginData().m_sessionKey));
uint8_t clientProof[SHA1_DIGEST_SIZE];
SHA1_Final(clientProof, &ctx);
msg.PutData(clientProof, sizeof(clientProof));
// TODO addons
msg.Put(static_cast<uint32_t>(0));
msg.Finalize();
this->Send(&msg);
return 1;
}
int32_t RealmConnection::HandleAuthResponse(uint32_t msgId, uint32_t time, CDataStore* msg) {
if (this->m_realmResponse) {
this->m_realmResponse->GameServerResult(this, "SMSG_AUTH_RESPONSE", nullptr, nullptr);
}
uint8_t authResult;
msg->Get(authResult);
// AUTH_OK or AUTH_WAIT_QUEUE
if (authResult == 12 || authResult == 27) {
// AUTH_OK
if (authResult == 12) {
this->m_authenticated = 1;
}
if (msg->Size() - msg->Tell() >= 10 + (authResult == 27 ? 5 : 0)) {
msg->Get(this->m_billingTimeRemaining);
msg->Get(this->m_billingFlags);
msg->Get(this->m_billingTimeRested);
msg->Get(this->m_accountExpansion);
}
// AUTH_WAIT_QUEUE
if (authResult == 27) {
msg->Get(this->m_queuePosition);
uint8_t freeCharacterMigration;
msg->Get(freeCharacterMigration);
this->m_freeCharacterMigration = freeCharacterMigration;
}
}
this->m_realmResponse->HandleAuthResponse(this, authResult);
return 1;
}

View File

@ -24,12 +24,20 @@ class RealmConnection : public NetClient {
// Member variables
RealmResponse* m_realmResponse;
uint8_t m_authenticated = 0;
uint32_t m_queuePosition = 0;
uint32_t m_freeCharacterMigration = 0;
uint32_t m_billingTimeRemaining = 0;
uint32_t m_billingTimeRested = 0;
uint8_t m_billingFlags = 0;
uint8_t m_accountExpansion = 0;
// Virtual member functions
virtual int32_t HandleAuthChallenge(AuthenticationChallenge* challenge);
// Member functions
RealmConnection(RealmResponse* realmResponse);
int32_t HandleAuthResponse(uint32_t msgId, uint32_t time, CDataStore* msg);
void SetSelectedRealm(uint32_t a2, uint32_t a3, uint32_t a4);
};

View File

@ -3,6 +3,9 @@
class RealmResponse {
public:
// Virtual member functions
virtual void HandleAuthResponse(RealmConnection* connection, uint8_t authResult) = 0;
virtual void GameServerResult(RealmConnection* connection, const char* a3, const char* a4, const char* a5) = 0;
};
#endif

View File

@ -1,6 +1,7 @@
#include "net/connection/WowConnection.hpp"
#include "net/connection/WowConnectionNet.hpp"
#include "net/connection/WowConnectionResponse.hpp"
#include "util/HMAC.hpp"
#include <common/DataStore.hpp>
#include <common/Time.hpp>
#include <storm/Error.hpp>
@ -8,6 +9,7 @@
#include <storm/String.hpp>
#include <storm/Thread.hpp>
#include <algorithm>
#include <cstring>
#include <new>
#if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
@ -27,10 +29,61 @@
uint64_t WowConnection::s_countTotalBytes;
int32_t WowConnection::s_destroyed;
int32_t WowConnection::s_lagTestDelayMin;
WowConnectionNet* WowConnection::s_network;
ATOMIC32 WowConnection::s_numWowConnections;
bool (*WowConnection::s_verifyAddr)(const NETADDR*);
static uint8_t s_arc4drop1024[1024] = { 0x00 };
static uint8_t s_arc4seed[] = {
// Receive key
0xCC, 0x98, 0xAE, 0x04, 0xE8, 0x97, 0xEA, 0xCA, 0x12, 0xDD, 0xC0, 0x93, 0x42, 0x91, 0x53, 0x57,
// Send key
0xC2, 0xB3, 0x72, 0x3C, 0xC6, 0xAE, 0xD9, 0xB5, 0x34, 0x3C, 0x53, 0xEE, 0x2F, 0x43, 0x67, 0xCE,
};
WowConnection::SENDNODE::SENDNODE(void* data, int32_t size, uint8_t* buf, bool raw) : TSLinkedNode<WowConnection::SENDNODE>() {
if (data) {
this->data = buf;
}
if (raw) {
memcpy(this->data, data, size);
this->size = size;
} else {
uint32_t headerSize = size > 0x7FFF ? 3 : 2;
if (!data) {
this->data = &buf[-headerSize];
}
auto headerBuf = static_cast<uint8_t*>(this->data);
// Write 2 or 3 byte data size value to header in big endian order
if (size > 0x7FFF) {
headerBuf[0] = ((size >> (8 * 2)) & 0xff) | 0x80;
headerBuf[1] = (size >> (8 * 1)) & 0xff;
headerBuf[2] = (size >> (8 * 0)) & 0xff;
} else {
headerBuf[0] = (size >> (8 * 1)) & 0xff;
headerBuf[1] = (size >> (8 * 0)) & 0xff;
}
if (data) {
memcpy(static_cast<uint8_t*>(&this->data[headerSize]), data, size);
}
this->size = size + headerSize;
}
this->datasize = size;
this->offset = 0;
this->allocsize = 0;
memcpy(this->header, this->data, std::min(this->size, 8u));
}
int32_t WowConnection::CreateSocket() {
int32_t sock = socket(AF_INET, SOCK_STREAM, 0);
@ -332,19 +385,17 @@ void WowConnection::DoMessageReads() {
// TODO
while (true) {
auto v36 = 2;
auto v35 = -1;
auto headerSize = 2;
auto size = -1;
if (this->m_readBytes >= 2) {
uint8_t v14;
if (*this->m_readBuffer >= 0) {
v35 = (this->m_readBuffer[1] | ((this->m_readBuffer[0] & 0x7F) << 8)) + 2;
if (this->m_readBytes >= headerSize) {
if ((this->m_readBuffer[0] & 0x80) == 0) {
size = (this->m_readBuffer[1] | ((this->m_readBuffer[0] & 0x7F) << 8)) + headerSize;
} else {
v36 = 3;
headerSize = 3;
if (this->m_readBytes >= 3) {
v35 = (this->m_readBuffer[2] | ((this->m_readBuffer[1] | ((this->m_readBuffer[0] & 0x7F) << 8)) << 8)) + 3;
if (this->m_readBytes >= headerSize) {
size = (this->m_readBuffer[2] | ((this->m_readBuffer[1] | ((this->m_readBuffer[0] & 0x7F) << 8)) << 8)) + headerSize;
}
}
}
@ -366,15 +417,15 @@ void WowConnection::DoMessageReads() {
}
}
int32_t v17;
int32_t bytesToRead;
if (v35 >= 0) {
v17 = v35 - this->m_readBytes;
if (this->m_readBufferSize - this->m_readBytes < v35 - this->m_readBytes) {
v17 = this->m_readBufferSize - this->m_readBytes;
if (size >= 0) {
bytesToRead = size - this->m_readBytes;
if (this->m_readBufferSize - this->m_readBytes < size - this->m_readBytes) {
bytesToRead = this->m_readBufferSize - this->m_readBytes;
}
} else {
v17 = v36 - this->m_readBytes;
bytesToRead = headerSize - this->m_readBytes;
}
#if defined(WHOA_SYSTEM_WIN)
@ -383,11 +434,11 @@ void WowConnection::DoMessageReads() {
ssize_t bytesRead;
#endif
if (v17 <= 0) {
if (bytesToRead <= 0) {
bytesRead = 0;
} else {
while (true) {
bytesRead = recv(this->m_sock, reinterpret_cast<char*>(&this->m_readBuffer[this->m_readBytes]), v17, 0x0);
bytesRead = recv(this->m_sock, reinterpret_cast<char*>(&this->m_readBuffer[this->m_readBytes]), bytesToRead, 0x0);
if (bytesRead >= 0) {
break;
@ -404,23 +455,30 @@ void WowConnection::DoMessageReads() {
#endif
}
// TODO
}
if (bytesRead <= 0 && v17 > 0) {
if (bytesRead <= 0) {
break;
}
}
// TODO
if (this->m_encrypt) {
auto v22 = headerSize + this->uint376 - this->m_readBytes;
auto v23 = v22 <= 0 ? 0 : v22;
if (v23 >= bytesRead) {
v23 = bytesRead;
}
SARC4ProcessBuffer(
&this->m_readBuffer[this->m_readBytes],
v23,
&this->m_receiveKey,
&this->m_receiveKey
);
}
this->m_readBytes += bytesRead;
if (v35 >= 0 && this->m_readBytes >= v35) {
CDataStore msg;
msg.m_data = &this->m_readBuffer[v36];
msg.m_alloc = -1;
msg.m_size = v35 - v36;
msg.m_read = 0;
if (size >= 0 && this->m_readBytes >= size) {
CDataStore msg = CDataStore(&this->m_readBuffer[headerSize], size - headerSize);
this->AcquireResponseRef();
@ -556,6 +614,11 @@ void WowConnection::DoWrites() {
this->Release();
}
void WowConnection::FreeSendNode(SENDNODE* sn) {
// TODO WDataStore::FreeBuffer(sn, sn->datasize + sizeof(SENDNODE) + 3);
SMemFree(sn, __FILE__, __LINE__, 0x0);
}
WOW_CONN_STATE WowConnection::GetState() {
return this->m_connState;
}
@ -568,6 +631,12 @@ void WowConnection::Init(WowConnectionResponse* response, void (*func)(void)) {
// TODO
this->m_sendDepth = 0;
this->m_sendDepthBytes = 0;
this->m_maxSendDepth = 100000;
// TODO
this->m_connState = WOWC_UNINITIALIZED;
// TODO
@ -590,12 +659,34 @@ void WowConnection::Init(WowConnectionResponse* response, void (*func)(void)) {
this->m_readBytes = 0;
this->m_readBufferSize = 0;
this->m_event = nullptr;
this->m_encrypt = false;
// TODO
this->SetState(WOWC_INITIALIZED);
this->m_type = WOWC_TYPE_MESSAGES;
}
WowConnection::SENDNODE* WowConnection::NewSendNode(void* data, int32_t size, bool raw) {
// TODO counters
// SENDNODEs are prefixed to their buffers, with an extra 3 bytes reserved for size-prefixing
uint32_t allocsize = size + sizeof(SENDNODE) + 3;
// TODO WDataStore::AllocBuffer(allocsize);
auto m = SMemAlloc(allocsize, __FILE__, __LINE__, 0x0);
auto buf = &static_cast<uint8_t*>(m)[sizeof(SENDNODE)];
auto sn = new (m) SENDNODE(data, size, buf, raw);
sn->allocsize = allocsize;
// TODO latency tracking
return sn;
}
void WowConnection::Release() {
if (SInterlockedDecrement(&this->m_refCount) <= 0) {
if (WowConnection::s_network) {
@ -624,6 +715,96 @@ void WowConnection::ReleaseResponseRef() {
this->m_responseLock.Leave();
}
WC_SEND_RESULT WowConnection::Send(CDataStore* msg, int32_t a3) {
uint8_t* data;
msg->GetDataInSitu(reinterpret_cast<void*&>(data), msg->Size());
WowConnection::s_countTotalBytes += msg->Size();
this->m_lock.Enter();
if (msg->Size() == 0 || this->m_connState != WOWC_CONNECTED) {
this->m_lock.Leave();
return WC_SEND_ERROR;
}
// Queue send
if (WowConnection::s_lagTestDelayMin || this->m_sendList.Head()) {
auto sn = this->NewSendNode(data, msg->Size(), false);
if (this->m_encrypt) {
auto bufSize = std::min(sn->size, sn->size + this->uint375 - sn->datasize);
SARC4ProcessBuffer(sn->data, bufSize, &this->m_sendKey, &this->m_sendKey);
}
this->m_sendList.LinkToTail(sn);
this->m_sendDepth++;
this->m_sendDepthBytes += sn->size;
WowConnection::s_network->PlatformChangeState(this, this->m_connState);
if (this->m_sendDepth < this->m_maxSendDepth) {
this->m_lock.Leave();
return WC_SEND_QUEUED;
} else {
// TODO handle max queue send depth reached
this->m_lock.Leave();
return WC_SEND_ERROR;
}
}
// Send immediately
SENDNODE* sn;
bool snOnStack;
if (msg->Size() > 100000) {
snOnStack = false;
sn = this->NewSendNode(data, msg->Size(), false);
} else if (a3 < 3) {
snOnStack = true;
auto m = alloca(msg->Size() + sizeof(SENDNODE) + 3);
auto buf = &static_cast<uint8_t*>(m)[sizeof(SENDNODE)];
sn = new (m) SENDNODE(data, msg->Size(), buf, false);
} else {
snOnStack = true;
auto m = alloca(msg->Size() + sizeof(SENDNODE));
auto buf = &static_cast<uint8_t*>(m)[sizeof(SENDNODE)];
sn = new (m) SENDNODE(nullptr, msg->Size(), buf, false);
}
if (this->m_encrypt) {
auto bufSize = std::min(sn->size, sn->size + this->uint375 - sn->datasize);
SARC4ProcessBuffer(sn->data, bufSize, &this->m_sendKey, &this->m_sendKey);
}
uint32_t written;
#if defined(WHOA_SYSTEM_WIN)
written = send(this->m_sock, reinterpret_cast<char*>(sn->data), sn->size, 0x0);
#elif defined(WHOA_SYSTEM_MAC)
written = write(this->m_sock, sn->data, sn->size);
#endif
if (written == sn->size) {
if (!snOnStack) {
this->FreeSendNode(sn);
}
this->m_lock.Leave();
return WC_SEND_SENT;
}
// TODO split writes, errors, etc
STORM_ASSERT(false);
return WC_SEND_ERROR;
}
WC_SEND_RESULT WowConnection::SendRaw(uint8_t* data, int32_t len, bool a4) {
WowConnection::s_countTotalBytes += len;
@ -635,7 +816,20 @@ WC_SEND_RESULT WowConnection::SendRaw(uint8_t* data, int32_t len, bool a4) {
STORM_ASSERT(this->m_sock >= 0);
#if defined (WHOA_SYSTEM_WIN)
if (this->m_sendList.Head()) {
// TODO
} else {
auto written = send(this->m_sock, reinterpret_cast<char*>(data), len, 0x0);
if (written == len) {
this->m_lock.Leave();
return WC_SEND_SENT;
}
if (written < 0) {
// TODO
}
}
#elif defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
if (this->m_sendList.Head()) {
// TODO
@ -657,8 +851,43 @@ WC_SEND_RESULT WowConnection::SendRaw(uint8_t* data, int32_t len, bool a4) {
return WC_SEND_ERROR;
}
void WowConnection::SetEncryptionType(WC_ENCRYPT_TYPE encryptType) {
// TODO
void WowConnection::SetEncryption(bool enabled) {
this->m_lock.Enter();
this->m_encrypt = enabled;
SARC4PrepareKey(this->m_sendKeyInit, sizeof(this->m_sendKeyInit), &this->m_sendKey);
SARC4PrepareKey(this->m_receiveKeyInit, sizeof(this->m_receiveKeyInit), &this->m_receiveKey);
SARC4ProcessBuffer(s_arc4drop1024, sizeof(s_arc4drop1024), &this->m_sendKey, &this->m_sendKey);
SARC4ProcessBuffer(s_arc4drop1024, sizeof(s_arc4drop1024), &this->m_receiveKey, &this->m_receiveKey);
this->m_lock.Leave();
}
void WowConnection::SetEncryptionKey(const uint8_t* key, uint8_t keyLen, uint8_t a4, const uint8_t* seedData, uint8_t seedLen) {
if (!seedData) {
seedData = s_arc4seed;
seedLen = sizeof(s_arc4seed);
}
const uint8_t* seeds[] = {
seedData,
&seedData[seedLen / 2]
};
// Note: The original HMAC-SHA1 implementation uses a second SHA1 implementation shipped in
// the client. For simplicity's sake, we're currently using a custom util function built on
// top of the SHA1 implementation used for SRP6 authentication.
HMAC_SHA1(seeds[a4], seedLen / 2, key, keyLen, this->m_sendKeyInit);
HMAC_SHA1(seeds[a4 ^ 1], seedLen / 2, key, keyLen, this->m_receiveKeyInit);
SARC4PrepareKey(this->m_sendKeyInit, sizeof(this->m_sendKeyInit), &this->m_sendKey);
SARC4PrepareKey(this->m_receiveKeyInit, sizeof(this->m_receiveKeyInit), &this->m_receiveKey);
SARC4ProcessBuffer(s_arc4drop1024, sizeof(s_arc4drop1024), &this->m_sendKey, &this->m_sendKey);
SARC4ProcessBuffer(s_arc4drop1024, sizeof(s_arc4drop1024), &this->m_receiveKey, &this->m_receiveKey);
}
void WowConnection::SetState(WOW_CONN_STATE state) {
@ -697,11 +926,15 @@ void WowConnection::StartConnect() {
return;
}
#if defined(WHOA_SYSTEM_MAC)
#if defined(WHOA_SYSTEM_WIN)
u_long argp = 1;
ioctlsocket(this->m_sock, FIONBIO, &argp);
#elif defined(WHOA_SYSTEM_MAC)
fcntl(this->m_sock, F_SETFL, O_NONBLOCK);
uint32_t opt = 1;
setsockopt(this->m_sock, SOL_SOCKET, 4130, &opt, sizeof(opt));
#endif
sockaddr_in addr;
addr.sin_family = AF_INET;
@ -720,11 +953,19 @@ void WowConnection::StartConnect() {
return;
}
#if defined(WHOA_SYSTEM_WIN)
if (WSAGetLastError() == WSAEWOULDBLOCK) {
this->m_lock.Leave();
return;
}
#elif defined(WHOA_SYSTEM_MAC)
if (errno == EAGAIN || errno == EINTR || errno == EINPROGRESS) {
this->m_lock.Leave();
return;
}
#endif
WowConnection::s_network->Remove(this);
this->CloseSocket(this->m_sock);
@ -733,5 +974,4 @@ void WowConnection::StartConnect() {
this->SetState(WOWC_ERROR);
this->m_lock.Leave();
#endif
}

View File

@ -4,6 +4,7 @@
#include "net/Types.hpp"
#include <cstdint>
#include <storm/Atomic.hpp>
#include <storm/Crypto.hpp>
#include <storm/List.hpp>
#include <storm/Thread.hpp>
@ -15,6 +16,7 @@
#include <winsock2.h>
#endif
class CDataStore;
class WowConnectionNet;
class WowConnectionResponse;
@ -26,11 +28,17 @@ class WowConnection {
uint32_t size;
uint32_t offset;
uint32_t datasize;
uint8_t header[8];
uint32_t uint20;
uint32_t allocsize;
SENDNODE(void* data, int32_t size, uint8_t* buf, bool raw);
};
// Static variables
static uint64_t s_countTotalBytes;
static int32_t s_destroyed;
static int32_t s_lagTestDelayMin;
static WowConnectionNet* s_network;
static ATOMIC32 s_numWowConnections;
static bool (*s_verifyAddr)(const NETADDR*);
@ -54,11 +62,22 @@ class WowConnection {
int32_t m_responseRef;
uintptr_t m_responseRefThread;
STORM_LIST(SENDNODE) m_sendList;
int32_t m_sendDepth;
uint32_t m_sendDepthBytes;
int32_t m_maxSendDepth;
uint32_t m_serviceFlags;
TSLink<WowConnection> m_netlink;
SCritSect m_lock;
ATOMIC32 m_serviceCount;
void* m_event;
WOWC_TYPE m_type;
SARC4Key m_sendKey;
SARC4Key m_receiveKey;
uint8_t m_sendKeyInit[20];
uint8_t m_receiveKeyInit[20];
bool m_encrypt;
uint8_t uint375;
uint8_t uint376;
// Member functions
WowConnection(WowConnectionResponse* response, void (*func)(void));
@ -77,12 +96,16 @@ class WowConnection {
void DoReads();
void DoStreamReads();
void DoWrites();
void FreeSendNode(SENDNODE* sn);
WOW_CONN_STATE GetState();
void Init(WowConnectionResponse* response, void (*func)(void));
SENDNODE* NewSendNode(void* data, int32_t size, bool raw);
void Release();
void ReleaseResponseRef();
WC_SEND_RESULT Send(CDataStore* msg, int32_t a3);
WC_SEND_RESULT SendRaw(uint8_t* data, int32_t len, bool a4);
void SetEncryptionType(WC_ENCRYPT_TYPE encryptType);
void SetEncryption(bool enabled);
void SetEncryptionKey(const uint8_t* key, uint8_t keyLen, uint8_t a4, const uint8_t* seed, uint8_t seedLen);
void SetState(WOW_CONN_STATE state);
void SetType(WOWC_TYPE type);
void StartConnect();

Some files were not shown because too many files have changed in this diff Show More