mirror of
https://github.com/Karaka-Management/cOMS.git
synced 2026-02-15 18:08: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
|
namespace Application
|
||||||
{
|
{
|
||||||
typedef struct {
|
struct ApplicationAbstract {
|
||||||
DataStorage::Database::ConnectionAbstract *db;
|
DataStorage::Database::ConnectionAbstract *db;
|
||||||
nlohmann::json config;
|
nlohmann::json config;
|
||||||
Threads::ThreadPool *pool;
|
Threads::ThreadPool *pool;
|
||||||
} ApplicationAbstract;
|
};
|
||||||
} // namespace Application
|
} // namespace Application
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,11 @@
|
||||||
|
|
||||||
namespace DataStorage::Database
|
namespace DataStorage::Database
|
||||||
{
|
{
|
||||||
typedef struct {
|
struct QueryResult {
|
||||||
size_t rows = 0;
|
size_t rows = 0;
|
||||||
size_t columns = 0;
|
size_t columns = 0;
|
||||||
char **results = NULL;
|
char **results = NULL;
|
||||||
} QueryResult;
|
};
|
||||||
|
|
||||||
struct ConnectionAbstract {
|
struct ConnectionAbstract {
|
||||||
void *con = NULL;
|
void *con = NULL;
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
namespace DataStorage::Database
|
namespace DataStorage::Database
|
||||||
{
|
{
|
||||||
typedef struct {
|
struct DbConnectionConfig {
|
||||||
DatabaseType db = DatabaseType::UNDEFINED;
|
DatabaseType db = DatabaseType::UNDEFINED;
|
||||||
|
|
||||||
const char *database = NULL;
|
const char *database = NULL;
|
||||||
|
|
@ -29,7 +29,7 @@ namespace DataStorage::Database
|
||||||
const char *login = NULL;
|
const char *login = NULL;
|
||||||
|
|
||||||
const char *password = NULL;
|
const char *password = NULL;
|
||||||
} DbConnectionConfig;
|
};
|
||||||
|
|
||||||
void free_DbConnectionConfig(DbConnectionConfig *dbdata)
|
void free_DbConnectionConfig(DbConnectionConfig *dbdata)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -35,10 +35,10 @@ namespace DataStorage::Database
|
||||||
FIELD_TYPE_BOOL = 4
|
FIELD_TYPE_BOOL = 4
|
||||||
} FieldType;
|
} FieldType;
|
||||||
|
|
||||||
typedef struct {
|
struct ModelStructure {
|
||||||
const char *name = NULL;
|
const char *name = NULL;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
} ModelStructure;
|
};
|
||||||
|
|
||||||
void free_ModelStructure(ModelStructure *data)
|
void free_ModelStructure(ModelStructure *data)
|
||||||
{
|
{
|
||||||
|
|
@ -49,13 +49,13 @@ namespace DataStorage::Database
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
struct DataMapperColumn {
|
||||||
const char *name = NULL;
|
const char *name = NULL;
|
||||||
int type = FieldType::FIELD_TYPE_INT;
|
int type = FieldType::FIELD_TYPE_INT;
|
||||||
const char *internal = NULL;
|
const char *internal = NULL;
|
||||||
bool readonly = false;
|
bool readonly = false;
|
||||||
bool autocomplete = false;
|
bool autocomplete = false;
|
||||||
} DataMapperColumn;
|
};
|
||||||
|
|
||||||
void free_DataMapperColumn(DataMapperColumn *data)
|
void free_DataMapperColumn(DataMapperColumn *data)
|
||||||
{
|
{
|
||||||
|
|
@ -68,7 +68,7 @@ namespace DataStorage::Database
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
struct TableRelation {
|
||||||
const char *member = NULL;
|
const char *member = NULL;
|
||||||
const char *mapper = NULL;
|
const char *mapper = NULL;
|
||||||
const char *external = NULL;
|
const char *external = NULL;
|
||||||
|
|
@ -77,7 +77,7 @@ namespace DataStorage::Database
|
||||||
const char *column = NULL;
|
const char *column = NULL;
|
||||||
bool conditional = false;
|
bool conditional = false;
|
||||||
const char *by = NULL;
|
const char *by = NULL;
|
||||||
} TableRelation;
|
};
|
||||||
|
|
||||||
void free_TableRelation(TableRelation *data)
|
void free_TableRelation(TableRelation *data)
|
||||||
{
|
{
|
||||||
|
|
@ -116,7 +116,7 @@ namespace DataStorage::Database
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
struct MapperData {
|
||||||
const char *TABLE = NULL;
|
const char *TABLE = NULL;
|
||||||
const char *PRIMARYFIELD = NULL;
|
const char *PRIMARYFIELD = NULL;
|
||||||
const char *CREATED_AT = NULL;
|
const char *CREATED_AT = NULL;
|
||||||
|
|
@ -137,7 +137,7 @@ namespace DataStorage::Database
|
||||||
|
|
||||||
int BELONGS_TO_COUNT = 0;
|
int BELONGS_TO_COUNT = 0;
|
||||||
DataStorage::Database::TableRelation *BELONGS_TO = NULL;
|
DataStorage::Database::TableRelation *BELONGS_TO = NULL;
|
||||||
} MapperData;
|
};
|
||||||
|
|
||||||
void free_MapperData(DataStorage::Database::MapperData *data)
|
void free_MapperData(DataStorage::Database::MapperData *data)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
namespace DataStorage::Database
|
namespace DataStorage::Database
|
||||||
{
|
{
|
||||||
typedef struct {
|
struct DbField {
|
||||||
char *name;
|
char *name;
|
||||||
char *type;
|
char *type;
|
||||||
void *def;
|
void *def;
|
||||||
|
|
@ -25,7 +25,7 @@ namespace DataStorage::Database
|
||||||
bool autoincrement = false;
|
bool autoincrement = false;
|
||||||
char *foreignTable;
|
char *foreignTable;
|
||||||
char *foreignKey;
|
char *foreignKey;
|
||||||
} DbField;
|
};
|
||||||
|
|
||||||
void free_DbField(DbField *field)
|
void free_DbField(DbField *field)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,11 @@
|
||||||
|
|
||||||
namespace DataStorage::Database
|
namespace DataStorage::Database
|
||||||
{
|
{
|
||||||
typedef struct {
|
struct DbSchema {
|
||||||
char *name;
|
char *name;
|
||||||
DbField *fields;
|
DbField *fields;
|
||||||
size_t field_size = 0;
|
size_t field_size = 0;
|
||||||
} DbSchema;
|
};
|
||||||
|
|
||||||
void free_DbSchema(DbSchema *schema)
|
void free_DbSchema(DbSchema *schema)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -23,12 +23,12 @@
|
||||||
|
|
||||||
namespace Hash
|
namespace Hash
|
||||||
{
|
{
|
||||||
typedef struct {
|
struct md5_context {
|
||||||
uint32_t lo, hi;
|
uint32_t lo, hi;
|
||||||
uint32_t a, b, c, d;
|
uint32_t a, b, c, d;
|
||||||
unsigned char buffer[64];
|
unsigned char buffer[64];
|
||||||
uint32_t block[16];
|
uint32_t block[16];
|
||||||
} md5_context;
|
};
|
||||||
|
|
||||||
static const void *body(md5_context *ctx, const void *data, size_t size)
|
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
|
#ifdef _WIN32
|
||||||
#include <XInput.h>
|
#include <XInput.h>
|
||||||
|
#include <windows.h>
|
||||||
#else
|
#else
|
||||||
#include <linux/joystick.h>
|
#include <linux/joystick.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../Stdlib/Types.h"
|
#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()
|
bool up = false;
|
||||||
{
|
bool down = false;
|
||||||
for (uint32 controller_index = 0; controller_index < XUSER_MAX_COUNT; ++controller_index) {
|
bool left = false;
|
||||||
XINPUT_STATE controller_state;
|
bool right = false;
|
||||||
if (XInputGetState(controller_index, &controller_state) == ERROR_SUCCESS) {
|
bool start = false;
|
||||||
} else {
|
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 void (*RouterFunc)(int, const char **);
|
||||||
|
|
||||||
typedef struct {
|
struct Router {
|
||||||
Stdlib::HashTable::ht *routes;
|
Stdlib::HashTable::ht *routes;
|
||||||
} Router;
|
};
|
||||||
|
|
||||||
Router create_router(int size)
|
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
|
namespace Stdlib::HashTable
|
||||||
{
|
{
|
||||||
typedef struct {
|
struct entry {
|
||||||
const char *key;
|
const char *key;
|
||||||
void *value;
|
void *value;
|
||||||
} entry;
|
};
|
||||||
|
|
||||||
struct ht {
|
struct ht {
|
||||||
bool is_fixed = false;
|
bool is_fixed = false;
|
||||||
|
|
@ -30,13 +30,13 @@ namespace Stdlib::HashTable
|
||||||
size_t size;
|
size_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
struct it {
|
||||||
const char *key;
|
const char *key;
|
||||||
void *value;
|
void *value;
|
||||||
|
|
||||||
ht *table;
|
ht *table;
|
||||||
size_t index;
|
size_t index;
|
||||||
} it;
|
};
|
||||||
|
|
||||||
inline unsigned long long hash_key(const char *key)
|
inline unsigned long long hash_key(const char *key)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -90,19 +90,19 @@ typedef union {
|
||||||
float e[4];
|
float e[4];
|
||||||
} f4;
|
} f4;
|
||||||
|
|
||||||
typedef struct {
|
struct mi32 {
|
||||||
int32_t *e;
|
int32_t *e;
|
||||||
size_t m, n;
|
size_t m, n;
|
||||||
} mi32;
|
};
|
||||||
|
|
||||||
typedef struct {
|
struct mi64 {
|
||||||
int64_t *e;
|
int64_t *e;
|
||||||
size_t m, n;
|
size_t m, n;
|
||||||
} mi64;
|
};
|
||||||
|
|
||||||
typedef struct {
|
struct mf {
|
||||||
float *e;
|
float *e;
|
||||||
size_t m, n;
|
size_t m, n;
|
||||||
} mf;
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -615,7 +615,7 @@ namespace Stdlib::SIMD
|
||||||
return 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;
|
f32_4_simd simd;
|
||||||
simd.s = _mm_min_ps(a.s, b.s);
|
simd.s = _mm_min_ps(a.s, b.s);
|
||||||
|
|
@ -623,7 +623,7 @@ namespace Stdlib::SIMD
|
||||||
return 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;
|
f32_8_simd simd;
|
||||||
simd.s = _mm256_min_ps(a.s, b.s);
|
simd.s = _mm256_min_ps(a.s, b.s);
|
||||||
|
|
@ -631,7 +631,7 @@ namespace Stdlib::SIMD
|
||||||
return 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;
|
f32_16_simd simd;
|
||||||
simd.s = _mm512_min_ps(a.s, b.s);
|
simd.s = _mm512_min_ps(a.s, b.s);
|
||||||
|
|
@ -639,7 +639,7 @@ namespace Stdlib::SIMD
|
||||||
return 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;
|
f32_4_simd simd;
|
||||||
simd.s = _mm_max_ps(a.s, b.s);
|
simd.s = _mm_max_ps(a.s, b.s);
|
||||||
|
|
@ -647,7 +647,7 @@ namespace Stdlib::SIMD
|
||||||
return 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;
|
f32_8_simd simd;
|
||||||
simd.s = _mm256_max_ps(a.s, b.s);
|
simd.s = _mm256_max_ps(a.s, b.s);
|
||||||
|
|
@ -655,7 +655,7 @@ namespace Stdlib::SIMD
|
||||||
return 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;
|
f32_16_simd simd;
|
||||||
simd.s = _mm512_max_ps(a.s, b.s);
|
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)
|
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)
|
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)
|
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)
|
inline int32 which_true(f32_4_simd a)
|
||||||
|
|
|
||||||
|
|
@ -611,7 +611,7 @@ namespace Stdlib::SIMD
|
||||||
return 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;
|
int32_4_simd simd;
|
||||||
simd.s = _mm_min_epi32(a.s, b.s);
|
simd.s = _mm_min_epi32(a.s, b.s);
|
||||||
|
|
@ -619,7 +619,7 @@ namespace Stdlib::SIMD
|
||||||
return 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;
|
int32_8_simd simd;
|
||||||
simd.s = _mm256_min_epi32(a.s, b.s);
|
simd.s = _mm256_min_epi32(a.s, b.s);
|
||||||
|
|
@ -627,7 +627,7 @@ namespace Stdlib::SIMD
|
||||||
return 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;
|
int32_16_simd simd;
|
||||||
simd.s = _mm512_min_epi32(a.s, b.s);
|
simd.s = _mm512_min_epi32(a.s, b.s);
|
||||||
|
|
@ -635,7 +635,7 @@ namespace Stdlib::SIMD
|
||||||
return 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;
|
int32_4_simd simd;
|
||||||
simd.s = _mm_max_epi32(a.s, b.s);
|
simd.s = _mm_max_epi32(a.s, b.s);
|
||||||
|
|
@ -643,7 +643,7 @@ namespace Stdlib::SIMD
|
||||||
return 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;
|
int32_8_simd simd;
|
||||||
simd.s = _mm256_max_epi32(a.s, b.s);
|
simd.s = _mm256_max_epi32(a.s, b.s);
|
||||||
|
|
@ -651,7 +651,7 @@ namespace Stdlib::SIMD
|
||||||
return 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;
|
int32_16_simd simd;
|
||||||
simd.s = _mm512_max_epi32(a.s, b.s);
|
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)
|
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)
|
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)
|
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)
|
inline int32 which_true(int32_4_simd a)
|
||||||
|
|
|
||||||
|
|
@ -28,4 +28,8 @@ typedef double f64;
|
||||||
|
|
||||||
typedef unsigned char byte;
|
typedef unsigned char byte;
|
||||||
|
|
||||||
|
#define internal static // only allows local "file" access
|
||||||
|
#define local_persist static
|
||||||
|
#define global_persist static
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,10 @@
|
||||||
typedef HANDLE pthread_t;
|
typedef HANDLE pthread_t;
|
||||||
typedef CONDITION_VARIABLE pthread_cond_t;
|
typedef CONDITION_VARIABLE pthread_cond_t;
|
||||||
|
|
||||||
typedef struct {
|
struct pthread_rwlock_t {
|
||||||
SRWLock lock;
|
SRWLock lock;
|
||||||
bool exclusive;
|
bool exclusive;
|
||||||
} pthread_rwlock_t;
|
};
|
||||||
|
|
||||||
struct timespec {
|
struct timespec {
|
||||||
long tv_sec;
|
long tv_sec;
|
||||||
|
|
@ -39,10 +39,10 @@ void ms_to_timespec(struct timespec *ts, unsigned int ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
typedef struct {
|
struct win_thread_start_t {
|
||||||
void *(*start_routine)(void *);
|
void *(*start_routine)(void *);
|
||||||
void *start_arg;
|
void *start_arg;
|
||||||
} win_thread_start_t;
|
};
|
||||||
|
|
||||||
static DWORD WINAPI win_thread_start(void *arg)
|
static DWORD WINAPI win_thread_start(void *arg)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
namespace Threads
|
namespace Threads
|
||||||
{
|
{
|
||||||
typedef struct {
|
struct ThreadPool {
|
||||||
Job *work_first;
|
Job *work_first;
|
||||||
Job *work_last;
|
Job *work_last;
|
||||||
pthread_mutex_t work_mutex;
|
pthread_mutex_t work_mutex;
|
||||||
|
|
@ -25,7 +25,7 @@ namespace Threads
|
||||||
size_t working_cnt;
|
size_t working_cnt;
|
||||||
size_t thread_cnt;
|
size_t thread_cnt;
|
||||||
bool stop;
|
bool stop;
|
||||||
} ThreadPool;
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
104
UI/window.h
104
UI/window.h
|
|
@ -1,116 +1,64 @@
|
||||||
#ifndef UI_WINDOW_H
|
#ifndef UI_WINDOW_H
|
||||||
#define UI_WINDOW_H
|
#define UI_WINDOW_H
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <windowsx.h>
|
|
||||||
|
|
||||||
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "../Stdlib/Types.h"
|
||||||
|
|
||||||
namespace UI
|
namespace UI
|
||||||
{
|
{
|
||||||
struct WindowStat {
|
struct Window {
|
||||||
double oldFrame = 0;
|
int32 width;
|
||||||
double newFrame = 0;
|
int32 height;
|
||||||
double dt = 0;
|
char wName[32];
|
||||||
};
|
|
||||||
|
|
||||||
void update_window_stat(WindowStat *stat)
|
int32 x;
|
||||||
{
|
int32 y;
|
||||||
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;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
void window_open(window* w)
|
void window_open(const Window* window)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
ShowWindow(w->hwnd, SW_SHOW);
|
ShowWindow(window->hwnd, SW_SHOW);
|
||||||
|
UpdateWindow(window->hwnd);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_WIN32) && defined(DIRECTX)
|
void window_create_windows(Window* window, WNDPROC proc)
|
||||||
void window_create_windows(window* w)
|
{
|
||||||
{
|
WNDCLASSEX wc = {};
|
||||||
HINSTANCE hinstance = GetModuleHandle(nullptr);
|
HINSTANCE hinstance = GetModuleHandle(0);
|
||||||
|
|
||||||
WNDCLASSEX wc;
|
|
||||||
ZeroMemory(&wc, sizeof(WNDCLASSEX));
|
|
||||||
|
|
||||||
wc.cbSize = sizeof(WNDCLASSEX);
|
wc.cbSize = sizeof(WNDCLASSEX);
|
||||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
wc.style = CS_OWNDC;
|
||||||
wc.lpfnWndProc = WindowProc;
|
wc.lpfnWndProc = proc;
|
||||||
wc.hInstance = hinstance;
|
wc.hInstance = hinstance;
|
||||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
wc.lpszClassName = (LPCWSTR) window->wName;
|
||||||
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
|
|
||||||
wc.lpszClassName = L"WindowClass1";
|
|
||||||
|
|
||||||
RegisterClassEx(&wc);
|
RegisterClassEx(&wc);
|
||||||
|
|
||||||
RECT wr = {0, 0, 800, 600};
|
window->hwnd = CreateWindowEx((DWORD) NULL,
|
||||||
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
|
|
||||||
|
|
||||||
w->hwnd = CreateWindowEx((DWORD) NULL,
|
|
||||||
wc.lpszClassName, NULL,
|
wc.lpszClassName, NULL,
|
||||||
WS_OVERLAPPEDWINDOW,
|
WS_OVERLAPPEDWINDOW,
|
||||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||||
wr.right - wr.left,
|
window->width,
|
||||||
wr.bottom - wr.top,
|
window->height,
|
||||||
NULL, NULL, hinstance, w
|
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;
|
void window_close(Window* window)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#if defined(DIRECTX)
|
CloseWindow(window->hwnd);
|
||||||
window_create_directx(w);
|
|
||||||
#else if defined(_WIN32) && defined(OPENGL)
|
|
||||||
window_create_opengl(w);
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,11 @@
|
||||||
|
|
||||||
namespace Utils::ColorUtils
|
namespace Utils::ColorUtils
|
||||||
{
|
{
|
||||||
typedef struct {
|
struct RGB {
|
||||||
unsigned char r = 0;
|
unsigned char r = 0;
|
||||||
unsigned char g = 0;
|
unsigned char g = 0;
|
||||||
unsigned char b = 0;
|
unsigned char b = 0;
|
||||||
} RGB;
|
};
|
||||||
|
|
||||||
inline RGB *int_to_rgb(int rgb)
|
inline RGB *int_to_rgb(int rgb)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -91,10 +91,10 @@ namespace Utils::FileUtils
|
||||||
return dot + 1;
|
return dot + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
struct file_body {
|
||||||
char *content;
|
char *content;
|
||||||
int size = 0; // doesn't include null termination (same as strlen)
|
int size = 0; // doesn't include null termination (same as strlen)
|
||||||
} file_body;
|
};
|
||||||
|
|
||||||
file_body read_file(const char *filename)
|
file_body read_file(const char *filename)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#define OMS_PI 3.14159265358979323846
|
#define OMS_PI 3.14159265358979323846f
|
||||||
|
|
||||||
#define oms_max(a, b) ((a) > (b) ? (a) : (b))
|
#define oms_max(a, b) ((a) > (b) ? (a) : (b))
|
||||||
#define oms_min(a, b) ((a) > (b) ? (b) : (a))
|
#define oms_min(a, b) ((a) > (b) ? (b) : (a))
|
||||||
|
|
|
||||||
|
|
@ -160,11 +160,11 @@ namespace Utils::StringUtils
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
struct text_diff {
|
||||||
char **values;
|
char **values;
|
||||||
int64_t *masks;
|
int64_t *masks;
|
||||||
size_t size;
|
size_t size;
|
||||||
} text_diff;
|
};
|
||||||
|
|
||||||
text_diff computeLCSDiff(const char **from, size_t fromSize, const char **to, size_t toSize)
|
text_diff computeLCSDiff(const char **from, size_t fromSize, const char **to, size_t toSize)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,42 @@
|
||||||
#ifndef UTILS_TEST_UTILS_H
|
#ifndef UTILS_TEST_UTILS_H
|
||||||
#define UTILS_TEST_UTILS_H
|
#define UTILS_TEST_UTILS_H
|
||||||
|
|
||||||
#include "MathUtils.h"
|
|
||||||
#include <stdio.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) \
|
#define ASSERT_EQUALS(a, b, t1, t2) \
|
||||||
({ \
|
({ \
|
||||||
if ((a) == (b)) { \
|
if ((a) == (b)) { \
|
||||||
|
|
@ -73,6 +106,11 @@
|
||||||
} \
|
} \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
#define ASSERT_SIMPLE(a) \
|
||||||
|
if ((a) == false) { \
|
||||||
|
*(volatile int *)0 = 0; \
|
||||||
|
}
|
||||||
|
|
||||||
#define ASSERT_TRUE(a) \
|
#define ASSERT_TRUE(a) \
|
||||||
({ \
|
({ \
|
||||||
if ((a) == true) { \
|
if ((a) == true) { \
|
||||||
|
|
|
||||||
|
|
@ -82,15 +82,15 @@ namespace Utils::WebUtils
|
||||||
return out->size;
|
return out->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
struct ResourceTypes {
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
const char **resources = NULL;
|
const char **resources = NULL;
|
||||||
} ResourceTypes;
|
};
|
||||||
|
|
||||||
typedef struct {
|
struct Urls {
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
const char **urls = NULL;
|
const char **urls = NULL;
|
||||||
} Urls;
|
};
|
||||||
|
|
||||||
Utils::FileUtils::file_body download (char *url)
|
Utils::FileUtils::file_body download (char *url)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user