diff --git a/Application/ApplicationAbstract.h b/Application/ApplicationAbstract.h index d7d5fd5..ee05fae 100755 --- a/Application/ApplicationAbstract.h +++ b/Application/ApplicationAbstract.h @@ -19,11 +19,11 @@ namespace Application { - typedef struct { + struct ApplicationAbstract { DataStorage::Database::ConnectionAbstract *db; nlohmann::json config; Threads::ThreadPool *pool; - } ApplicationAbstract; + }; } // namespace Application #endif diff --git a/DataStorage/Database/Connection/ConnectionAbstract.h b/DataStorage/Database/Connection/ConnectionAbstract.h index 557e88c..d6bb46a 100755 --- a/DataStorage/Database/Connection/ConnectionAbstract.h +++ b/DataStorage/Database/Connection/ConnectionAbstract.h @@ -19,11 +19,11 @@ namespace DataStorage::Database { - typedef struct { + struct QueryResult { size_t rows = 0; size_t columns = 0; char **results = NULL; - } QueryResult; + }; struct ConnectionAbstract { void *con = NULL; diff --git a/DataStorage/Database/Connection/DbConnectionConfig.h b/DataStorage/Database/Connection/DbConnectionConfig.h index b601e69..24a063c 100755 --- a/DataStorage/Database/Connection/DbConnectionConfig.h +++ b/DataStorage/Database/Connection/DbConnectionConfig.h @@ -17,7 +17,7 @@ namespace DataStorage::Database { - typedef struct { + struct DbConnectionConfig { DatabaseType db = DatabaseType::UNDEFINED; const char *database = NULL; @@ -29,7 +29,7 @@ namespace DataStorage::Database const char *login = NULL; const char *password = NULL; - } DbConnectionConfig; + }; void free_DbConnectionConfig(DbConnectionConfig *dbdata) { diff --git a/DataStorage/Database/Mapper/DataMapperTypes.h b/DataStorage/Database/Mapper/DataMapperTypes.h index 1830c00..e6e1fd1 100755 --- a/DataStorage/Database/Mapper/DataMapperTypes.h +++ b/DataStorage/Database/Mapper/DataMapperTypes.h @@ -35,10 +35,10 @@ namespace DataStorage::Database FIELD_TYPE_BOOL = 4 } FieldType; - typedef struct { + struct ModelStructure { const char *name = NULL; size_t size = 0; - } ModelStructure; + }; void free_ModelStructure(ModelStructure *data) { @@ -49,13 +49,13 @@ namespace DataStorage::Database */ } - typedef struct { + struct DataMapperColumn { const char *name = NULL; int type = FieldType::FIELD_TYPE_INT; const char *internal = NULL; bool readonly = false; bool autocomplete = false; - } DataMapperColumn; + }; void free_DataMapperColumn(DataMapperColumn *data) { @@ -68,7 +68,7 @@ namespace DataStorage::Database } } - typedef struct { + struct TableRelation { const char *member = NULL; const char *mapper = NULL; const char *external = NULL; @@ -77,7 +77,7 @@ namespace DataStorage::Database const char *column = NULL; bool conditional = false; const char *by = NULL; - } TableRelation; + }; void free_TableRelation(TableRelation *data) { @@ -116,7 +116,7 @@ namespace DataStorage::Database */ } - typedef struct { + struct MapperData { const char *TABLE = NULL; const char *PRIMARYFIELD = NULL; const char *CREATED_AT = NULL; @@ -137,7 +137,7 @@ namespace DataStorage::Database int BELONGS_TO_COUNT = 0; DataStorage::Database::TableRelation *BELONGS_TO = NULL; - } MapperData; + }; void free_MapperData(DataStorage::Database::MapperData *data) { diff --git a/DataStorage/Database/Schema/DbField.h b/DataStorage/Database/Schema/DbField.h index 55e69cd..c7abaf2 100755 --- a/DataStorage/Database/Schema/DbField.h +++ b/DataStorage/Database/Schema/DbField.h @@ -15,7 +15,7 @@ namespace DataStorage::Database { - typedef struct { + struct DbField { char *name; char *type; void *def; @@ -25,7 +25,7 @@ namespace DataStorage::Database bool autoincrement = false; char *foreignTable; char *foreignKey; - } DbField; + }; void free_DbField(DbField *field) { diff --git a/DataStorage/Database/Schema/DbSchema.h b/DataStorage/Database/Schema/DbSchema.h index 6fe0c3b..35f4c9b 100755 --- a/DataStorage/Database/Schema/DbSchema.h +++ b/DataStorage/Database/Schema/DbSchema.h @@ -17,11 +17,11 @@ namespace DataStorage::Database { - typedef struct { + struct DbSchema { char *name; DbField *fields; size_t field_size = 0; - } DbSchema; + }; void free_DbSchema(DbSchema *schema) { diff --git a/Hash/MD5.h b/Hash/MD5.h index 79c3744..6b7ebf4 100755 --- a/Hash/MD5.h +++ b/Hash/MD5.h @@ -23,12 +23,12 @@ namespace Hash { - typedef struct { + struct md5_context { uint32_t lo, hi; uint32_t a, b, c, d; unsigned char buffer[64]; uint32_t block[16]; - } md5_context; + }; static const void *body(md5_context *ctx, const void *data, size_t size) { diff --git a/Input/Input.h b/Input/Input.h new file mode 100644 index 0000000..10a6c9c --- /dev/null +++ b/Input/Input.h @@ -0,0 +1,252 @@ +/** + * Karaka + * + * @package Stdlib + * @copyright Dennis Eichhorn + * @license OMS License 1.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef INPUT_H +#define INPUT_H + +#ifdef _WIN32 + #include +#else +#endif + +#include "../Stdlib/Types.h" +#include "../Utils/TestUtils.h" +#include "../Utils/MathUtils.h" +#include "../UI/Window.h" + +#define MAX_KEY_PRESSES 4 +#define MIN_INPUT_DEVICES 2 + +#define INPUT_TYPE_MOUSE 0x01 +#define INPUT_TYPE_KEYBOARD 0x02 +#define INPUT_TYPE_OTHER 0x03 + +namespace Input { + struct InputState { + // Device + bool is_connected = false; + char name[256]; + byte type = INPUT_TYPE_OTHER; + HANDLE handle_keyboard; + HANDLE handle_mouse; + + // Keyboard + bool key_down = false; + bool key_up = false; + uint16 key = 0; + + // After handling the keyboard state change the game loop should set this to false + bool state_change_keyboard = false; + + // We only consider up to 4 pressed keys + // Depending on the keyboard you may only be able to detect a limited amount of key presses anyway + uint16 keys_down[MAX_KEY_PRESSES]; + + // Mouse + // After handling the mouse state change the game loop should set this to false + bool state_change_mouse = false; + + uint32 x; + uint32 y; + + uint32 x_last; + uint32 y_last; + + bool mouse1_down = false; + bool mouse1_up = false; + + bool mouse2_down = false; + bool mouse2_up = false; + + bool mouse3_down = false; + bool mouse3_up = false; + + bool mouse4_down = false; + bool mouse4_up = false; + + bool mouse5_down = false; + bool mouse5_up = false; + + int16 wheel_delta = 0; + uint32 raw_button = 0; + }; + + InputState* init_input(const UI::Window* w) + { + uint32 nDevices; + GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST)); + PRAWINPUTDEVICELIST pRawInputDeviceList = (PRAWINPUTDEVICELIST) malloc(sizeof(RAWINPUTDEVICELIST) * nDevices); + nDevices = GetRawInputDeviceList(pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST)); + + nDevices = oms_max(MIN_INPUT_DEVICES, nDevices); + + // We always want at least one empty input device slot + // @todo Change so that we store the actual number of devices + InputState *inputs = (InputState *) calloc((nDevices + 1), sizeof(InputState)); + + if (nDevices == 0) { + free(pRawInputDeviceList); + + return inputs; + } + + uint32 cb_size = 256; + + for (uint32 i = 0; i < nDevices; ++i) { + GetRawInputDeviceInfoA(pRawInputDeviceList[i].hDevice, RIDI_DEVICENAME, inputs[i].name, &cb_size); + + cb_size = sizeof(RID_DEVICE_INFO); + RID_DEVICE_INFO rdi; + GetRawInputDeviceInfoA(pRawInputDeviceList[i].hDevice, RIDI_DEVICEINFO, &rdi, &cb_size); + + switch (rdi.dwType) { + case RIM_TYPEMOUSE: { + inputs[i].handle_mouse = pRawInputDeviceList[i].hDevice; + inputs[i].is_connected = true; + inputs[i].type = INPUT_TYPE_MOUSE; + } break; + case RIM_TYPEKEYBOARD: { + inputs[i].handle_keyboard = pRawInputDeviceList[i].hDevice; + inputs[i].is_connected = true; + inputs[i].type = INPUT_TYPE_KEYBOARD; + } break; + case RIM_TYPEHID: { + inputs[i].type = INPUT_TYPE_OTHER; + } break; + default: { + + } + } + } + + RAWINPUTDEVICE rid2[4]; + + // Mouse + rid2[0].usUsagePage = 0x01; // @todo doesn't work with 0x05 for games? + rid2[0].usUsage = 0x02; + rid2[0].dwFlags = RIDEV_DEVNOTIFY; + rid2[0].hwndTarget = w->hwnd; + + // Joystick + rid2[1].usUsagePage = 0x01; // @todo doesn't work with 0x05 for games? + rid2[1].usUsage = 0x04; + rid2[1].dwFlags = RIDEV_DEVNOTIFY; + rid2[1].hwndTarget = w->hwnd; + + // Gamepad + rid2[2].usUsagePage = 0x01; // @todo doesn't work with 0x05 for games? + rid2[2].usUsage = 0x05; + rid2[2].dwFlags = RIDEV_DEVNOTIFY; + rid2[2].hwndTarget = w->hwnd; + + // Keyboard + rid2[3].usUsagePage = 0x01; // @todo doesn't work with 0x05 for games? + rid2[3].usUsage = 0x06; + rid2[3].dwFlags = RIDEV_DEVNOTIFY; + rid2[3].hwndTarget = w->hwnd; + + if (!RegisterRawInputDevices((PCRAWINPUTDEVICE) rid2, 4, sizeof(RAWINPUTDEVICE))) { + // @todo Log + } + + // free(rid); + free(pRawInputDeviceList); + + return inputs; + } + + void handle_input(LPARAM lParam, InputState* states) + { + uint32 db_size; + GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &db_size, sizeof(RAWINPUTHEADER)); + + // @todo pull out, we only need to register this memory once + // Maybe even put it into the general memory pool + LPBYTE lpb = (BYTE *) malloc(db_size * sizeof(BYTE)); + + GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &db_size, sizeof(RAWINPUTHEADER)); + + RAWINPUT* raw = (RAWINPUT*) lpb; + + uint32 i = 0; + if (raw->header.dwType == RIM_TYPEMOUSE) { + // @todo Change so we can directly access the correct state (maybe map handle address to index?) + while (states[i].is_connected && states[i].handle_mouse != raw->header.hDevice) {++i;} + + if (!states[i].is_connected) { + return; + } + + // https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-rawmouse + if (raw->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) { + RECT rect; + if (raw->data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP) { + rect.left = GetSystemMetrics(SM_XVIRTUALSCREEN); + rect.top = GetSystemMetrics(SM_YVIRTUALSCREEN); + rect.right = GetSystemMetrics(SM_CXVIRTUALSCREEN); + rect.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN); + } else { + rect.left = 0; + rect.top = 0; + rect.right = GetSystemMetrics(SM_CXSCREEN); + rect.bottom = GetSystemMetrics(SM_CYSCREEN); + } + + states[i].x_last = states[i].x; + states[i].y_last = states[i].y; + + states[i].x = MulDiv(raw->data.mouse.lLastX, rect.right, 65535) + rect.left; + states[i].y = MulDiv(raw->data.mouse.lLastY, rect.bottom, 65535) + rect.top; + + states[i].state_change_mouse = true; + } else if (raw->data.mouse.lLastX != 0 || raw->data.mouse.lLastY != 0) { + states[i].x_last = states[i].x; + states[i].y_last = states[i].y; + + states[i].x = states[i].x + raw->data.mouse.lLastX; + states[i].y = states[i].y + raw->data.mouse.lLastY; + + states[i].state_change_mouse = true; + } + } else if (raw->header.dwType == RIM_TYPEKEYBOARD) { + // @todo Change so we can directly access the correct state (maybe map handle address to index?) + while (states[i].is_connected && states[i].handle_keyboard != raw->header.hDevice) {++i;} + + if (!states[i].is_connected) { + return; + } + + // https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-rawkeyboard + + RAWKEYBOARD rawKB = raw->data.keyboard; + + states[i].key = raw->data.keyboard.MakeCode; + states[i].key_up = raw->data.keyboard.Flags & RI_KEY_BREAK; + states[i].key_down = raw->data.keyboard.Flags & RI_KEY_MAKE; + + if (states[i].key_down) { + for (int j = 0; j < MAX_KEY_PRESSES; ++j) { + if (states[i].keys_down[j] == NULL) { + states[i].keys_down[j] = states[i].key; + } + } + } else if (states[i].key_up) { + for (int j = 0; j < MAX_KEY_PRESSES; ++j) { + if (states[i].keys_down[j] == states[i].key) { + states[i].keys_down[j] = NULL; + } + } + } + + states[i].state_change_keyboard = true; + } + } +} + +#endif \ No newline at end of file diff --git a/Input/XInput.h b/Input/XInput.h index 6576785..8b13bbd 100644 --- a/Input/XInput.h +++ b/Input/XInput.h @@ -12,22 +12,159 @@ #ifdef _WIN32 #include + #include #else #include #endif #include "../Stdlib/Types.h" +#include "../Utils/MathUtils.h" -uint32 find_joysticks() {} +#define MIN_CONTROLLER_DEVICES 4 -void destory_joysticks() {} +namespace Input { + struct ControllerState { + uint32 id = 0; + bool is_connected = false; -void handle_controller_input() -{ - for (uint32 controller_index = 0; controller_index < XUSER_MAX_COUNT; ++controller_index) { - XINPUT_STATE controller_state; - if (XInputGetState(controller_index, &controller_state) == ERROR_SUCCESS) { - } else { + bool up = false; + bool down = false; + bool left = false; + bool right = false; + bool start = false; + bool back = false; + + bool shoulder_left = false; + bool shoulder_right = false; + + byte trigger_left = 0; + byte trigger_right = 0; + + bool button_a = false; + bool button_b = false; + bool button_x = false; + bool button_y = false; + + int16 stickl_x = 0; + int16 stickl_y = 0; + bool stickl_press = false; + + int16 stickr_x = 0; + int16 stickr_y = 0; + bool stick2_press = false; + }; + + // @todo consider to remove some global_persist and defines since we are never calling it somewhere else + + // BEGIN: Dynamically load XInput + typedef DWORD WINAPI x_input_get_state(DWORD, XINPUT_STATE*); + DWORD WINAPI XInputGetStateStub(DWORD, XINPUT_STATE*) { + return 0; + } + global_persist x_input_get_state* XInputGetState_ = XInputGetStateStub; + #define XInputGetState XInputGetState_ + + typedef DWORD WINAPI x_input_set_state(DWORD, XINPUT_VIBRATION*); + DWORD WINAPI XInputSetStateStub(DWORD, XINPUT_VIBRATION*) { + return 0; + } + global_persist x_input_set_state* XInputSetState_ = XInputSetStateStub; + #define XInputSetState XInputSetState_ + + void xinput_load() { + HMODULE lib = LoadLibraryExA((LPCSTR) "xinput1_4.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); + if(!lib) { + // @todo Log + lib = LoadLibraryExA((LPCSTR) "xinput1_3.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); + } + + if (!lib) { + // @todo Log + return; + } + + XInputGetState = (x_input_get_state *) GetProcAddress(lib, "XInputGetState"); + XInputSetState = (x_input_set_state *) GetProcAddress(lib, "XInputSetState"); + + if (!XInputGetState || !XInputSetState) { + // @todo Log + return; + } + } + // END: Dynamically load XInput + + ControllerState* init_controllers() + { + uint32 c = 0; + for (uint32 controller_index = 0; controller_index < XUSER_MAX_COUNT; ++controller_index) { + XINPUT_STATE controller_state; + if (XInputGetState(controller_index, &controller_state) == ERROR_SUCCESS) { + ++c; + } + } + + c = oms_max(MIN_CONTROLLER_DEVICES, c); + + // We always want at least one empty controller slot + // @todo Change so that we store the actual number of devices + ControllerState *controllers = (ControllerState *) calloc((c + 1), sizeof(ControllerState)); + + if (c == 0) { + return controllers; + } + + c = 0; + for (uint32 controller_index = 0; controller_index < XUSER_MAX_COUNT; ++controller_index) { + XINPUT_STATE controller_state; + if (XInputGetState(controller_index, &controller_state) == ERROR_SUCCESS) { + ++c; + + controllers[c].id = controller_index; + controllers[c].is_connected = true; + } + } + + return controllers; + } + + void handle_controller_input(ControllerState* states) + { + uint32 controller_index = 0; + while(states[controller_index].is_connected) { + XINPUT_STATE controller_state; + if (XInputGetState(controller_index, &controller_state) != ERROR_SUCCESS) { + ++controller_index; + + continue; + } + + states[controller_index].up = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP; + states[controller_index].down = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN; + states[controller_index].left = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT; + states[controller_index].right = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT; + states[controller_index].start = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_START; + states[controller_index].back = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK; + + states[controller_index].shoulder_left = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER; + states[controller_index].shoulder_right = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER; + + states[controller_index].trigger_left = controller_state.Gamepad.bLeftTrigger; + states[controller_index].trigger_right = controller_state.Gamepad.bRightTrigger; + + states[controller_index].button_a = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_A; + states[controller_index].button_b = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_B; + states[controller_index].button_x = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_X; + states[controller_index].button_y = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_Y; + + states[controller_index].stickl_x = controller_state.Gamepad.sThumbLX; + states[controller_index].stickl_y = controller_state.Gamepad.sThumbLY; + states[controller_index].stickl_press = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB; + + states[controller_index].stickr_x = controller_state.Gamepad.sThumbRX; + states[controller_index].stickr_y = controller_state.Gamepad.sThumbRY; + states[controller_index].stick2_press = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB; + + ++controller_index; } } } diff --git a/Router/Router.h b/Router/Router.h index 0831e15..578ffd1 100755 --- a/Router/Router.h +++ b/Router/Router.h @@ -24,9 +24,9 @@ namespace Router { typedef void (*RouterFunc)(int, const char **); - typedef struct { + struct Router { Stdlib::HashTable::ht *routes; - } Router; + }; Router create_router(int size) { diff --git a/Sound/DirectSound.h b/Sound/DirectSound.h new file mode 100644 index 0000000..cee60ad --- /dev/null +++ b/Sound/DirectSound.h @@ -0,0 +1,199 @@ +/** + * Karaka + * + * @package Stdlib + * @copyright Dennis Eichhorn + * @license OMS License 1.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef SOUND_DIRECT_SOUND_H +#define SOUND_DIRECT_SOUND_H + +#include +#include +#include + +#include "../Stdlib/Types.h" +#include "../Utils/MathUtils.h" +#include "../UI/Window.h" + +#define SOUND_API_DIRECT_SOUND 0 + +namespace Sound { + struct DirectSoundSetting { + uint32 sample_rate; + uint32 sample_size; + uint32 sample_index; + int16 volume; + uint32 buffer_size; + int16* buffer; + + bool playing = false; + byte type = SOUND_API_DIRECT_SOUND; + + // Api specific data from here on + LPDIRECTSOUND8 direct_sound; + LPDIRECTSOUNDBUFFER primary_buffer; + LPDIRECTSOUNDBUFFER secondary_buffer; + }; + + // BEGIN: Dynamically load DirectSound + typedef HRESULT WINAPI direct_sound_create(LPCGUID, LPDIRECTSOUND8*, LPUNKNOWN); + HRESULT WINAPI DirectSoundCreate8Stub(LPCGUID, LPDIRECTSOUND8*, LPUNKNOWN) { + return 0; + } + // END: Dynamically load DirectSound + + void direct_sound_load(UI::Window* w, DirectSoundSetting* setting) { + HMODULE lib = LoadLibraryExA((LPCSTR) "dsound.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); + if (!lib) { + // @todo Log + return; + } + + direct_sound_create* DirectSoundCreate8 = (direct_sound_create *) GetProcAddress(lib, "DirectSoundCreate8"); + + if (!DirectSoundCreate8 || !SUCCEEDED(DirectSoundCreate8(0, &setting->direct_sound, 0))) { + // @todo Log + return; + } + + if(!SUCCEEDED(setting->direct_sound->SetCooperativeLevel(w->hwnd, DSSCL_PRIORITY))) { + // @todo Log + } + + WAVEFORMATEX wf = {}; + wf.wFormatTag = WAVE_FORMAT_PCM; + wf.nChannels = 2; + wf.wBitsPerSample = 16; + wf.nBlockAlign = (wf.nChannels * wf.wBitsPerSample) / 8; + wf.nSamplesPerSec = setting->sample_rate; + wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign; + wf.cbSize; + + // Create primary buffer + DSBUFFERDESC bufferDesc; + ZeroMemory(&bufferDesc, sizeof(DSBUFFERDESC)); + + bufferDesc.dwSize = sizeof(DSBUFFERDESC); + bufferDesc.dwFlags = DSBCAPS_PRIMARYBUFFER; + + if(!SUCCEEDED(setting->direct_sound->CreateSoundBuffer(&bufferDesc, &setting->primary_buffer, 0))) { + // @todo Log + } + + if (!SUCCEEDED(setting->primary_buffer->SetFormat(&wf))) { + // @todo Log + } + + setting->buffer_size = setting->sample_rate * setting->sample_size; + + // Create secondary buffer + DSBUFFERDESC bufferDesc2; + ZeroMemory(&bufferDesc2, sizeof(DSBUFFERDESC)); + + bufferDesc2.dwSize = sizeof(DSBUFFERDESC); + bufferDesc2.dwFlags = 0; + bufferDesc2.dwBufferBytes = setting->buffer_size; + bufferDesc2.lpwfxFormat = &wf; + + if(!SUCCEEDED(setting->direct_sound->CreateSoundBuffer(&bufferDesc2, &setting->secondary_buffer, 0))) { + // @todo Log + } + } + + void direct_sound_play(DirectSoundSetting* setting) + { + setting->secondary_buffer->Play(0, 0, DSBPLAY_LOOPING); + setting->playing = true; + } + + void direct_sound_free(DirectSoundSetting* setting) + { + if (setting->direct_sound) { + setting->direct_sound->Release(); + } + + if (setting->primary_buffer) { + setting->primary_buffer->Release(); + } + + if (setting->secondary_buffer) { + setting->secondary_buffer->Release(); + } + } + + bool direct_sound_should_update(DirectSoundSetting* setting) + { + return true; + } + + int16 *direct_sound_return_buffer(DirectSoundSetting* setting) + { + + } + + void direct_sound_play_buffer(DirectSoundSetting* setting) + { + DWORD player_cursor; + DWORD write_cursor; + if (!SUCCEEDED(setting->secondary_buffer->GetCurrentPosition(&player_cursor, &write_cursor))) { + // @todo Log + return; + } + + void *region1; + DWORD region1_size; + + void *region2; + DWORD region2_size; + + DWORD bytes_to_lock = (setting->sample_index * setting->sample_size) % setting->buffer_size; + DWORD bytes_to_write = 0; + + if (bytes_to_lock == player_cursor) { + bytes_to_write = setting->playing ? 0 : setting->buffer_size; + } else if (bytes_to_lock > player_cursor) { + bytes_to_write = setting->buffer_size - bytes_to_lock; + bytes_to_write += player_cursor; + } else { + bytes_to_write = player_cursor - bytes_to_lock; + } + + setting->secondary_buffer->Lock( + bytes_to_lock, bytes_to_write, + ®ion1, ®ion1_size, + ®ion2, ®ion2_size, + 0 + ); + + int16* sample_out = (int16 *) region1; + DWORD region1_sample_count = region1_size / setting->sample_size; + + for (DWORD idx = 0; idx < region1_sample_count; ++idx) { + f32 t = ((f32) 1.0f / (f32) (48000 / 256)) * 2.0f * OMS_PI; + f32 sine_value = sinf(t); + int16 sample_value = (int16) (sine_value * setting->volume); + + *sample_out++ = sample_value; + *sample_out++ = sample_value; + } + + sample_out = (int16 *) region2; + DWORD region2_sample_count = region2_size / setting->sample_size; + + for (DWORD idx = 0; idx < region2_sample_count; ++idx) { + f32 t = ((f32) 1.0f / (f32) (48000 / 256)) * 2.0f * OMS_PI; + f32 sine_value = sinf(t); + int16 sample_value = (int16) (sine_value * setting->volume); + + *sample_out++ = sample_value; + *sample_out++ = sample_value; + } + + setting->secondary_buffer->Unlock(region1, region1_size, region2, region2_size); + } +} + +#endif \ No newline at end of file diff --git a/Sound/XAudio2.h b/Sound/XAudio2.h new file mode 100644 index 0000000..08d5f39 --- /dev/null +++ b/Sound/XAudio2.h @@ -0,0 +1,189 @@ +/** + * Karaka + * + * @package Stdlib + * @copyright Dennis Eichhorn + * @license OMS License 1.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef SOUND_XAUDIO2_H +#define SOUND_XAUDIO2_H + +#include +#include +#include + +#include "../Stdlib/Types.h" +#include "../Utils/MathUtils.h" +#include "../UI/Window.h" + +#define SOUND_API_XAUDIO2 1 + +namespace Sound { + struct XAudio2Setting { + uint32 sample_rate; + uint32 sample_size; + uint32 sample_index; + int16 volume; + uint32 buffer_size; + + bool playing = false; + byte type = SOUND_API_XAUDIO2; + + // Api specific data from here on + IXAudio2* xaudio2; + IXAudio2SourceVoice* source_voice; + IXAudio2MasteringVoice* mastering_voice; + + XAUDIO2_BUFFER buffer[2]; + }; + + // BEGIN: Dynamically load XAudio2 + typedef HRESULT WINAPI xaudio2_create(IXAudio2**, UINT32, XAUDIO2_PROCESSOR); + HRESULT WINAPI XAudio2CreateStub(IXAudio2**, UINT32, XAUDIO2_PROCESSOR) { + return 0; + } + // END: Dynamically load XAudio2 + + void xaudio2_load(XAudio2Setting* setting) { + HMODULE lib = LoadLibraryExA((LPCSTR) "xaudio2_9.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); + if (!lib) { + // @todo Log + lib = LoadLibraryExA((LPCSTR) "xaudio2_8.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); + } + + if (!lib) { + // @todo Log + return; + } + + xaudio2_create* XAudio2Create = (xaudio2_create *) GetProcAddress(lib, "XAudio2Create"); + if (!XAudio2Create || !SUCCEEDED(XAudio2Create(&setting->xaudio2, 0, XAUDIO2_DEFAULT_PROCESSOR))) { + // @todo Log + return; + } + + if (!SUCCEEDED(setting->xaudio2->CreateMasteringVoice(&setting->mastering_voice))) { + // @todo Log + return; + } + + WAVEFORMATEX wf = {}; + wf.wFormatTag = WAVE_FORMAT_PCM; + wf.nChannels = 2; + wf.wBitsPerSample = 16; + wf.nBlockAlign = (wf.nChannels * wf.wBitsPerSample) / 8; + wf.nSamplesPerSec = setting->sample_rate; + wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign; + wf.cbSize = 0; + + if (!SUCCEEDED(setting->xaudio2->CreateSourceVoice(&setting->source_voice, &wf))) { + // @todo Log + return; + } + + setting->buffer_size = setting->sample_rate * wf.nBlockAlign; + + // @question Consider to move to the heap? + setting->buffer[0].Flags = 0; + setting->buffer[0].AudioBytes = setting->buffer_size; + setting->buffer[0].pAudioData = (BYTE *) malloc(setting->buffer_size * sizeof(BYTE)); + setting->buffer[0].PlayBegin = 0; + setting->buffer[0].PlayLength = 0; + setting->buffer[0].LoopBegin = 0; + setting->buffer[0].LoopLength = 0; + setting->buffer[0].LoopCount = 0; + setting->buffer[0].pContext = NULL; + + setting->buffer[1].Flags = 0; + setting->buffer[1].AudioBytes = setting->buffer_size; + setting->buffer[1].pAudioData = (BYTE *) malloc(setting->buffer_size * sizeof(BYTE)); + setting->buffer[1].PlayBegin = 0; + setting->buffer[1].PlayLength = 0; + setting->buffer[1].LoopBegin = 0; + setting->buffer[1].LoopLength = 0; + setting->buffer[1].LoopCount = 0; + setting->buffer[1].pContext = NULL; + + setting->sample_index = 0; + } + + void xaudio2_play(XAudio2Setting* setting) { + if (!setting->source_voice) { + // @todo Log + + return; + } + + setting->source_voice->Start(0, XAUDIO2_COMMIT_NOW); + setting->playing = true; + } + + void xaudio2_free(XAudio2Setting* setting) + { + if (setting->buffer[0].pAudioData) { + free((void *) setting->buffer[0].pAudioData); + } + + if (setting->buffer[1].pAudioData) { + free((void *) setting->buffer[1].pAudioData); + } + + if (setting->source_voice) { + setting->source_voice->DestroyVoice(); + } + + if (setting->mastering_voice) { + setting->mastering_voice->DestroyVoice(); + } + + if (setting->xaudio2) { + setting->xaudio2->Release(); + } + } + + bool xaudio2_should_update(XAudio2Setting* setting) + { + if (!setting->source_voice) { + // @todo Log + + return false; + } + + XAUDIO2_VOICE_STATE state; + setting->source_voice->GetState(&state); + if (state.BuffersQueued > 1) { + return false; + } + + return true; + } + + int16* xaudio2_return_buffer(XAudio2Setting* setting) + { + return (int16 *) setting->buffer[setting->sample_index].pAudioData; + } + + int16* xaudio2_fill_buffer(XAudio2Setting* setting, int16* buffer) + { + int16* sample_out = (int16 *) setting->buffer[setting->sample_index].pAudioData; + } + + void xaudio2_play_buffer(XAudio2Setting* setting) { + if (!setting->source_voice) { + // @todo Log + + return; + } + + setting->sample_index = (setting->sample_index + 1) % 2; + + if (!SUCCEEDED(setting->source_voice->SubmitSourceBuffer(&setting->buffer[setting->sample_index]))) { + // @todo Log + return; + } + } +} + +#endif diff --git a/Stdlib/HashTable.h b/Stdlib/HashTable.h index f4b4d8e..7da237e 100755 --- a/Stdlib/HashTable.h +++ b/Stdlib/HashTable.h @@ -18,10 +18,10 @@ namespace Stdlib::HashTable { - typedef struct { + struct entry { const char *key; void *value; - } entry; + }; struct ht { bool is_fixed = false; @@ -30,13 +30,13 @@ namespace Stdlib::HashTable size_t size; }; - typedef struct { + struct it { const char *key; void *value; ht *table; size_t index; - } it; + }; inline unsigned long long hash_key(const char *key) { diff --git a/Stdlib/Mathtypes.h b/Stdlib/Mathtypes.h index 0ba1450..50aaa09 100644 --- a/Stdlib/Mathtypes.h +++ b/Stdlib/Mathtypes.h @@ -90,19 +90,19 @@ typedef union { float e[4]; } f4; -typedef struct { +struct mi32 { int32_t *e; size_t m, n; -} mi32; +}; -typedef struct { +struct mi64 { int64_t *e; size_t m, n; -} mi64; +}; -typedef struct { +struct mf { float *e; size_t m, n; -} mf; +}; #endif \ No newline at end of file diff --git a/Stdlib/SIMD/SIMD_F32.h b/Stdlib/SIMD/SIMD_F32.h index 5dbb2ef..3b93d46 100644 --- a/Stdlib/SIMD/SIMD_F32.h +++ b/Stdlib/SIMD/SIMD_F32.h @@ -615,7 +615,7 @@ namespace Stdlib::SIMD return simd; } - inline f32_4_simd min(f32_4_simd a, f32_4_simd b) + inline f32_4_simd simd_min(f32_4_simd a, f32_4_simd b) { f32_4_simd simd; simd.s = _mm_min_ps(a.s, b.s); @@ -623,7 +623,7 @@ namespace Stdlib::SIMD return simd; } - inline f32_8_simd min(f32_8_simd a, f32_8_simd b) + inline f32_8_simd simd_min(f32_8_simd a, f32_8_simd b) { f32_8_simd simd; simd.s = _mm256_min_ps(a.s, b.s); @@ -631,7 +631,7 @@ namespace Stdlib::SIMD return simd; } - inline f32_16_simd min(f32_16_simd a, f32_16_simd b) + inline f32_16_simd simd_min(f32_16_simd a, f32_16_simd b) { f32_16_simd simd; simd.s = _mm512_min_ps(a.s, b.s); @@ -639,7 +639,7 @@ namespace Stdlib::SIMD return simd; } - inline f32_4_simd max(f32_4_simd a, f32_4_simd b) + inline f32_4_simd simd_max(f32_4_simd a, f32_4_simd b) { f32_4_simd simd; simd.s = _mm_max_ps(a.s, b.s); @@ -647,7 +647,7 @@ namespace Stdlib::SIMD return simd; } - inline f32_8_simd max(f32_8_simd a, f32_8_simd b) + inline f32_8_simd simd_max(f32_8_simd a, f32_8_simd b) { f32_8_simd simd; simd.s = _mm256_max_ps(a.s, b.s); @@ -655,7 +655,7 @@ namespace Stdlib::SIMD return simd; } - inline f32_16_simd max(f32_16_simd a, f32_16_simd b) + inline f32_16_simd simd_max(f32_16_simd a, f32_16_simd b) { f32_16_simd simd; simd.s = _mm512_max_ps(a.s, b.s); @@ -833,17 +833,17 @@ namespace Stdlib::SIMD inline f32_4_simd clamp(f32_4_simd min_value, f32_4_simd a, f32_4_simd max_value) { - return min(max(a, min_value), max_value); + return simd_min(simd_max(a, min_value), max_value); } inline f32_8_simd clamp(f32_8_simd min_value, f32_8_simd a, f32_8_simd max_value) { - return min(max(a, min_value), max_value); + return simd_min(simd_max(a, min_value), max_value); } inline f32_16_simd clamp(f32_16_simd min_value, f32_16_simd a, f32_16_simd max_value) { - return min(max(a, min_value), max_value); + return simd_min(simd_max(a, min_value), max_value); } inline int32 which_true(f32_4_simd a) diff --git a/Stdlib/SIMD/SIMD_I32.h b/Stdlib/SIMD/SIMD_I32.h index 0527065..1cbfa84 100644 --- a/Stdlib/SIMD/SIMD_I32.h +++ b/Stdlib/SIMD/SIMD_I32.h @@ -611,7 +611,7 @@ namespace Stdlib::SIMD return simd; } - inline int32_4_simd min(int32_4_simd a, int32_4_simd b) + inline int32_4_simd simd_min(int32_4_simd a, int32_4_simd b) { int32_4_simd simd; simd.s = _mm_min_epi32(a.s, b.s); @@ -619,7 +619,7 @@ namespace Stdlib::SIMD return simd; } - inline int32_8_simd min(int32_8_simd a, int32_8_simd b) + inline int32_8_simd simd_min(int32_8_simd a, int32_8_simd b) { int32_8_simd simd; simd.s = _mm256_min_epi32(a.s, b.s); @@ -627,7 +627,7 @@ namespace Stdlib::SIMD return simd; } - inline int32_16_simd min(int32_16_simd a, int32_16_simd b) + inline int32_16_simd simd_min(int32_16_simd a, int32_16_simd b) { int32_16_simd simd; simd.s = _mm512_min_epi32(a.s, b.s); @@ -635,7 +635,7 @@ namespace Stdlib::SIMD return simd; } - inline int32_4_simd max(int32_4_simd a, int32_4_simd b) + inline int32_4_simd simd_max(int32_4_simd a, int32_4_simd b) { int32_4_simd simd; simd.s = _mm_max_epi32(a.s, b.s); @@ -643,7 +643,7 @@ namespace Stdlib::SIMD return simd; } - inline int32_8_simd max(int32_8_simd a, int32_8_simd b) + inline int32_8_simd simd_max(int32_8_simd a, int32_8_simd b) { int32_8_simd simd; simd.s = _mm256_max_epi32(a.s, b.s); @@ -651,7 +651,7 @@ namespace Stdlib::SIMD return simd; } - inline int32_16_simd max(int32_16_simd a, int32_16_simd b) + inline int32_16_simd simd_max(int32_16_simd a, int32_16_simd b) { int32_16_simd simd; simd.s = _mm512_max_epi32(a.s, b.s); @@ -769,17 +769,17 @@ namespace Stdlib::SIMD inline int32_4_simd clamp(int32_4_simd min_value, int32_4_simd a, int32_4_simd max_value) { - return min(max(a, min_value), max_value); + return simd_min(simd_max(a, min_value), max_value); } inline int32_8_simd clamp(int32_8_simd min_value, int32_8_simd a, int32_8_simd max_value) { - return min(max(a, min_value), max_value); + return simd_min(simd_max(a, min_value), max_value); } inline int32_16_simd clamp(int32_16_simd min_value, int32_16_simd a, int32_16_simd max_value) { - return min(max(a, min_value), max_value); + return simd_min(simd_max(a, min_value), max_value); } inline int32 which_true(int32_4_simd a) diff --git a/Stdlib/Types.h b/Stdlib/Types.h index fda4d91..6e534ea 100644 --- a/Stdlib/Types.h +++ b/Stdlib/Types.h @@ -28,4 +28,8 @@ typedef double f64; typedef unsigned char byte; +#define internal static // only allows local "file" access +#define local_persist static +#define global_persist static + #endif diff --git a/Threads/OSWrapper.h b/Threads/OSWrapper.h index f540622..f907bd7 100755 --- a/Threads/OSWrapper.h +++ b/Threads/OSWrapper.h @@ -17,10 +17,10 @@ typedef HANDLE pthread_t; typedef CONDITION_VARIABLE pthread_cond_t; - typedef struct { + struct pthread_rwlock_t { SRWLock lock; bool exclusive; - } pthread_rwlock_t; + }; struct timespec { long tv_sec; @@ -39,10 +39,10 @@ void ms_to_timespec(struct timespec *ts, unsigned int ms) } #ifdef _WIN32 - typedef struct { + struct win_thread_start_t { void *(*start_routine)(void *); void *start_arg; - } win_thread_start_t; + }; static DWORD WINAPI win_thread_start(void *arg) { diff --git a/Threads/ThreadPool.h b/Threads/ThreadPool.h index 697f5c2..96faca0 100755 --- a/Threads/ThreadPool.h +++ b/Threads/ThreadPool.h @@ -16,7 +16,7 @@ namespace Threads { - typedef struct { + struct ThreadPool { Job *work_first; Job *work_last; pthread_mutex_t work_mutex; @@ -25,7 +25,7 @@ namespace Threads size_t working_cnt; size_t thread_cnt; bool stop; - } ThreadPool; + }; } #endif \ No newline at end of file diff --git a/UI/window.h b/UI/window.h index 928c435..07bc66f 100644 --- a/UI/window.h +++ b/UI/window.h @@ -1,116 +1,64 @@ #ifndef UI_WINDOW_H #define UI_WINDOW_H -#include - #ifdef _WIN32 #include - #include - - LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); #endif +#include "../Stdlib/Types.h" + namespace UI { - struct WindowStat { - double oldFrame = 0; - double newFrame = 0; - double dt = 0; - }; + struct Window { + int32 width; + int32 height; + char wName[32]; - void update_window_stat(WindowStat *stat) - { - stat->newFrame = (double) clock() / CLOCKS_PER_SEC; - stat->dt = stat->newFrame - stat->oldFrame; - stat->oldFrame = stat->newFrame; - } - - struct window { - unsigned int width; - unsigned int height; + int32 x; + int32 y; #ifdef _WIN32 HWND hwnd; #endif }; - void window_open(window* w) + void window_open(const Window* window) { #ifdef _WIN32 - ShowWindow(w->hwnd, SW_SHOW); + ShowWindow(window->hwnd, SW_SHOW); + UpdateWindow(window->hwnd); #endif } - #if defined(_WIN32) && defined(DIRECTX) - void window_create_windows(window* w) - { - HINSTANCE hinstance = GetModuleHandle(nullptr); - - WNDCLASSEX wc; - ZeroMemory(&wc, sizeof(WNDCLASSEX)); + void window_create_windows(Window* window, WNDPROC proc) + { + WNDCLASSEX wc = {}; + HINSTANCE hinstance = GetModuleHandle(0); wc.cbSize = sizeof(WNDCLASSEX); - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = WindowProc; + wc.style = CS_OWNDC; + wc.lpfnWndProc = proc; wc.hInstance = hinstance; - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)COLOR_WINDOW; - wc.lpszClassName = L"WindowClass1"; + wc.lpszClassName = (LPCWSTR) window->wName; RegisterClassEx(&wc); - RECT wr = {0, 0, 800, 600}; - AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); - - w->hwnd = CreateWindowEx((DWORD) NULL, + window->hwnd = CreateWindowEx((DWORD) NULL, wc.lpszClassName, NULL, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, - wr.right - wr.left, - wr.bottom - wr.top, - NULL, NULL, hinstance, w + window->width, + window->height, + NULL, NULL, hinstance, window ); + + //SetWindowLongA(window->hwnd, GWL_STYLE, 0); } - #else if defined(_WIN32) && defined(OPENGL) - void window_create_opengl(window* w) - { - HINSTANCE hinstance = GetModuleHandle(nullptr); - WNDCLASSEX wc; - ZeroMemory(&wc, sizeof(WNDCLASSEX)); - - wc.cbSize = sizeof(WNDCLASSEX); - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = WindowProc; - wc.hInstance = hinstance; - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)COLOR_WINDOW; - wc.lpszClassName = L"WindowClass1"; - - RegisterClassEx(&wc); - - RECT wr = {0, 0, 800, 600}; - AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); - - w->hwnd = CreateWindowEx((DWORD) NULL, - wc.lpszClassName, NULL, - WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, CW_USEDEFAULT, - wr.right - wr.left, - wr.bottom - wr.top, - NULL, NULL, hinstance, w - ); - } - #endif - - void window_create(window* w) + void window_close(Window* window) { #ifdef _WIN32 - #if defined(DIRECTX) - window_create_directx(w); - #else if defined(_WIN32) && defined(OPENGL) - window_create_opengl(w); - #endif + CloseWindow(window->hwnd); #endif } } diff --git a/Utils/ColorUtils.h b/Utils/ColorUtils.h index eae73fc..e8dae8c 100644 --- a/Utils/ColorUtils.h +++ b/Utils/ColorUtils.h @@ -15,11 +15,11 @@ namespace Utils::ColorUtils { - typedef struct { + struct RGB { unsigned char r = 0; unsigned char g = 0; unsigned char b = 0; - } RGB; + }; inline RGB *int_to_rgb(int rgb) { diff --git a/Utils/FileUtils.h b/Utils/FileUtils.h index c0a6249..297deff 100755 --- a/Utils/FileUtils.h +++ b/Utils/FileUtils.h @@ -91,10 +91,10 @@ namespace Utils::FileUtils return dot + 1; } - typedef struct { + struct file_body { char *content; int size = 0; // doesn't include null termination (same as strlen) - } file_body; + }; file_body read_file(const char *filename) { diff --git a/Utils/MathUtils.h b/Utils/MathUtils.h index 6c85876..7d82094 100755 --- a/Utils/MathUtils.h +++ b/Utils/MathUtils.h @@ -12,7 +12,7 @@ #include -#define OMS_PI 3.14159265358979323846 +#define OMS_PI 3.14159265358979323846f #define oms_max(a, b) ((a) > (b) ? (a) : (b)) #define oms_min(a, b) ((a) > (b) ? (b) : (a)) diff --git a/Utils/StringUtils.h b/Utils/StringUtils.h index 0e97226..b0faaac 100755 --- a/Utils/StringUtils.h +++ b/Utils/StringUtils.h @@ -160,11 +160,11 @@ namespace Utils::StringUtils return result; } - typedef struct { + struct text_diff { char **values; int64_t *masks; size_t size; - } text_diff; + }; text_diff computeLCSDiff(const char **from, size_t fromSize, const char **to, size_t toSize) { diff --git a/Utils/TestUtils.h b/Utils/TestUtils.h index 44998ef..fefdd82 100755 --- a/Utils/TestUtils.h +++ b/Utils/TestUtils.h @@ -10,9 +10,42 @@ #ifndef UTILS_TEST_UTILS_H #define UTILS_TEST_UTILS_H -#include "MathUtils.h" #include +#ifdef _WIN32 + #include +#else + #include +#endif + +namespace Test { + global_persist uint64 performance_count_frequency; + struct TimingStat { + uint64 oldFrame = 0; + uint64 newFrame = 0; + uint64 dc = 0; + double dt = 0.0; + }; + + void update_timing_stat(TimingStat *stat) + { + #ifdef _WIN32 + LARGE_INTEGER counter; + QueryPerformanceCounter(&counter); + + stat->newFrame = counter.QuadPart; + #else + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + stat->newFrame = now.tv_sec + now.tv_nsec; + #endif + + stat->dc = stat->newFrame - stat->oldFrame; + stat->dt = (double) stat->dc / (double) performance_count_frequency; + stat->oldFrame = stat->newFrame; + } +} + #define ASSERT_EQUALS(a, b, t1, t2) \ ({ \ if ((a) == (b)) { \ @@ -73,6 +106,11 @@ } \ }) +#define ASSERT_SIMPLE(a) \ + if ((a) == false) { \ + *(volatile int *)0 = 0; \ + } + #define ASSERT_TRUE(a) \ ({ \ if ((a) == true) { \ diff --git a/Utils/WebUtils.h b/Utils/WebUtils.h index c08f501..603002f 100755 --- a/Utils/WebUtils.h +++ b/Utils/WebUtils.h @@ -82,15 +82,15 @@ namespace Utils::WebUtils return out->size; } - typedef struct { + struct ResourceTypes { size_t size = 0; const char **resources = NULL; - } ResourceTypes; + }; - typedef struct { + struct Urls { size_t size = 0; const char **urls = NULL; - } Urls; + }; Utils::FileUtils::file_body download (char *url) {