mirror of
https://github.com/Karaka-Management/cOMS.git
synced 2026-01-11 11:18:40 +00:00
update
Some checks failed
Some checks failed
This commit is contained in:
parent
3cd7ada19e
commit
02ee4480ad
|
|
@ -19,11 +19,11 @@
|
|||
|
||||
namespace Application
|
||||
{
|
||||
typedef struct {
|
||||
struct ApplicationAbstract {
|
||||
DataStorage::Database::ConnectionAbstract *db;
|
||||
nlohmann::json config;
|
||||
Threads::ThreadPool *pool;
|
||||
} ApplicationAbstract;
|
||||
};
|
||||
} // namespace Application
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
252
Input/Input.h
Normal file
252
Input/Input.h
Normal file
|
|
@ -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 <windows.h>
|
||||
#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
|
||||
153
Input/XInput.h
153
Input/XInput.h
|
|
@ -12,22 +12,159 @@
|
|||
|
||||
#ifdef _WIN32
|
||||
#include <XInput.h>
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <linux/joystick.h>
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
199
Sound/DirectSound.h
Normal file
199
Sound/DirectSound.h
Normal file
|
|
@ -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 <dsound.h>
|
||||
#include <windows.h>
|
||||
#include <math.h>
|
||||
|
||||
#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
|
||||
189
Sound/XAudio2.h
Normal file
189
Sound/XAudio2.h
Normal file
|
|
@ -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 <xaudio2.h>
|
||||
#include <windows.h>
|
||||
#include <math.h>
|
||||
|
||||
#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
|
||||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
104
UI/window.h
104
UI/window.h
|
|
@ -1,116 +1,64 @@
|
|||
#ifndef UI_WINDOW_H
|
||||
#define UI_WINDOW_H
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#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))
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,9 +10,42 @@
|
|||
#ifndef UTILS_TEST_UTILS_H
|
||||
#define UTILS_TEST_UTILS_H
|
||||
|
||||
#include "MathUtils.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <time.h>
|
||||
#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) { \
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user