update
Some checks failed
CI / code-tests: ${{ matrix.os }} / ${{ matrix.platform }} (ubuntu-latest, x64) (push) Has been cancelled
CI / code-tests: ${{ matrix.os }} / ${{ matrix.platform }} (ubuntu-latest, x86) (push) Has been cancelled
CI / general_module_workflow_c (push) Has been cancelled

This commit is contained in:
Dennis Eichhorn 2024-05-29 05:12:23 +02:00
parent 3cd7ada19e
commit 02ee4480ad
26 changed files with 921 additions and 154 deletions

View File

@ -19,11 +19,11 @@
namespace Application
{
typedef struct {
struct ApplicationAbstract {
DataStorage::Database::ConnectionAbstract *db;
nlohmann::json config;
Threads::ThreadPool *pool;
} ApplicationAbstract;
};
} // namespace Application
#endif

View File

@ -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;

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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
View 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

View File

@ -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;
}
}
}

View File

@ -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
View 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,
&region1, &region1_size,
&region2, &region2_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
View 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

View File

@ -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)
{

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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)
{

View File

@ -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

View File

@ -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
}
}

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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))

View File

@ -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)
{

View File

@ -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) { \

View File

@ -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)
{